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

📄 新建 文本文档.txt

📁 USB 到 UART 协议转换程序 [简易的 - 少量的FIFO] 目标 MCU :AT90S2313-10
💻 TXT
📖 第 1 页 / 共 5 页
字号:
		inc	temp0				;pocet moznych dodanych bajtov (plus byte dlzky 缓冲区)
		cp	ACC,temp0			;ak sa neziada viac ako mozem dodat
		brcc	NoShortGetRS232Buffer		;vysli tolko kolko sa ziada
		mov	temp0,ACC
NoShortGetRS232Buffer:
		dec	temp0				;uber byte dlzky
		lds	temp1,RS232BufferBegin+1	;zisti ukazovatel citania 缓冲区 RS232 kodu : 2.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
		add	temp1,temp0			;zisti kde je koniec
		cpi	temp1,RS232BufferBegin+MAXRS232LENGTH+1	;ak by mal pretiect
		brcs	ReadNoOverflow
		subi	temp1,RS232BufferBegin+MAXRS232LENGTH+1	;vypocitaj kolko sa neprenesie
		sub	temp0,temp1			;a o to skrat dlzku citania
		ldi	temp1,RS232BufferBegin+4	;a zacni od nuly
ReadNoOverflow:
		lds	ZL,RS232BufferBegin+1		;zisti ukazovatel citania 缓冲区 RS232 kodu : 2.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
		sts	RS232BufferBegin+1,temp1	;zapis novy ukazovatel citania 缓冲区 RS232 kodu : 2.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
		dec	ZL				;priestor pre udaj dlky - prenasa sa ako prvy bajt

		sub	RS232BufferFull,temp0		;zniz dlzku 缓冲区
		st	Z,RS232BufferFull		;a uloz skutocnu dlzku do paketu
		inc	temp0				;a o tento jeden bajt zvys pocet prenasanych bajtov (dlzka 缓冲区)
		inc	RAMread				;RAMread=1 - cita sa z RAM-ky
		rjmp	ComposeEndXXXDescriptor		;a priprav data
;----------------------------- END USER FUNCTIONS ----------------------------------

OneZeroAnswer:		;posle jednu nulu
		ldi	temp0,1				;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeGET_STATUS2

StandardRequest:
		cpi	temp1,GET_STATUS		;00 主机请求设备、接口、或终端的特性状态
		breq	ComposeGET_STATUS		;

		cpi	temp1,CLEAR_FEATURE		;01 主机请求使一个设备、接口、或终端的一个特性不可用
		breq	ComposeCLEAR_FEATURE		;

		cpi	temp1,SET_FEATURE		;03 主机请求使能一个设备、接口、或终端
		breq	ComposeSET_FEATURE		;

		cpi	temp1,SET_ADDRESS		;05 主机指定以后与设备通讯的地址
		breq	ComposeSET_ADDRESS		;nastav adresu

		cpi	temp1,GET_DESCRIPTOR		;06 主机请求一个特定的描述符
		breq	ComposeGET_DESCRIPTOR		;vygeneruj ho

		cpi	temp1,SET_DESCRIPTOR		;07 主机增加一个描述符或更新一个存在的描述符
		breq	ComposeSET_DESCRIPTOR		;

		cpi	temp1,GET_CONFIGURATION		;08 主机请求目前设备的配置值
		breq	ComposeGET_CONFIGURATION	;

		cpi	temp1,SET_CONFIGURATION		;09 引导设备使用所选择的配置
		breq	ComposeSET_CONFIGURATION	;

		cpi	temp1,GET_INTERFACE		;0A 主机请求当前的接口号
		breq	ComposeGET_INTERFACE		;

		cpi	temp1,SET_INTERFACE		;0B 主机请求使用一个接口
		breq	ComposeSET_INTERFACE		;

		cpi	temp1,SYNCH_FRAME		;0C 设备设置和报告一个终端同步帧的序号
		breq	ComposeSYNCH_FRAME		;
							;ak sa nenasla znama poziadavka
		rjmp	ZeroDATA1Answer			;ak to bolo nieco nezname, tak priprav nulovu odpoved

ComposeSET_ADDRESS:     ;05 主机指定以后与设备通讯的地址
		lds	temp1,InputBufferBegin+4	;取得新地址
		rcall	SetMyNewUSBAddresses		;ENG;and compute NRZI and bitstuffing coded adresses
		ldi	State,AddressChangeState	;改变地址状态
		rjmp	ZeroDATA1Answer			;返回一个0长度数据包

ComposeSET_CONFIGURATION:       ;09 引导设备使用所选择的配置
		lds	ConfigByte,InputBufferBegin+4	;取得主机要求的配置
