⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr309-usb 到 uart 协议转换程序.txt

📁 AVR309-USB 到 UART 协议转换程序。
💻 TXT
📖 第 1 页 / 共 5 页
字号:
       ld    temp0,Y                    ;从缓冲区取出数据
       mov   temp2,temp0                ;保存到temp2
       ror   temp2                      ;将 C 移入
       eor   temp2,temp0                ;解码 NRZI
       com   temp2                      ;取反
       st    Y+,temp2                   ;将完成解码的数据存入
       cp    USBBufptrY,ByteCount       ;所有数据解码完成吗?
       brne  NRZIloop                   ;没有完成,继续解码
       pop   ByteCount
       pop   USBBufptrY
       ret
;------------------------------------------------------------------------------------------
BitStuff:   ;位填充处理 (NRZI 编码 6个逻辑1之后插入一位0)
;在接收USB数据中删除/添加位填充。位填充是主机硬件依照USB规范为了数据采样同步而添加的。
;这个例程去除接收数据中的位填充,发送数据时添加位填充。
       clr   temp3                      ;pocitadlo vynechanych bitov
       clr   lastBitstufNumber          ;0xFF --> lastBitstufNumber
       dec   lastBitstufNumber
BitStuffRepeat:
       push  USBBufptrY                 ;临时保存
       push  ByteCount                  ;临时保存
       mov   temp1,temp3                ;pocitadlo vsetkych bitov
       ldi   temp0,8                    ;每字节8位
SumAllBits:  ;计算所有数据的总位数
       add   temp1,temp0
       dec   ByteCount
       brne  SumAllBits
       ldi   temp2,6                    ;6个逻辑1之后插入一位0
       pop   ByteCount                  ;恢复数据,不改变堆栈内容
       push  ByteCount
       add   ByteCount,USBBufptrY       ;指向缓冲区结尾
       inc   ByteCount                  ;+ 2 (kvoli posuvaniu)
       inc   ByteCount
BitStuffLoop:
       ld    temp0,Y                    ;从缓冲区取出数据
       ldi   bitcount,8
BitStuffByteLoop:
       ror   temp0                      ;移位 LSB 到 C
       brcs  IncrementBitstuff          ;判断最低位 LSB=0 ?
       ldi   temp2,7                    ;为0,重新计数"6个逻辑1之后插入一位0"
IncrementBitstuff:
       dec   temp2                      ;连续6个逻辑1吗?
       brne  DontShiftBuffer            ;不是连续6个逻辑1,缓冲区的数据不操作
       cp    temp1,lastBitstufNumber    ;是连续6个逻辑1
       ldi   temp2,6                    ;初始化判断计数 (ak by sa nerobil bitstuffing tak sa musi zacat odznova)
       brcc  DontShiftBuffer            ;ak sa tu uz robil bitstuffing - neposun buffer

       dec   temp1                      ;
       mov   lastBitstufNumber,temp1    ;zapamataj si poslednu poziciu bitstuffingu
       cpi   bitcount,1                 ;aby sa ukazovalo na 7 bit (ktory sa ma vymazat alebo kde sa ma vlozit nula)
       brne  NoBitcountCorrect
       ldi   bitcount,9
       inc   USBBufptrY                 ;zvys 指针 do 缓冲区
NoBitcountCorrect:
       dec   bitcount
       bst   BitStuffInOut,0
       brts  CorrectOutBuffer           ;是增加位填充还是滤除位填充? 增加=1 滤除=0
       rcall ShiftDeleteBuffer          ;滤除填充位
       dec   temp3                      ;zniz pocitadlo vynechani
       rjmp  CorrectBufferEnd
CorrectOutBuffer:
       rcall ShiftInsertBuffer          ;插入填充位
       inc   temp3                      ;zvys pocitadlo vynechani
CorrectBufferEnd:
       pop   ByteCount                  ;obnov dlzku 缓冲区
       pop   USBBufptrY                 ;obnov 指针 do 缓冲区
       rjmp  BitStuffRepeat             ;a restartni od zaciatku
DontShiftBuffer:
       dec   temp1                      ;所有位都判断完成吗?
       breq  EndBitStuff                ;ukonci cyklus
       dec   bitcount                   ;当前字节判断完成吗?
       brne  BitStuffByteLoop           ;继续判断填充
                   ;inak nahraj dalsi byte
       inc   USBBufptrY                 ;zvys 指针 do 缓冲区
       rjmp  BitStuffLoop               ;a opakuj

EndBitStuff:
       pop   ByteCount                  ;obnov dlzku 缓冲区
       pop   USBBufptrY                 ;obnov 指针 do 缓冲区
       bst   BitStuffInOut,0
       brts  IncrementLength            ;是增加位填充还是滤除位填充? 增加=1 滤除=0
