📄 avr309-usb 到 uart 协议转换程序.txt
字号:
;***************************************************************************
;* U S B S T A C K F O R T H E A V R F A M I L Y
;*
;* 文件名 :"USB90S2313.asm"
;* 标题 :AVR309:USB 到 UART 协议转换程序 (简易的 - 少量的FIFO)
;* 日期 :24.11.2004
;* 版本 :2.2
;* 目标 MCU :AT90S2313-10
;* 创造者 :Ing. Igor Cesko
;* Slovakia
;* cesko@internet.sk
;* http://www.cesko.host.sk
;* 翻译 :吴险峰
;* 描述:
;* 通过 MCU 执行 USB 协议,完成软 USB 接口:
;* 设备:
;* 通用的 USB 接口 (8-bit I/O口 + RS232 串行通讯 + EEPROM)
;* + 附加的 RS232 FIFO 缓冲器
;*
;* 使用 12 MHz 振荡器 ( MCU 超频 !!!)
;*
;*
;* 添加自己的功能 - 请看: TEMPLATE OF YOUR FUNCTION
;*
;* 做成自己公司的产品必须更改 VendorUSB ID (VID)
;* 获得分配到自己公司的 VID (更多的信息请查看 www.usb.org)
;*
;***************************************************************************
.include "2313def.inc"
;- - - - - - - - - - I/O定义 - - - - - - - - - -
.equ inputport =PINB
.equ outputport =PORTB
.equ USBdirection =DDRB
.equ DATAplus =1 ;PB1模拟 D+ 信号
.equ DATAminus =0 ;PB0模拟 D- 信号 - 接1.5K上拉电阻,低速模式
.equ USBpinmask =0b11111100 ;屏蔽 PB 低2位 (D+,D-)
.equ USBpinmaskDplus =~(1<<DATAplus) ;屏蔽 PB D+ 位
.equ USBpinmaskDminus =~(1<<DATAminus) ;屏蔽 PB D- 位
.equ TSOPPort =PINB
.equ TSOPpullupPort =PORTB
.equ TSOPPin =2 ;红外遥控接收头 TSOP1738 输出到 PB2
.equ LEDPortLSB =PORTD ;用户自定义 PD 输出口
.equ LEDPinLSB =PIND ;用户自定义 PD 输入口
.equ LEDdirectionLSB =DDRD ;用户自定义 PD 口方向
.equ LEDPortMSB =PORTB ;用户自定义 PB 输出口
.equ LEDPinMSB =PINB ;用户自定义 PB 输入口
.equ LEDdirectionMSB =DDRB ;用户自定义 PB 口方向
.equ LEDlsb0 =3 ;用户自定义口 PD3
.equ LEDlsb1 =5 ;用户自定义口 PD5
.equ LEDlsb2 =6 ;用户自定义口 PD6
.equ LEDmsb3 =3 ;用户自定义口 PB3
.equ LEDmsb4 =4 ;用户自定义口 PB4
.equ LEDmsb5 =5 ;用户自定义口 PB5
.equ LEDmsb6 =6 ;用户自定义口 PB6
.equ LEDmsb7 =7 ;用户自定义口 PB7
;
;- - - - - - - - - - 常数定义 - - - - - - - - -
.equ SOPbyte =0b10000000 ;起始包(Start) byte
.equ DATA0PID =0b11000011 ;数据循环位0(DATA0) 令牌(PID)
.equ DATA1PID =0b01001011 ;数据循环位1(DATA1) 令牌(PID)
.equ OUTPID =0b11100001 ;输出(OUT) 令牌(PID)
.equ INPID =0b01101001 ;输入(IN) 令牌(PID)
.equ SOFPID =0b10100101 ;SOF 令牌(PID)
.equ SETUPPID =0b00101101 ;设置(SETUP) 令牌(PID)
.equ ACKPID =0b11010010 ;ACK 令牌(PID)
.equ NAKPID =0b01011010 ;NAK 令牌(PID)
.equ STALLPID =0b00011110 ;STALL 令牌(PID)
.equ PREPID =0b00111100 ;PRE 令牌(PID)
.equ nSOPbyte =0b00000001 ;起始包(Start) byte - 反向移位
.equ nDATA0PID =0b11000011 ;数据循环位0(DATA0) 令牌(PID) - 反向移位
.equ nDATA1PID =0b11010010 ;数据循环位1(DATA1) 令牌(PID) - 反向移位
.equ nOUTPID =0b10000111 ;输出(OUT) 令牌(PID) - 反向移位
.equ nINPID =0b10010110 ;输入(IN) 令牌(PID) - 反向移位
.equ nSOFPID =0b10100101 ;SOF 令牌(PID) - 反向移位
.equ nSETUPPID =0b10110100 ;设置(SETUP) 令牌(PID) - 反向移位
.equ nACKPID =0b01001011 ;ACK 令牌(PID) - 反向移位
.equ nNAKPID =0b01011010 ;NAK 令牌(PID) - 反向移位
.equ nSTALLPID =0b01111000 ;STALL 令牌(PID) - 反向移位
.equ nPREPID =0b00111100 ;PRE 令牌(PID) - 反向移位
.equ nNRZITokenPID =~0b10000000 ;令牌屏蔽 (IN,OUT,SOF,SETUP) - 反向移位 反向不归零码(NRZI)
.equ nNRZISOPbyte =~0b10101011 ;起始包(Start) byte - 反向移位 反向不归零码(NRZI)
.equ nNRZIDATA0PID =~0b11010111 ;数据循环位0(DATA0) 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZIDATA1PID =~0b11001001 ;数据循环位1(DATA1) 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZIOUTPID =~0b10101111 ;输出(OUT) 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZIINPID =~0b10110001 ;输入(IN) 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZISOFPID =~0b10010011 ;SOF 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZISETUPPID =~0b10001101 ;设置(SETUP) 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZIACKPID =~0b00100111 ;ACK 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZINAKPID =~0b00111001 ;NAK 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZISTALLPID =~0b00000111 ;STALL 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZIPREPID =~0b01111101 ;PRE 令牌(PID) - 反向移位 反向不归零码(NRZI)
.equ nNRZIADDR0 =~0b01010101 ;地址=0 - 反向移位 反向不归零码(NRZI)
;工作状态
.equ BaseState =0 ;
.equ SetupState =1 ;Setup状态
.equ InState =2 ;
.equ OutState =3 ;
.equ SOFState =4 ;
.equ DataState =5 ;
.equ AddressChangeState =6 ;
;工作标志
.equ DoNone =0
.equ DoReceiveOutData =1
.equ DoReceiveSetupData =2 ;要求或正在处理设置包(Setup)
.equ DoPrepareOutContinuousBuffer =3 ;从缓冲区输出连续数据
.equ DoReadySendAnswer =4
.equ CRC5poly =0b00101 ;CRC5 polynom
.equ CRC5zvysok =0b01100 ;CRC5 zvysok po uspesnpm CRC5
.equ CRC16poly =0b1000000000000101 ;CRC16 polynom
.equ CRC16zvysok =0b1000000000001101 ;CRC16 zvysok po uspesnom CRC16
.equ MAXUSBBYTES =14 ;USB 输入最大的字节数
.equ MAXRS232LENGTH =36 ;RS232 缓冲区长度
.equ NumberOfFirstBits =10 ;kolko prvych bitov moze byt dlhsich
.equ NoFirstBitsTimerOffset =256-12800*12/1024 ;定时 12.8ms (12800us 12Mhz:时钟, 1024:定时器分频, 256:定时器溢出值)
.equ InitBaudRate =12000000/16/57600-1;UART 波特率57600 (注 12MHz=12000000Hz)
;
;- - - - - - - - - - SRAM定义 - - - - - - - - -
.equ InputBufferBegin =RAMEND-127 ;输入数据缓冲区
.equ InputShiftBufferBegin =InputBufferBegin+MAXUSBBYTES ;输入移位缓冲区
.equ RS232BufferBegin =InputShiftBufferBegin+MAXUSBBYTES ;RS232 缓冲区
.equ MyInAddressSRAM =RS232BufferBegin+MAXRS232LENGTH+1 ;RS232数据输入指针
.equ MyOutAddressSRAM =MyInAddressSRAM+1 ;RS232数据输出指针
.equ OutputBufferBegin =RAMEND-MAXUSBBYTES-2 ;USB 输出缓冲区
.equ AckBufferBegin =OutputBufferBegin-3 ;USB Ack 缓冲区
.equ NakBufferBegin =AckBufferBegin-3 ;USB Nak 缓冲区
.equ StackBegin =NakBufferBegin-1 ;堆栈开始位置
;
;- - - - - - - - - 工作寄存器定义 - - - - - - - - -
.def ConfigByte =R1 ;目前设备的配置值 没有配置状态=0
.def backupbitcount =R2 ;INT0 中备份移位计数器(bitcount)
.def RAMread =R3 ;读取数据到RAM的位置
.def backupSREGTimer =R4 ;定时器中断中的SREG备份
.def backupSREG =R5 ;INT0 中断中的SREG备份
.def ACC =R6 ;累加器(软件模拟的)
.def lastBitstufNumber =R7 ;pozicia bitstuffingu
.def OutBitStuffNumber =R8 ;kolko bitov sa ma este odvysielat z posledneho bytu - bitstuffing
.def BitStuffInOut =R9 ;是增加位填充还是滤除位填充(只使用Bit0 增加=1 滤除=0)
.def TotalBytesToSend =R10 ;发送的总字节
.def TransmitPart =R11 ;传送的次数
.def InputBufferLength =R12 ;dlzka pripravena vo vstupnom USB bufferi
.def OutputBufferLength =R13 ;dlzka odpovede pripravena v USB bufferi
.def MyOutAddress =R14 ;USB 设备地址(IN)
.def MyInAddress =R15 ;USB 设备地址(OUT)
.def ActionFlag =R16 ;工作标志
.def temp3 =R17 ;临时寄存器
.def temp2 =R18 ;临时寄存器
.def temp1 =R19 ;临时寄存器
.def temp0 =R20 ;临时寄存器
.def bitcount =R21 ;移位计数器
.def ByteCount =R22 ;数据长度
.def inputbuf =R23 ;prijimaci 寄存器
.def shiftbuf =R24 ;posuvny prijimaci 寄存器
.def State =R25 ;工作状态
.def RS232BufptrX =R26 ;XL 寄存器 - 用作 prijatych IR kodov 缓冲区指针
.def RS232BufferFull =R27 ;XH 寄存器 - priznak plneho RS232 缓冲区
.def USBBufptrY =R28 ;YL 寄存器 - 用作 USB 输入/输出缓冲区指针
.def ROMBufptrZ =R30 ;ZL 寄存器 - 用作 ROM 缓冲区 dat 指针
;
;- - - - - - - - - USB协议数据定义 - - - - - - -
; USB 规范定义的控制传输的11种标准请求
.equ GET_STATUS =0 ;主机请求设备、接口或终端的特性的状态
.equ CLEAR_FEATURE =1 ;主机请求使一个设备、接口或终端的一个特性不可用
.equ SET_FEATURE =3 ;主机请求使能一个设备、接口或终端
.equ SET_ADDRESS =5 ;主机指定以后与设备通讯的地址
.equ GET_DESCRIPTOR =6 ;主机请求一个特定的描述符
.equ SET_DESCRIPTOR =7 ;主机增加一个描述符或更新一个存在的描述符
.equ GET_CONFIGURATION =8 ;主机请求目前设备的配置的值
.equ SET_CONFIGURATION =9 ;引导设备使用所选择的配置
.equ GET_INTERFACE =10 ;用于具有支持多个接口的配置的设备,主机请求当前的接口号
.equ SET_INTERFACE =11 ;用于具有支持多个接口的配置的设备,主机请求一个接口的设置
.equ SYNCH_FRAME =12 ;设备设置和报告一个终端的同步帧
;描述符包含的信息的类型
.equ DEVICE =1 ;设备
.equ CONFIGURATION =2 ;配置
.equ STRING =3 ;字符串
.equ INTERFACE =4 ;接口
.equ ENDPOINT =5 ;终端
.equ USER_FNC_NUMBER =100
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt table
;********************************************************************
.cseg
;------------------------------------------------------------------------------------------
.org 0 ;复位
rjmp reset
;------------------------------------------------------------------------------------------
.org INT0addr ;外中断INT0
rjmp INT0handler
;
;********************************************************************
;* UART 中断处理
;********************************************************************
.org URXCaddr ;UART接收完成
push temp0
in temp0,UDR ;读入异步串行数据到 temp0
sei ;打开中断,为了模拟 USB
in backupSREGTimer,SREG ;保存 SREG
cbi UCR,RXCIE ;清除 UART 接收完成标志
cpi RS232BufferFull,MAXRS232LENGTH-4
brcc NoIncRS232BufferFull
push RS232BufptrX
lds RS232BufptrX,RS232BufferBegin+2 ;取出 RS232 缓冲区指针: 3.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
st X+,temp0 ;将接收到的数据存入缓冲区
cpi RS232BufptrX,RS232BufferBegin+MAXRS232LENGTH+1 ;RS232缓冲区是否溢出
brne NoUARTBufferOverflow ;没有溢出
ldi RS232BufptrX,RS232BufferBegin+4 ;溢出,重新开始接收
NoUARTBufferOverflow:
sts RS232BufferBegin+2,RS232BufptrX ;保存 RS232 缓冲区指针: 3.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
inc RS232BufferFull ;增加接收数据计数
pop RS232BufptrX
NoIncRS232BufferFull:
pop temp0
out SREG,backupSREGTimer ;恢复 SREG
cli ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -