📄 avr309-usb 到 uart 协议转换程序.txt
字号:
CRC16LoopByte:
bst temp1,7 ;do T uloz MSB zvysku (zvysok je iba 16 bitovy - 8 bit vyssieho byte)
bld bitcount,0 ;do bitcount LSB uloz T - MSB zvysku
eor bitcount,temp2 ;XOR bitu spravy a bitu zvysku - v LSB bitcount
rol temp0 ;posun zvysok dolava - nizsi byte (dva byty - cez carry)
rol temp1 ;posun zvysok dolava - vyssi byte (dva byty - cez carry)
cbr temp0,1 ;znuluj LSB zvysku
lsr temp2 ;posun spravu doprava
ror bitcount ;vysledok XOR-u bitov z LSB do carry
brcc CRC16NoXOR ;ak je XOR bitu spravy a MSB zvysku = 0 , tak nerob XOR
ldi bitcount,CRC16poly>>8 ;do bitcount CRC polynom - vrchny byte
eor temp1,bitcount ;a urob XOR zo zvyskom a CRC polynomom - vrchny byte
ldi bitcount,CRC16poly ;do bitcount CRC polynom - spodny byte
eor temp0,bitcount ;a urob XOR zo zvyskom a CRC polynomom - spodny byte
CRC16NoXOR:
dec temp3 ;boli uz vsetky bity v byte
brne CRC16LoopByte ;ak nie, tak chod na dalsi bit
cp USBBufptrY,ByteCount ;bol uz koniec spravy
brne CRC16Loop ;ak nie tak opakuj
CRC16End:
ret ;inak skonci (v temp0 a temp1 je vysledok)
;------------------------------------------------------------------------------------------
LoadDescriptorFromROM: ;从 ROM 加载描述符
;从ROM 加载数据到USB 输出缓冲区(用于USB 应答)
lpm ;从 ROM 中取出数据到 r0
st Y+,R0 ;将 R0 的数据存入缓冲区
adiw ZH:ZL,1 ;指向 ROM 的指针加1
dec ByteCount ;数据加载完成吗?
brne LoadDescriptorFromROM ;接着加载
rjmp EndFromRAMROM ;完成
;------------------------------------------------------------------------------------------
LoadDescriptorFromROMZeroInsert:
;从ROM 加载数据到USB 输出缓冲区(用于USB 应答)但所有偶数字节都添加为0。当一个字符
;串被作为UNICODE 格式请求时(节约ROM)。
lpm ;从ROM中取出数据到R0
st Y+,R0 ;R0 存入到缓冲区
bst RAMread,3 ;Bit3 是否插入一个"0数据"字节
brtc InsertingZero ;Bit3 为 0 ,加载"0数据"字节
adiw ZH:ZL,1 ;指向 ROM 的指针加1
lpm ;从ROM中取出数据到R0
st Y+,R0 ;将 R0 的数据存入缓冲区
clt ;清除 T
bld RAMread,3 ;T 存入RAMread Bit3
rjmp InsertingZeroEnd ;
InsertingZero:
clr R0 ;加载"0数据"字节
st Y+,R0 ;
InsertingZeroEnd:
adiw ZH:ZL,1 ;指向 ROM 的指针加1
subi ByteCount,2 ;数据加载完成吗?
brne LoadDescriptorFromROMZeroInsert ;接着加载
rjmp EndFromRAMROM ;完成
;------------------------------------------------------------------------------------------
LoadDescriptorFromSRAM:
;从RAM 加载数据到USB 输出缓冲区(用于USB 应答)
ld R0,Z ;从RAM中取出数据到 R0
st Y+,R0 ;R0 存入到缓冲区
inc ZL ;指向下一个 RAM
dec ByteCount ;能加载的字节数完成吗?
brne LoadDescriptorFromSRAM ;接着取数
rjmp EndFromRAMROM ;完成
;------------------------------------------------------------------------------------------
LoadDescriptorFromEEPROM:
;从EEPROM 加载数据到USB 输出缓冲区(用于USB 应答)。
out EEAR,ZL ;加载 EEPROM 地址
sbi EECR,EERE ;允许读 EEPROM
in R0,EEDR ;读入EEPROM 的内容到 R0
st Y+,R0 ;R0 存入到缓冲区
inc ZL ;指向下一个 EEPROM
dec ByteCount ;数据加载完成吗?
brne LoadDescriptorFromEEPROM ;接着加载
rjmp EndFromRAMROM ;完成
;------------------------------------------------------------------------------------------
LoadXXXDescriptor:
;选择回答的源位置:ROM, RAM 或 EEPROM。
ldi temp0,SOPbyte ;加载SOP到输出缓冲区
sts OutputBufferBegin,temp0
ldi ByteCount,8 ;数据包的大小
ldi USBBufptrY,OutputBufferBegin+2 ;Y指针指向发送缓冲区+2
and RAMread,RAMread ;RAMread 是否为0
brne FromRAMorEEPROM ;0=ROM,1=RAM,2=EEPROM,4=ROM(允许插入一个"0数据"字节)
FromROM:
rjmp LoadDescriptorFromROM ;从 ROM 中加载数据
FromRAMorEEPROM:
sbrc RAMread,2 ;RAMread=4
rjmp LoadDescriptorFromROMZeroInsert ;从 ROM 中加载数据
sbrc RAMread,0 ;RAMread=1
rjmp LoadDescriptorFromSRAM ;从 SRAM 中加载数据
rjmp LoadDescriptorFromEEPROM ;从 EEPROM 中加载数据
EndFromRAMROM:
sbrc RAMread,7 ;Bit7=1 表示要求清除 RAMread
clr RAMread ;清除 RAMread
rcall ToggleDATAPID ;切换循环位DATA1/DATA0
ldi USBBufptrY,OutputBufferBegin+1 ;加载USB输出缓冲区指针 - 包含 DATA PID
ret
;------------------------------------------------------------------------------------------
PrepareUSBOutAnswer: ;在缓冲区中准备输出响应数据
;根据USB 主机的请求在输出缓冲区准备USB 应答,并执行请求的动作。添加位填充到应答中。
rcall PrepareUSBAnswer ;根据配置数据进行进一步的处理
MakeOutBitStuff:
inc BitStuffInOut ;增加填充位 增加=1 滤除=0
ldi USBBufptrY,OutputBufferBegin ;给出安排填充位的缓冲区
rcall BitStuff ;安排填充位
mov OutputBufferLength,ByteCount ;获得安排填充位后的数据长度
clr BitStuffInOut ;
ret
;------------------------------------------------------------------------------------------
PrepareUSBAnswer: ;在缓冲区中准备应答
;执行请求动作和准备相应回答的主例程。此例程首先判断哪个动作要执行—从输入数据包得到函数
;编号—接着执行函数。函数参数定位于输入数据包。
;例程分为两个大的部分
;1.标准请求
;2.卖主请求(厂家指定的请求)
clr RAMread ;描述符数据源=ROM
lds temp0,InputBufferBegin+2 ;取出 bmRequestType
lds temp1,InputBufferBegin+3 ;取出 bRequest
cbr temp0,0b10011111 ;保留 bmRequestType 第6位和第5位(请求类型)
brne VendorRequest ;判断是不是卖主请求
rjmp StandardRequest ;00 是 USB 的11种标准请求
;--------------------------
DoSetInfraBufferEmpty:
rjmp OneZeroAnswer ;告诉主机 确认"正确"处理
;--------------------------
DoSetRS232Baud:
lds temp0,InputBufferBegin+4 ;取出 RS232 的波特率设置
out UBRR,temp0 ;更改 RS232 的波特率设置
rjmp OneZeroAnswer ;告诉主机 确认"正确"处理
;--------------------------
DoGetRS232Baud:
in R0,UBRR ;获得当前设备的RS232 的波特率设置到R0
rjmp DoGetIn ;a ukonci
;--------------------------
DoRS232Send:
lds temp0,InputBufferBegin+4 ;取得要发送的 RS232 数据
out UDR,temp0 ;送入 UART
WaitForRS232Send:
sbis UCR,TXEN ;是否允许 UART 发送数据
rjmp OneZeroAnswer ;回应完成 (AT90S2323/2343没有UART)
sbis USR,TXC ;发送的数据是否完成
rjmp WaitForRS232Send ;等待RS232发送完成
rjmp OneZeroAnswer ;发送完成,回应主机
;--------------------------
DoRS232Read:
rjmp TwoZeroAnswer ;回应"错误"
;--------------------------
VendorRequest: ;卖主请求
;厂家指定的请求要求能够获得厂家指定的数据(在USB 控制传输中)。这个AVR 设备与主机的
;通信使用USB 控制传输。开发者可以添加他们自己的函数到这里来扩展设备的功能。源代码中不
;同文档的内建函数可以作为添加定制函数的模板使用。
clr ZH ;由于 RAM 和 EEPROM 只会使用ZL, 所以清除ZH
cpi temp1,1 ;函数名:FNCNumberDoSetInfraBufferEmpty
breq DoSetInfraBufferEmpty ;restartne infra prijimanie (ak bolo zastavene citanim z RAM-ky)
cpi temp1,2 ;函数名:FNCNumberDoGetInfraCode
breq DoGetInfraCode ;vysle prijaty infra kod (ak je v bufferi)
cpi temp1,3 ;函数名:FNCNumberDoSetDataPortDirection
breq DoSetDataPortDirection ;设置I/O口方向
cpi temp1,4 ;函数名:FNCNumberDoGetDataPortDirection
breq DoGetDataPortDirection ;获得I/O口方向
cpi temp1,5 ;函数名:FNCNumberDoSetOutDataPort
breq DoSetOutDataPort ;设置OUT I/O (输出或pull-up数据)
cpi temp1,6 ;函数名:FNCNumberDoGetOutDataPort
breq DoGetOutDataPort ;获得OUT I/O (输出或pull-up数据)
cpi temp1,7 ;函数名:FNCNumberDoGetInDataPort
breq DoGetInDataPort ;获得IN I/O
cpi temp1,8 ;函数名:FNCNumberDoEEPROMRead
breq DoEEPROMRead ;读EEPROM
cpi temp1,9 ;函数名:FNCNumberDoEEPROMWrite
breq DoEEPROMWrite ;写EEPROM
cpi temp1,10 ;函数名:FNCNumberDoRS232Send
breq DoRS232Send ;发送RS232数据
cpi temp1,11 ;函数名:FNCNumberDoRS232Read
breq DoRS232Read ;读入RS232数据
cpi temp1,12 ;函数名:FNCNumberDoSetRS232Baud
breq DoSetRS232Baud ;设置RS232波特率
cpi temp1,13 ;函数名:FNCNumberDoGetRS232Baud
breq DoGetRS232Baud ;获得RS232波特率
cpi temp1,14 ;函数名:FNCNumberDoGetRS232Buffer
breq DoGetRS232Buffer ;获得RS232缓冲区的数据
;15 FNCNumberDoSetRS232DataBits
;16 FNCNumberDoGetRS232DataBits
;17 FNCNumberDoSetRS232Parity
;18 FNCNumberDoGetRS232Parity
;19 FNCNumberDoSetRS232StopBits
;20 FNCNumberDoGetRS232StopBits
cpi temp1,USER_FNC_NUMBER+0 ;
breq DoUserFunction0 ;用户自定义功能0
cpi temp1,USER_FNC_NUMBER+1 ;
breq DoUserFunction1 ;用户自定义功能1
cpi temp1,USER_FNC_NUMBER+2 ;
breq DoUserFunction2 ;用户自定义功能2
rjmp ZeroDATA1Answer ;ak to bolo nieco nezname, tak priprav nulovu odpoved
;-------------------------- 自定义功能 --------------------------
;--------------------------自定义功能的模板----------------------
;------------------ 开始: 这是书写自定义功能的模板 --------------
;能自由使用的寄存器:
;temp0,temp1,temp2,temp3,ACC,ZH,ZL
;其它寄存器在使用时是被破坏的 (必须使用 push/pop 保存内容)
;在你的程序中必须恰当设置的寄存器:
;RAMread - 0=从ROM中读, 1=从RAM中读, 2=从EEPROM中读
;temp0 - 发送数据的字节数
;ZH,ZL - 指针指向发送数据的缓冲区 (指针指向 ROM/RAM/EEPROM)
;被发送的数据 (准备好数据到缓冲区) :
;发送数据必须跳转到 "ComposeEndXXXDescriptor"
;发送一个零字节数据必须跳转到 "OneZeroAnswer" (一般使用为确认"正确"处理)
;发送二个零字节数据必须跳转到 "TwoZeroAnswer" (一般使用为确认"错误"处理)
DoUserFunctionX:
DoUserFunction0: ;send byte(s) of RAM starting at position given by first parameter in function
lds temp0,InputBufferBegin+4 ;prvy parameter Lo do temp0
;lds temp1,InputBufferBegin+5 ;prvy parameter Hi do temp1
;lds temp2,InputBufferBegin+6 ;druhy parameter
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -