реклама на сайте
подробности

 
 
> Декодер манчестерского кода на ассемблере, Пишу приемник для PRUSS (AM335x)
kowapuk
сообщение Mar 22 2016, 08:27
Сообщение #1





Группа: Участник
Сообщений: 7
Регистрация: 21-03-16
Пользователь №: 90 958



Введение:
Взял себе плату BeagleBone с процессором AM335x. У него на борту есть два реал-тайм ядра PRU (PRU0 и PRU1). Хочу через GPIO научить их обмениваться данными. Данный кодируются в манчестерском коде. У прушек свой компилятор - pasm. Частота работы ядер 200 МГц

Проблема:
Понятно, что алгоритм передачи написать не так сложно: сначала переводит байт в МК(манчестерский код), потом передаем бит за битом. С приемом, естественно, немного сложнее, но идея проста: принимаем стартовую последовательность, а далее делаем некоторое количество отсчетов за 1/3 периода. Записываем значение счетчика и сравниваем с следующим отсчетом.
В коде я сделал немного иначе и вместо 1/3 взял чуть меньше 1/2. Вот пример кода:
Код
LISEN:                            // прослушка линии
    QBEQ START, r9, 15    // если принято 16 бит, то выход
    MOV r2, 0                   // обнуляем счетчик длительности
    QBBC CLR0, IN           // проверка на 0-ь.
    QBBS SET1, IN           // проверка на 1-цу
CLR0:                // метка установки 0
    ADD r2, r2, 1        // счетчик длительности
    QBBC CLR0, IN        // проверяет текущий уровень
    QBGE CLR10, r2, 50   //  считаем, что  половина периода -  150 нс. Тогда переход на CLR10, если 0 длится больше 150
    CLR r5.t16                // устанавливаем 0
    LSR r5, r5, 1        // сдвигаем
    ADD r9, r9, 1        // счетчик принятых бит
    QBA LISEN        // возвращаемся на прослушку
CLR10:                // пришло два нуля
    CLR r5.t16        // устанавливаем и сдвигаем
    LSR r5, r5, 1        
    CLR r5.t16
    LSR r5, r5, 1
    ADD r9, r9, 2        // принято 2 бита
    QBA LISEN        // возврат на прослушку
//--------------------------------------------------------------------------
SET1:                // метка установки 1
    ADD r2, r2, 1        // счетчик длительности
    QBBS SET1, IN        // проверяет текущий уровень
    QBGE SET01, r2, 50   //  считаем, что период 150 нс.
    SET r5.t16                // устанавливаем 1
    LSR r5, r5, 1        // сдвигаем
    ADD r9, r9, 1        // счетчик принятых бит
    QBA LISEN                // возвращаемся на прослушку
SET01:                // пришло две 1-ы
    SET r5.t16        // устанавливаем и сдвигаем
    LSR r5, r5, 1        
    SET r5.t16
    LSR r5, r5, 1
    ADD r9, r9, 2        // принято 2 бита
    QBA LISEN        // возврат на прослушку

Код, естественно, работает не совсем корректно, поэтому для теста я написал тестовую программку для 4-ех бит, а именно ситуаций, когда в линии 0011, 1100, 1001, 0110. Мне думается, что весь мой косяк в том, что я не правильно произвожу выборку.

Глоссарии:
SBCO - команда записи данных в память
QBBS, QBBC - команды перехода на метку, если 1 или 0
QBNE - переход на метку, пока не ровно.
QBGE - переход на метку, если больше.

Недочеты кода:
переход на метки SET01 и CLR10 происходит в тот момент, когда переход от 1 к 0, тогда в линии у нас 1001, либо от 0 к 1, тогда 0110. . Как только условия соблюдены, у нас происходит ещё 9 тактов - это доп. смещение, которое ломает общий алгоритм. Либо нужно увеличивать длительность сигнала, либо придумать компенсацию. А может я ошибаюсь..

UPD: перед входом к метке LISEN стоит команда WBS IN. Вход в метку будет в тот момент, когда по линии придет единица. Если смогу принять одни байт информации, то можно будет уже перейти на пакеты.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 4)
kowapuk
сообщение Apr 11 2016, 06:21
Сообщение #2





Группа: Участник
Сообщений: 7
Регистрация: 21-03-16
Пользователь №: 90 958



Передатчик можно написать, исходя из кода приемника. Это не самое трудное.
Далее, нужно добавить пару строчек перевода кода манчестера в классический.
Код
// приемник для передачи сигнала со скоростью 2 мегабита
.origin 0
.entrypoint PRE

#include "GPIOCTR.hp"
#include "TRSBNI.hp"

#define USR0 21                // led 0
#define USR1 22                // led 1
#define USR2 23                // led 2
#define USR3 24                // led 3
#define GPIO1 0x4804C000    // адресс регистров GPIO1
#define PRU1_ARM_INT 20        // значение прерывания от PRU1 to ARM


#define RAM0 C24        // Локальная память PRU1
#define RAM1 C25        // Локальная память PRU0
#define IN r31.t6        // входной GPIO

//Определим основные регистры
#define REQ r1             // в этот регистр будет помещаться информация от PRU0
#define COUNT r2        // считает колличество принятых байт
#define VALUE r3
//Приветствуем в программа приемника кода на PRU
PRE:
    MOV R4, 2
INIT:
    MOV REQ, 0
    MOV COUNT, 8
    MOV VALUE, 0
    LBCO REQ, RAM0, 0, 1        // выход из программы.
    QBEQ EXIT, REQ, 0
START:
// Знаем, что в линии, если ничего не приходит идет сигнал низкого уровня
// Длительность задержки 45 нс. Проверяющий сигнал между байтами равен 9 мкс
// Или 4.5 HIGH и 4.5 LOW. Для начала будем ждать сигнал от PRU0, что он начал передачу
    
    LBCO REQ, RAM0, 1, 1             // сюда помещаем разрешающее значения
    QBNE START, REQ, 0            // Пока не будет установлен 0, будет прыгать на старт.
    
// в начале посылки каждого байта будем получать переход из 1 в 0. Задержка кажого сигнала 4.5 мкс
    WBS IN        // ждем 4.5 мкс
    WBC IN        // после этого нужно поставить задержку, равную 100
    CDELAY 101    // компенсация задержки хоста 100+1. CDELAY 1 - 45 нс.
POOL:
    REC9 IN, VALUE, COUNT        //макрос приемника
    SBCO VALUE, RAM0, R4, 1        // запись в память
    ADD R4, R4, 1                // добавляем 1 в счетчик бит
    QBEQ EXIT, R4, 35
    QBA INIT
// Дальше начинают приходить биты с длительностью от 480 до 500 нс (-45 нс)
EXIT:                // Ждем прерывания от хоста и выключаем PRU
    MOV r31.b0, 20+16
    HALT


Синтаксис макроса REC9 (REC9 - это приемник с задержкой 9):
Код
.macro REC9            // Макрос приема данных с задержкой 9            
.mparam IN, OUT, COUNT      // входные параметры: IN - вход GPIO; OUT - выходной регистр;
// COUNT - регистр, содержащий в себе число бит.
RECIVE:
    QBBS SET1X, IN   // проверяем 1 сейчас. Если нет, то сразу переход на 0
    QBEQ BACK, COUNT, 0
SET0X:
    WBC IN        // проверям, точно ли 0.
    CDELAY 9    // ждем 405 НС. До смены остается ещё 30 НС
    WBC IN        // вторая проверка. Debbug точка
    CDELAY 1    // после неё станет ясно, что пришло. Сигнал уже как 20 нс новый.
    QBBC SET00, IN  // пришел 0? Если нет, значит 1-ца. -25 нс.
SET01:            // ЗАписываем переход из 0 в 1
    CLR OUT.t1    // Записываем 01
    SET OUT.t0
    LSL OUT, OUT, 2    //смещаем. -45нс.
    CDELAY 9         // Сигналу осталось минимум 30 нс. -405-40+480
    SUB COUNT, COUNT, 2    // принято 2-а байта. 25 нс.
    CDELAY 1        // -20 нс нового сигнала
    QBA RECIVE        // возвращаемся на прием. -25
SET00:                //записываем переход из 0 в 0
    CLR OUT.t1
    CLR OUT.t0
    LSL OUT, OUT, 2
    CDELAY 9
    SUB COUNT, COUNT, 2
    CDELAY 1
    QBA RECIVE        // возвращаемся на прием -25
SET1X:            // для установки 1-ы и....
    WBS IN        // аналогично с нулем
    CDELAY 9
    WBS IN
    CDELAY 1
    QBBS SET11, IN
SET10:
    SET OUT.t1
    CLR OUT.t0
    LSL OUT, OUT, 2
    CDELAY 9
    SUB COUNT, COUNT, 2
    CDELAY 1
    QBA RECIVE    // переход на прием
SET11:
    SET OUT.t1
    SET OUT.t0
    LSL OUT, OUT, 2
    CDELAY 9
    SUB COUNT, COUNT, 2
    CDELAY 1
    QBA RECIVE     // переход на прием
BACK:            // метка записи значения
    LSR OUT, OUT, 2 // когда приходят последний 2 бита, то он сдвигаются влево. Это необходимо учесть

.endm


Тему можно закрывать.
Go to the top of the page
 
+Quote Post
vladec
сообщение Apr 11 2016, 06:40
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 167
Регистрация: 3-10-05
Из: Москва
Пользователь №: 9 158



А вообще, зачем Вам Манчестер? Чем Вам обычный UART не подходит? Вы, что, соединяетесь через трансформатор?
Go to the top of the page
 
+Quote Post
kowapuk
сообщение Apr 11 2016, 07:11
Сообщение #4





Группа: Участник
Сообщений: 7
Регистрация: 21-03-16
Пользователь №: 90 958



Цитата(vladec @ Apr 11 2016, 12:40) *
А вообще, зачем Вам Манчестер? Чем Вам обычный UART не подходит? Вы, что, соединяетесь через трансформатор?

Для того объекта, с которым будет вестись обмен, не предусмотрен UART для обмена данными. Для этого бы приходилось влазить в "ту" систему. А это, пока что, исключено.
Go to the top of the page
 
+Quote Post
kowapuk
сообщение Apr 12 2016, 10:53
Сообщение #5





Группа: Участник
Сообщений: 7
Регистрация: 21-03-16
Пользователь №: 90 958



Цитата(vladec @ Apr 11 2016, 12:40) *
А вообще, зачем Вам Манчестер? Чем Вам обычный UART не подходит? Вы, что, соединяетесь через трансформатор?

А вообще, да. Через трансформатор.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 15:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01427 секунд с 7
ELECTRONIX ©2004-2016