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

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

📁 AVR309-USB 到 UART 协议转换程序。
💻 TXT
📖 第 1 页 / 共 5 页
字号:
       breq  SetMyNewUSBAddress         ;设置新的本机地址
       ldi   State,InState              ;输入状态
       ldi   ActionFlag,DoPrepareOutContinuousBuffer ;从缓冲区输出连续数据动作标志,主程序中将剩余的数据发送出去
       rjmp  EndInt0Handler             ;结束中断0处理

ReceiveSetupData:       ;设置状态的 DATA 包处理
       push  temp2                      ;保护数据
       push  temp3
       push  RS232BufptrX
       push  ACC
       rcall SendACK                    ;响应 SETUP 包,发送 ACK 
       rcall FinishReceiving            ;将接收到的数据从移位缓冲区移到将要执行解码的缓冲区
       ldi   ActionFlag,DoReceiveSetupData   ;收到配置数据工作标志,主程序中处理配置数据
       rjmp  EndInt0Handler             ;结束中断0处理

ReceiveOutData:         ;OUT 状态的 DATA 包处理
       push  temp2                      ;保护数据
       push  temp3
       push  RS232BufptrX
       push  ACC
       cpi   ActionFlag,DoReceiveSetupData ;配置数据工作状态?
       breq  NoReadySend                ;发送 NAK
       rcall SendACK                    ;发送 ACK
       clr   ActionFlag                 ;清除动作标志
       rjmp  EndInt0Handler             ;结束中断0处理
NoReadySend:
       rcall SendNAK                    ;发送 NAK
       rjmp  EndInt0Handler             ;结束中断0处理
;------------------------------------------------------------------------------------------
SetMyNewUSBAddress:      ;设置新的本机地址
       lds   MyInAddress,MyInAddressSRAM
       lds   MyOutAddress,MyOutAddressSRAM
       rjmp  EndInt0Handler             ;结束中断0处理
;
;********************************************************************
;* 子程序
;********************************************************************
;将接收到的数据从移位缓冲区移到将要执行解码的缓冲区
FinishReceiving:      ;将接收缓冲区中不满8Bit的数据填满
       cpi   bitcount,7                 ;缓冲区是否接收到完整的字节
       breq  NoRemainingBits            ;接收到完整的数据就不填充
       inc   bitcount
ShiftRemainingBits:
       rol   shiftbuf                   ;填充数据
       dec   bitcount
       brne  ShiftRemainingBits
       st    Y+,shiftbuf                ;将移位缓冲区中的数据存入输入缓冲区
NoRemainingBits:
       mov   ByteCount,USBBufptrY       ;取出输入缓冲区当前指针
       subi  ByteCount,InputShiftBufferBegin-1   ;取得接收到的数据量

       mov   InputBufferLength,ByteCount      ;保存接收到的数据量
       ldi   USBBufptrY,InputShiftBufferBegin ;指针指向 USB 输入缓冲区首址
       ldi   RS232BufptrX,InputBufferBegin+1  ;将输入缓冲区+1用作将要执行解码的缓冲区
MoveDataBuffer:
       ld    temp0,Y+                   ;将数据移到输入缓冲区
       st    X+,temp0
       dec   ByteCount
       brne  MoveDataBuffer

       ldi   ByteCount,nNRZISOPbyte
       sts   InputBufferBegin,ByteCount ;设置数据包的第1字节为起始包(Start) byte
       ret
;------------------------------------------------------------------------------------------
;********************************************************************
;* Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset:    ;初始化 USB 界面到默认值(与开启电源后的状态一样)
       ldi   temp0,nNRZIADDR0           ;初始化 USB 端口地址为 0
       mov   MyOutAddress,temp0
       mov   MyInAddress,temp0
       clr   State                      ;初始化工作状态
       clr   BitStuffInOut
       clr   OutBitStuffNumber
       clr   ActionFlag
       clr   RAMread                    ;0=ROM,1=RAM,2=EEPROM,4=ROM
       clr   ConfigByte                 ;没有配置状态=0
       ret
