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

📄 usb90s23x3.asm

📁 单片机AT90S系列 制作简易USB接口(软件模拟,无usb硬件)。asm源代码
💻 ASM
📖 第 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
;* 
;* File Name            :"USB90S2313.asm"
;* Title                :USB stack + Infrared remote control to nonUSB MCU
;* Date                 :5.4.2003
;* Version              :1.6
;* Target MCU           :AT90S2313-10,AT90S2323-10,AT90S2343-10
;* AUTHOR		:Ing. Igor Cesko
;* 			 Slovakia
;* 			 cesko@internet.sk
;* 			 http://www.cesko.host.sk
;*
;* DESCRIPTION:
;*  USB protocol implementation into MCU with noUSB interface:
;*  Device:
;*  Infrared remote control with TSOP17xx/SFH511x sensor and USB connection
;*  + Universal USB interface (8-bit I/O port + RS232 serial line + EEPROM)
;*
;* The timing is adapted for 12 MHz crystal (overclocked MCU !!!)
;*
;* Copyright (c) Ing. Igor Cesko 2002-2003
; *
;*     This program is free software; you can redistribute it and/or modify
;*    it under the terms of the GNU General Public License as published by
;*    the Free Software Foundation; either version 2 of the License, or
;*    (at your option) any later version.
;*
;*    This program is distributed in the hope that it will be useful,
;*    but WITHOUT ANY WARRANTY; without even the implied warranty of
;*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;*    GNU General Public License for more details.
;*
;*    You should have received a copy of the GNU General Public License
;*    along with this program; if not, write to the Free Software
;*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;*
;***************************************************************************
.include "2313def.inc"

.EQU	R4              	=4
.EQU	inputport			=PINB
.EQU	outputport			=PORTB
.EQU	USBdirection		=DDRB
.EQU	DATAplus			=1				;signal D+ na PB1
.EQU	DATAminus			=0				;signal D- na PB0 - treba dat na tento pin pull-up 1.5kOhm
.EQU	USBpinmask			=0b11111100		;mask low 2 bits (D+,D-) on PB
.EQU	USBpinmaskDplus		=~(1<<DATAplus)	;mask D+ bit on PB
.EQU	USBpinmaskDminus	=~(1<<DATAminus);mask D- bit on PB

.EQU	TSOPPort			=PINB
.EQU	TSOPpullupPort		=PORTB
.EQU	TSOPPin				=2			;signal OUT z IR senzora TSOP1738 na PB2

.EQU	LEDPortLSB			=PORTD		;pripojenie LED diod LSB
.EQU	LEDPinLSB			=PIND		;pripojenie LED diod LSB (vstup)
.EQU	LEDdirectionLSB		=DDRD		;vstup/vystup LED LSB
.EQU	LEDPortMSB			=PORTB		;pripojenie LED diod MSB
.EQU	LEDPinMSB			=PINB		;pripojenie LED diod MSB  (vstup)
.EQU	LEDdirectionMSB		=DDRB		;vstup/vystup LED MSB
.EQU	LEDlsb0				=3		;LED0 na pin PD3
.EQU	LEDlsb1				=5		;LED1 na pin PD5
.EQU	LEDlsb2				=6		;LED2 na pin PD6
.EQU	LEDmsb3				=3		;LED3 na pin PB3
.EQU	LEDmsb4				=4		;LED4 na pin PB4
.EQU	LEDmsb5				=5		;LED5 na pin PB5
.EQU	LEDmsb6				=6		;LED6 na pin PB6
.EQU	LEDmsb7				=7		;LED7 na pin 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		;

						;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			;maximum bytes in USB input message