ComposeCLEAR_FEATURE:   ;01 主机请求使一个设备、接口、或终端的一个特性不可用
ComposeSET_FEATURE:     ;03 主机请求使能一个设备、接口、或终端
ComposeSET_INTERFACE:   ;0B 主机请求使用一个接口
ZeroStringAnswer:
		rjmp	ZeroDATA1Answer			;posli nulovu odpoved

ComposeGET_STATUS:     ;00 主机请求设备、接口、或终端的特性状态
TwoZeroAnswer:
		ldi	temp0,2				;pocet mojich bytovych odpovedi do temp0
ComposeGET_STATUS2:
		ldi	ZH, high(StatusAnswer<<1)	;加载ROM指针(设备、接口、或终端的状态)
		ldi	ZL,  low(StatusAnswer<<1)
		rjmp	ComposeEndXXXDescriptor
ComposeGET_CONFIGURATION:       ;08 主机请求目前设备的配置值
		and	ConfigByte,ConfigByte		;是否为0(为0表示还没有配置)
		breq	OneZeroAnswer			;
		ldi	temp0,1				;pocet mojich bytovych odpovedi do temp0
		ldi	ZH, high(ConfigAnswerMinus1<<1)	;加载ROM指针
		ldi	ZL,  low(ConfigAnswerMinus1<<1)+1
		rjmp	ComposeEndXXXDescriptor		;a dokonci
ComposeGET_INTERFACE:   ;0A 主机请求当前的接口号
		ldi	ZH, high(InterfaceAnswer<<1)	;ROM指针 na odpoved
		ldi	ZL,  low(InterfaceAnswer<<1)
		ldi	temp0,1				;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeEndXXXDescriptor		;a dokonci

ComposeSYNCH_FRAME:     ;0C 设备设置和报告一个终端同步帧的序号
ComposeSET_DESCRIPTOR:  ;07 主机增加一个描述符或更新一个存在的描述符
		rcall	ComposeSTALL                    ;不支持
		ret

ComposeGET_DESCRIPTOR:  ;06 主机请求一个特定的描述符
		lds	temp1,InputBufferBegin+5	;DescriptorType do temp1
		cpi	temp1,DEVICE			;设备描述符(DeviceDescriptor)
		breq	ComposeDeviceDescriptor		;
		cpi	temp1,CONFIGURATION		;配置描述符(ConfigurationDescriptor)
		breq	ComposeConfigDescriptor		;
		cpi	temp1,STRING			;字符串描述符(StringDeviceDescriptor)
		breq	ComposeStringDescriptor		;
		ret
ComposeDeviceDescriptor:
		ldi	ZH, high(DeviceDescriptor<<1)	;ROM指针 na descriptor
		ldi	ZL,  low(DeviceDescriptor<<1)
		ldi	temp0,0x12			;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeEndXXXDescriptor		;a dokonci
ComposeConfigDescriptor:
		ldi	ZH, high(ConfigDescriptor<<1)	;ROM指针 na descriptor
		ldi	ZL,  low(ConfigDescriptor<<1)
		ldi	temp0,9+9+7			;pocet mojich bytovych odpovedi do temp0
ComposeEndXXXDescriptor:
		lds	TotalBytesToSend,InputBufferBegin+8	;取得回应给主机的最大字节数
		cp	TotalBytesToSend,temp0
		brcs	HostConfigLength		;当前回应的数据量大于最大字节数,不允许回应的数据超量
		mov	TotalBytesToSend,temp0		;当前回应的数据量少于最大字节数,有多少回应多少
HostConfigLength:
		mov	temp0,TotalBytesToSend

		clr	TransmitPart			;传送的次数(每次传送8字节)
		andi	temp0,0b00000111		;字节数模8
		breq	Length8Multiply			;是否为8字节的整数
		inc	TransmitPart			;不是,就得多传送1次
Length8Multiply:
		mov	temp0,TotalBytesToSend		;
		lsr	temp0				;右移3次(除以8)
		lsr	temp0
		lsr	temp0
		add	TransmitPart,temp0		;得到总共需要传输的次数
		ldi	temp0,DATA0PID			;开始PID为DATAO,以后就是DATA1/DATA0变换
		sts	OutputBufferBegin+1,temp0	;送入到输出缓冲区+1
		rjmp	ComposeNextAnswerPart

