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

📄 新建 文本文档.txt

📁 USB 到 UART 协议转换程序 [简易的 - 少量的FIFO] 目标 MCU :AT90S2313-10
💻 TXT
📖 第 1 页 / 共 5 页
字号:
		ret
;------------------------------------------------------------------------------------------
CheckCRC:	;vstup: USBBufptrY = zaciatok spravy	,ByteCount = dlzka spravy
		add	ByteCount,USBBufptrY	;ByteCount ukazuje na koniec spravy
		inc	USBBufptrY		;nastav 指针 na zaciatok spravy - vynechat SOP
		ld	temp0,Y+		;nahraj PID do temp0
						;a nastav 指针 na zaciatok spravy - vynechat aj PID
		cpi	temp0,DATA0PID		;ci je DATA0 pole
		breq	ComputeDATACRC		;pocitaj CRC16
		cpi	temp0,DATA1PID		;ci je DATA1 pole
		brne	CRC16End		;ak nie tak skonci
ComputeDATACRC:
		ser	temp0			;初始化 zvysku LSB na 0xff
		ser	temp1			;初始化 zvysku MSB na 0xff
CRC16Loop:
		ld	temp2,Y+		;nahraj spravu do temp2 a zvys 指针 do 缓冲区
		ldi	temp3,8			;pocitadlo bitov v byte - temp3
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:
		lpm				;nahraj z pozicie ROM pointra do R0
		st	Y+,R0			;R0 uloz do 缓冲区 a zvys buffer
		adiw	ZH:ZL,1			;zvys ukazovatel do ROM
		dec	ByteCount		;pokial nie su vsetky byty
		brne	LoadDescriptorFromROM	;tak nahravaj dalej
		rjmp	EndFromRAMROM		;inak skonci
;------------------------------------------------------------------------------------------
LoadDescriptorFromROMZeroInsert:
		lpm				;nahraj z pozicie ROM pointra do R0
		st	Y+,R0			;R0 uloz do 缓冲区 a zvys buffer

		bst	RAMread,3		;ak je 3 bit jednotkovy - nebude sa vkladat nula
		brtc	InsertingZero		;inak sa bude vkladat nula
		adiw	ZH:ZL,1			;zvys ukazovatel do ROM
		lpm				;nahraj z pozicie ROM pointra do R0
		st	Y+,R0			;R0 uloz do 缓冲区 a zvys buffer
		clt				;a znuluj
		bld	RAMread,3		;treti bit v RAMread - aby sa v dalsom vkladali nuly
		rjmp	InsertingZeroEnd	;a pokracuj
InsertingZero:
		clr	R0			;na vkladanie nul
		st	Y+,R0			;nulu uloz do 缓冲区 a zvys buffer
InsertingZeroEnd:
		adiw	ZH:ZL,1			;zvys ukazovatel do ROM
		subi	ByteCount,2		;pokial nie su vsetky byty
		brne	LoadDescriptorFromROMZeroInsert	;tak nahravaj dalej
		rjmp	EndFromRAMROM		;inak skonci
;------------------------------------------------------------------------------------------
LoadDescriptorFromSRAM:
		ld	R0,Z			;nahraj z pozicie RAM pointra do R0
		st	Y+,R0			;R0 uloz do 缓冲区 a zvys buffer
		inc	ZL			;zvys ukazovatel do RAM
		dec	ByteCount		;pokial nie su vsetky byty
		brne	LoadDescriptorFromSRAM	;tak nahravaj dalej
		rjmp	EndFromRAMROM		;inak skonci
;------------------------------------------------------------------------------------------
LoadDescriptorFromEEPROM:
		out	EEAR,ZL			;nastav adresu EEPROM
		sbi	EECR,EERE		;vycitaj EEPROM do registra EEDR
		in	R0,EEDR			;nahraj z EEDR do R0
		st	Y+,R0			;R0 uloz do 缓冲区 a zvys buffer
		inc	ZL			;zvys ukazovatel do RAM
		dec	ByteCount		;pokial nie su vsetky byty
		brne	LoadDescriptorFromEEPROM;tak nahravaj dalej
		rjmp	EndFromRAMROM		;inak skonci
;------------------------------------------------------------------------------------------
LoadXXXDescriptor:
		ldi	temp0,SOPbyte			;加载SOP到输出缓冲区
		sts	OutputBufferBegin,temp0
		ldi	ByteCount,8			;8 bytov nahrat
		ldi	USBBufptrY,OutputBufferBegin+2	;Y指针指向发送缓冲区+2

		and	RAMread,RAMread			;RAMread 是否为0
		brne	FromRAMorEEPROM			;0=ROM,1=RAM,2=EEPROM,4=ROM s vkladanim nuly
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			;ak je najvyssi bit v premennej RAMread=1
		clr	RAMread				;znuluj RAMread
		rcall	ToggleDATAPID			;循环DATA1/DATA0
		ldi	USBBufptrY,OutputBufferBegin+1	;do vysielacieho 缓冲区 - pozicia DATA PID
		ret
