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

📄 usbhidio.asm

📁 单片机开发的与PC机的VB程序通信方法
💻 ASM
📖 第 1 页 / 共 4 页
字号:
     mov [interrupt_mask],A
     ipret Global_Interrupt

;----------------------------------------------------------------------
;GPIO interrupt
;Can be configured to trigger when a port bit toggles.
;Unused here.
;----------------------------------------------------------------------

GPIO_ISR:
     push A
     push X

     pop X
     mov [interrupt_mask],A
     ipret Global_Interrupt

;----------------------------------------------------------------------
;Endpoint 1 ISR
;Endpoint 1 can do IN (device to host) transfers only.
;This interrupt triggers when the host acknowledges
;receiving data from Endpoint 1.
;The ISR toggles the data 0/1 bit for the next transaction and
;sets the EnableRespondToIN bit so the chip will respond to the 
;next poll of the endpoint.
;----------------------------------------------------------------------

USB_EP1_ISR:
     push A
;Toggle the data 0/1 bit so it's correct for the next transaction.
     iord USB_EP1_TX_Config  
     xor A,40h
;The interrupt clears the EnableRespondToIN bit (bit 7) in the TX Config.
;Set this bit to 1 so data will go out on the next poll.
;This will ensure that a ReadFile API call in a Windows application
;won't hang, waiting for the device to send something.
     or A, 92h
     iowr USB_EP1_TX_Config
;Enable interrupts and return.
     mov A, [interrupt_mask]
     ipret Global_Interrupt

;----------------------------------------------------------------------
; Reset processing
; Triggers on Reset or "reserved" interrupt.
;To be safe, initialize everything.
;----------------------------------------------------------------------

Reset:
;Place the data stack pointer at the lowest address of Endpoint 0's buffer.
;This keeps the stack from writing over the USB buffers.
;The USB buffers are in high RAM;
;the data stack pointer pre-decrements on a Push instruction.

     mov A, Endpoint_0
     swap A, dsp

;Initialize to FFh
     mov A, 0ffh
     iowr Port0_Data                 ; output ones to port 0
     iowr Port1_Pullup               ; disable port 1 pullups
                                     ; select rising edge interrupts
     iowr Port1_Isink0               ; maximum isink current Port1 bit 0
     iowr Port1_Isink1               ; maximum isink current Port1 bit 1
     iowr Port1_Isink2               ; maximum isink current Port1 bit 2
     iowr Port1_Isink3               ; maximum isink current Port1 bit 3

;Initialize to 00h
     mov A, 0h
     iowr Port1_Data                 ; output zeros to port 1
     iowr Port0_Interrupt            ; disable port 0 interrupts
     iowr Port0_Pullup               ; enable port 0 pullups
     iowr Port0_Isink0               ; minimum sink current Port0 bit 0
     iowr Port0_Isink1               ; minimum sink current Port0 bit 1
     iowr Port0_Isink2               ; minimum sink current Port0 bit 2
     iowr Port0_Isink3               ; minimum sink current Port0 bit 3
     iowr Port0_Isink4               ; minimum sink current Port0 bit 4
     iowr Port0_Isink5               ; minimum sink current Port0 bit 5
     iowr Port0_Isink6               ; minimum sink current Port0 bit 6
     iowr Port0_Isink7               ; minimum sink current Port0 bit 7
     mov [Endpoint1_Byte0],A
     mov [Endpoint1_Byte1],A
     mov [Endpoint1_Byte2],A
     mov [endpoint_stall], A
     mov [remote_wakeup_status], A
     mov [configuration_status], A
     mov [loop_temp], A
     mov [start_send], A
     iowr Watchdog                   ; clear watchdog timer

;Initialize values to transmit at Endpoint 1.
;     mov A, A5h
;     mov [Data_Byte0], A
;     mov A, F0h
;     mov [Data_Byte1], A

;Enable Port 1, bit 0 interrupts.
;     mov A, 01h
;     iowr Port1_Interrupt
;
;Test what kind of reset occurred: bus or watchdog?
     iord Status_Control
;Was it a bus reset?
     and A, USBReset
;If yes, jump to handle it.
     jnz BusReset
     iord Status_Control
;Was it a watchdog reset?
     and A, WatchDogReset
;If no, continue to wait for a bus reset
     jz suspendReset
;
;Watchog reset:
;A watchdog reset means that the watchdog timer
;wasn't cleared for 8.192 milliseconds.
;Wait for a bus reset to bring the system alive again.
;Enable 1-millisecond interrupt only
     mov A, TIMER_ONLY
     mov [interrupt_mask],A
     iowr Global_Interrupt
