完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
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卡 } 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=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=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 ("程序初始化结束:->rn"); if(SD_Initialize()) //检测SD卡 { printf ("未检测到SD卡:->rn"); while(SD_Initialize()) { printf("别看着了,滚去找原因,根本没插卡:rn"); LED1=!LED1; delay_ms(500); } LED1=1; } printf("SD卡正常加载:rn"); printf("申请内存结果:%drn",(unsigned int)exfuns_init());//为fatfs相关变量申请内存,返回0成功 f_mount(fs[0],"0:",1); //挂载SD卡 exf_getfree((u8*)"0",&total,&free);//得到SD卡的总容量和剩余容量 printf("SD卡的容量是:%drn",free); printf("开始扫描串口数据**************************rn"); 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()执行完毕,数据写入成功rn"); } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1817 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1631 浏览 1 评论
1103 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
739 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1692 浏览 2 评论
1951浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
754浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
586浏览 3评论
605浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
568浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-30 10:24 , Processed in 0.954929 second(s), Total 77, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号