;------------------------------------------------------------------------------------------
PrepareUSBOutAnswer:	;pripravenie odpovede do 缓冲区
		rcall	PrepareUSBAnswer		;根据配置数据进行进一步的处理
MakeOutBitStuff:
		inc	BitStuffInOut			;vysielaci buffer - vkladanie bitstuff bitov
		ldi	USBBufptrY,OutputBufferBegin	;do vysielacieho 缓冲区
		rcall	BitStuff                        ;安排填充位
		mov	OutputBufferLength,ByteCount	;dlzku odpovede zapamatat pre vysielanie
		clr	BitStuffInOut			;prijimaci buffer - mazanie bitstuff bitov
		ret
;------------------------------------------------------------------------------------------
PrepareUSBAnswer:	;pripravenie odpovede do 缓冲区
		clr	RAMread				;nulu do RAMread premennej - cita sa z ROM-ky
		lds	temp0,InputBufferBegin+2	;取出 bmRequestType
		lds	temp1,InputBufferBegin+3	;取出 bRequest
		cbr	temp0,0b10011111		;保留 bmRequestType 第6位和第5位(请求类型)
		brne	VendorRequest			;tak to nie je  Vendor Request
		rjmp	StandardRequest			;00 是 USB 的11种标准请求
;--------------------------
DoSetInfraBufferEmpty:
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
;--------------------------
DoSetRS232Baud:
		lds	temp0,InputBufferBegin+4	;prvy parameter - hodnota baudrate na RS232
		out	UBRR,temp0			;nastav rychlost UART-u
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
;--------------------------
DoGetRS232Baud:
		in	R0,UBRR				;vrat rychlost UART-u v R0
		rjmp	DoGetIn				;a ukonci
;--------------------------
DoRS232Send:
		lds	temp0,InputBufferBegin+4	;prvy parameter - hodnota vysielana na RS232
		out	UDR,temp0			;vysli data na UART
WaitForRS232Send:
		sbis	UCR,TXEN			;ak nie je povoleny UART vysielac
		rjmp	OneZeroAnswer			;tak skonci - ochrana kvoli zacykleniu v AT90S2323/2343
		sbis	USR,TXC				;pockat na dovysielanie bytu
		rjmp	WaitForRS232Send
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
;--------------------------
DoRS232Read:
		rjmp	TwoZeroAnswer			;iba potvrd prijem dvoma nulami
;--------------------------
VendorRequest:
		clr	ZH				;pre citanie z RAM alebo EEPROM

		cpi	temp1,1				;
		breq	DoSetInfraBufferEmpty		;restartne infra prijimanie (ak bolo zastavene citanim z RAM-ky)

		cpi	temp1,2				;
		breq	DoGetInfraCode			;vysle prijaty infra kod (ak je v bufferi)

		cpi	temp1,3				;
		breq	DoSetDataPortDirection		;nastavi smer toku datovych bitov
		cpi	temp1,4				;
		breq	DoGetDataPortDirection		;zisti smer toku datovych bitov

		cpi	temp1,5				;
		breq	DoSetOutDataPort		;nastavi datove bity (ak su vstupne, tak ich pull-up)
		cpi	temp1,6				;
		breq	DoGetOutDataPort		;zisti nastavenie datovych out bitov (ak su vstupne, tak ich pull-up)

		cpi	temp1,7				;
		breq	DoGetInDataPort			;vrati hodnotu datoveho vstupneho portu

		cpi	temp1,8				;
		breq	DoEEPROMRead			;vrati obsah EEPROM od urcitej adresy
		cpi	temp1,9				;
		breq	DoEEPROMWrite			;zapise EEPROM na urcitu adresu urcite data

		cpi	temp1,10			;
		breq	DoRS232Send			;vysle byte na seriovy linku
		cpi	temp1,11			;
		breq	DoRS232Read			;vrati prijaty byte zo seriovej linky (ak sa nejaky prijal)

		cpi	temp1,12			;
		breq	DoSetRS232Baud			;nastavi prenosovu rychlost seriovej linky
		cpi	temp1,13			;
		breq	DoGetRS232Baud			;vrati prenosovu rychlost seriovej linky
		cpi	temp1,14			;
		breq	DoGetRS232Buffer		;vrati RS232 buffer

		cpi	temp1,USER_FNC_NUMBER+0		;
		breq	DoUserFunction0			;vykona uzivatelsku rutinu0
		cpi	temp1,USER_FNC_NUMBER+1		;
		breq	DoUserFunction1			;vykona uzivatelsku rutinu1
		cpi	temp1,USER_FNC_NUMBER+2		;
		breq	DoUserFunction2			;vykona uzivatelsku rutinu2

		rjmp	ZeroDATA1Answer			;ak to bolo nieco nezname, tak priprav nulovu odpoved