;Wait for a bus reset.
WatchdogHandler:
     jmp WatchdogHandler

suspendReset:
;Return to suspend mode to wait for a USB bus reset.
     mov A, 09h
     iowr Status_Control
     nop
     jmp suspendReset

BusReset:
;Clear all reset bits.
;Set bit 0 (the run bit).
     mov A, RunBit
     iowr Status_Control
;Set up for enumeration (Endpoint 0 and 1-millisecond interrupts enabled)
     mov A, ENUMERATE_MASK
     mov [interrupt_mask],A
     iowr Global_Interrupt

wait:
;Wait until configured.
     iord USB_EP1_TX_Config
     cmp A, 0
;Clear the watchdog timer
     iowr Watchdog
;If not configured, continue to wait.
     jz wait     
;When configured, initialize loop_temp.
;Loop_temp adds a delay in the start of transmission of data.
;The chip will respond to the first IN packet no sooner than 
;230 milliseconds after enumeration is complete.
;The delay was included in Cypress' joystick code to prevent problems 
;that occurred when power cycled off and on or the joystick was plugged
;in before the host powered up.
;I've left it in because it does no harm and 
;other hardware might have similar behavior.
;During the delay, the chip sends a NAK in response to any IN packet.
     mov A, 0ffh
     mov [loop_temp], A

;Enable endpoint 1
     iord USB_EP1_TX_Config
     or A, 92h
     iowr USB_EP1_TX_Config

;======================================================================
; The main program loop.
;======================================================================

main:
;Find out if the loop_temp delay has timed out.
;Loop_temp =0 if not timed out, FFh if timed out.
     mov A, [loop_temp]
     cmp A, 0Ah
;If no, don't enable transmitting.
     jnc no_set
;If yes, enable transmitting.
     mov A, 01h
     mov [start_send], A
no_set:
;Clear the watchdog timer.
;This has to be done at least once every 8 milliseconds!
     iowr Watchdog
     iord Port0_Data
nochange:
     jmp main

;----------------------------------------------------------------------
;The Endpoint 0 ISR supports the control endpoint.
;This code enumerates and configures the hardware.
;It also responds to Set Report requests that receive data from the host.
;----------------------------------------------------------------------

USB_EP0_ISR:
     push A
     iord USB_EP0_RX_Status
;Has a Setup packet been received?
     and A, 01h
;If no, find out if it's an OUT packet.
     jz check_for_out_packet
;If yes, handle it.
;Disable Endpoint 0 interrupts.
     mov A,[interrupt_mask]
     and A, 0F7h
     mov [interrupt_mask], A
     iowr Global_Interrupt
;Find out what the Setup packet contains and handle the request.
      call StageOne
;Re-enable Endpoint 0 interrupts.
     mov A, [interrupt_mask]
     or A, 08h
     mov [interrupt_mask], A
     jmp done_with_packet

check_for_out_packet:
     iord USB_EP0_RX_Status
;Is it an OUT packet?
     and A, 02h
;If no, ignore it.
     jz done_with_packet
;If yes, process the received data.
;Disable Endpoint 0 interrupts.
     mov A,[interrupt_mask]
     and A, 0F7h
     mov [interrupt_mask], A
     iowr Global_Interrupt

;For debugging: set Port 0, bit 1 to show that we're here.
;    iord Port0_Data
;    or a, 2
;    iowr Port0_Data

;Read the first byte in the buffer
     mov a, [Endpoint_0]
;For debugging: if the first byte =12h, bring Port 0, bit 0 high
;      cmp a, 12h
;      jnz not_a_match
;      iord Port0_Data
;      or a, 4
;      iowr Port0_Data

not_a_match:

;For debugging, add 1 to each byte read
;and copy the bytes to RAM.
;These bytes will be sent back to the host.

      push X
      ;data_count holds the number of bytes left to read.
      ;X holds the index of the address to read
      ;and the index of the address to store the received data.
      ;Initialize the X register.
      mov X, 0
      
      Get_Received_Data:
      ;Find out if there are any bytes to read.
      mov A, 0
      cmp A, [data_count]
      ;Jump if nothing to read.
      jz DoneWithReceivedData

      ;Get a byte.
      mov A, [X + Endpoint_0]
      ;For debugging, increment the received value.
      ;(Endpoint 1 will send it back to the host.)
      ;If the value is 255, reset to 0.
      ;Otherwise increment it.
      cmp A, 255
      jz ResetToZero
      inc A
      jmp NewValueSet
      ResetToZero:
      mov A, 0
      NewValueSet:
      ;Save the value.
      mov [X + Data_Byte0], A
      ;Decrement the number of bytes left to read.
      dec [data_count]
      ;Increment the address to read.
      inc X
      ;Do another
      jmp Get_Received_Data

      DoneWithReceivedData:
      pop X