;------------------------------------------------------------------------------------------
SendPreparedUSBAnswer:
;发送准备好的NRZI应答到USB,数据长度=OutputBufferLength 
;发送输出缓冲区的内容到USB 线。传送过程执行NRZI 编码和位填充。包以EOP 结束。
       mov   ByteCount,OutputBufferLength     ;取出数据长度
SendUSBAnswer:     ;从输出缓冲区发送准备好的NRZI应答到USB
       ldi   USBBufptrY,OutputBufferBegin     ;USB 输入/输出缓冲区指针指向USB 输出缓冲区
SendUSBBuffer:     ;从输出缓冲区发送准备好的NRZI到USB
       ldi   temp1,0                    ;zvysovanie pointra (pomocna premenna)
       mov   temp3,ByteCount            ;数据长度移到temp3
       ldi   temp2,0b00000011           ;屏蔽非USB口
       ld    inputbuf,Y+                ;取出数据到inputbuf
                   ;USB ako vystup:
       cbi   outputport,DATAplus        ;拉低D+
       sbi   outputport,DATAminus       ;置高D-
       sbi   USBdirection,DATAplus      ;D+为输出口
       sbi   USBdirection,DATAminus     ;D-为输出口

       in    temp0,outputport           ;读入输出口的状态
SendUSBAnswerLoop:
       ldi   bitcount,7                 ;移位计数器
SendUSBAnswerByteLoop:
       nop                              ;nop 为了配平消耗的时间,使程序发出的脉宽符合USB规范
       ror   inputbuf                   ;将要发送的位移到C (低位先)
       brcs  NoXORSend                  ;判断C的内容
       eor   temp0,temp2                ;D+ D-取反
NoXORSend:
       out   outputport,temp0           ;发送到USB
       dec   bitcount                   ;判断低7位是否发送完成
       brne  SendUSBAnswerByteLoop      ;继续移位发送
       sbrs  inputbuf,0                 ;发送最高1位
       eor   temp0,temp2                ;D+ D-取反
NoXORSendLSB:
       dec   temp3                      ;所有字节都发送完
       ld    inputbuf,Y+                ;取出下一字节
       out   outputport,temp0           ;最高1位发送到USB
       brne  SendUSBAnswerLoop          ;没有发送完,继续 (完成 temp3=0)
;
       mov   bitcount,OutBitStuffNumber ;取出填充后增加的位
       cpi   bitcount,0                 ;是否有填充位
       breq  ZeroBitStuf
SendUSBAnswerBitstuffLoop:
       ror   inputbuf                   ;将要发送的位移到C (低位先)
       brcs  NoXORBitstuffSend          ;判断C的内容
       eor   temp0,temp2                ;D+ D-取反
NoXORBitstuffSend:
       out   outputport,temp0           ;发送到USB
       nop                              ;配平时间
       dec   bitcount                   ;判断填充后增加的位是否发送完成
       brne  SendUSBAnswerBitstuffLoop  ;没有完成,继续移位发送
       ld    inputbuf,Y                 ;2个指令周期
ZeroBitStuf:
       nop                              ;配平时间
       cbr   temp0,3
       out   outputport,temp0           ;拉低D+ D- 发出 EOP 到 USB

       ldi   bitcount,5                 ;延时: EOP 需要 2 位宽度 (12MHz 时 16周期)
SendUSBWaitEOP:
       dec   bitcount
       brne  SendUSBWaitEOP

       sbi   outputport,DATAminus       ;准备进入IDLE状态
       sbi   outputport,DATAminus       ;2周期 : Idle 需要 1 bit (12MHz 时 8周期)
       cbi   USBdirection,DATAplus      ;转换到输入口,释放总线
       cbi   USBdirection,DATAminus     ;
       cbi   outputport,DATAminus       ;取消上拉
       ret
;------------------------------------------------------------------------------------------
ToggleDATAPID: ;切换循环位
;在DATA0 和DATA1 PID 之间绑定DATAPID 包标识符。每个USB 规范都要求在传送过程中绑定。
       lds   temp0,OutputBufferBegin+1  ;循环位DATA1/DATA0
       cpi   temp0,DATA1PID
       ldi   temp0,DATA0PID
       breq  SendData0PID
       ldi   temp0,DATA1PID
SendData0PID:
       sts   OutputBufferBegin+1,temp0
       ret
