📄 usbtors232.asm
字号:
;***************************************************************************
;* 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 :"USBtoRS232.asm"
;* Title :AVR309:USB to UART protocol converter
;* Date :01.02.2004
;* Version :2.8
;* Target MCU :ATmega8
;* AUTHOR :Ing. Igor Cesko
;* Slovakia
;* cesko@internet.sk
;* http://www.cesko.host.sk
;*
;* DESCRIPTION:
;* USB protocol implementation into MCU with noUSB interface:
;* Device:
;* Universal USB interface (3x8-bit I/O port + RS232 serial line + EEPROM)
;* + added RS232 FIFO buffer
;*
;* The timing is adapted for 12 MHz crystal
;*
;*
;* to add your own functions - see section: TEMPLATE OF YOUR FUNCTION
;*
;* to customize device to your company you must change VendorUSB ID (VID)
;* to VID assigned to your company (for more information see www.usb.org)
;*
;***************************************************************************
.include "m8def.inc"
;comment for AT90S2313
.equ UCR =UCSRB
.equ UBRR =UBRRL
.equ EEAR =EEARL
.equ USR =UCSRA
.equ E2END =127
.equ RAMEND128 =96+127
.equ inputport =PINB
.equ outputport =PORTB
.equ USBdirection =DDRB
.equ DATAplus =1 ;signal D+ on PB1
.equ DATAminus =0 ;signal D- on PB0 - give on this pin pull-up 1.5kOhm
.equ USBpinmask =0b11111100 ;mask low 2 bit (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 from IR sensor TSOP1738 on PB2
;connecting LED diode LSB
;connecting LED diode LSB (input)
;input/output LED LSB
;connecting LED diode MSB
;connecting LED diode MSB (input)
;input/output LED MSB
;LED0 on pin PD3
;LED1 on pin PD5
;LED2 on pin PD6
;LED3 on pin PB3
;LED4 on pin PB4
;LED5 on pin PB5
;LED6 on pin PB6
;LED7 on pin PB7
.equ SOPbyte =0b10000000 ;Start of Packet byte
.equ DATA0PID =0b11000011 ;PID for DATA0 field
.equ DATA1PID =0b01001011 ;PID for DATA1 field
.equ OUTPID =0b11100001 ;PID for OUT field
.equ INPID =0b01101001 ;PID for IN field
.equ SOFPID =0b10100101 ;PID for SOF field
.equ SETUPPID =0b00101101 ;PID for SETUP field
.equ ACKPID =0b11010010 ;PID for ACK field
.equ NAKPID =0b01011010 ;PID for NAK field
.equ STALLPID =0b00011110 ;PID for STALL field
.equ PREPID =0b00111100 ;PID for FOR field
.equ nSOPbyte =0b00000001 ;Start of Packet byte - reverse order
.equ nDATA0PID =0b11000011 ;PID for DATA0 field - reverse order
.equ nDATA1PID =0b11010010 ;PID for DATA1 field - reverse order
.equ nOUTPID =0b10000111 ;PID for OUT field - reverse order
.equ nINPID =0b10010110 ;PID for IN field - reverse order
.equ nSOFPID =0b10100101 ;PID for SOF field - reverse order
.equ nSETUPPID =0b10110100 ;PID for SETUP field - reverse order
.equ nACKPID =0b01001011 ;PID for ACK field - reverse order
.equ nNAKPID =0b01011010 ;PID for NAK field - reverse order
.equ nSTALLPID =0b01111000 ;PID for STALL field - reverse order
.equ nPREPID =0b00111100 ;PID for FOR field - reverse order
.equ nNRZITokenPID =~0b10000000 ;PID mask for Token packet (IN,OUT,SOF,SETUP) - reverse order NRZI
.equ nNRZISOPbyte =~0b10101011 ;Start of Packet byte - reverse order NRZI
.equ nNRZIDATA0PID =~0b11010111 ;PID for DATA0 field - reverse order NRZI
.equ nNRZIDATA1PID =~0b11001001 ;PID for DATA1 field - reverse order NRZI
.equ nNRZIOUTPID =~0b10101111 ;PID for OUT field - reverse order NRZI
.equ nNRZIINPID =~0b10110001 ;PID for IN field - reverse order NRZI
.equ nNRZISOFPID =~0b10010011 ;PID for SOF field - reverse order NRZI
.equ nNRZISETUPPID =~0b10001101 ;PID for SETUP field - reverse order NRZI
.equ nNRZIACKPID =~0b00100111 ;PID for ACK field - reverse order NRZI
.equ nNRZINAKPID =~0b00111001 ;PID for NAK field - reverse order NRZI
.equ nNRZISTALLPID =~0b00000111 ;PID for STALL field - reverse order NRZI
.equ nNRZIPREPID =~0b01111101 ;PID for FOR field - reverse order NRZI
.equ nNRZIADDR0 =~0b01010101 ;Address = 0 - reverse order NRZI
;status bytes - State
.equ BaseState =0 ;
.equ SetupState =1 ;
.equ InState =2 ;
.equ OutState =3 ;
.equ SOFState =4 ;
.equ DataState =5 ;
.equ AddressChangeState =6 ;
;Flags of action
.equ DoNone =0
.equ DoReceiveOutData =1
.equ DoReceiveSetupData =2
.equ DoPrepareOutContinuousBuffer =3
.equ DoReadySendAnswer =4
.equ CRC5poly =0b00101 ;CRC5 polynomial
.equ CRC5zvysok =0b01100 ;CRC5 remainder after successful CRC5
.equ CRC16poly =0b1000000000000101 ;CRC16 polynomial
.equ CRC16zvysok =0b1000000000001101 ;CRC16 remainder after successful CRC16
.equ MAXUSBBYTES =14 ;maximum bytes in USB input message
.equ NumberOfFirstBits =10 ;how many first bits allowed be longer
.equ NoFirstBitsTimerOffset =256-12800*12/1024 ;Timeout 12.8ms (12800us) to terminate after firsts bits
.equ InitBaudRate =12000000/16/57600-1 ;UART on 57600 (for 12MHz=12000000Hz)
.equ InputBufferBegin =RAMEND128-127 ;compare of receiving shift buffer
.equ InputShiftBufferBegin =InputBufferBegin+MAXUSBBYTES ;compare of receiving buffera
.equ MyInAddressSRAM =InputShiftBufferBegin+MAXUSBBYTES
.equ MyOutAddressSRAM =MyInAddressSRAM+1
.equ OutputBufferBegin =RAMEND128-MAXUSBBYTES-2 ;compare of transmitting buffer
.equ AckBufferBegin =OutputBufferBegin-3 ;compare of transmitting buffer Ack
.equ NakBufferBegin =AckBufferBegin-3 ;compare of transmitting buffer Nak
.equ ConfigByte =NakBufferBegin-1 ;0=unconfigured state
.equ AnswerArray =ConfigByte-8 ;8 byte answer array
.equ StackBegin =AnswerArray-1 ;low reservoir (stack is big cca 68 byte)
.equ MAXRS232LENGTH =RAMEND-RAMEND128-10 ;maximum length RS232 code
.equ RS232BufferBegin =RAMEND128+1 ;compare of buffer for RS232 - receiving
.equ RS232BufferEnd =RS232BufferBegin+MAXRS232LENGTH
.equ RS232ReadPosPtr =RS232BufferBegin+0
.equ RS232WritePosPtr =RS232BufferBegin+2
.equ RS232LengthPosPtr =RS232BufferBegin+4
.equ RS232Reserved =RS232BufferBegin+6
.equ RS232FIFOBegin =RS232BufferBegin+8
.def RS232BufferFull =R1 ;flag of full RS232 buffer
.def backupbitcount =R2 ;backup bitcount register in INT0 disconnected
.def RAMread =R3 ;if reading from SRAM
.def backupSREGTimer =R4 ;backup Flag register in Timer interrupt
.def backupSREG =R5 ;backup Flag register in INT0 interrupt
.def ACC =R6 ;accumulator
.def lastBitstufNumber =R7 ;position in bitstuffing
.def OutBitStuffNumber =R8 ;how many bits to send last byte - bitstuffing
.def BitStuffInOut =R9 ;if insertion or deleting of bitstuffing
.def TotalBytesToSend =R10 ;how many bytes to send
.def TransmitPart =R11 ;order number of transmitting part
.def InputBufferLength =R12 ;length prepared in input USB buffer
.def OutputBufferLength =R13 ;length answers prepared in USB buffer
.def MyOutAddress =R14 ;my USB address (Out Packet) for update
.def MyInAddress =R15 ;my USB address (In/SetupPacket)
.def ActionFlag =R16 ;what to do in main program loop
.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 ;counter of maximum number of received bytes
.def inputbuf =R23 ;receiver register
.def shiftbuf =R24 ;shift receiving register
.def State =R25 ;state byte of status of state machine
.def RS232BufptrX =R26 ;XL register - pointer to buffer of received IR codes
.def RS232BufptrXH =R27
.def USBBufptrY =R28 ;YL register - pointer to USB buffer input/output
.def ROMBufptrZ =R30 ;ZL register - pointer to buffer of ROM data
;requirements on descriptors
.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
;descriptor types
.equ DEVICE =1
.equ CONFIGURATION =2
.equ STRING =3
.equ INTERFACE =4
.equ ENDPOINT =5
;databits
.equ DataBits5 =0
.equ DataBits6 =1
.equ DataBits7 =2
.equ DataBits8 =3
;parity
.equ ParityNone =0
.equ ParityOdd =1
.equ ParityEven =2
.equ ParityMark =3
.equ ParitySpace =4
;stopbits
.equ StopBit1 =0
.equ StopBit2 =1
;user function start number
.equ USER_FNC_NUMBER =100
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt table
;********************************************************************
.cseg
;------------------------------------------------------------------------------------------
.org 0 ;after reset
rjmp reset
;------------------------------------------------------------------------------------------
.org INT0addr ;external interrupt INT0
rjmp INT0handler
;------------------------------------------------------------------------------------------
.org URXCaddr ;receiving from serial line
push temp0
cbi UCR,RXCIE ;disable interrupt from UART receiving
sei ;enable interrupts to service USB
in temp0,UDR ;put to temp0 received data from UART
in backupSREGTimer,SREG ;backup SREG
push temp2
push temp3
lds temp2,RS232LengthPosPtr
lds temp3,RS232LengthPosPtr+1 ;determine length of RS232 code buffer
cpi temp3,HIGH(RS232BufferEnd-RS232FIFOBegin-1) ;if the buffer would overflow
brlo FIFOBufferNoOverflow ;if not overflow then write to FIFO
brne NoIncRS232BufferFull ;if buffer would overflow, then prevent of overwriting
;otherwise (if equall) still compare Lo bytes
cpi temp2,LOW(RS232BufferEnd-RS232FIFOBegin-1) ;if buffer would overflow (Lo byte)
brcc NoIncRS232BufferFull ;then prevent of overwriting
FIFOBufferNoOverflow:
push RS232BufptrX
push RS232BufptrXH
lds RS232BufptrX,RS232WritePosPtr ;set position to begin of buffer write RS232 code
lds RS232BufptrXH,RS232WritePosPtr+1 ;set position to begin of buffer write RS232 code
st X+,temp0 ;and save it to buffer
cpi RS232BufptrXH,HIGH(RS232BufferEnd+1) ;if not reached maximum of RS232 buffer
brlo NoUARTBufferOverflow ;then continue
brne UARTBufferOverflow ;check althen LSB
cpi RS232BufptrX,LOW(RS232BufferEnd+1) ;if not reached maximum of RS232 buffer
brlo NoUARTBufferOverflow ;then continue
UARTBufferOverflow:
ldi RS232BufptrX,LOW(RS232FIFOBegin) ;otherwise set position to buffer begin
ldi RS232BufptrXH,HIGH(RS232FIFOBegin) ;otherwise set position to buffer begin
NoUARTBufferOverflow:
sts RS232WritePosPtr,RS232BufptrX ;save new offset of buffer write RS232 code
sts RS232WritePosPtr+1,RS232BufptrXH ;save new offset of buffer write RS232 code
ldi temp0,1 ;increment length of RS232 buffer
add temp2,temp0
ldi temp0,0
adc temp3,temp0
sts RS232LengthPosPtr,temp2 ;save length of buffer RS232 code
sts RS232LengthPosPtr+1,temp3 ;save length of buffer RS232 code
pop RS232BufptrXH
pop RS232BufptrX
NoIncRS232BufferFull:
pop temp3
pop temp2
pop temp0
out SREG,backupSREGTimer ;restore SREG
cli ;disable interrupt because to prevent reentrant interrupt call
sbi UCR,RXCIE ;enable interrupt from receiving of UART
reti
;------------------------------------------------------------------------------------------
;********************************************************************
;* Init program
;********************************************************************
;------------------------------------------------------------------------------------------
reset: ;initialization of processor and variables to right values
ldi temp0,StackBegin ;initialization of stack
out SPL,temp0
clr XH ;RS232 pointer
clr YH ;USB pointer
clr ZH ;ROM pointer
ldi temp0,LOW(RS232FIFOBegin) ;set Low to begin of buffer
sts RS232ReadPosPtr,temp0 ;zero index of reading
sts RS232WritePosPtr,temp0 ;zero index of writing
ldi temp0,HIGH(RS232FIFOBegin) ;set High to begin of buffer
sts RS232ReadPosPtr+1,temp0 ;zero index of reading
sts RS232WritePosPtr+1,temp0 ;zero index of writing
sts RS232LengthPosPtr,YH ;zero index of length
sts RS232LengthPosPtr+1,YH ;zero index of length
clr RS232BufferFull
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -