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卡读写、时钟芯片应用
【实例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 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,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。