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

📄 usb90s23x3.asm

📁 单片机AT90S系列 制作简易USB接口(软件模拟,无usb硬件)。asm源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		lsl		temp2			;nula do dalsieho spodneho bitu masky
		rjmp	HalfDeletePosuvMask
DoneMask:
		and		temp1,temp2		;odmaskuj aby zostali iba vrchne posunute bity v temp1
		com		temp2			;invertuj masku
		ld		temp0,Y			;nahraj byte ktory este treba posunut od pozicie bitcount do temp0
		and		temp0,temp2		;odmaskuj aby zostali iba spodne neposunute bity v temp0
		or		temp1,temp0		;a zluc posunutu a neposunutu cast
		st		Y,temp1			;a nahraj spat
		ret				;a skonci
;------------------------------------------------------------------------------------------
MirrorInBufferBytes:
		push	USBBufptrY
		push	ByteCount
		ldi		USBBufptrY,InputBufferBegin
		rcall	MirrorBufferBytes
		pop		ByteCount
		pop		USBBufptrY
		ret
;------------------------------------------------------------------------------------------
MirrorBufferBytes:
		add		ByteCount,USBBufptrY	;ByteCount ukazuje na koniec spravy
MirrorBufferloop:
		ld		temp0,Y			;nahraj prijaty byte z buffera
		ldi		temp1,8			;pocitadlo bitov
MirrorBufferByteLoop:
		ror		temp0			;do carry dalsi najnizsi bit
		rol		temp2			;z carry dalsi bit na obratene poradie
		dec		temp1			;bol uz cely byte
		brne	MirrorBufferByteLoop	;ak nie tak opakuj dalsi najnizsi bit
		st		Y+,temp2		;ulozenie spat ako obrateny byte  a zvys pointer do buffera
		cp		USBBufptrY,ByteCount	;ak este neboli vsetky
		brne	MirrorBufferloop	;tak opakuj
		ret				;inak skonci
;------------------------------------------------------------------------------------------
CheckCRCIn:
		push	USBBufptrY
		push	ByteCount
		ldi		USBBufptrY,InputBufferBegin
		rcall	CheckCRC
		pop		ByteCount
		pop		USBBufptrY
		ret
;------------------------------------------------------------------------------------------
AddCRCOut:
		push	USBBufptrY
		push	ByteCount
		ldi		USBBufptrY,OutputBufferBegin
		rcall	CheckCRC
		com		temp0			;negacia CRC
		com		temp1
		st		Y+,temp1		;ulozenie CRC na koniec buffera (najskor MSB)
		st		Y,temp0			;ulozenie CRC na koniec buffera (potom LSB)
		dec		USBBufptrY		;pointer na poziciu CRC
		ldi		ByteCount,2		;otocit 2 byty CRC
		rcall	MirrorBufferBytes	;opacne poradie bitov CRC (pri vysielani CRC sa posiela naskor MSB)
		pop		ByteCount
		pop		USBBufptrY
		ret
;------------------------------------------------------------------------------------------
CheckCRC:	;vstup: USBBufptrY = zaciatok spravy	,ByteCount = dlzka spravy
		add		ByteCount,USBBufptrY	;ByteCount ukazuje na koniec spravy
		inc		USBBufptrY		;nastav pointer na zaciatok spravy - vynechat SOP
		ld		temp0,Y+		;nahraj PID do temp0
						;a nastav pointer 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			;inicializacia zvysku LSB na 0xff
		ser		temp1			;inicializacia zvysku MSB na 0xff		
CRC16Loop:
		ld		temp2,Y+		;nahraj spravu do temp2 a zvys pointer do buffera
		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 buffera 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 buffera 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 buffera 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 buffera 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 buffera 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 buffera 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 byte
		sts		OutputBufferBegin,temp0		;na zaciatok vysielacieho buffera dat SOP
		ldi		ByteCount,8			;8 bytov nahrat
		ldi		USBBufptrY,OutputBufferBegin+2	;do vysielacieho buffera

		and		RAMread,RAMread			;ci sa bude citat z RAM alebo ROM-ky alebo EEPROM-ky
		brne	FromRAMorEEPROM			;0=ROM,1=RAM,2=EEPROM,4=ROM s vkladanim nuly
