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

📄 usb_ch9.asm

📁 基于PIC16C745单片机的一个USB样例程序
💻 ASM
📖 第 1 页 / 共 4 页
字号:
;                            Software License Agreement
;
; The software supplied herewith by Microchip Technology Incorporated (the "Company")
; for its PICmicro(r) Microcontroller is intended and supplied to you, the Company's
; customer, for use solely and exclusively on Microchip PICmicro Microcontroller
; products.
;
; The software is owned by the Company and/or its supplier, and is protected under
; applicable copyright laws. All rights are reserved. Any use in violation of the
; foregoing restrictions may subject the user to criminal sanctions under applicable
; laws, as well as to civil liability for the breach of the terms and conditions of
; this license.
;
; THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, WHETHER EXPRESS,
; IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE
; COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
; CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;
; ###############################################################################
;	filename:	USB_CH9.ASM
;
; Implements the chapter 9 enumeration commands for Microchip's
; PIC16C7x5 parts.
;
; ###############################################################################
;
;	Author(s):		Dan Butler and Reston Condit
;	Company:		Microchip Technology Inc
;
;	Revision:		1.25
;	Date:			23 April 2002
;	Assembled using:	MPASM 2.80
;################################################################################
;
;	include files:
;		P16C765.inc	Rev 1.00
;		usb_defs.inc	Rev 1.00
;
;################################################################################

#include <p16C765.inc>
#include "usb_defs.inc"

	errorlevel -302		; supress "register not in bank0, check page bits" message

#define	SHOW_ENUM_STATUS

unbanked	udata_shr		; these will get assigned to unbanked RAM (0x70-0x7F)
temp			res	1	; short term temp register used in Get Interface
GPtemp			res	1	; temporary storage location used in Get and PutEPn

	global	BufferDescriptor
	global	BufferData
	global	temp
	global	temp2
	global	EP0_maxLength
	global	EP0_start
	global	EP0_end

bank2	udata
BufferDescriptor	res	3
BufferData		res	8
USBMaskedInterrupts	res	1
USB_Curr_Config		res	1
USB_status_device	res	1	; status of device
USB_dev_req		res	1
USB_address_pending	res	1
USBMaskedErrors		res	1
PIDs 			res	1
EP0_start		res	2	; pointer to first byte of data to send
EP0_end			res	1	; pointer to last byte of data to send
EP0_maxLength		res	1
temp2			res	1
bufindex		res	1
USB_Interface		res	3	; allow 3 interfaces to have alternate endpoints
inner			res	1
outer			res	1
dest_ptr		res	1	; used in buffer copies for Get and
source_ptr		res	1	; Put USB calls
hid_dest_ptr		res	1	; used in buffer copies for HIDSetReport
hid_source_ptr		res	1	;
counter			res	1
bytecounter		res	1	; saved copy that will be returned in W
RP_save			res	1	; save bank bits while copying buffers
IS_IDLE			res	1
USB_USTAT		res	1	; copy of the USTAT register before clearing TOK_DNE

	global	USB_Curr_Config 
	global	USB_status_device
	global	USB_dev_req
	global	USB_Interface

#ifdef	COUNTERRORS
USB_PID_ERR		res	2	; 16 bit counters for each error condition
USB_CRC5_ERR		res	2
USB_CRC16_ERR		res	2
USB_DFN8_ERR		res	2
USB_BTO_ERR		res	2
USB_WRT_ERR		res	2
USB_OWN_ERR		res	2
USB_BTS_ERR		res	2
#endif

	extern	Config_desc_index
	extern	Descriptions
	extern	string_index
	extern	String0
	extern	String0_end
	extern	ClassSpecificRequest
	extern	Check_Class_Specific_IN
	extern	Get_Report_Descriptor
	extern	Get_HID_Descriptor
	extern	DeviceDescriptor
	extern	StringDescriptions

; **********************************************************************
; This section contains the functions to interface with the main 
; application.
; **********************************************************************

interface	code

; **********************************************************************
; GETEP1 and GETEP2
;
; Note:  These functions are macros defined in usb_defs.inc.
;        To save ROM, delete the instances below that you will not need.
;
; Enter with buffer pointer in IRP+FSR.  
; Each function checks the UOWNs bit for the particular OUT endpoint, 
; and copies the buffer if available.  Upon completion of the function, 
; the bank bits are restored to the state they were in when this 
; function was entered.
;
; Returns the bytecount in the W register and return status in the carry
; bit as follows:
; 0 - no buffer available,
; 1 - Buffer copied and buffer made available for next transfer.
; 
; The number of bytes moved is returned in W reg.
; **********************************************************************

	GETEP1		; create instance of GETEP1
	GETEP2		; create instance of GETEP2

; **********************************************************************
; PUTEP1 and PUTEP2
;
; Note:  These functions are macros defined in usb_defs.inc.
;        To save ROM, delete the instances below that you will not need.
;
; Enter with bytecount in W and buffer pointer in IRP+FSR.
;
; Tests the UOWNs bit for the IN side of the specified Endpoint.
; If we own the buffer, the buffer pointed to by the FSR is copied
; to the EPn IN buffer, then the UOWNs bit is set so the data will be
; TX'd next time polled.  
;
; Returns the status in the carry bit as follows:
; 1 - buffer available and copied.
; 0 - buffer not available (try again later)
; **********************************************************************

	PUTEP1		; create instance of PUTEP1
	PUTEP2		; create instance of PUTEP2

; *********************************************************************
; Stall Endpoint.
; Sets the stall bit in the Endpoint Control Register.  For the control
; Endpoint, this implements a Protocol stall and is used when the request
; is invalid for the current device state.  For non-control Endpoints,
; this is a Functional Stall, meaning that the device needs outside 
; intervention and trying again later won't help until it's been serviced.
; enter with endpoint # to stall in Wreg.
; *********************************************************************
StallUSBEP
	bsf	STATUS,IRP	; select banks 2/3
	andlw	0x03		; try to keep things under control
	addlw	low UEP0	; add address of endpoint control reg
	movwf	FSR
	bsf	INDF,EP_STALL	; set stall bit
	return

; *********************************************************************
; Unstall Endpoint.
; Sets the stall bit in the Endpoint Control Register.  For the control
; Endpoint, this implements a Protocol stall and is used when the request
; is invalid for the current device state.  For non-control Endpoints,
; this is a Functional Stall, meaning that the device needs outside 
; intervention and trying again later won't help until it's been serviced.
; enter with endpoint # to stall in Wreg.
; *********************************************************************
UnstallUSBEP
	bsf	STATUS,IRP	; select banks 2/3
	andlw	0x03		; try to keep things under control
	addlw	low UEP0	; add address of endpoint control reg
	movwf	FSR
	bcf	INDF,EP_STALL	; clear stall bit
	return

; *********************************************************************
; CheckSleep
; Checks the USB Sleep bit.  If the bit is set, the
; Endpoint, this implements a Protocol stall and is used when the request
; is invalid for the current device state.  For non-control Endpoints,
; this is a Functional Stall, meaning that the device needs outside 
; intervention and trying again later won't help until it's been serviced.
; enter with endpoint # to stall in Wreg.
; *********************************************************************
CheckSleep
	global	CheckSleep

	banksel	IS_IDLE
	btfss	IS_IDLE,0	; test the bus idle bit
	return

#ifdef	SHOW_ENUM_STATUS
	banksel	PORTB
	bsf	PORTB,4		; turn on LED 4 to indicate we've gone to sleep
	banksel	UIR
#endif
	bsf 	STATUS,RP0  	; point to bank 3
	bcf 	UIR,ACTIVITY
	bsf 	UIE,ACTIVITY	; enable the USB activity interrupt
	bsf 	UCTRL,SUSPND	; put USB regulator and transciever in low power state
	sleep   		; and go to sleep
	nop
	bcf 	UCTRL,SUSPND
	bcf 	UIR,UIDLE
	bsf 	UIE,UIDLE
	bcf 	UIR,ACTIVITY
	bcf 	UIE,ACTIVITY
#ifdef	SHOW_ENUM_STATUS
	banksel	PORTB
	bcf	PORTB,4		; turn off LED 4 to indicate we're back.
#endif
	return

; *********************************************************************
; Remote Wakeup
; Checks USB_status_device to see if the host enabled Remote Wakeup
; If so, perform Remote wakeup and disable remote wakeup feature
; It is called by PortBChange.  
; *********************************************************************
RemoteWakeup
	global	RemoteWakeup

	banksel USB_status_device	; BANK 2
	btfss	USB_status_device, 1
	return

	bsf	STATUS, RP0	; BANK 3
	bcf	UCTRL, SUSPND
	bsf	UIE,UIDLE
	bcf	UIR,UIDLE
	bcf	UIE,ACTIVITY
	bcf	UIR,ACTIVITY
	bsf	UCTRL, 2	; RESUME SIGNALING
	bcf	STATUS, RP0	; BANK 2

	clrf	inner
	movlw	0x80
	movwf	outer
	pagesel RemoteLoop
RemoteLoop	
	decfsz	inner, f
	goto	RemoteLoop
	decfsz	outer, f
	goto	RemoteLoop

	bsf	STATUS, RP0	; BANK 3
	bcf	UCTRL, 2	; Clear Resume bit
	return


; *********************************************************************
; USB Soft Detach
; Clears the DEV_ATT bit, electrically disconnecting the device to the bus.
; This removes the device from the bus, then reconnects so it can be
; re-enumerated by the host.  This is envisioned as a last ditch effort
; by the software.
; *********************************************************************
SoftDetachUSB
	global	SoftDetachUSB

	banksel	UCTRL
	bcf	UCTRL,DEV_ATT	; clear attach bit

	bcf	STATUS, RP0	; bank 2
    
	clrf	outer
	clrf	inner
	pagesel	SoftDetachLoop
SoftDetachLoop
	incfsz	inner,f
	goto	SoftDetachLoop
	incfsz	outer,f
	goto	SoftDetachLoop

	pagesel	InitUSB
	call	InitUSB		; reinitialize the USB peripheral
	return


; ******************************************************************
; Init USB
; Initializes the USB peripheral, sets up the interrupts
; ******************************************************************
InitUSB
	global	InitUSB

	banksel	USWSTAT
	clrf	USWSTAT		; default to powered state
	movlw	0x01		; mask all USB interrupts except reset
	movwf	UIE
	clrf	UIR		; clear all USB Interrupt flags
	movlw	0x08		; Device attached
	movwf	UCTRL

	bcf	STATUS, RP0	; bank 2
	clrf	USB_Curr_Config
	movlw	1
	movwf	USB_status_device
	clrf	USB_Interface
	clrf	USB_Interface+1
	clrf	USB_Interface+2
	movlw	0xFF
	movwf	USB_dev_req	; no device requests in process
#ifdef COUNTERRORS
	clrf	USB_PID_ERR
	clrf	USB_PID_ERR+1
	clrf	USB_CRC5_ERR
	clrf	USB_CRC5_ERR+1
	clrf	USB_CRC16_ERR
	clrf	USB_CRC16_ERR+1
	clrf	USB_DFN8_ERR
	clrf	USB_DFN8_ERR+1
	clrf	USB_BTO_ERR
	clrf	USB_BTO_ERR+1
	clrf	USB_WRT_ERR
	clrf	USB_WRT_ERR+1
	clrf	USB_OWN_ERR
	clrf	USB_OWN_ERR+1
	clrf	USB_BTS_ERR
	clrf	USB_BTS_ERR+1
#endif

	banksel PIR1		; bank 0
	bcf 	PIR1,USBIF	; clear the USB flag
	bsf 	STATUS,RP0	; bank 1
	bsf 	PIE1,USBIE	; enable usb interrupt
	bsf  	INTCON, 6	; enable global and peripheral interrupts
	bsf 	INTCON, 7
#ifdef SHOW_ENUM_STATUS
	bcf 	STATUS,RP0	; select bank 0
	bsf 	PORTB,0		; set bit zero to indicate Powered status
#endif
	return


