如何将 数据 写入 TF 外置存储卡?
为什么要写到 外置存储卡? 容量大,适合大批量数据读写;价格实在!
所以 有必要:
#include <iostm8s103k3.h> #define uchar unsigned char #define uint unsigned int #define SPI_CS PF_ODR_ODR4 //SD卡的片选 // 命令:手册上查找; uchar CMD0[] = {0x40,0x00,0x00,0x00,0x00,0x95}; // SPI 初始化指令 uchar CMD1[] = {0x41,0x00,0x00,0x00,0x00,0xff}; // SPI 激活指令 uchar CMD17[]= {0x51,0x00,0x00,0x00,0x00,0xff}; // 单块读指令 uchar CMD24[]= {0x58,0x00,0x00,0x00,0x00,0xff}; // 单块写指令 int flag; // 初始化 时钟; void CLK_Init(void) { CLK_CKDIVR = 0x07; //16M/128 } // 初始化 IO 口; /**************************** PF4 片选; PC7 MISO; PC6 MOSI PC5 SCK *****************************/ void GPIO_Init(void) { PC_CR2 = 0x60; // 0110 0000 PC_DDR = 0x60; // 0110 0000 PC_CR1 = 0x80; // 1000 0000 PF_DDR = 0x10; // 0001 0000 PF_CR1 = 0x10; // 0001 0000 } // 初始化 SPI; void SPI_Init(void) { SPI_CR1 = 0x3f; // 0011 1111 ( 16M/128/256; MSB 先;主设备;CPOL = 1;CPHA= 0 ) SPI_CR2 = 0x03; // 0000 0011 ( 双线全双工;软件管理;无CRC ) SPI_CR1 |= 0x40; // 开启 SPI 总线 0100 0000 } // 简单延时 void delay(int x) { int i,j; for(i=x;i>0;i--) for(j=10;j>0;j--); } // SPI 写 数据; void Write_Byte(uchar x) // 向SD卡写入一个字节的数据 { SPI_DR = x; // 数据写入 while(!(SPI_SR&0x02)); // 等待发送完成,缓冲为空 } // SPI 读 数据; uchar Read_Byte(void) // 从SD卡读出一个字节的数据 { uchar c; SPI_DR=0xff; // 拉高MOSI电位八个时钟 while(!(SPI_SR&0x02)); // 等待发送完成,缓冲为空 while(!(SPI_SR&0x01)); // 等待接收缓冲区非空 c = SPI_DR; //数据读回 return c; } void delay1(void) //延时80个时钟周期 { int i; for(i=10;i>0;i--) {SPI_DR = 0xff; while(!(SPI_SR&0x02));// 等待发送完成,缓冲为空 } } void Write_CMD(uchar *cmd) { int i; SPI_CS = 1; Read_Byte(); // 延时 SPI_CS = 0; // 写入 指令的 6 个 字节; for(i=0; i<6; i++) { SPI_DR = (*cmd++); while(!(SPI_SR & 0x02));// 等待发送完成,缓冲为空 } } // SD 卡 初始化 void SD_SPI_Init(void) // { int c, r; while(flag==0) // CMD0 书写成功判断 { delay1(); // 时钟延时 74 个时钟 周期; Write_CMD(CMD0); // 书写指令CMD0 Read_Byte(); //读取 第一个 应答信号 ;忽略第一个应答 c = 0; while((c<100)&&(r!=0x01)) { c++; // 读回应答信号100次 r = Read_Byte(); } if(r==0x01) flag = 1; //当我们得到满意应答之后,跳出循环 } flag =0; // 初始化 成功之后 操作; while(flag ==0) { c = 0; Write_CMD(CMD1); // 书写指令CMD1 Read_Byte(); // 忽略第一个应答信号 while((c<100)&&(r!=0x00)) // 返因字节 00; { c++; // 读回应答信号100次 r = Read_Byte(); } if (r ==0) flag =1; //当我们得到满意应答之后,跳出循环 } } // SD卡, 写单块 函数 void W_Block(char x) { uint n; int r; uchar c; flag = 0; while(flag==0) { { Write_CMD(CMD24); // 书写指令CMD24 单块写指令 Read_Byte(); // 忽略第一个应答信号 r = 0xff; while((c<100)&&(r!=0x00)) // 返回信号 0; { r = Read_Byte(); // 进行100次地循环 c++; } if(r==0x00) flag=1; // 当我们得到满意应答之后,跳出循环 } for(n =0; n<100; n++) Read_Byte(); // 100和时钟的延时 Write_Byte(0xfe); // 书写发送 数据起始标志 for(n=0; n<512; n++) Write_Byte(x); // 对一个快进行书写 Write_Byte(0xff); // 发送2字节的 CRC 校验码;两个字节的伪CRC Write_Byte(0xff); r = Read_Byte(); // 等待 接收 响应; while(Read_Byte() == 0xff); // 证明数据被接受 SPI_CS = 1; // 拉高片选 } } //SD卡, 单块读函数 void R_Block(uchar *dat) { int c; unsigned int count; uchar r; c = 0; flag =0; while(flag==0) { Write_CMD(CMD17); // 读块:指令 17 单块读指令 r = Read_Byte(); // 忽略第一个应答信号 do { r = Read_Byte(); c++; //循环100次进行应答信号的读取 }while((r!=0)&&(c<100)); // 应当信号 为 0 ,表示,命令 写入; c=0; if(r ==0) flag =1; //直到得到满意的应答 } while (Read_Byte() != 0xfe); // 读取接收数据的起始 (看是否为 FE ) for (count=0; count<512; count++) // 接收 512 个 字节; { *dat++ = Read_Byte(); // 放到这个 dat 数组中; count++; // 循环读回512次 } count = 0; Read_Byte(); // 伪CRC Read_Byte(); // 伪CRC SPI_CS=1; // 拉高片选操作结束 } void main() { uchar R_Buffer[512]={0x00}; // 读数据缓冲 CLK_Init(); // 时钟初始化 GPIO_Init(); // 端口初始化 SPI_Init(); // 单片机 SPI总线 初始化 SD_SPI_Init(); // SD卡 的 SPI模式 初始化 W_Block(16); // 写入 数据 16 delay(100); // 延时 R_Block(R_Buffer); // 读回 数据 while(1); }
联系人:客服在线
手机:全工:13903011251
电话:李R:13530006400
邮箱:729986191@qq.com
地址: GUANGDONG PROVINCE