📄 avr309-usb 到 uart 协议转换程序.txt
字号:
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 + -