;------------------------------------------------------------------------------------------
ComposeZeroDATA1PIDAnswer:
;组成0 回答的传送。0 回答不包含数据,在一些情况下回答,当设备上没有可用的额外数据时。
       ldi   temp0,DATA0PID             ;循环位 DATA0 令牌(PID)
       sts   OutputBufferBegin+1,temp0  ;存入缓冲区
ComposeZeroAnswer:
       ldi   temp0,SOPbyte
       sts   OutputBufferBegin+0,temp0  ;起始包(Start) byte
       rcall ToggleDATAPID              ;切换循环位
       ldi   temp0,0x00
       sts   OutputBufferBegin+2,temp0  ;清除 CRC 校验字节
       sts   OutputBufferBegin+3,temp0  ;清除 CRC 校验字节
       ldi   ByteCount,2+2              ;缓冲区有效数据长度 (起始包+循环位+CRC16校验字节)
       ret
;------------------------------------------------------------------------------------------
InitACKBufffer:
;在RAM 中生成包含ACK 数据的缓冲区(ACK 握手包)。在应答时此缓冲区频繁地发送,因此它总
;是保存在存储器里。
       ldi   temp0,SOPbyte
       sts   ACKBufferBegin+0,temp0     ;起始包(Start) byte
       ldi   temp0,ACKPID
       sts   ACKBufferBegin+1,temp0     ;ACK 令牌(PID)
       ret
;------------------------------------------------------------------------------------------
SendACK:
;发送ACK 包到USB 数据线。
       push  USBBufptrY
       push  bitcount
       push  OutBitStuffNumber
       ldi   USBBufptrY,ACKBufferBegin  ;发送缓冲区指针指到ACK开始位置
       ldi   ByteCount,2                ;发送2字节 (起始包 + ACK令牌(PID))
       clr   OutBitStuffNumber
       rcall SendUSBBuffer              ;从输出缓冲区发送准备好的NRZI到USB
       pop   OutBitStuffNumber
       pop   bitcount
       pop   USBBufptrY
       ret
;------------------------------------------------------------------------------------------
InitNAKBufffer:
;在RAM 中生成包含NAK 数据的缓冲区(NAK 握手包)。在应答时此缓冲区频繁地发送,因此它
;总是保存在存储器里。
       ldi   temp0,SOPbyte
       sts   NAKBufferBegin+0,temp0     ;起始包(Start) byte
       ldi   temp0,NAKPID
       sts   NAKBufferBegin+1,temp0     ;NAK 令牌(PID)
       ret
;------------------------------------------------------------------------------------------
SendNAK:
;发送NAK 包到USB 数据线。
       push  OutBitStuffNumber
       ldi   USBBufptrY,NAKBufferBegin  ;发送缓冲区指针指到NAK开始位置
       ldi   ByteCount,2                ;发送2字节 (起始包 + NAK令牌(PID))
       clr   OutBitStuffNumber
       rcall SendUSBBuffer              ;从输出缓冲区发送准备好的NRZI到USB
       pop   OutBitStuffNumber
       ret
;------------------------------------------------------------------------------------------
ComposeSTALL:
;在RAM 中生成包含STALL 数据的缓冲区(STALL 握手包)。在应答时此缓冲区频繁地发送,因此
;它总是保存在存储器里。
       ldi   temp0,SOPbyte
       sts   OutputBufferBegin+0,temp0  ;起始包(Start) byte
       ldi   temp0,STALLPID
       sts   OutputBufferBegin+1,temp0  ;STALL 令牌(PID)
       ldi   ByteCount,2                ;缓冲区有效数据长度 (起始包 + STALL 令牌(PID))
       ret
;------------------------------------------------------------------------------------------
DecodeNRZI:  ;将 NRZI 编码解释为二进制码
;执行NRZI 解码。缓冲区从USB 数据线得到的数据是NRZI 编码的。这个例程从数据中移除NRZI
;编码。
       push  USBBufptrY
       push  ByteCount
       add   ByteCount,USBBufptrY       ;计算缓冲区中有效数据结束地址
       ser   temp0                      ;置temp0 为了移位后C为1
NRZIloop:
       ror   temp0                      ;将数据右移 Bit0-->C

⌨️ 快捷键说明

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