DecrementLength:    ;ak je In buffer - zniz dlzku In 缓冲区
       cpi   temp3,0                    ;bolo aspon jedno znizenie
       breq  NoChangeByteCount          ;ak nie - nemen dlzku 缓冲区
       dec   ByteCount                  ;ak je In buffer - zniz dlzku 缓冲区
       subi  temp3,256-8                ;ak nebolo viac ako 8 bitov naviac
       brcc  NoChangeByteCount          ;tak skonci
       dec   ByteCount                  ;inak este zniz dlzku 缓冲区
       ret                              ;a skonci
IncrementLength:
       mov   OutBitStuffNumber,temp3    ;zapamataj si pocet bitov naviac
       subi  temp3,8                    ;ak nebolo viac ako 8 bitov naviac
       brcs  NoChangeByteCount          ;tak skonci
       inc   ByteCount                  ;inak zvys dlzku 缓冲区
       mov   OutBitStuffNumber,temp3    ;a zapamataj si pocet bitov naviac (znizene o 8)
NoChangeByteCount:
       ret                              ;skonci
;------------------------------------------------------------------------------------------
ShiftInsertBuffer: ;posuv 缓冲区 o jeden bit vpravo od konca az po poziciu: byte-USBBufptrY a bit-bitcount
;执行位填充增加时的辅助例程。添加一位到输出数据缓冲区会增加缓冲区的长度。缓冲区的剩余部
;分移出。
       mov   temp0,bitcount             ;vypocet: bitcount= 9-bitcount
       ldi   bitcount,9
       sub   bitcount,temp0             ;do bitcount poloha bitu, ktory treba nulovat

       ld    temp1,Y                    ;nahraj byte ktory este treba posunut od pozicie bitcount
       rol   temp1                      ;a posun vlavo cez Carry (prenos z vyssieho byte a LSB do Carry)
       ser   temp2                      ;FF do masky - temp2
HalfInsertPosuvMask:
       lsl   temp2                      ;nula do dalsieho spodneho bitu masky
       dec   bitcount                   ;az pokial sa nedosiahne hranica posuvania v byte
       brne  HalfInsertPosuvMask

       and   temp1,temp2                ;odmaskuj aby zostali iba vrchne posunute bity v temp1
       com   temp2                      ;invertuj masku
       lsr   temp2                      ;posun masku vpravo - na vlozenie nuloveho bitu
       ld    temp0,Y                    ;nahraj byte ktory este treba posunut od pozicie bitcount do temp0
       and   temp0,temp2                ;odmaskuj aby zostali iba spodne neposunute bity v temp0
       or    temp1,temp0                ;a zluc posunutu a neposunutu cast

       ld    temp0,Y                    ;nahraj byte ktory este treba posunut od pozicie bitcount
       rol   temp0                      ;a posun ho vlavo cez Carry (aby sa nastavilo spravne Carry pre dalsie prenosy)
       st    Y+,temp1                   ;a nahraj spat upraveny byte
ShiftInsertBufferLoop:
       cpse  USBBufptrY,ByteCount       ;ak nie su vsetky cele byty
       rjmp  NoEndShiftInsertBuffer     ;tak pokracuj
       ret                              ;inak skonci
NoEndShiftInsertBuffer:
       ld    temp1,Y                    ;nahraj byte
       rol   temp1                      ;a posun vlavo cez Carry (prenos z nizsieho byte a LSB do Carry)
       st    Y+,temp1                   ;a nahraj spat
       rjmp  ShiftInsertBufferLoop      ;a pokracuj
;------------------------------------------------------------------------------------------
ShiftDeleteBuffer: ;posuv 缓冲区 o jeden bit vlavo od konca az po poziciu: byte-USBBufptrY a bit-bitcount
;执行位填充删除时的辅助例程。从输出缓冲删除一位时会减少缓冲区长度。缓冲区的剩余部分移入。
       mov   temp0,bitcount             ;vypocet: bitcount= 9-bitcount
       ldi   bitcount,9
       sub   bitcount,temp0             ;do bitcount poloha bitu, ktory este treba posunut
       mov   temp0,USBBufptrY           ;uschovanie 指针a do 缓冲区
       inc   temp0                      ;pozicia celych bytov do temp0
       mov   USBBufptrY,ByteCount       ;maximalna pozicia do pointra
ShiftDeleteBufferLoop:
       ld    temp1,-Y                   ;zniz buffer a nahraj byte
       ror   temp1                      ;a posun vpravo cez Carry (prenos z vyssieho byte a LSB do Carry)
       st    Y,temp1                    ;a nahraj spat
       cpse  USBBufptrY,temp0           ;ak nie su vsetky cele byty
       rjmp  ShiftDeleteBufferLoop      ;tak pokracuj

       ld    temp1,-Y                   ;zniz buffer a nahraj byte ktory este treba posunut od pozicie bitcount
       ror   temp1                      ;a posun vpravo cez Carry (prenos z vyssieho byte a LSB do Carry)
       ser   temp2                      ;FF do masky - temp2
