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

📄 新建 文本文档.txt

📁 USB 到 UART 协议转换程序 [简易的 - 少量的FIFO] 目标 MCU :AT90S2313-10
💻 TXT
📖 第 1 页 / 共 5 页
字号:
;***************************************************************************
;* 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"

.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 of Packet byte
.equ	DATA0PID		=0b11000011	;PID pre DATA0 pole
.equ	DATA1PID		=0b01001011	;PID pre DATA1 pole
.equ	OUTPID			=0b11100001	;PID pre OUT pole
.equ	INPID			=0b01101001	;PID pre IN pole
.equ	SOFPID			=0b10100101	;PID pre SOF pole
.equ	SETUPPID		=0b00101101	;PID pre SETUP pole
.equ	ACKPID			=0b11010010	;PID pre ACK pole
.equ	NAKPID			=0b01011010	;PID pre NAK pole
.equ	STALLPID		=0b00011110	;PID pre STALL pole
.equ	PREPID			=0b00111100	;PID pre PRE pole

.equ	nSOPbyte		=0b00000001	;Start of Packet byte - opacne poradie
.equ	nDATA0PID		=0b11000011	;PID pre DATA0 pole - opacne poradie
.equ	nDATA1PID		=0b11010010	;PID pre DATA1 pole - opacne poradie
.equ	nOUTPID			=0b10000111	;PID pre OUT pole - opacne poradie
.equ	nINPID			=0b10010110	;PID pre IN pole - opacne poradie
.equ	nSOFPID			=0b10100101	;PID pre SOF pole - opacne poradie
.equ	nSETUPPID		=0b10110100	;PID pre SETUP pole - opacne poradie
.equ	nACKPID			=0b01001011	;PID pre ACK pole - opacne poradie
.equ	nNAKPID			=0b01011010	;PID pre NAK pole - opacne poradie
.equ	nSTALLPID		=0b01111000	;PID pre STALL pole - opacne poradie
.equ	nPREPID			=0b00111100	;PID pre PRE pole - opacne poradie

.equ	nNRZITokenPID		=~0b10000000	;PID maska pre Token paket (IN,OUT,SOF,SETUP) - opacne poradie NRZI
.equ	nNRZISOPbyte		=~0b10101011	;Start of Packet byte - opacne poradie NRZI
.equ	nNRZIDATA0PID		=~0b11010111	;PID pre DATA0 pole - opacne poradie NRZI
.equ	nNRZIDATA1PID		=~0b11001001	;PID pre DATA1 pole - opacne poradie NRZI
.equ	nNRZIOUTPID		=~0b10101111	;PID pre OUT pole - opacne poradie NRZI
.equ	nNRZIINPID		=~0b10110001	;PID pre IN pole - opacne poradie NRZI
.equ	nNRZISOFPID		=~0b10010011	;PID pre SOF pole - opacne poradie NRZI
.equ	nNRZISETUPPID		=~0b10001101	;PID pre SETUP pole - opacne poradie NRZI
.equ	nNRZIACKPID		=~0b00100111	;PID pre ACK pole - opacne poradie NRZI
.equ	nNRZINAKPID		=~0b00111001	;PID pre NAK pole - opacne poradie NRZI
.equ	nNRZISTALLPID		=~0b00000111	;PID pre STALL pole - opacne poradie NRZI
.equ	nNRZIPREPID		=~0b01111101	;PID pre PRE pole - opacne poradie NRZI
.equ	nNRZIADDR0		=~0b01010101	;Adresa = 0 - opacne poradie NRZI

						;stavove byty - State
.equ	BaseState		=0		;
.equ	SetupState		=1		;
.equ	InState			=2		;
.equ	OutState		=3		;
.equ	SOFState		=4		;
.equ	DataState		=5		;
.equ	AddressChangeState	=6		;

						;Flagy pozadovanej akcie
.equ	DoNone					=0
.equ	DoReceiveOutData			=1
.equ	DoReceiveSetupData			=2
.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			;maximalna dlzka RS232 kodu (pocet jednotiek a nul spolu) (pozor: MAXRS232LENGTH musi byt parne cislo !!!)
.equ	NumberOfFirstBits	=10			;kolko prvych bitov moze byt dlhsich
.equ	NoFirstBitsTimerOffset	=256-12800*12/1024	;Timeout 12.8ms (12800us) na ukoncenie prijmu po uvodnych bitoch (12Mhz:clock, 1024:timer predivider, 256:timer overflow value)
.equ	InitBaudRate		=12000000/16/57600-1	;nastavit vysielaciu rychlost UART-u na 57600 (pre 12MHz=12000000Hz)

.equ	InputBufferBegin	=RAMEND-127				;zaciatok prijimacieho shift 缓冲区
.equ	InputShiftBufferBegin	=InputBufferBegin+MAXUSBBYTES		;zaciatok prijimacieho 缓冲区
.equ	RS232BufferBegin	=InputShiftBufferBegin+MAXUSBBYTES	;zaciatok 缓冲区 pre RS232 prijem

.equ	MyInAddressSRAM		=RS232BufferBegin+MAXRS232LENGTH+1
.equ	MyOutAddressSRAM	=MyInAddressSRAM+1

.equ	OutputBufferBegin	=RAMEND-MAXUSBBYTES-2	;zaciatok vysielacieho 缓冲区
.equ	AckBufferBegin		=OutputBufferBegin-3	;zaciatok vysielacieho 缓冲区 Ack
.equ	NakBufferBegin		=AckBufferBegin-3	;zaciatok vysielacieho 缓冲区 Nak

.equ	StackBegin		=NakBufferBegin-1	;堆栈开始位置

.def	ConfigByte		=R1		;0=unconfigured state
.def	backupbitcount		=R2		;INT0 中保存 bitcount
.def	RAMread			=R3		;ci sa ma citat zo SRAM-ky
.def	backupSREGTimer		=R4		;定时器中断中的SREG备份
.def	backupSREG		=R5		;INT0 中断中的SREG备份
.def	ACC			=R6		;accumulator
.def	lastBitstufNumber	=R7		;pozicia bitstuffingu
.def	OutBitStuffNumber	=R8		;kolko bitov sa ma este odvysielat z posledneho bytu - bitstuffing
.def	BitStuffInOut		=R9		;ci sa ma vkladat alebo mazat bitstuffing
.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		;moja USB adresa na update
.def	MyInAddress		=R15		;moja USB adresa


.def	ActionFlag		=R16		;工作标志
.def	temp3			=R17		;临时寄存器
.def	temp2			=R18		;临时寄存器
.def	temp1			=R19		;临时寄存器
.def	temp0			=R20		;临时寄存器
.def	bitcount		=R21		;counter of bits in byte
.def	ByteCount		=R22		;pocitadlo maximalneho poctu prijatych bajtov
.def	inputbuf		=R23		;prijimaci 寄存器
.def	shiftbuf		=R24		;posuvny prijimaci 寄存器
.def	State			=R25		;byte stavu stavoveho stroja
.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 指针

;poziadavky na deskriptory
.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

;typy deskriptorov
.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						;po resete
		rjmp	reset
;------------------------------------------------------------------------------------------
.org INT0addr					;externe prerusenie INT0
		rjmp	INT0handler
;------------------------------------------------------------------------------------------
.org URXCaddr					;prijem zo seriovej linky
		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	;nastavenie sa na zaciatok 缓冲区 zapisu RS232 kodu : 3.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
		st	X+,temp0			;a uloz ho do 缓冲区
		cpi	RS232BufptrX,RS232BufferBegin+MAXRS232LENGTH+1	;ak sa nedosiahol maximum RS232 缓冲区
		brne	NoUARTBufferOverflow		;tak pokracuj
		ldi	RS232BufptrX,RS232BufferBegin+4	;inak sa nastav na zaciatok 缓冲区
 NoUARTBufferOverflow:
		sts	RS232BufferBegin+2,RS232BufptrX	;ulozenie noveho offsetu 缓冲区 zapisu RS232 kodu : 3.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
		inc	RS232BufferFull			;zvys dlzku RS232 缓冲区
		pop	RS232BufptrX
 NoIncRS232BufferFull:
		pop	temp0
		out	SREG,backupSREGTimer		;恢复 SREG
		cli					;zakazat interrupt kvoli zacykleniu
		sbi	UCR,RXCIE			;允许 interrupt od prijimania UART
		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
;------------------------------------------------------------------------------------------
;********************************************************************
;* Main program
;********************************************************************
		sei					;允许全局中断
Main:
		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 复位

⌨️ 快捷键说明

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