;----------------------------- USER FUNCTIONS --------------------------------------

;------------------------------TEMPLATE OF YOUR FUNCTION----------------------------
;------------------ BEGIN: This is template how to write own function --------------

;free of use are 寄存器s:
	;temp0,temp1,temp2,temp3,ACC,ZH,ZL
	;寄存器s are destroyed after execution (use push/pop to save content)

;at the end of routine you must correctly set 寄存器s:
	;RAMread - 0=reading from ROM, 1=reading from RAM, 2=reading from EEPROM
	;temp0 - number of transmitted data bytes
	;ZH,ZL - 指针 to buffer of transmitted data (指针 to ROM/RAM/EEPROM)

;to transmit data (preparing data to buffer) :
	;to transmit data you must jump to "ComposeEndXXXDescriptor"
	;to transmit one zero byte you can jump to "OneZeroAnswer"  (commonly used as confirmation of correct processing)
	;to transmit two zero byte you can jump to "TwoZeroAnswer"  (commonly used as confirmation of error in processing)

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 Lo do temp2
		;lds	temp3,InputBufferBegin+7	;druhy parameter Hi do temp3
		;lds	ACC,InputBufferBegin+8		;pocet pozadovanych bytov do ACC

		;Tu si pridajte vlastny kod:
		;-------------------------------------------------------------------
		nop					;priklad na kod - nic nerobi
		nop
		nop
		nop
		nop
		;-------------------------------------------------------------------

		mov	ZL,temp0			;bude sa posielat hodnota RAM adresy ulozena v temp0 (prvy parameter funkcie)
		inc	RAMread				;RAMread=1 - cita sa z RAM-ky
		ldi	temp0,RAMEND+1			;posli max pocet byte - celu RAM
		rjmp	ComposeEndXXXDescriptor		;a priprav data
DoUserFunction1:
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
DoUserFunction2:
		rjmp	TwoZeroAnswer			;potvrd prijem dvoma nulami
;------------------ END: This is template how to write own function ----------------

;----------------------------- USER FUNCTIONS --------------------------------------

DoGetInfraCode:
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou

DoEEPROMRead:
		lds	ZL,InputBufferBegin+4		;prvy parameter - offset v EEPROM-ke
		ldi	temp0,2
		mov	RAMread,temp0			;RAMread=2 - cita sa z EEPROM-ky
		ldi	temp0,E2END+1			;pocet mojich bytovych odpovedi do temp0 - cela dlzka EEPROM
		rjmp	ComposeEndXXXDescriptor		;inak priprav data
DoEEPROMWrite:
		lds	ZL,InputBufferBegin+4		;prvy parameter - offset v EEPROM-ke (adresa)
		lds	R0,InputBufferBegin+6		;druhy parameter - data, ktore sa maju zapisat do EEPROM-ky (data)
		rjmp	EEPROMWrite			;zapis do EEPROM a aj ukonci prikaz
DoSetDataPortDirection:
		lds	ACC,InputBufferBegin+4		;prvy parameter - smer datovych bitov
		rcall	SetDataPortDirection
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
DoGetDataPortDirection:
		rcall	GetDataPortDirection
		rjmp	DoGetIn

DoSetOutDataPort:
		lds	ACC,InputBufferBegin+4		;prvy parameter - hodnota datovych bitov
		rcall	SetOutDataPort
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
DoGetOutDataPort:
		rcall	GetOutDataPort
		rjmp	DoGetIn

DoGetInDataPort:
		rcall	GetInDataPort
 DoGetIn:
		ldi	ZL,0				;posiela sa hodnota v R0
		ldi	temp0,0x81			;RAMread=1 - cita sa z RAM-ky
		mov	RAMread,temp0			;(najvyssi bit na 1 - aby sa hned premenna RAMread znulovala)
		ldi	temp0,1				;posli iba jeden byte
		rjmp	ComposeEndXXXDescriptor		;a priprav data

DoGetRS232Buffer:
		mov	temp0,RS232BufferFull		;zisti dlzku 缓冲区 RS232 kodu
		cpi	temp0,0				;ak je RS232 Buffer prazdny
		breq	OneZeroAnswer			;tak nic neposli a potvrd prijem jednou nulou

		lds	ACC,InputBufferBegin+8		;pocet pozadovanych bytov do ACC

⌨️ 快捷键说明

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