HalfDeletePosuvMask:
       dec   bitcount                   ;az pokial sa nedosiahne hranica posuvania v byte
       breq  DoneMask
       lsl   temp2                      ;nula do dalsieho spodneho bitu masky
       rjmp  HalfDeletePosuvMask
DoneMask:
       and   temp1,temp2                ;odmaskuj aby zostali iba vrchne posunute bity v temp1
       com   temp2                      ;invertuj masku
       ld    temp0,Y                    ;nahraj byte ktory este treba posunut od pozicie bitcount do temp0
       and   temp0,temp2                ;odmaskuj aby zostali iba spodne neposunute bity v temp0
       or    temp1,temp0                ;a zluc posunutu a neposunutu cast
       st    Y,temp1                    ;a nahraj spat
       ret                              ;a skonci
;------------------------------------------------------------------------------------------
MirrorInBufferBytes:                    ;镜像输入缓冲区
;以字节为单位交换顺序,因为从USB 线接收到缓冲区的数据是反序的(LSB/MSB)
       push  USBBufptrY
       push  ByteCount
       ldi   USBBufptrY,InputBufferBegin
       rcall MirrorBufferBytes
       pop   ByteCount
       pop   USBBufptrY
       ret
;------------------------------------------------------------------------------------------
MirrorBufferBytes:      ;镜像Y指针指定的缓冲区(Bit7←→BiT0、Bit4←→BiT3)
       add   ByteCount,USBBufptrY       ;取得缓冲区有效数据的结束地址
MirrorBufferloop:
       ld    temp0,Y                    ;从缓冲区中取出数据
       ldi   temp1,8                    ;每字节8位,为了移位计数
MirrorBufferByteLoop:
       ror   temp0                      ;右移到C
       rol   temp2                      ;将C中的数据左移到TEMP2,一个右移一个左移就完成了高低位交换
       dec   temp1                      ;当前字节完成吗?
       brne  MirrorBufferByteLoop       ;没有完成,接着移吧
       st    Y+,temp2                   ;将镜像后的数据保存
       cp    USBBufptrY,ByteCount       ;是否完成所有的数据
       brne  MirrorBufferloop           ;没有完成,接着移吧
       ret                              ;返回
;------------------------------------------------------------------------------------------
;CheckCRCIn:
;对接收的数据包进行CRC 校验。USB 包添加CRC 来检测数据的损坏。
;      push  USBBufptrY
;      push  ByteCount
;      ldi   USBBufptrY,InputBufferBegin
;      rcall CheckCRC
;      pop   ByteCount
;      pop   USBBufptrY
;      ret
;------------------------------------------------------------------------------------------
AddCRCOut:
;给输出数据包添加CRC 域。依照USB 规范提供的USB 域计算CRC。
       push  USBBufptrY
       push  ByteCount
       ldi   USBBufptrY,OutputBufferBegin
       rcall CheckCRC
       com   temp0                      ;取反 CRC
       com   temp1
       st    Y+,temp1                   ;将CRC结果存入缓冲区 (MSB)
       st    Y,temp0                    ;将CRC结果存入缓冲区 (LSB)
       dec   USBBufptrY                 ;指针指向 CRC 开始位置
       ldi   ByteCount,2                ;2字节 CRC 长度
       rcall MirrorBufferBytes          ;镜像Y指针指定的缓冲区 (CRC)
       pop   ByteCount
       pop   USBBufptrY
       ret
;------------------------------------------------------------------------------------------
CheckCRC: ;提示: USBBufptrY = zaciatok spravy   ,ByteCount = dlzka spravy
;检查和添加CRC 的辅助例程。
       add   ByteCount,USBBufptrY       ;取得缓冲区有效数据的结束地址
       inc   USBBufptrY                 ;CRC 要包括 SOP
       ld    temp0,Y+                   ;取得 PID
                   ;a nastav 指针 na zaciatok spravy - vynechat aj PID
       cpi   temp0,DATA0PID             ;判断是不是循环位 DATA0
       breq  ComputeDATACRC             ;
       cpi   temp0,DATA1PID             ;判断是不是循环位 DATA1
       brne  CRC16End                   ;不是循环位 DATA1/DATA0,不进行CRC处理
ComputeDATACRC:
       ser   temp0                      ;初始化 LSB 到 0xff
       ser   temp1                      ;初始化 MSB 到 0xff
CRC16Loop:
       ld    temp2,Y+                   ;根据指针取出数据到缓冲区
       ldi   temp3,8                    ;每字节8位

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -