欢迎光临~啄木鸟电子科技

软件设计

软件:TF卡 读写

如何将 数据 写入 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

用手机扫描二维码关闭
二维码