📄 avr309-usb 到 uart 协议转换程序.txt
字号:
sbi UCR,RXCIE ;
reti
;------------------------------------------------------------------------------------------
;********************************************************************
;* 初始化程序
;********************************************************************
;------------------------------------------------------------------------------------------
reset: ;初始化AVR资源:堆栈、串行口、USB缓冲区、中断
ldi temp0,StackBegin ;初始化堆栈
out SPL,temp0
clr XH ;RS232 指针
clr YH ;USB 指针
clr ZH ;ROM 指针
sts RS232BufferBegin+0,YH ;znuluj dlzky RS232 kodu v bufferi
ldi temp0,RS232BufferBegin+4
sts RS232BufferBegin+1,temp0 ;znuluj ukazovatel citania
sts RS232BufferBegin+2,temp0 ;znuluj ukazovatel zapisu
clr RS232BufferFull
rcall InitACKBufffer ;初始化 ACK 缓冲区
rcall InitNAKBufffer ;初始化 NAK 缓冲区
rcall USBReset ;初始化 USB 接口到默认值
sbi TSOPpullupPort,TSOPpin ;上拉红外接收口
ldi temp0,(1<<LEDlsb0)+(1<<LEDlsb1)+(1<<LEDlsb2)
out LEDPortLSB,temp0 ;用户自定义 PD 输出高
ldi temp0,(1<<LEDmsb3)+(1<<LEDmsb4)+(1<<LEDmsb5)+(1<<LEDmsb6)+(1<<LEDmsb7)
out LEDPortMSB,temp0 ;用户自定义 PB 输出高
sbi PORTD,0 ;上拉串行接收口 RxD
ldi temp0,InitBaudRate ;串行通讯波特率
out UBRR,temp0
sbi UCR,TXEN ;允许串行发送
sbi UCR,RXEN ;允许串行接收
sbi UCR,RXCIE ;允许 interrupt od prijimania UART
ldi temp0,0x0F ;设置 INT0、INT1 上升沿中断
out MCUCR,temp0 ;
ldi temp0,1<<INT0 ;允许外部中断 INT0
out GIMSK,temp0
;
;********************************************************************
;* 主程序
;********************************************************************
sei ;允许全局中断
Main:
;主循环。检查动作标志,如果标志置位,执行请求的动作。另外,这个例程检查数据线上的USB
;复位,如果检测到则重新初始化USB 微控制器界面。
sbis inputport,DATAminus ;测试 D- 是否为0
rjmp CheckUSBReset ;如果为0检查 USB 复位
cpi ActionFlag,DoReceiveSetupData ;是否接收到配置数据
breq ProcReceiveSetupData
cpi ActionFlag,DoPrepareOutContinuousBuffer ;是否准备从缓冲区输出连续数据
breq ProcPrepareOutContinuousBuffer
rjmp Main
CheckUSBReset:
ldi temp0,255 ;进入 USB 复位时间 (10ms - 100us),集线器发出至少10mS
WaitForUSBReset:
sbic inputport,DATAminus ;测试 D+ 是否为0
rjmp Main
dec temp0 ;等待复位
brne WaitForUSBReset ;集线器开始重新设置本设备前,会复位本设备
rcall USBReset ;USB 复位
rjmp Main
ProcPrepareOutContinuousBuffer:
rcall PrepareOutContinuousBuffer ;从缓冲区输出连续数据
ldi ActionFlag,DoReadySendAnswer ;工作标志
rjmp Main
ProcReceiveSetupData: ;处理接收到配置数据
ldi USBBufptrY,InputBufferBegin ;将输入缓冲区用作 USB 输入/输出缓冲区
mov ByteCount,InputBufferLength ;接收到的数据长度(设置状态的 DATA 包)
rcall DecodeNRZI ;将 NRZI 编码解释为二进制码
rcall MirrorInBufferBytes ;镜像输入缓冲区
rcall BitStuff ;去掉填充位
;rcall CheckCRCIn ;CRC 校验
rcall PrepareUSBOutAnswer ;根据配置数据进行进一步的处理
ldi ActionFlag,DoReadySendAnswer
rjmp Main
;
;********************************************************************
;* INT0 中断处理
;********************************************************************
INT0Handler: ;处理 INT0
;这是INT0 外部中断的中断服务例程。主要的接收/发送引擎,从USB 数据线模仿,储存数据到缓
;冲,判断USB 包的所有者(USB 地址),包确认,发送回答到USB 主机。USB 引擎的主要基础。
in backupSREG,SREG ;INT0 中断中的SREG备份
push temp0
push temp1
ldi temp0,3 ;为下面检测低电平有效数据准备
ldi temp1,2 ;为下面检测高电平有效数据准备
;测试信号沿,用来达到同步(中断响应可能延迟 +/-4 个周期)
CheckchangeMinus:
sbis inputport,DATAminus ;等待 D- 为 1
rjmp CheckchangeMinus
CheckchangePlus:
sbis inputport,DATAplus ;等待 D+ 为 1
rjmp CheckchangePlus
DetectSOPEnd: ;检测起始包结束
sbis inputport,DATAplus ;检测数据为1还是为0
rjmp Increment0 ;D+ =0
Increment1:
ldi temp0,3 ;加载低电平检测次数(连续3次相同才开始有效数据)
dec temp1 ;高电平检测
nop
breq USBBeginPacket ;起始包SOP 检测完成,开始数据移位
rjmp DetectSOPEnd
Increment0:
ldi temp1,2 ;加载高电平检测次数(连续2次相同才开始有效数据)
dec temp0 ;低电平检测
nop
brne DetectSOPEnd ;继续检测起始包SOP 完成
rjmp EndInt0HandlerPOP2 ;起始包SOP 检测失败,退出中断服务程序
;
EndInt0Handler: ;结束中断0处理
pop ACC
pop RS232BufptrX
pop temp3
pop temp2
EndInt0HandlerPOP: ;结束中断0处理
pop USBBufptrY
pop ByteCount
mov bitcount,backupbitcount ;恢复移位计数器
EndInt0HandlerPOP2: ;结束中断0处理
pop temp1
pop temp0
out SREG,backupSREG ;恢复 SREG
ldi shiftbuf,1<<INTF0 ;znulovat flag interruptu INTF0
out GIFR,shiftbuf
reti ;inak skonci (bol iba SOF - kazdu milisekundu)
USBBeginPacket: ;起始包SOP 完成,开始数据移位
mov backupbitcount,bitcount ;备份移位计数器 (在中断返回时恢复)
;(读入第0位)
in shiftbuf,inputport ;读入 USB 通讯口到移位缓冲区
USBloopBegin:
push ByteCount ;保护字节计数
push USBBufptrY
ldi bitcount,6 ;初始化移位计数器
ldi ByteCount,MAXUSBBYTES ;初始化到 USB 输入最大的字节数
ldi USBBufptrY,InputShiftBufferBegin ;将输入缓冲区用作 USB 输入缓冲区
USBloop1_6: ;(读入第1-6位)
in inputbuf,inputport ;读入 USB 通讯口到输入缓冲区
cbr inputbuf,USBpinmask ;保留 USB 通讯口的2Bit,其余的清0
breq USBloopEnd ;是否挂起(同时为0)
ror inputbuf ;将D-移到CY中
rol shiftbuf ;将CY中的数据移到移位缓冲区
dec bitcount ;移位计数减1
brne USBloop1_6 ;继续移位
nop ;准备将移位缓冲区中的数据存入输入缓冲区
USBloop7: ;(读入第7位)
in inputbuf,inputport ;读入 USB 通讯口到输入缓冲区
cbr inputbuf,USBpinmask ;保留 USB 通讯口的2Bit,其余的清0
breq USBloopEnd ;是否挂起(同时为0,数据中途中断或完成)
ror inputbuf ;将D-移到CY中
rol shiftbuf ;将CY中的数据移到移位缓冲区
;保存已经接受到的8Bit数据
ldi bitcount,7 ;初始化移位计数器
st Y+,shiftbuf ;将移位缓冲区中的数据存入输入缓冲区
USBloop0: ;(读入第0位)
in shiftbuf,inputport ;读入 USB 通讯口到输入缓冲区
cbr shiftbuf,USBpinmask ;保留 USB 通讯口的2Bit,其余的清0
breq USBloopEnd ;是否挂起(同时为0,数据中途中断或完成)
dec bitcount ;移位计数减1
nop ;
dec ByteCount ;移字节计数减1
brne USBloop1_6 ;将剩下的数据接收完成
rjmp EndInt0HandlerPOP ;结束中断0处理
;
;检测标志包类型
USBloopEnd: ;挂起(同时为0,数据中途中断或完成)
cpi USBBufptrY,InputShiftBufferBegin+3 ;接收到的数据是否少于3字节
brcs EndInt0HandlerPOP ;少于3字节,结束中断0处理
lds temp0,InputShiftBufferBegin+0 ;取出输入移位缓冲区第0字节
lds temp1,InputShiftBufferBegin+1 ;取出输入移位缓冲区第1字节
brne TestDataPacket ;接收到的数据大于3字节时,只能是循环位(DATA0)或(DATA1)
;接收到的数据等于3字节,可能是 SETUP、OUT、IN、循环位(DATA0)或(DATA1) 包
TestIOPacket:
; cp temp1,MyInAddress ;ak to nie je urcene (adresa) pre mna
; brne TestDataPacket ;tak to moze byt este Data Packet
TestSetupPacket:;检测是不是 SETUP 包
cpi temp0,nNRZISETUPPID ;是不是 SETUP 包
brne TestOutPacket
cp temp1,MyInAddress ;是不是本机地址(IN) ;注:如果不是本机地址。可能是设置包后面的数据包
brne TestDataPacket ; 所以跳转到数据包检测
ldi State,SetupState ;标记为设置状态
rjmp EndInt0HandlerPOP ;结束中断0处理
TestOutPacket: ;检测是不是 OUT 包
cpi temp0,nNRZIOUTPID ;是不是 OUT 包
brne TestInPacket
cp temp1,MyOutAddress ;是不是本机地址(OUT)
brne TestDataPacket
ldi State,OutState ;标记为 OUT 状态
rjmp EndInt0HandlerPOP ;结束中断0处理
TestInPacket: ;检测是不是 IN 包
cpi temp0,nNRZIINPID ;是不是 IN 包
brne TestDataPacket
cp temp1,MyInAddress ;是不是本机地址(IN)
breq AnswerToInRequest
TestDataPacket: ;检测是不是循环位(DATA0)或(DATA1)
cpi temp0,nNRZIDATA0PID ;是不是循环位(DATA0)包
breq Data0Packet
cpi temp0,nNRZIDATA1PID ;是不是循环位(DATA1)包
brne NoMyPacked ;不是本机能识别的包
Data0Packet:
cpi State,SetupState ;是不是设置状态的 DATA 包
breq ReceiveSetupData
cpi State,OutState ;是不是 OUT 状态的 DATA 包
breq ReceiveOutData
NoMyPacked: ;不是本机能识别的包(主机只能使用 SETUP 和 OUT 包向终端发送数据)
ldi State,BaseState ;
rjmp EndInt0HandlerPOP ;结束中断0处理
;
;进入数据包处理
AnswerToInRequest: ;IN 包处理
push temp2 ;保护数据
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReadySendAnswer ;是否发送已经准备就绪,发送回应
brne NoReadySend ;发送 NAK
rcall SendPreparedUSBAnswer ;发送准备就绪的回应数据
cpi State,AddressChangeState ;是否要求改变地址
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -