为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

13、U盘、IC卡、SD卡读写、时钟芯片应用

2018-08-23 31页 doc 61KB 12阅读

用户头像

is_624976

暂无简介

举报
13、U盘、IC卡、SD卡读写、时钟芯片应用13、U盘、IC卡、SD卡读写、时钟芯片应用 【实例94】读写U盘 1(变量定义和基本操作函数 (1)变量的定义 #include #define uchar unsigned char uchar volatile xdata CH372_CMD_PORT _at_ 0x7DFF; // CH372命令端口的I/O地址 uchar volatile xdata CH372_DAT_PORT _at_ 0x7CFE; //CH372数据端口的I/O地址 uchar Usb_Length; //USB数据缓冲区中数据...
13、U盘、IC卡、SD卡读写、时钟芯片应用
13、U盘、IC卡、SD卡读写、时钟芯片应用 【实例94】读写U盘 1(变量定义和基本操作函数 (1)变量的定义 #include #define uchar unsigned char uchar volatile xdata CH372_CMD_PORT _at_ 0x7DFF; // CH372命令端口的I/O地址 uchar volatile xdata CH372_DAT_PORT _at_ 0x7CFE; //CH372数据端口的I/O地址 uchar Usb_Length; //USB数据缓冲区中数据的长度 uchar Usb_Buffer[ CH372_MAX_DATA_LEN ]; // USB数据缓冲区 #define CH372_MAX_DATA_LEN 0x40 //最大数据包的长度,内部缓冲区的长度 //命令代码 #define CMD_RESET_ALL 0x05 //执行硬件复位 #define CMD_CHECK_EXIST 0x06 //测试工作状态 #define CMD_SET_USB_ID 0x12 // 设置USB厂商VID和产品PID #define CMD_SET_USB_ADDR 0x13 //设置USB地址 #define CMD_SET_USB_MODE 0x15 //设置USB工作模式 #define CMD_SET_ENDP2 0x18 //设置USB端点0的接收器 #define CMD_SET_ENDP3 0x19 //设置USB端点0的发送器 #define CMD_SET_ENDP4 0x1A //设置USB端点1的接收器 #define CMD_SET_ENDP5 0x1B //设置USB端点1的发送器 #define CMD_SET_ENDP6 0x1C //设置USB端点2/主机端点的接收器 #define CMD_SET_ENDP7 0x1D //设置USB端点2/主机端点的发送器 //命令CMD_SET_ENDP2~CMD_SET_ENDP7输入为:工作方式,位7为1则位6为同步触发位, 否则同步触发位不变,位3~位0为事务响应方: 0000~1000-就绪ACK,1101-忽略,1110-正忙NAK,1111-错误STALL #define CMD_GET_TOGGLE 0x0A //获取OUT事务的同步状态,输入:数据1AH, 输出:同步状态 #define CMD_GET_STATUS 0x22 // 获取中断状态并取消中断请求 #define CMD_UNLOCK_USB 0x23 //释放当前USB缓冲区 #define CMD_RD_USB_DATA 0x28 //从当前USB中断的端点缓冲区读取数据块, 并 释放缓冲区 #define CMD_WR_USB_DATA3 0x29 //向USB端点0的发送缓冲区写入数据块 #define CMD_WR_USB_DATA5 0x2A //向USB端点1的发送缓冲区写入数据块 #define CMD_WR_USB_DATA7 0x2B // 向USB端点2的发送缓冲区写入数据块 //操作状态 #define CMD_RET_SUCCESS 0x51 //命令操作成功 #define CMD_RET_ABORT 0x5F //命令操作失败 (2)基本操作函数 ?函数DelayMs:在CH372读写过程中需要用到毫秒延时,该函数可以满足要求,程 序代码如下。 void DelayMs(uchar n) { uchar i; unsigned int j; for(i=0; i分析
中断状态 { case USB_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 ); } else break; //长度为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 ); // 写入数据到CH372 buf ++; } while ( -- length ); } break; case USB_INT_EP2_IN: //批量端点上传成功,数据已发送成功 { WR_CH372_ CMD_PORT( CMD_UNLOCK_USB ); //释放当前USB缓冲区,收到 上 传成功中断后,必须解锁USB缓冲区,以便继续收发 break; } case USB_INT_EP1_IN:// 中断端点上传成功,中断数据发送成功 { WR_CH372_CMD_PORT ( CMD_UNLOCK_USB ); //释放当前USB缓冲区 break; } case USB_INT_EP1_OUT: //辅助端点下传成功,接收到辅助数据辅助端点可以用于计算 机 端向单片机端发送包 { WR_CH372_ CMD_PORT( CMD_UNLOCK_USB ); //释放当前USB缓冲区 break; } } } 【实例95】非接触IC卡读写 MF RC500的命令集的程序定义代码如下。 #define M500Pcd_IDLE 0x00 //取消当前命令 #define M500Pcd _WRITEE2 0x01 //写EEPROM #define M500Pcd _READE2 0x03 //读EEPROM #define M500Pcd _LOADCONFIG 0x07 //调EEPROM中保存的RC500设置 #define M500Pcd _LOADKEYE2 0x0B //将EEPROM中保存的密钥调入缓存 #define M500Pcd _AUTHENT1 0x0C //验证密钥第一步 #define M500Pcd _AUTHENT2 0x14 //验证密钥第二步 #define M500Pcd _RECEIVE 0x16 //接收数据 #define M500Pcd _LOADKEY 0x19 //传送密钥 #define M500Pcd _TRANSMIT 0x1A //发送数据 #define M500Pcd _TRANSCEIVE 0x1E //发送并接收数据 #define M500Pcd _Startup 0x3F //复位 #define M500Pcd _CALCCRC 0x12 //CRC计算 MF RC500的64个寄存器的程序定义代码如下。 // PAGE 0 #define RegPage 0x00 #define RegCommand 0x01 #define RegFIFOData 0x02 #define RegPrimaryStatus 0x03 #define RegFIFOLength 0x04 #define RegSecondaryStatus 0x05 #define RegInterruptEn 0x06 #define RegInterruptRq 0x07 // PAGE 1 #define RegPage 0x08 #define RegControl 0x09 #define RegErrorFlag 0x0A #define RegCollPos 0x0B #define RegTimerValue 0x0C #define RegCRCResultLSB 0x0D #define RegCRCResultMSB 0x0E #define RegBitFraming 0x0F // PAGE 2 #define RegPage 0x10 #define RegTxControl 0x11 #define RegCwConductance 0x12 #define RFU13 0x13 #define RegCoderControl 0x14 #define RegModWidth 0x15 #define RFU16 0x16 #define RFU17 0x17 // PAGE 3 #define RegPage 0x18 #define RegRxControl1 0x19 #define RegDecoderControl 0x1A #define RegBitPhase 0x1B #define RegRxThreshold 0x1C #define RFU1D 0x1D #define RegRxControl2 0x1E #define RegClockQControl 0x1F // PAGE 4 #define RegPage 0x20 #define RegRxWait 0x21 #define RegChannelRedundancy 0x22 #define RegCRCPresetLSB 0x23 #define RegCRCPresetMSB 0x24 #define RFU25 0x25 #define RegMfOutSelect 0x26 #define RFU27 0x27 // PAGE 5 #define RegPage 0x28 #define RegFIFOLevel 0x29 #define RegTimerClock 0x2A #define RegTimerControl 0x2B #define RegTimerReload 0x2C #define RegIRqPinConfig 0x2D #define RFU2E 0x2E #define RFU2F 0x2F // PAGE 6 #define RegPage 0x30 #define RFU31 0x31 #define RFU32 0x32 #define RFU33 0x33 #define RFU34 0x34 #define RFU35 0x35 #define RFU36 0x36 #define RFU37 0x37 // PAGE 7 #define RegPage 0x38 #define RFU39 0x39 #define RegTestAnaSelect 0x3A #define RFU3B 0x3B #define RFU3C 0x3C #define RegTestDigiSelect 0x3D #define RFU3E 0x3E #define RegTestDigiAccess 0x3F 主程序的代码如下: #define MI_OK 0 #define uchar unsigned char #define uint unsigned int //操作子函数 extern char M500PcdReset();//复位并初始化RC500 extern char M500PcdRequest(uchar req_code); //寻卡 extern char M500PcdAnticoll(uchar *snr); //防冲撞 extern char M500PcdSelect(uchar *snr); //选定一张卡 extern char M500ChangeCodeKey(uchar *uncoded,uchar *coded); //转换密钥格式 extern char M500PcdAuthKey(uchar *coded); //传送密钥 extern char M500PcdAuth(uchar auth_mode,uchar block,uchar *snr); //验证密钥 extern char M500PcdRead(uchar addr,uchar *readdata); //读块 extern char M500PcdWrite(uchar addr,uchar *writedata); //写块 extern char M500PcdHalt(void); //卡休眠 extern char M500PcdReadE2(uint startaddr,uchar length,uchar *readdata); //读RC500-EEPROM数据 extern char M500PcdWriteE2(uint startaddr,uchar length,uchar *writedata); //写数据到 RC500-EEPROM extern char M500PcdConfigRestore();//恢复RC500出厂设置 //Mifarel卡命令字 #define PICC_REQIDL 0x26 //寻天线区内未进入休眠状态的卡 #define PICC_REQALL 0x52 //寻天线区内全部卡 #define PICC_ANTICOLL1 0x93 //防冲撞 #define PICC_AUTHENT1A 0x60 //验证A密钥 #define PICC_AUTHENT1B 0x61 //验证B密钥 #define PICC_READ 0x30 //读块 #define PICC_WRITE 0xA0 //写块 #define PICC_DECREMENT 0xC0 //减值 #define PICC_INCREMENT 0xC1 //加值 #define PICC_RESTORE 0xC2 //存储 #define PICC_TRANSFER 0xB0 //传送 #define PICC_HALT 0x50 //休眠 void main (void) { int count; idata struct TranSciveBuffer{uchar MFCommand; uchar MFLength; uchar MFData[16]; }MFComData; M500PcdReset() ; //初始化RC500 M500PcdReadE2(startaddr, length, readdata); //读MF RC500的系列号并存贮它 For (count = 0 ;count<100 ;count + + ) { status = M500PcdRequest(req_code); //发送请求代码给卡,并等待应答 if (status= =MI_OK) status= M500PcdAnticoll(serialno); //防冲撞 if (status= =MI_OK) status= M500PcdSelect(serialno); //选择一个指定的卡 if (status= =MI_OK) status = M500ChangeCodeKey(uncoded, coded); //转换密钥格式 if (status= =MI_OK) status =M500PcdAuthKey(coded); //传送密钥 if (status= =MI_OK) status = M500PcdAuth(auth_mode, block, serialno); //验证密钥,鉴定卡 if (status= =MI_OK) status = M500PcdRead(addr, blockdata); //读卡 for ( i=0;i<16;i + + ) *(blockdata+i) = MFComData.MFData[i]; ; if (status==MI_OK) status= M500PcdWrite(addr, blockdata); //写卡 } } 【实例96】SD卡读写 1(SD卡读写的操作子函数 (1)延时函数delay void delay(uint n) { while(--n) { } } (2)函数SD_read_byte uchar SD_read_byte (void) { uchar Byte = 0; uchar i = 0; DI=1; for (i=0; i<8; i++) { CLK=0; delay(4); Byte=Byte<<1; //先接收最高位。 if (DO==1) { Byte |= 0x01; } CLK=1; delay(4); } return (Byte); } (3)函数SD_write_byte void SD_write_byte(uchar Byte) { uchar i ; CLK=1; for (i =0; i<8; i++) { if (Byte&0x80) //先写高位的。 { DI=1; } else { DI=0; } CLK=0; delay(4); Byte=Byte<<1; CLK=1; delay(4); } DI=1; } (4)函数SD_write_command uchar SD_write_command (uchar *cmd) { uchar tmp = 0xff; uint Timeout = 0; uchar a; SD_Disable(); SD_write_byte(0xFF); //发送8个时钟 SD_Enable(); for(a = 0;a<0x06;a++) //发送6字节命令 { SD_write_byte(cmd[a]); } while (tmp == 0xff) { tmp = SD_read_byte(); //等待回复 if (Timeout++ > 500) { break; //超时返回 } } return(tmp); //返回响应信息 } 2(SD卡的上电初始化 SD卡的上电初始化程序代码如下。 //预定义变量 sbit CS=P2^0; sbit CLK= P2^3; sbit DI=P2^1; sbit DO=P2^2; #define SD_Disable() CS=1 //片选关 #define SD_Enable() CS=0 //片选开 uchar SD_read_byte (void) //读出一字节 void SD_write_byte(uchar Byte) //写入一个字节 uchar SD_write_command (uchar *cmd)//发送SD命令 uchar SD_write_sector(ulong addr,uchar *Buffer)//写单块,512字节 void SD_read_block(uchar *cmd,uchar *Buffer,uint Bytes) //读N个字节数据放在缓冲区内 uchar SD_read_sector (ulong addr,uchar *Buffer)//读单块,512字节 uchar SD_init () //sd 初始化 void delay(uint n) //延时微秒 //SD初始化 uchar SD_init ( ) { uchar Timeout = 0; uchar b; uchar idata CMD[ ] = {0x40,0x00,0x00,0x00,0x00,0x95}; //CMD0 for (i=0;i<0x0f;i++) { SD_write_byte(0xff); //延迟74个以上的时钟 } SD_Enable( ); //开片选 //发送CMD0 while(SD_write_command (CMD) !=0x01) //等于1示复位成功 { if (Timeout++ > 5) { return(1); } } //发送 CMD1 Timeout = 0; CMD[0] = 0x41; CMD[5] = 0xFF; //CMD1 while( SD_write_command (CMD) !=0) { if (Timeout++ > 100) { return(2); } } SD_Disable(); return(0); //成功 } 2(对SD卡的读写操作 写SD卡的程序代码如下。 //写单块,512字节 uchar SD_write_sector (ulong addr,uchar *Buffer)//参数:写扇区的地址,数据的指针 { uchar tmp; uint a ; uchar idata cmd[] = {0x58,0x00,0x00,0x00,0x00,0xFF}; //CMD24 addr = addr << 9; //addr = addr * 512 cmd[1] = ((addr & 0xFF000000) >>24 ); cmd[2] = ((addr & 0x00FF0000) >>16 ); cmd[3] = ((addr & 0x0000FF00) >>8 ); tmp = SD_write_command (cmd); //发送命令cmd24,写单块512字节 if (tmp != 0) { return(tmp); } for (a=0;a<100;a++) { SD_read_byte(); } SD_write_byte(0xFE); //发送读、写命令后都要发送起始令牌FEH for ( a=0;a<512;a++) { SD_write_byte(*Buffer++); } //写入CRC字节 SD_write_byte(0xFF); SD_write_byte(0xFF); while (SD_read_byte() != 0xff) { }; SD_Disable(); return(0); } 读SD卡的程序代码如下。 //读N个字节数据放在缓冲区内 void SD_read_block(uchar *cmd,uchar *Buffer,uint N_Byte)//参数:命令、缓冲区指针、长度 { uint a; if (SD_write_command (cmd) != 0) { return; } while (SD_read_byte( )!= 0xfe) { }; for (a=0;a< N_Byte;a++) { *Buffer++ = SD_read_byte(); } //取走CRC字节 SD_read_byte(); SD_read_byte(); SD_Disable(); return; } //读一个扇区数据 uchar SD_read_sector (ulong addr,uchar *Buffer)//参数:扇区地址,缓冲区指针 { uchar idata cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; //读单块 addr = addr << 9; //addr = addr * 512 cmd[1] = ((addr & 0xFF000000) >>24 ); cmd[2] = ((addr & 0x00FF0000) >>16 ); cmd[3] = ((addr & 0x0000FF00) >>8 ); SD_read_block(cmd,Buffer,512); return(0); } 【实例97】高精度实时时钟芯片的应用 1(变量及SD2300A的相关定义 //变量定义 #define true 1 #define false 0 //SD2300A相关定义 sbit SDA=P2^0; sbit SCL=P2^1; uchar data1,data2,data3,data4; uchar date[7]; //日期数组 //date[6]=year,date[5]=month,date[4]=day,date[3]=week, // date[2]=hour,date[1]=minute,date[0]=second //SD2300A函数名 void I2C_delay(void); bit I2C_Start(void); void I2C_Stop(void); void I2C_Ack(void); void I2C_NoAck(void); bit I2C_Read_ACK(void); void I2C_Send_Byte(uchar demand); uchar I2C_Receive_Byte(void); void I2C_Read_Date(void); void Delay(uint nn); void I2C_Write_Date(void); 2(SD2300A的相关子程序 2(1)函数_delay的程序代码如下。 IC 2void Delay(void) IC { nop();nop();nop();nop(); } 2(2)函数_Start IC bit I2C_Start(void) { SDA=1; SCL=1; I2C_delay(); if(!SDA) return false;//SDA线为低电平则总线忙,退出 SDA=0; I2C_delay(); while(SDA) return false;//SDA线为高电平则总线出错,退出 SCL=0; I2C_delay(); 2 return true;//开启总线 IC } 2(3)函数_Stop IC void I2C_Stop(void) { SDA=0; SCL=0; I2C_delay(); SCL=1; I2C_delay(); SDA=1; } 2(4)函数_Ack IC void I2C_Ack(void) { SDA=0; SCL=0; I2C_delay(); SCL=1; I2C_delay(); SCL=0; } 2(5)函数_NoAck IC void I2CNoAck(void) { SDA=1; SCL=0; I2C_delay(); SCL=1; I2C_delay(); SCL=0; } 2_Read_Ack (6)函数IC bit I2C_Read_ACK(void) //返回true=1时有ACK, true=0时无ACK { uchar errtime=255; SCL=0; SDA=1; I2C_delay(); SCL=1; I2C_delay(); while(SDA) { errtime--; if(!errtime) SCL=0; return false; } SCL=0; return true; } 22(7)函数_Send_Byte和_Receive_Byte ICIC//向SD2300A发送一个字节 void I2C_Send_Byte(uchar demand) //数据从高位到低位发送 { uchar i=8; while(i--) { SCL=0; nop(); SDA=(bit)(demand&0x80); demand<<=1; I2C_delay(); SCL=1; I2C_delay(); } SCL=0; } //从SD2300A读入一字节 uchar I2C_Receive_Byte(void) //数据从高位到低位 { uchar i=8; uchar ddata=0; SDA=1; while(i--) { ddata<<=1; //数据从高位开始读取 SCL=0; I2C_delay(); SCL=1; I2C_delay(); //从高位开始 ddata|=SDA;ddata<<=1 if(SDA) { ddata|=0x01; } } SCL=0; return ddata; } 2(8)函数_Read_Date IC void I2C_Read_Date(void) { uchar n; I2C_Start(); I2C_Stop(); I2C_Start(); I2C_Send_Byte(0x64); //从年开始读取数据 I2C_Read_ACK(); I2C_Send_Byte(0x00); I2C_Read_ACK(); I2C_Start(); I2C_Send_Byte(0x65); I2C_Read_ACK(); for(n=0;n<7;n++) { date[n]= I2C_Receive_Byte(); if (n!=6) //最后一个数据不应答 { I2C_Ack(); } } I2CNoAck(); I2C_Stop(); } 2(9)函数_Write_Date IC void I2C_Write_Date(void) { I2C_Start(); I2C_Stop(); I2C_Start(); I2C_Send_Byte(0x64); I2C_Read_ACK(); I2C_Send_Byte(0xf0);//设置写起始地址 I2C_Read_ACK(); I2C_Send_Byte(0x20);//二十四小时制 I2C_Read_ACK(); I2C_Send_Byte(0x01);//秒 I2C_Read_ACK(); I2C_Send_Byte(0x01);//分 I2C_Read_ACK(); I2C_Send_Byte(0x08);//时 I2C_Read_ACK(); I2C_Send_Byte(0x01);//日 I2C_Read_ACK(); I2C_Send_Byte(0x01);//周 I2C_Read_ACK(); I2C_Send_Byte(0x07);//月 I2C_Read_ACK(); I2C_Send_Byte(0x04);//年 I2C_Read_ACK(); I2C_Send_Byte(0x00);//清零数字调整寄存器 I2C_Read_ACK(); I2C_Stop(); } (10)函数Delay void Delay(uint nn) { while(nn--); } 3(主程序 main() { P2=0xFF; I2C_Write_Date(); while(1) { I2C_Read_Date(); Delay(250); Delay(250); } }
/
本文档为【13、U盘、IC卡、SD卡读写、时钟芯片应用】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索