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

📄 main.c

📁 usb cdc 类(AVR MCU 实现 CDC)
💻 C
字号:
/* Name: main.c * Project: AVR USB driver for CDC interface on Low-Speed USB
 *          - Simple parallel port controller * Author: Osamu Tamura * Creation Date: 2007-01-06 * Tabsize: 4 * Copyright: (c) 2007 by Recursion Co., Ltd. * License: Proprietary, free under certain conditions. See Documentation. *
 */#include <string.h>#include <avr/io.h>#include <avr/interrupt.h>#include <avr/pgmspace.h>#include <avr/wdt.h>#include "usbdrv.h"#include "oddebug.h"#define HW_CDC_PACKET_SIZE1      1
#define HW_CDC_PACKET_SIZE2      8
/* Size of bulk transfer packets. The standard demands 8 bytes, but we may * be better off with less. Try smaller values if the communication hangs. */
enum {    SEND_ENCAPSULATED_COMMAND = 0,    GET_ENCAPSULATED_RESPONSE,    SET_COMM_FEATURE,    GET_COMM_FEATURE,    CLEAR_COMM_FEATURE,    SET_LINE_CODING = 0x20,    GET_LINE_CODING,    SET_CONTROL_LINE_STATE,    SEND_BREAK};
static PROGMEM char deviceDescrCDC[] = {    /* USB device descriptor */    18,         /* sizeof(usbDescriptorDevice): length of descriptor in bytes */    USBDESCR_DEVICE,        /* descriptor type */    0x01, 0x01,             /* USB version supported */    0x02,                   /* device class: CDC */    0,                      /* subclass */    0,                      /* protocol */    8,                      /* max packet size */    USB_CFG_VENDOR_ID,      /* 2 bytes */    0xe1, 0x05,             /* 2 bytes: shared PID for CDC-ACM devices */    USB_CFG_DEVICE_VERSION, /* 2 bytes */    1,                      /* manufacturer string index */    2,                      /* product string index */    0,                      /* serial number string index */    1,                      /* number of configurations */};static PROGMEM char configDescrCDC[] = {   /* USB configuration descriptor */    9,          /* sizeof(usbDescrConfig): length of descriptor in bytes */    USBDESCR_CONFIG,    /* descriptor type */    67,    0,          /* total length of data returned (including inlined descriptors) */    2,          /* number of interfaces in this configuration */    1,          /* index of this configuration */    0,          /* configuration name string index */#if USB_CFG_IS_SELF_POWERED    USBATTR_SELFPOWER,  /* attributes */#else    USBATTR_BUSPOWER,   /* attributes */#endif    USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */    /* interface descriptor follows inline: */    9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */    USBDESCR_INTERFACE, /* descriptor type */    0,          /* index of this interface */    0,          /* alternate setting for this interface */    USB_CFG_HAVE_INTRIN_ENDPOINT,   /* endpoints excl 0: number of endpoint descriptors to follow */    USB_CFG_INTERFACE_CLASS,    USB_CFG_INTERFACE_SUBCLASS,    USB_CFG_INTERFACE_PROTOCOL,    0,          /* string index for interface */    /* CDC Class-Specific descriptor */    5,           /* sizeof(usbDescrCDC_HeaderFn): length of descriptor in bytes */    0x24,        /* descriptor type */    0,           /* header functional descriptor */    0x10, 0x01,    4,           /* sizeof(usbDescrCDC_AcmFn): length of descriptor in bytes */    0x24,        /* descriptor type */    2,           /* abstract control management functional descriptor */    0x02,        /* SET_LINE_CODING,    GET_LINE_CODING, SET_CONTROL_LINE_STATE    */    5,           /* sizeof(usbDescrCDC_UnionFn): length of descriptor in bytes */    0x24,        /* descriptor type */    6,           /* union functional descriptor */    0,           /* CDC_COMM_INTF_ID */    1,           /* CDC_DATA_INTF_ID */    5,           /* sizeof(usbDescrCDC_CallMgtFn): length of descriptor in bytes */    0x24,        /* descriptor type */    1,           /* call management functional descriptor */    3,           /* allow management on data interface, handles call management by itself */    1,           /* CDC_DATA_INTF_ID */    /* Endpoint Descriptor */    7,           /* sizeof(usbDescrEndpoint) */    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */    0x83,        /* IN endpoint number 3 */    0x03,        /* attrib: Interrupt endpoint */    8, 0,        /* maximum packet size */    100,         /* in ms */    /* Interface Descriptor  */    9,           /* sizeof(usbDescrInterface): length of descriptor in bytes */    USBDESCR_INTERFACE,           /* descriptor type */    1,           /* index of this interface */    0,           /* alternate setting for this interface */    2,           /* endpoints excl 0: number of endpoint descriptors to follow */    0x0A,        /* Data Interface Class Codes */    0,    0,           /* Data Interface Class Protocol Codes */    0,           /* string index for interface */    /* Endpoint Descriptor */    7,           /* sizeof(usbDescrEndpoint) */    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */    0x01,        /* OUT endpoint number 1 */    0x02,        /* attrib: Bulk endpoint */    HW_CDC_PACKET_SIZE1, 0,        /* maximum packet size 8->6 */    0,           /* in ms */    /* Endpoint Descriptor */    7,           /* sizeof(usbDescrEndpoint) */    USBDESCR_ENDPOINT,  /* descriptor type = endpoint */    0x81,        /* IN endpoint number 1 */    0x02,        /* attrib: Bulk endpoint */    HW_CDC_PACKET_SIZE2, 0,        /* maximum packet size */
    0,           /* in ms */};
