Цитата(MrYuran @ Apr 22 2010, 13:12)

Это откуда? Я что-то не нашел...
Признаю, мой грех. Следует читать "AVR" вместо "MSP430". Слишком велико было желание выдать мечту за действительное.
"... То есть подаём сигнал на вход UARTа в режиме SPI, а таймером формируем тактовые клоки.
Задвинули 8 тактов, прерывание от SPI, складываем в буфер."
"...Его можно отловить компаратором. То есть если обе линии в одном состоянии - получаем прерывание от компаратора.
Приняли весь пакет - обрабатываем. Декодируем NRZI, выкидываем биты стаффинга и т.д."
Извините, М-р Юран, но в кристалле MSP430F2013 нет аппаратного UART и нет компаратора, там только АЦП16.
"Хотя можно и исходный алгоритм переработать. Но в этом случае во время обмена контроллер не сможет ни на что отвлекаться. Потому что счёт на такты процессора. То есть все прерывания должны быть запрещены.
В принципе, автор как раз и подчёркивает, что для его реализации не нужна никакая периферия, только опрос порта и 100% занятость процессора в момент обмена."
После чтения и перевода на русский статьи Старкйохана возникли вопросы и сомнения. Конечный вариант кода -
Код
rxbit0:
in x1, port;1 цикл на чтение данных из порта ввода\вывода
andi x1, mask; 1 цикл на проверку конца пакета передачи SE0
breq end_of_packet; 1 цикл (так как переход по ветви не произошёл)
eor x2, x1; 1 цикл на декодирование NRZI – без возврата к нулю инверт
ror x2; 1 цикл на приём бита из LSB -> carry
ror shift; 1 цикл накопление битов данных
cpi shift, 4; 1 цикл на проверку наличия 6-ти последовательных нулей
brlo do_unstaff; 1 цикл (так как переход по ветви не произошёл)
rxbit1:
in x2, port;1 цикл на чтение данных из порта ввода\вывода
breq end_of_packet; 1 цикл (так как переход по ветви не произошёл)
eor x1, x2; 1 цикл на декодирование NRZI – без возврата к нулю инверт
ror x1; 1 цикл на приём бита из LSB -> carry
ror shift; 1 цикл накопление битов данных
cpi shift, 4; 1 цикл на проверку наличия 6-ти последовательных нулей
brlo do_unstaff; 1 цикл (так как переход по ветви не произошёл)
mov x2, x1; 1 цикл (сохранение ввода для следующего цикла)
итого 16 циклов
Удаление набитого незначащего приткнутого бита.
С первого взгляда разрушение одного бита должно быть простым. Только прикиньтесь манекеном – сделайте чтение и ожидание:
do_unstuff0: ; 1 цикл (переход из точки ветвления по условию)
in x1, port;1 цикл на чтение данных из порта ввода\вывода
andi x1, mask; 1 цикл на проверку конца пакета передачи SE0
breq end_of_packet; 1 цикл (так как переход по ветви не произошёл)
nop ;1 цикл на отсутствие операции – пустая команда
nop ;1 цикл на отсутствие операции – пустая команда
rjmp rxbit1;2 цикла (переход из точки ветвления по условию)
итого 8 циклов
Впервые у нас два свободных цикла! Делаем необходимые копирование и запись и заменяем проверки конца пакета для управления переходом по петле и готово. Но постойте! Что произойдёт, если за всунутым незначащим битом следует такой же? Наш сдвиговый регистр содержит сохранённые данные и в нём окажется 7 нулей подряд. Следующий бит будет поэтому проигнорирован, хотя вставка незначащего бита была только что отработана. Программная ошибка!
На этот раз всё действительно серьёзно. Нам надо исключить ситуацию, когда в сдвиговом регистре более 5 старших нулей подряд, но в нём данные, которые нам нужны. И мы не можем и не должны их менять. Можно сделать копию регистра и использовать её для обнаружения битстаффинга. Но где взять свободные циклы, чтобы позаботиться о копии. И в конце концов, хранение обширных данных не может быть эффективным. В чём мы действительно нуждаемся, так это в другой Хорошей Идее.
Если решение существует, он должно состоять в изменении содержимого регистра сдвига. Это единственный способ плотно упаковать код для чтения битов, чтобы выжить без изменения. Отлично. Итак, мы должны установить по меньшей мере самый старший значащий бит в сдвиге в ходе do_unstuff. Но как нам тогда восстановить полученный байт?
Ключ к решению – в том, что мы знаем, что мы модифицируем. Мы устанавливаем в «1» бит, про который известно, что его значение - «0». И мы знаем, где они будут приземляться, поскольку петля цикла развёрнута и фиксировано количество операций сдвига, следующих до момента сохранения данных. Мы просто собираем биты, которые мы изменили, в отдельном регистре и возвращаем их назад сразу перед сохранением. К счастью, у нас оставалось два свободных цикла в do_unstuff:
do_unstuff0: ; 1 цикл (переход из точки ветвления по условию)
in x1, port;1 цикл на чтение данных из порта ввода\вывода
andi x1, mask; 1 цикл на проверку конца пакета передачи SE0
breq end_of_packet; 1 цикл (так как переход по ветви не произошёл)
ori shift, 0xfc;1 цикл маскировка 6ти свежих бит подряд
andi x3, 0xfe;1 цикл спрятанные нами биты сдвинуты вправо на 7
rjmp rxbit1;2 цикла (переход из точки ветвления по условию)
Попытался реализовать в IAR Embedded Workbench IDE 4.21.8.
Код
;*******************************************************************************
; MSP430F20xx Demo - USB 1.1 Echo, 12MHz SMCLK
;
; Description: Use data latch
; to implement USB function @ 1500000 baud. Software directly reads and
; writes to RX and TX pins, all software activity is stopped besides CPU.
; No interrupt is available.
; After a character has been received, CPU forces echo's back the received character.
; MCLK = SMCLK = DCO = 12 MHz
;
;
; MSP430F20xx
; -----------------
; /|\| XIN|-
; | | |
; --|RST XOUT|-
; | |
; | CCI0B/TXD/P1.5|-------->
; | | 1500000 8N1
; | CCI0A/RXD/P1.1|<--------
;
; April 2010
; Built with IAR Embedded Workbench Version: 4.21.8
;*******************************************************************************
RXD EQU 002h ; RXD on P1.1
TXD EQU 020h ; TXD on P1.5
;
; CPU Registers Used
#define Rx1 R4
#define Rx2 R5
#define Rx3 R6
;
; Conditions for 150000 Baud SW USB1.1, SMCLK = 12000000
Bitime_5 EQU 04 ; ~0.5 bit length
Bitime EQU 08 ; 667ns bit length ~ 1.5 Mbaud
#include "msp430x20x3.h"
;-------------------------------------------------------------------------------
ORG 0F800h ; Program Reset
;-------------------------------------------------------------------------------
RESET mov.w #0280h,SP ; Initialize stackpointer
StopWDT mov.w #WDTPW+WDTHOLD,&WDTCTL; Stop Watchdog Timer
SetupBCS mov.w #CALBC1_12MHZ,&BCSCTL1 ; SMCLK, 12MHz
SetupDC0 mov.w #CALBC0_12MHZ,&DCOCTL ; DCO = 12MHz
SetupP1 bis.b #TXD+RXD,&P1SEL ;
bis.b #TXD,&P1DIR ;
SetupX3 mov.w 0xff,Rx3
;
Rxbit0 mov.w &020h,Rx1 ; read data from I\O port
cmp.b msk,RX1 ; check for SE0
jne End_of_Packet ;
xor.b Rx2,Rx1 ; NRZI decoding
rrc.b Rx2 ; Data bit -> carry
rrc.b shift ; collect data bits
cmp.w shift,4 ; check for 6 consecutieve 0 bits
jnz do_unstuff0; ; Stuffed bit? Will be ignored!
Rxbit1 mov.w &020h,Rx2 ; read data from I\O port
cmp.b msk,RX2 ; check for SE0
jne End_of_Packet ;
xor.b Rx1,Rx2 ; NRZI decoding
rrc.b Rx1 ; Data bit -> carry
rrc.b shift ; collect data bits
cmp.w shift,4 ; check for 6 consecutieve 0 bits
jnz do_unstuff1; ; Stuffed bit? Will be ignored!
do_unstuff0 mov.w &020h,Rx1 ; read data from I\O port
cmp.b msk,RX1 ; check for SE0
jne End_of_Packet ;
xor.b shift,0xfc ; mask out 6 recently received bits
cmp.b Rx3,0xfe ; shift masked bits right 7
jnz rxbit1; ;
do_unstuff1 mov.w &020h,Rx2 ; read data from I\O port
cmp.b msk,RX2 ; check for SE0
jne End_of_Packet ;
xor.b shift,0xfc ; mask out 6 recently received bits
cmp.b Rx3,0xfe ; shift masked bits right 7
jnz rxbit0; ;
End_of_Packet
nop
;-------------------------------------------------------------------------------
; Interrupt Vectors
;-------------------------------------------------------------------------------
ORG 0FFFEh ; MSP430 RESET Vector
DW RESET ;
ORG 0FFF2h ; Timer_A0 Vector
DW TA0_ISR ;
END
При попытке компиляции выскакивает ошибка Error [431] Accessing SFR using incorrect size. На строку SetupBCS. Помогите, пожалуйста, понять, что не так?