.EQU	MAXINFRALENGTH			=36			;maximalna dlzka Infra kodu (pocet jednotiek a nul spolu) (pozor: MAXINFRALENGTH 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	BaudRate				=12000000/16/57600-1	;nastavit vysielaciu rychlost UART-u na 57600 (pre 12MHz=12000000Hz)

.EQU	InputBufferBegin		=RAMEND-127				;zaciatok prijimacieho shift buffera
.EQU	InputShiftBufferBegin	=InputBufferBegin+MAXUSBBYTES		;zaciatok prijimacieho buffera
.EQU	InfraBufferBegin		=InputShiftBufferBegin+MAXUSBBYTES	;zaciatok buffera pre Infra prijem

.EQU	OutputBufferBegin		=RAMEND-MAXUSBBYTES-2	;zaciatok vysielacieho buffera
.EQU	AckBufferBegin			=OutputBufferBegin-3	;zaciatok vysielacieho buffera Ack
.EQU	NakBufferBegin			=AckBufferBegin-3	;zaciatok vysielacieho buffera Nak

.EQU	StackBegin		=NakBufferBegin-1	;spodok zasobnika

.DEF	ConfigByte		=R1		;0=unconfigured state
.DEF	backupbitcount	=R2		;zaloha bitcount registra v INT0 preruseni
.DEF	RAMread			=R3		;ci sa ma citat zo SRAM-ky
.DEF	backupSREGTimer	=R4		;zaloha Flag registra v Timer interrupte
.DEF	backupSREG		=R5		;zaloha Flag registra v INT0 preruseni
.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		;kolko sa ma poslat bytov
.DEF	TransmitPart		=R11		;poradove cislo vysielacej casti
.DEF	InputBufferLength	=R12		;dlzka pripravena vo vstupnom USB bufferi
.DEF	OutputBufferLength	=R13		;dlzka odpovede pripravena v USB bufferi
.DEF	MyUpdatedAddress	=R14		;moja USB adresa na update
.DEF	MyAddress			=R15		;moja USB adresa


.DEF	ActionFlag		=R16		;co sa ma urobit v hlavnej slucke programu
.DEF	temp3			=R17		;temporary register
.DEF	temp2			=R18		;temporary register
.DEF	temp1			=R19		;temporary register
.DEF	temp0			=R20		;temporary register
.DEF	bitcount		=R21		;counter of bits in byte
.DEF	ByteCount		=R22		;pocitadlo maximalneho poctu prijatych bajtov
.DEF	inputbuf		=R23		;prijimaci register
.DEF	shiftbuf		=R24		;posuvny prijimaci register
.DEF	State			=R25		;byte stavu stavoveho stroja
.DEF	InfraBufptrX	=R26		;XL register - pointer do buffera prijatych IR kodov
.DEF	InfraBufferFull	=R27		;XH register - priznak plneho Infra Buffera
.DEF	USBBufptrY		=R28		;YL register - pointer do USB buffera input/output
.DEF	ROMBufptrZ		=R30		;ZL register - pointer do buffera 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


;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt table
		;; 
;********************************************************************.cseg
;------------------------------------------------------------------------------------------
.org 0						;po resete
		rjmp	reset
;------------------------------------------------------------------------------------------.org INT0addr					;externe prerusenie INT0
		rjmp	INT0handler
;------------------------------------------------------------------------------------------.org INT1addr					;externe prerusenie INT1 (pre AT89S2323 je tu Timer0 prerusenie)
		sei				;povol interrupty na obsluhu USB
		in		backupSREGTimer,SREG
		rjmp	OVF0handler2323		;na kompatibilitu s AT89S2323 sa skoci na pretecenie casovaca T0
;------------------------------------------------------------------------------------------
;********************************************************************
;* Timer0 interrupt handler
;********************************************************************
.org OVF0addr					;citac/casovac 0
OVF0handler:
		sei				;povol interrupty na obsluhu USB
		in		backupSREGTimer,SREG
OVF0handler2323:
		push	temp0
		ldi		temp0,0<<TOIE0		;zakazat interrupt od casovaca
		out		TIMSK,temp0
		ldi		temp0,5			;nastav clock input na CLK/1024 = tick kazdych 0.0853ms
		out		TCCR0,temp0
		push	temp1
		push	temp2
		push	temp3

		clr		temp2			;vynulovanie offsetu v bufferi (a flagu pretecenia)
		ldi		temp3,1			;timeout - plnenie citaca (pre prve bity iny ako pre dalsie bity: aby sa nikdy nevyslala dlzka kodu 255, tak sa musi plnit aspon na 1)
StartTSOPsampling:
		ldi		InfraBufptrX,InfraBufferBegin+3	;nastavenie sa na zaciatok buffera Infra kodu + 3byty hlavicky (dlzka kodu + counter + offset)
		clr		temp1			;vynulovanie dlzky Infra kodu
WaitForTOSOP1:
		sbis	TSOPPort,TSOPPin	;ak je TSOPPin v nule
		rjmp	CheckWaitForTOSOP1	;tak cakaj na jednotku
		rjmp	StoreToInfraBuffer
WaitForTOSOP0:
		sbic	TSOPPort,TSOPPin	;ak je TSOPPin v jednotke
		rjmp	CheckWaitForTOSOP0	;tak cakaj na nulu
StoreToInfraBuffer:
		in		temp0,TCNT0		;odchyt citac
		sub		temp0,temp3		;koriguj odchyteny citac vzhladom na jeho plnenie
		cpi		temp1,NumberOfFirstBits	;ak este neboli prve bity
		brne	WasNotFirstBits		;tak nechaj plnenie citaca na nule
		ldi		temp3,NoFirstBitsTimerOffset	;inak zmen plnenie citaca
WasNotFirstBits:
		out		TCNT0,temp3		;nastav citac aby bol ako casovac
		out		UDR,temp0		;vysli data na UART
		cpi		InfraBufferFull,0	;ak je infra buffer plny
		brne	NoStoreToInfraBuffer	;tak neukladaj data
		sbrs	RAMread,0		;ak RAMread=1 cita sa z RAM - potom neukladaj data
		st		X+,temp0		;a uloz ho do buffera
NoStoreToInfraBuffer:
		inc		temp1			;zvys dlzku Infra Buffera
		cpi		temp1,MAXINFRALENGTH	;ak sa nedosiahol maximum Infra buffera
		brne	NoTSOPoverflow		;tak pokracuj
		inc		temp2			;inak si poznac ze pretiekol
		cpi		temp2,3			;ak boli uz 3 pretecenia
		dec		temp1			;tak uber posledny bit
		breq	EndInfraSampling	;a skonci so samplovanim
		rjmp	StartTSOPsampling 	;a zacni odznova (pozor: MAXINFRALENGTH musi byt parne cislo !!!)
NoTSOPoverflow:
		sbic	TSOPPort,TSOPPin	;ak je TSOPPin v jednotke
		rjmp	WaitForTOSOP0		;tak cakaj na nulu
						;inak cakaj na jednotku
CheckWaitForTOSOP1:
		in		temp0,TIFR		;odchyt flag pretecenia citaca
		sbrc	temp0,TOV0		;ak pretiekol
		rjmp	EndInfraSampling	;tak skonci so samplovanim
		rjmp	WaitForTOSOP1		;inak cakaj na zmenu stavu
CheckWaitForTOSOP0:
		in		temp0,TIFR		;odchyt flag pretecenia citaca
		sbrc	temp0,TOV0		;ak pretiekol
		rjmp	EndInfraSampling	;tak skonci so samplovanim
		rjmp	WaitForTOSOP0		;inak cakaj na zmenu stavu
EndInfraSampling:
		sbrs	InfraBufferFull,0	;ak je infra buffer plny - tak neukladaj hlavicku
		sbrc	RAMread,0		;ak RAMread=1 cita sa z RAM
		rjmp	EndTSOPSampling		;potom neukladaj hlavicku
		cpi		temp2,0			;ak nebolo nejake pretecenie
		breq	NoOverflow		;tak nic nerob
		mov		temp2,temp1		;inak zaznamenaj offset
		ldi		temp1,MAXINFRALENGTH	;a maximalnu dlzku buffera
NoOverflow:
		sts		InfraBufferBegin,temp1	;dlzku kodu na zaciatok Infra buffera
		cpi		temp1,3			;zisti ci je dlzka kodu aspon 3
		lds		temp1,InfraBufferBegin+1;nacitaj pocitadlo infra kodov
		brcs	NoIncrementCodeCounter	;ak je dlzka kodu vacsia alebo rovna 3
		inc		temp1			;tak zvys pocitadlo infra kodov
		ldi		InfraBufferFull,1	;a nastav plnost buffera
NoIncrementCodeCounter:
		sts		InfraBufferBegin+1,temp1;uloz nove pocitadlo infra kodov
		sts		InfraBufferBegin+2,temp2;uloz offset zaciatku buffera
EndTSOPSampling:
		pop		temp3
		pop		temp2
		pop		temp1
		ldi		temp0,0xFF		;napln temp0 hodnotou 0xFF (ukoncovaci znak)

⌨️ 快捷键说明

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