uchar usbFunctionDescriptor(usbRequest_t *rq){uchar *p = NULL, len = 0;    if(rq->wValue.bytes[1] == USBDESCR_DEVICE){        p = (uchar *)deviceDescrCDC;        len = sizeof(deviceDescrCDC);    }else{  /* must be config descriptor */        p = (uchar *)configDescrCDC;        len = sizeof(configDescrCDC);    }
    usbMsgPtr = p;    return len;}static uchar    requestType;static uchar	modeBuffer[7];static uchar    intr3Status;    /* used to control interrupt endpoint transmissions *//* ------------------------------------------------------------------------- *//* ----------------------------- USB interface ----------------------------- *//* ------------------------------------------------------------------------- */uchar usbFunctionSetup(uchar data[8]){usbRequest_t    *rq = (void *)data;    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */        if( rq->bRequest==GET_LINE_CODING || rq->bRequest==SET_LINE_CODING ){            requestType	= rq->bRequest;            return 0xff;        /*    GET_LINE_CODING -> usbFunctionRead()    */        /*    SET_LINE_CODING -> usbFunctionWrite()    */        }        if(rq->bRequest == SET_CONTROL_LINE_STATE){            /* Report serial state (carrier detect). On several Unix platforms,             * tty devices can only be opened when carrier detect is set.             */            intr3Status = 2;        }    }    return 0;}/*---------------------------------------------------------------------------*//* usbFunctionRead                                                           *//*---------------------------------------------------------------------------*/uchar usbFunctionRead( uchar *data, uchar len ){
    if(requestType == GET_LINE_CODING){		memcpy( data, modeBuffer, 7 );    	return 7;
	}    return 0;   /* error -> terminate transfer */}/*---------------------------------------------------------------------------*//* usbFunctionWrite                                                          *//*---------------------------------------------------------------------------*/uchar usbFunctionWrite( uchar *data, uchar len ){    if(requestType == SET_LINE_CODING){		/* enforce DATA0 token for next transfer */
		USB_SET_DATATOKEN1(USBPID_DATA1);

		memcpy( modeBuffer, data, 7 );    	return 1;
	}
    return 1;   /* error -> accept everything until end */}
static uchar tos, val;
static uchar rcnt, tcnt;
static char rbuf[8], tbuf[8];
void usbFunctionWriteOut( uchar *data, uchar len ){    /*    usb -> rs232c:  request   */    do {

		//	delimiter?
		if( *data>0x20 ) {
			char	c;

			c	= *data++;
			if( 'a'<=c && c<='z' )
				c	-= 0x20;	//	to upper case
			rbuf[rcnt++]	= c;
			rcnt	&= 7;
			rbuf[rcnt]	= 0;
			continue;
		}
		if( rcnt==0 )
			continue;

		//	command
		if( rcnt==1 ) {
			uchar	*addr	= (uchar *)((unsigned int)tos);
			uchar	h, x;

			switch( rbuf[0] ) {
			case '?':	//	get
						x	= *addr;
						h	= x >> 4;
						tbuf[tcnt++]	= h<=9? h+'0':h-10+'A';
						h	= x & 0x0f;
						tbuf[tcnt++]	= h<=9? h+'0':h-10+'A';
						break;
			case '=':	//	set
						cli();
						*addr	= val;
						sei();
						break;
			case '&':	//	and & set
						cli();
						*addr	&= val;
						sei();
						break;
			case '|':	//	or & set
						cli();
						*addr	|= val;
						sei();
						break;
			case '^':	//	xor & set
						cli();
						*addr	^= val;
						sei();
						break;
			default:	//	error
						tbuf[tcnt++]	= '!';
			}
			tbuf[tcnt++]	= '\r';
			tbuf[tcnt++]	= '\n';
			rcnt	= 0;
			continue;
		}

		//	number
		if( rcnt==2 ) {
			val	= tos;
			tos	= rbuf[0]<='9'? rbuf[0]-'0':rbuf[0]-'A'+10;
			tos	= (tos<<4) | (rbuf[1]<='9'? rbuf[1]-'0':rbuf[1]-'A'+10);
			rcnt	= 0;
			continue;
		}

		//	sfr
		if( rcnt>=4 ) {
			val	= tos;
#if defined URSEL
			tos	= 0x30 + ( 'D' - rbuf[--rcnt] ) * 3;
#else
			tos	= 0x20 + ( rbuf[--rcnt] - 'A' ) * 3;
#endif
			rbuf[rcnt]	= 0;
			if( !strcmp(rbuf,"PIN") )
				tos	+= 0;
			else if( !strcmp(rbuf,"DDR") )
				tos	+= 1;
			else if( !strcmp(rbuf,"PORT") )
				tos	+= 2;
			else
				tos	= 0x20;		//	error
			rcnt	= 0;
		}	} while(--len);}static void hardwareInit(void){uchar    i, j;    /* activate pull-ups except on USB lines */    USB_CFG_IOPORT   = (uchar)~((1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT));    /* all pins input except USB (-> USB reset) */#ifdef USB_CFG_PULLUP_IOPORT    /* use usbDeviceConnect()/usbDeviceDisconnect() if available */    USBDDR    = 0;    /* we do RESET by deactivating pullup */    usbDeviceDisconnect();#else    USBDDR    = (1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT);#endif    j = 0;    while(--j){          /* USB Reset by device only required on Watchdog Reset */        i = 0;        while(--i);      /* delay >10ms for USB reset */    }#ifdef USB_CFG_PULLUP_IOPORT    usbDeviceConnect();#else    USBDDR    = 0;      /*  remove USB reset condition */#endif
}int main(void){
    wdt_enable(WDTO_1S);    odDebugInit();    hardwareInit();    usbInit();
	rcnt	= 0;
	tcnt	= 0;
    sei();    for(;;){    /* main event loop */        wdt_reset();        usbPoll();
        /*    rs232c -> usb:  transmit char        */        if( usbInterruptIsReady() ) {
			static uchar sendEmptyFrame = 1;
            if( tcnt || sendEmptyFrame ) {	            usbSetInterrupt((uchar *)tbuf, tcnt);				/* send an empty block after last data block to indicate transfer end */
                sendEmptyFrame = tcnt==HW_CDC_PACKET_SIZE2? 1:0;
			}
            tcnt	= 0;        }

        /* We need to report rx and tx carrier after open attempt */        if(intr3Status != 0 && usbInterruptIsReady3()){            static uchar serialStateNotification[10] = {0xa1, 0x20, 0, 0, 0, 0, 2, 0, 3, 0};            if(intr3Status == 2){                usbSetInterrupt3(serialStateNotification, 8);            }else{                usbSetInterrupt3(serialStateNotification+8, 2);            }            intr3Status--;        }    }
    return 0;}

⌨️ 快捷键说明

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