; ******************************************************************
; DeInit USB
; Shuts down the USB peripheral, clears the interrupt enable.
; ******************************************************************
DeInitUSB
	global	DeInitUSB

	banksel	UCTRL
	bcf	UCTRL,DEV_ATT	; D+/D- go high Z
	bsf	UCTRL,SUSPND	; Place USB module in low power mode.

	clrf	USWSTAT		; set device state to powered.

	bcf	STATUS,RP1	; select bank 1
	bcf	PIE1,USBIE	; clear USB interrupt enable
#ifdef SHOW_ENUM_STATUS
	bcf 	STATUS,RP0
	movlw	0x01
	movwf	PORTB		; clear all lights except powered
	bsf 	STATUS,RP0
#endif
	return


core	code
; The functions below are the core functions
; ******************************************************************
; USB interrupt triggered, Why?
; Poll the USB interrupt flags to find the cause.
; ******************************************************************
ServiceUSBInt
	global	ServiceUSBInt

	banksel	UIR
	movf	UIR,w		; get the USB interrupt register
	andwf	UIE,w		; mask off the disabled interrupts
	bcf	STATUS, RP0	; BANK 2
	pagesel	ExitServiceUSBInt
	btfsc	STATUS,Z	; is there any unmasked interrupts?
	goto	ExitServiceUSBInt	; no, bail out.

	movwf	USBMaskedInterrupts
	pagesel	TokenDone
	btfsc	USBMaskedInterrupts,ACTIVITY
	call	USBActivity
	pagesel	USBReset
	btfsc	USBMaskedInterrupts,USB_RST
	call	USBReset
	pagesel	USBStall
	btfsc	USBMaskedInterrupts,TOK_DNE	; was it a token done?
	call	TokenDone
	pagesel	USBActivity
	btfsc	USBMaskedInterrupts,STALL
	call	USBStall
	pagesel	USBError
	btfsc	USBMaskedInterrupts,UERR
	call	USBError
	pagesel	USBSleep
	btfsc	USBMaskedInterrupts,UIDLE
	call	USBSleep
	pagesel	ServiceUSBInt
	goto	ServiceUSBInt

ExitServiceUSBInt
	banksel	PIR1
	bcf 	PIR1,USBIF
	return

; ******************************************************************
; USB Reset interrupt triggered (SE0)
; initialize the Buffer Descriptor Table,
; Transition to the DEFAULT state,
; Set address to 0
; enable the USB
; ******************************************************************
USBReset	; START IN BANK2

	clrf	USB_Curr_Config
	clrf	IS_IDLE
	bsf 	STATUS, RP0	; bank 3
	
	bcf 	UIR,TOK_DNE	; hit this 4 times to clear out the
	bcf 	UIR,TOK_DNE	; USTAT FIFO
	bcf 	UIR,TOK_DNE
	bcf 	UIR,TOK_DNE
	
	movlw	0x8
	movwf	BD0OBC
	movlw	USB_Buffer	; Endpoint 0 OUT gets a buffer
	movwf	BD0OAL		; set up buffer address
	movlw	0x88		; set owns bit (SIE can write)
	movwf	BD0OST
	
	movlw	USB_Buffer+8	; Endpoint 0 IN gets a buffer
	movwf	BD0IAL		; set up buffer address
	movlw	0x08		; Clear owns bit (PIC can write)
	movwf	BD0IST

	clrf	UADDR		; set USB Address to 0
	clrf	UIR		; clear all the USB interrupt flags
	banksel	PIR1		; switch to bank 0
	bcf 	PIR1,USBIF

; Set up the Endpoint Control Registers.  The following patterns are defined
; ENDPT_DISABLED - endpoint not used
; ENDPT_IN_ONLY  - endpoint supports IN transactions only
; ENDPT_OUT_ONLY - endpoint supports OUT transactions only
; ENDPT_CONTROL  - Supports IN, OUT and CONTROL transactions - Only use with EP0
; ENDPT_NON_CONTROL - Supports both IN and OUT transactions

	banksel	UEP0
	movlw	ENDPT_CONTROL
	movwf	UEP0		; endpoint 0 is a control pipe and requires an ACK
	
	movlw	0x3B		; enable all interrupts except activity
	movwf	UIE
	
	movlw	0xFF		; enable all error interrupts

⌨️ 快捷键说明

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