历史上的今天
今天是:2025年08月21日(星期四)
2018年08月21日 | STM32F103测试SD卡串口写入测试
2018-08-21 来源:eefocus
1.硬件引脚介绍:
本测试采用SPI模式读写SD卡,相关引脚配置如下:
片选:SD_CS->PB13,对应SD卡的1脚,低电平有效
时钟:SPI1_SCK->PA5,对应SD卡的5脚
主入从出:MISO->PA6,对应SD卡的7脚
主出从入:MOSI->PA7,对应SD卡的2脚
2.初始化步骤:
while(SD_Initialize())
{
//提示检查SD卡
}
//初始化SD卡
u8 SD_Initialize(void)
{
u8 r1; // 存放SD卡的返回值
u16 retry; // 用来进行超时计数
u8 buf[4];
u16 i;
SD_SPI_Init(); //初始化IO
SD_SPI_SpeedLow(); //设置到低速模式
for(i=0;i<10;i++)SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
retry=20;
do
{
r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
}while((r1!=0X01) && retry--);
SD_Type=0;//默认无卡
if(r1==0X01)
{
if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
{
for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
{
retry=0XFFFE;
do
{
SD_SendCmd(CMD55,0,0X01); //发送CMD55
r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
}while(r1&&retry--);
if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
{
for(i=0;i<4;i++)buf[i]=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //检查CCS
else SD_Type=SD_TYPE_V2;
}
}
}else//SD V1.x/ MMC V3
{
SD_SendCmd(CMD55,0,0X01); //发送CMD55
r1=SD_SendCmd(CMD41,0,0X01); //发送CMD41
if(r1<=1)
{
SD_Type=SD_TYPE_V1;
retry=0XFFFE;
do //等待退出IDLE模式
{
SD_SendCmd(CMD55,0,0X01); //发送CMD55
r1=SD_SendCmd(CMD41,0,0X01);//发送CMD41
}while(r1&&retry--);
}else//MMC卡不支持CMD55+CMD41识别
{
SD_Type=SD_TYPE_MMC;//MMC V3
retry=0XFFFE;
do //等待退出IDLE模式
{
r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
}while(r1&&retry--);
}
if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
}
}
SD_DisSelect();//取消片选
SD_SPI_SpeedHigh();//高速
if(SD_Type)return 0;
else if(r1)return r1;
return 0xaa;//其他错误
}
如果返回值为正常类型,则跳出初始化循环,接下来介绍该函数中的SD_SPI_Init()函数及其内部调用的SPI_Init()函数
SD_SPI_Init()配置片选引脚PB13并拉低电平设置片选有效,然后调用SPI_Init()函数,代码略
SPI_Init()函数初始化单片机的SPI1外设,具体配置为PA5.6.7三个引脚的设置
//以下是SPI模块的初始化代码,配置成主机模式,访问SD Card
SPI_InitTypeDef SPI_InitStructure;
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //选择了串行时钟的稳态:时钟悬空高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第二个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
SPI1_ReadWriteByte(0xff);//启动传输
}
3.主函数部分:
int main(void)
{
u32 total,free;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
delay_init(); //延时函数初始
LED_Init();
uart_init(19200); //串口初始化为19200
exfuns_init(); //为fatfs相关变量申请内存
mem_init(); //初始化内存池
printf ("程序初始化结束:->\r\n");
if(SD_Initialize()) //检测SD卡
{
printf ("未检测到SD卡:->\r\n");
while(SD_Initialize())
{
printf("别看着了,滚去找原因,根本没插卡:\r\n");
LED1=!LED1;
delay_ms(500);
}
LED1=1;
}
printf("SD卡正常加载:\r\n");
printf("申请内存结果:%d\r\n",(unsigned int)exfuns_init());//为fatfs相关变量申请内存,返回0成功
f_mount(fs[0],"0:",1); //挂载SD卡
exf_getfree((u8*)"0",&total,&free);//得到SD卡的总容量和剩余容量
printf("SD卡的容量是:%d\r\n",free);
printf("开始扫描串口数据**************************\r\n");
while(1) //测试使用串口输入函数名是成功的
{
if(USART_RX_STA&0x8000)//不断检测串口接收完成?这里可以去串口中断服务函数中做一些if判断来限制串口的数据格式,数据大小
{
WriteData(); //串口接收完成开始写入SD卡,该函数是自己封装的,详细请看下面介绍的SD卡写入步骤
USART_RX_STA=0; //清零标志位
}
LED0=!LED0;//程序运行指示灯
delay_ms(500);
}
}
4.向SD卡中写入的步骤:(采用库函数)
由于里面的函数都是SD驱动函数封装起来的,所以要了解底层写入过程,还要参考SD卡的通讯时序等等,不在此赘述,以后会另做记录
void WriteData(void) //一旦在串口中断标志置位,则调用该函数,开始启动创建文件的步骤:
{
//*********写入SD卡****************************
mf_mount(0,1); //注册工作区域
mf_open(fileName,4); //创建文件
mf_close();
mf_open(fileName,2); //以可写方式打开文件
mf_lseek(mf_size()); //将指针移动到文件末尾,以便追加数据
mf_write(USART_RX_BUF,142); //追加写入串口发来的数据到SD卡
mf_close(); //关闭文件
printf("WriteData()执行完毕,数据写入成功\r\n");
}
下一篇:STM32 IAP程序升级
史海拾趣
|
【招聘】奥笙北京软件招聘信息(新增深圳软件技术支持职位)(论坛xdjm优先) 由于不能删帖,只能重新发一篇招聘信息了,注意哦,论坛的兄弟姐妹们优先。论坛的兄姐妹们有意可以直接发邮件给我:jandy.wang@orpheusys.com, 奥笙公司软件部门招聘信息(北京职位) 公司简介 奥笙时代科技(北京)有限公司(www. ...… 查看全部问答> |
|
本帖最后由 jameswangsynnex 于 2015-3-3 19:57 编辑 自2009年年底起,3D在国内成为了“时尚”的代名词,继3D电影《阿凡达》、《爱丽丝梦游仙境》在中国市场赚得盆满钵满,3D似乎也成为了报刊企业的又一掘金点。 2010年4月16日,湖北《十堰晚 ...… 查看全部问答> |
|
USB型51/AVR编程器 可能大家都已经等不及了,不过“磨刀不误砍柴工”,大家还是耐心等待我们将该学习板调试完,确保大家能够更好的学习 说明:该编程器支持AT89S51/52系列单片机,还支持AVR的全系列单片机。 该编程器使 ...… 查看全部问答> |
|
程序预览没问题,拍照800*600也没问题 但是当拍照改为1024*768,1280*1024,1600*1200时,会出现无效数据,随着分辨率的增大,无效数据会越来越多。 当为1600*1200时,有效的部分好像是800*600的两倍。 感觉好像取到的数据一直是800*600,又感觉 ...… 查看全部问答> |
|
我利用MSP430控制CC1101进行两个模块之间的无线通信,发现如果地址控制字PKTCTRL1如果为0x06或0x02,通信没问题,但是如果设置为0,就只能通信几次,之后就不行了。 通信方式:模块A定时循环发送消息,模块B循环等待接收。 CC1101寄存器设置:模 ...… 查看全部问答> |
|
我最近研究WCE下的SDK编程的ToolTip的使用,发现同样的代码,VC可以正常,而EVC就是不能正常使用ToolTip,大家有任何关于WCE的ToolTip的代码不,发个来参考下。 贴上来或者发到我邮箱都可以:magic_kaoya@163.com… 查看全部问答> |




