【实例94】读写U盘1.变量定义和基本操作函数(1)变量的定义#includereg51.h#defineucharunsignedcharucharvolatilexdataCH372_CMD_PORT_at_0x7DFF;//CH372命令端口的I/O地址ucharvolatilexdataCH372_DAT_PORT_at_0x7CFE;//CH372数据端口的I/O地址ucharUsb_Length;//USB数据缓冲区中数据的长度ucharUsb_Buffer[CH372_MAX_DATA_LEN];//USB数据缓冲区#defineCH372_MAX_DATA_LEN0x40//最大数据包的长度,内部缓冲区的长度//命令代码#defineCMD_RESET_ALL0x05//执行硬件复位#defineCMD_CHECK_EXIST0x06//测试工作状态#defineCMD_SET_USB_ID0x12//设置USB厂商VID和产品PID#defineCMD_SET_USB_ADDR0x13//设置USB地址#defineCMD_SET_USB_MODE0x15//设置USB工作模式#defineCMD_SET_ENDP20x18//设置USB端点0的接收器#defineCMD_SET_ENDP30x19//设置USB端点0的发送器#defineCMD_SET_ENDP40x1A//设置USB端点1的接收器#defineCMD_SET_ENDP50x1B//设置USB端点1的发送器#defineCMD_SET_ENDP60x1C//设置USB端点2/主机端点的接收器#defineCMD_SET_ENDP70x1D//设置USB端点2/主机端点的发送器//命令CMD_SET_ENDP2~CMD_SET_ENDP7输入为:工作方式,位7为1则位6为同步触发位,否则同步触发位不变,位3~位0为事务响应方:0000~1000-就绪ACK,1101-忽略,1110-正忙NAK,1111-错误STALL#defineCMD_GET_TOGGLE0x0A//获取OUT事务的同步状态,输入:数据1AH,输出:同步状态#defineCMD_GET_STATUS0x22//获取中断状态并取消中断请求#defineCMD_UNLOCK_USB0x23//释放当前USB缓冲区#defineCMD_RD_USB_DATA0x28//从当前USB中断的端点缓冲区读取数据块,并释放缓冲区#defineCMD_WR_USB_DATA30x29//向USB端点0的发送缓冲区写入数据块#defineCMD_WR_USB_DATA50x2A//向USB端点1的发送缓冲区写入数据块#defineCMD_WR_USB_DATA70x2B//向USB端点2的发送缓冲区写入数据块//操作状态#defineCMD_RET_SUCCESS0x51//命令操作成功#defineCMD_RET_ABORT0x5F//命令操作失败(2)基本操作函数①函数DelayMs:在CH372读写过程中需要用到毫秒延时,该函数可以满足要求,程序代码如下。voidDelayMs(ucharn){uchari;unsignedintj;for(i=0;in;i++)for(j=0;j1000;j++)j=j;}②函数Delayµs:在读写命令的过程中经常要用到微秒的延时,该函数可以用来调用,其程序代码如下。voidDelay(uchari){while(i)i--;}③函数WR_CH372_CMD_PORT该函数用以向CH372命令端口写命令数据,周期不小于4µS,如果太快则延时,其程序代码如下。voidWR_CH372_CMD_PORT(ucharcmd){Delay(2);CH372_CMD_PORT=cmd;Delay(2);//至少延时2µS}④WR_CH372_DAT_PORT该函数用以向CH372数据端口写数据,周期不小于1.5µS,如果太快则延时,其程序代码如下。voidWR_CH372_DAT_PORT(uchard){CH372_DAT_PORT=d;Delay(2);}⑤RD_CH372_DAT_PORT该函数用以从CH372命令端口读数据,周期不小于1.5µS,如果太快则延时,其程序代码如下。ucharRD_CH372_DAT_PORT(){Delay(2);return(CH372_DAT_PORT);}2.系统初始化CH372初始化的程序代码如下。voidCH372_init(){uchari,j;WR_CH372_CMD_PORT(CMD_CHECK_EXIST);//测试CH372是否工作正常WR_CH372_CMD_PORT(0x68);//写入测试数据i=~0x68;//返回数据应该是测试数据取反j=RD_CH372_CMD_PORT();if(j!=i)//CH372不正常{for(i=80;i!=0;i--){CH372_CMD_PORT=CMD_RESET_ALL;//多次重复发送命令,执行硬件复位Delay(2);}CH372_CMD_PORT=0;DelayMs(100);//延时100ms}//设置USB工作模式WR_CH372_CMD_PORT(CMD_SET_USB_MODE);DELAY(2);WR_CH372_CMD_PORT(2);//设置为使用内部固件工作模式DELAY(4);for(i=100;i!=0;i--)//等待操作成功{if(RD_CH372_CMD_PORT()==CMD_RET_SUCCESS)//设备初始化成功break;}}3.读写接口函数及中断服务函数(1)CH372的读取数据函数CH372_RD_EP2voidCH372_RD_EP2(){ucharlength;ucharbuf;WR_CH372_CMD_PORT(CMD_RD_USB_DATA);//从当前USB中断的端点缓冲区读取数据块,并释放缓冲区Usb_Length=RD_CH372_DAT_PORT();//首先读取后续数据长度length=Usb_Length;if(length){//接收数据放到缓冲区中buf=Usb_Buffer;//指向缓冲区do{*buf=RD_CH372_DAT_PORT();buf++;}while(--length);}else;//长度为0,没有数据{WR_CH372_CMD_PORT(CMD_SET_ENDP7);//设置USB端点2的批量上传端点WR_CH372_DAT_PORT(0X0E);//同步触发位不变,设置USB端点2忙,返回NAK}}(2)CH372的写数据函数CH372_WR_EP2voidCH372_RD_EP2(){ucharlength;ucharbuf;WR_CH372_CMD_PORT(CMD_WR_USB_DATA7);//向USB端点2的发送缓冲区写入数据块length=Usb_Length;WR_CH372_DAT_PORT(length);//首先写入后续数据长度if(length){//将缓冲区中的数据发出buf=Usb_Buffer;//指向缓冲区do{WR_CH372_DAT_PORT(*buf);//写入数据到CH372buf++;}while(--length);break;}}(3)CH372的中断服务函数CH372_Int0CH372的中断服务函数的程序代码如下:voidCH372_Int0(void)interrupt0using1{ucharIntStatus;ucharlength;ucharbuf;WR_CH372_CMD_PORT(CMD_GET_STATUS);//获取中断状态并取消中断请求IntStatus=RD_CH372_DAT_PORT();//获取中断状态IE0=0;//清中断标志switch(IntStatus)//分析中断状态{caseUSB_INT_EP2_OUT://批量端点2下传成功,接收到数据{WR_CH372_CMD_PORT(CMD_RD_USB_DATA);//从当前USB中断的端点缓冲区读取数据块,并释放缓冲区Usb_Length=RD_CH372_DAT_PORT();//首先读取后续数据长度length=Usb_Length;if(length){//接收数据放到缓冲区中buf=Usb_Buffer;//指向缓冲区do{*buf=RD_CH372_DAT_PORT();buf++;}while(--length);}elsebreak;//长度为0,没有数据//下面是回传数据WR_CH372_CMD_PORT(CMD_WR_USB_DATA7);//向USB端点2的发送缓冲区写入数据块length=Usb_Length;WR_CH372_DAT_PORT(length);//首先写入后续数据长度if(length){//将缓冲区中的数据发出buf=Usb_Buffer;//指向缓冲区do{WR_CH372_DAT_PORT(*buf);//写入数据到CH372buf++;}while(--length);}break;caseUSB_INT_EP2_IN://批量端点上传成功,数据已发送成功{WR_CH372_CMD_PORT(CMD_UNLOCK_USB);//释放当前USB缓冲区,收到上传成功中断后,必须解锁USB缓冲区,以便继续收发break;}caseUSB_INT_EP1_IN://中断端点上传成功,中断数据发送成功{WR_CH372_CMD_PORT(CMD_UNLOCK_USB);//释放当前USB缓冲区break;}caseUSB_INT_EP1_OUT://辅助端点下传成功,接收到辅助数据辅助端点可以用于计算机端向单片机端发送包{WR_CH372_CMD_PORT(CMD_UNLOCK_USB);//释放当前USB缓冲区break;}}}【实例95】非接触IC卡读写MFRC500的命令集的程序定义代码如下。#defineM500Pcd_IDLE0x00//取消当前命令#defineM500Pcd_WRITEE20x01//写EEPROM#defineM500Pcd_READE20x03//读EEPROM#defineM500Pcd_LOADCONFIG0x07//调EEPROM中保存的RC500设置#defineM500Pcd_LOADKEYE20x0B//将EEPROM中保存的密钥调入缓存#defineM500Pcd_AUTHENT10x0C//验证密钥第一步#defineM500Pcd_AUTHENT20x14//验证密钥第二步#defineM500Pcd_RECEIVE0x16//接收数据#defineM500Pcd_LOADKEY0x19//传送密钥#defineM500Pcd_TRANSMIT0x1A//发送数据#defineM500Pcd_TRANSCEIVE0x1E//发送并接收数据#defineM500Pcd_Startup0x3F//复位#defineM500Pcd_CALCCRC0x12//CRC计算MFRC500的64个寄存器的程序定义代码如下。//PAGE0#defineRegPage0x00#defineRegCommand0x01#defineRegFIFOData0x02#defineRegPrimaryStatus0x03#defineRegFIFOLength0x04#defineRegSecondaryStatus0x05#defineRegInterruptEn0x06#defineRegInterruptRq0x07//PAGE1#defineRegPage0x08#defineRegControl0x09#defineRegErrorFlag0x0A#defineRegCollPos0x0B#defineRegTimerValue