;For debugging, set Port 0 to match the value written.
;     iowr Port0_Data

;Handshake by sending a 0-byte data packet.
call Send0ByteDataPacket

done_with_packet:
;Re-enable Endpoint 0 interrupts.
     mov A,[interrupt_mask]
     or A, 08h
     mov [interrupt_mask], A
     ipret Global_Interrupt

;========================================================================
;Control transfers
;========================================================================

;------------------------------------------------------------------------
;Control transfer, stage one.
;Find out whether the request is a standard device or HID-class request,
;the direction of data transfer, 
;and whether the request is to a device, interface, or endpoint.
;(from Table 9.2 in the USB spec)
;------------------------------------------------------------------------

StageOne:
;Clear the Setup flag
     mov A, 00h
     iowr USB_EP0_RX_Status
;Set the StatusOuts bit to cause auto-handshake after receiving a data packet.
     mov A, 8
     iowr USB_Status_Control
;bmRequestType contains the request.
      mov A, [bmRequestType]

;Standard device requests. From the USB spec.
; host to device requests
        cmp A, 00h
        jz RequestType00                 ; bmRequestType = 00000000 device
;       cmp A, 01h                       *** not required ***  
;       jz RequestType01                 ; bmRequestType = 00000001 interface
        cmp A, 02h              
        jz RequestType02                 ; bmRequestType = 00000010 endpoint
        cmp A, 80h             
; device to host requests
        jz RequestType80                 ; bmRequestType = 10000000 device
        cmp A, 81h
        jz RequestType81                 ; bmRequestType = 10000001 interface
        cmp A, 82h
        jz RequestType82                 ; bmRequestType = 10000010 endpoint

;HID-class device requests. From the HID spec
; host to device requests
        cmp A, 21h
        jz RequestType21                 ; bmRequestType = 00100001 interface
        cmp A, 22h                       ; *** not in HID spec ***
        jz RequestType22                 ; bmRequestType = 00100010 endpoint
; device to host requests
        cmp A, A1h
        jz RequestTypeA1                 ; bmRequestType = 10100001 interface

; Stall unsupported requests
SendStall:
      mov A, A0h
     iowr USB_EP0_TX_Config
      ret

;----------------------------------------------------------------------
;Control transfer, stage two
;Find out which request it is.
;----------------------------------------------------------------------

;Host to device with device as recipient
RequestType00:

;The Remote Wakeup feature is disabled on reset.
     mov A, [bRequest]     ; load bRequest
; Clear Feature                      bRequest = 1
     cmp A, clear_feature
     jz ClearRemoteWakeup 
; Set Feature                     bRequest = 3
     cmp A, set_feature
     jz SetRemoteWakeup

; Set the device address to a non-zero value.
; Set Address                     bRequest = 5
     cmp A, set_address
     jz SetAddress

; Set Descriptor is optional.
; Set Descriptor                bRequest = 7    *** not supported ***

;If wValue is zero, the device is not configured.
;The only other legal value for this firmware is 1.
;Set Configuration           bRequest = 9
    cmp A, set_configuration
    jz SetConfiguration

;Stall unsupported requests.
    jmp SendStall


;Host to device with interface as recipient    *** not required ***
; RequestType01:
;        mov A, [bRequest]       ; load bRequest

; There are no interface features defined in the spec.
; Clear Feature                 bRequest = 1    *** not supported ***
; Set Feature                   bRequest = 3    *** not supported ***

; Set Interface is optional.
; Set Interface                 bRequest = 11   *** not supported ***

;Stall unsupported requests.
;        jmp SendStall

;Host to device with endpoint as recipient
RequestType02:
     mov A, [bRequest]     ; load bRequest

; The only standard feature defined for an endpoint is endpoint_stalled.
; Clear Feature               bRequest = 1
     cmp A, clear_feature
     jz ClearEndpointStall
; Set Feature               bRequest = 3
     cmp A, set_feature
     jz SetEndpointStall
 
;Stall unsupported functions.
    jmp SendStall

;Device to host with device as recipient
RequestType80:

⌨️ 快捷键说明

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