ComposeStringDescriptor:
		ldi	temp1,4+8			;ak RAMread=4(vkladaj nuly z ROM-koveho citania) + 8(za prvy byte nevkldadaj nulu)
		mov	RAMread,temp1
		lds	temp1,InputBufferBegin+4	;DescriptorIndex do temp1
		cpi	temp1,0				;LANGID String
		breq	ComposeLangIDString		;
		cpi	temp1,2				;DevNameString
		breq	ComposeDevNameString		;
		brcc	ZeroStringAnswer		;ak je DescriptorIndex vyssi nez 2 - posli nulovu odpoved
							;inak to bude VendorString
ComposeVendorString:
		ldi	ZH, high(VendorStringDescriptor<<1)	;ROM指针 na descriptor
		ldi	ZL,  low(VendorStringDescriptor<<1)
		ldi	temp0,(VendorStringDescriptorEnd-VendorStringDescriptor)*4-2	;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeEndXXXDescriptor		;a dokonci
ComposeDevNameString:
		ldi	ZH, high(DevNameStringDescriptor<<1)	;ROM指针 na descriptor
		ldi	ZL,  low(DevNameStringDescriptor<<1)
		ldi	temp0,(DevNameStringDescriptorEnd-DevNameStringDescriptor)*4-2	;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeEndXXXDescriptor		;a dokonci
ComposeLangIDString:
		clr	RAMread
		ldi	ZH, high(LangIDStringDescriptor<<1)	;ROM指针 na descriptor
		ldi	ZL,  low(LangIDStringDescriptor<<1)
		ldi	temp0,(LangIDStringDescriptorEnd-LangIDStringDescriptor)*2;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeEndXXXDescriptor		;a dokonci
;------------------------------------------------------------------------------------------
ZeroDATA1Answer:
		rcall	ComposeZeroDATA1PIDAnswer	
		ret
;------------------------------------------------------------------------------------------
SetMyNewUSBAddresses:		;nastavi nove USB adresy v NRZI kodovani	;ENG;set new USB addresses in NRZI coded
		mov	temp2,temp1		;address to temp2 and temp1 and temp3
 		mov	temp3,temp1		;
		cpi	temp1,0b01111111	;ENG;if address contains less than 6 ones
		brne	NewAddressNo6ones	;ENG;then don't add bitstuffing
		ldi	temp1,0b10111111	;ENG;else insert one zero - bitstuffing
 NewAddressNo6ones:
		andi	temp3,0b00000111	;ENG;mask 3 low bits of Address
		cpi	temp3,0b00000111	;ENG;and if 3 low bits of Address is no all ones
		brne	NewAddressNo3ones	;ENG;then no change address
						;ENG;else insert zero after 3-rd bit (bitstuffing)
		sec				;set carry
		rol	temp2			;ENG;rotate left
		andi	temp2,0b11110111	;ENG;and inserted zero after 3-rd bit
 NewAddressNo3ones:
		sts	MyOutAddressSRAM,temp2	;ENG;store new non-coded address Out (temp2)
						;ENG;and now perform NRZI coding
		rcall	NRZIforAddress		;ENG;NRZI for AddressIn (in temp1)
		sts	MyInAddressSRAM,ACC	;ENG;store NRZI coded AddressIn

		lds	temp1,MyOutAddressSRAM	;ENG;load non-coded address Out (in temp1)
		rcall	NRZIforAddress		;ENG;NRZI for AddressOut
		sts	MyOutAddressSRAM,ACC	;ENG;store NRZI coded AddressOut

		ret				;ENG;and return
;------------------------------------------------------------------------------------------
NRZIforAddress:
		clr	ACC			;vychodzi stav odpovede - mojej nNRZI USB adresy	;ENG;original answer state - of my nNRZI USB address
		ldi	temp2,0b00000001	;maska na xorovanie	;ENG;mask for xoring
		ldi	temp3,8			;pocitadlo bitov	;ENG;bits counter
SetMyNewUSBAddressesLoop:
		mov	temp0,ACC		;zapamatat si koncovu odpoved	;ENG;remember final answer
		ror	temp1			;do carry vysielany bit LSB (v smere naskor LSB a potom MSB)	;ENG;to carry transmitting bit LSB (in direction firstly LSB then MSB)
		brcs	NoXORBits		;ak je jedna - nemen stav	;ENG;if one - don't change state
		eor	temp0,temp2		;inak sa bude stav menit podla posledneho bitu odpovede	;ENG;otherwise state will be changed according to last bit of answer
NoXORBits:
		ror	temp0			;posledny bit zmenenej odpovede do carry	;ENG;last bit of changed answer to carry
		rol	ACC			;a z carry do koncovej odpovede na miesto LSB (a sucasne prehodenie LSB a MSB poradia)	;ENG;and from carry to final answer to the LSB place (and reverse LSB and MSB order)
		dec	temp3			;zmensi pocitadlo bitov	;ENG;decrement bits counter
		brne	SetMyNewUSBAddressesLoop	;ak pocitadlo bitov nie je nulove opakuj vysielanie s dalsim bitom	;ENG;if bits counter isn't zero repeat transmitting with next bit
		ret
;------------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------------
PrepareOutContinuousBuffer:
		rcall	PrepareContinuousBuffer
		rcall	MakeOutBitStuff
		ret
;------------------------------------------------------------------------------------------
PrepareContinuousBuffer:
		mov	temp0,TransmitPart
		cpi	temp0,1
		brne	NextAnswerInBuffer		;ak uz je buffer prazdny
		rcall	ComposeZeroAnswer		;priprav nulovu odpoved
		ret
NextAnswerInBuffer:
		dec	TransmitPart			;znizit celkovu dlzku odpovede
ComposeNextAnswerPart:
		mov	temp1,TotalBytesToSend	;发送的总字节
		subi	temp1,8			;是否大于8字节
		ldi	temp3,8			;不够8字节也发送1次
		brcc	Nad8Bytov
		mov	temp3,TotalBytesToSend	;剩下发送的总字节<8字节
		clr	TransmitPart
		inc	TransmitPart		;发送1次
Nad8Bytov:
		mov	TotalBytesToSend,temp1	;保存发送的总字节-8
		rcall	LoadXXXDescriptor       ;加载XXX描述符
		ldi	ByteCount,2		;dlzka vystupneho 缓冲区 (iba SOP a PID)
		add	ByteCount,temp3		;+ pocet bytov
		rcall	AddCRCOut		;输出缓冲区 CRC 校验
		inc	ByteCount		;增加2个CRC16的发送字节数
		inc	ByteCount
		ret				;skonci
;------------------------------------------------------------------------------------------
.equ	USBversion		=0x0101		;pre aku verziu USB je to (1.01)
.equ	VendorUSBID		=0x03EB		;identifikator dodavatela (Atmel=0x03EB)
.equ	DeviceUSBID		=0x21FE		;identifikator vyrobku (USB to RS232 converter AT90S2313=0x21FE)
.equ	DeviceVersion		=0x0002		;cislo verzie vyrobku (verzia=0.02)
.equ	MaxUSBCurrent		=46		;prudovy odber z USB (46mA)
;------------------------------------------------------------------------------------------
DeviceDescriptor:       ;设备描述符
		.db	0x12,0x01		;0 byte - 描述符长度
						;1 byte - 固定设备(01)
		.dw	USBversion		;2,3 byte - USB 发布号 (1.01版)
		.db	0x00,0x00		;4 byte - 类代码
						;5 byte - 子类代码
		.db	0x00,0x08		;6 byte - 协议代码
						;7 byte - 终端0最大包大小
		.dw	VendorUSBID		;8,9 byte - 销售商ID (Cypress=0x04B4)
		.dw	DeviceUSBID		;10,11 byte - 产品ID (teplomer=0x0002)
		.dw	DeviceVersion		;12,13 byte - 设备发布号BCD (verzia=0.01)
		.db	0x01,0x02		;14 byte - 给制造商的字符串描述符的指针 "vyrobca"
						;15 byte - 给产品的字符串描述符的指针 "vyrobok"
		.db	0x00,0x01		;16 byte - 包括了序列号的字符串描述符的指针 "seriove cislo"
						;17 byte - 可能的配置的号码
DeviceDescriptorEnd:
;------------------------------------------------------------------------------------------
ConfigDescriptor:       ;配置描述符
		.db	0x9,0x02		;0 byte - 描述符长度
                                                ;1 byte - 固定配置(02)
ConfigDescriptorLength:
		.dw	9+9+7			;这个配置返回的所有数据的字节大小
	ConfigAnswerMinus1:
		.db	1,1			;支持的接口号,SET_CONFIGURATION和GET_CONFIGURATION请求的标示符
		.db	0,0x80			;这个配置的字符串描述符的指针,自供电/总线供电和远程唤醒设置
		.db	MaxUSBCurrent/2,0x09	;需要的总线电能, 接口描述符长度
		.db	0x04,0			;固定接口(04); 识别这个接口的号
	InterfaceAnswer:
		.db	0,1			;用于选择一个替换设置的值,支持的终端号码
	StatusAnswer:
		.db	0,0			;类代码,子类代码
		.db	0,0			;协议代码,接口的字符串描述符的指针
		.db	0x07,0x5		;终端描述符的长度,固定终端(05)
		.db	0x81,0			;终端号和方向,支持

⌨️ 快捷键说明

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