FromROM:
		rjmp	LoadDescriptorFromROM		;nahrat descriptor z ROM-ky
FromRAMorEEPROM:
		sbrc	RAMread,2			;ak RAMread=4
		rjmp	LoadDescriptorFromROMZeroInsert	;citaj z ROM s vkladanim nuly
		sbrc	RAMread,0			;ak RAMread=1
		rjmp	LoadDescriptorFromSRAM		;nahraj data zo SRAM-ky
		rjmp	LoadDescriptorFromEEPROM	;inak citaj z EEPROM
EndFromRAMROM:
		sbrc	RAMread,7			;ak je najvyssi bit v premennej RAMread=1
		clr		RAMread				;znuluj RAMread
		rcall	ToggleDATAPID			;zmenit DATAPID
		ldi		USBBufptrY,OutputBufferBegin+1	;do vysielacieho buffera - pozicia DATA PID
		ret
;------------------------------------------------------------------------------------------
PrepareUSBOutAnswer:	;pripravenie odpovede do buffera
		rcall	PrepareUSBAnswer		;pripravenie odpovede do buffera
MakeOutBitStuff:
		inc		BitStuffInOut			;vysielaci buffer - vkladanie bitstuff bitov
		ldi		USBBufptrY,OutputBufferBegin	;do vysielacieho buffera
		rcall	BitStuff
		mov		OutputBufferLength,ByteCount	;dlzku odpovede zapamatat pre vysielanie
		clr		BitStuffInOut			;prijimaci buffer - mazanie bitstuff bitov
		ret
;------------------------------------------------------------------------------------------
PrepareUSBAnswer:	;pripravenie odpovede do buffera
		clr		RAMread				;nulu do RAMread premennej - cita sa z ROM-ky
		lds		temp0,InputBufferBegin+2	;bmRequestType do temp0
		lds		temp1,InputBufferBegin+3	;bRequest do temp1
		cbr		temp0,0b10011111		;ak je 5 a 6 bit nulovy
		brne	VendorRequest			;tak to nie je  Vendor Request
		rjmp	StandardRequest			;ale je to standardny request
;--------------------------
DoSetInfraBufferEmpty:
		clr		InfraBufferFull			;nastav prazdnost buffera
SendZeroAnswerInfraEmpty:
		rjmp	OneZeroAnswer			;potvrd prijem jednou nulou
;--------------------------
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

		rjmp	ZeroDATA1Answer			;ak to bolo nieco nezname, tak priprav nulovu odpoved
;----------------------------- USER FUNCTIONS --------------------------------------
DoGetInfraCode:
		cpi		InfraBufferFull,0		;ak je Infra Buffer prazdny
		breq	SendZeroAnswerInfraEmpty	;tak nic neposli
		ldi		ZL,InfraBufferBegin
		lds		temp1,InputBufferBegin+4	;prvy parameter - offset v infra bufferi
		add		ZL,temp1			;plus offset v buffri
		lds		temp0,InfraBufferBegin		;pocet mojich bytovych odpovedi do temp0
		ldi		temp1,3				;plus 3 byty hlavicky
		add		temp0,temp1
		inc		RAMread				;RAMread=1 - cita sa z RAM-ky
		rjmp	ComposeEndXXXDescriptor		;a priprav data
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

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:
		sbis	USR,RXC				;ak je prijimaci register prazdny
		rjmp	TwoZeroAnswer			;tak iba potvrd prijem dvoma nulami
		in		R0,UDR				;inak nacitaj do R0 prijate data z UART-u
		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
		sbic	USR,OR				;ak bolo pretecenie prijimacieho buffera
		ldi		temp0,3				;posli 3 byty :prvy je prijata hodnota (na ostatnych nezalezi)

⌨️ 快捷键说明

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