STM32CubeMx,keil,正点原子STM32F103,SD卡。
选择4线传输。
2.2.1 参数配置:
在 Parameter Settings 进行具体参数配置。
1、Clock transition on which the bit capture is made: Rising transition(上升沿)。主时钟 SDIOCLK 产生 CLK 引脚时钟有效沿选择,可选上升沿或下降沿,它设定 SDIO 时钟控制寄存器(SDIO_CLKCR)的 NEGEDGE 位的值,一般选择设置为上升沿。
2、SDIO Clock divider bypass: Disable。时钟分频旁路使用,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 BYPASS 位。如果使能旁路,SDIOCLK 直接驱动 CLK 线输出时钟;如果禁用,使用 SDIO_CLKCR 寄存器的 CLKDIV 位值分频 SDIOCLK,然后输出到 CLK 线。一般选择禁用时钟分频旁路。这里选择失能。后面选择分频得到时钟频率。
**3、SDIO Clock output enable when the bus is idle: Disable the power save for the clock。**节能模式选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 PWRSAV 位的值。如果使能节能模式,CLK 线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能 CLK 线输出时钟。这里功耗要求不大,所以失能它。
**4、SDIO hardware flow control: The hardware control flow is disabled。**硬件流控制选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 HWFC_EN 位的值。硬件流控制功能可以避免 FIFO 发送上溢和下溢错误。
5、SDIOCLK clock divide factor: 6。时钟分频系数,它设定 SDIO_CLKCR 寄存器的 CLKDIV 位的值,设置 SDIOCLK 与 CLK 线输出时钟分频系数:CLK 线时钟频率=SDIOCLK/([CLKDIV+2])。
SD卡在初始化时频率要求低于400KHz,初始化过后可以改为高频率,最高一般位25MHz。所以我们在上面选择分频时,要注意频率不能超过25MHz,SDIOCLK为72MHz.
选择循环模式(Circular),方向内存到外设(Memory)。
Priority:
当发生多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通 道编号,编号越低优先权越高,比如通道 0 高于通道 1。在大容量产品和互联型产品中,DMA1 控制器拥有高于 DMA2 控制器的优先级。
1、Mode:
Normal 表示单次传输,传输一次后终止传输。
Circular 表示循环传输,传输完成后又重新开始继续传输,不断循环永不停止。(选择这个)
2、Increment Address:
Peripheral 表示外设地址自增。
Memory 表示内存地址自增。(选择这个)
3Data Width:
Byte 一个字节。
Half Word 半个字,等于两字节。
Word 一个字,等于四字节。(选择这个)
1、Locale and Namespace Parameters:
CODE_PAGE(Code page on target): Simplified Chinese GBK(DBCS,OEM,Windows) 支持简体中文编码
USE_LFN(Use Long Filename): Enabled with dynamic working buffer on the STACK 支持长文件名,并指定使用栈 空间为缓冲区。
其他保持不变。
缓存工作区为什么放在栈?其实fatfs提供了三个选项:BSS,STACK , HEAP,根据个人情况选一个。在BSS上启用带有静态工作缓冲区的LFN,不能动态分配。如果选择了HEAP(堆)且自己有属于自己的malloc就去重写ff_memalloc ff_memfree函数。如果是库的malloc就不需要。一般都选择使用STACK(栈),能动态分配。当使用堆栈作为工作缓冲区时,请注意堆栈溢出。
2、Physical Drive Parameters:
VOLUMES(Logical drivers): 2 指定物理设备数量,这里设置为 1,预留 SD 卡
MAX_SS(Maximum Sector Size): 512 指定扇区大小的最大值。SD 卡扇区大小一般都为 512 字节,SPI Flash 芯片扇区大小一般设置为 4096 字节,所以需要把 _MAX_SS 改为 512
MIN_SS(Minimum Sector Size): 512 指定扇区大小的最小值
其他保持不变。
如果不配置,生成工程时会报错,就算硬件没有设计,也要随便配置一个引脚位检测引脚。后面生成工程后,要在代码里把它屏蔽掉。
然后我们就可以在main.c里添加测试代码了:
先不着急我们先来了解一下FATFS,SDIO的一些接口函数。
FatFs API
1.1 f_mount
功能 在FatFs模块上注册、注销一个工作区(文件系统对象)
函数定义 FRESULT f_mount(FATFS* fs, const TCHAR* path, BYTE opt)
参数 fs:工作区(文件系统对象)指针
path:注册/注销工作区的逻辑驱动器号
opt:注册或注销选项
返回 操作结果。 FR_OK 成功,其他失败。
1 .2f_open
功能 创建/打开一个文件对象
函数定义 FRESULT f_open(FIL* fp, const TCHAR* path, BYTE mode)
参数 fp:将被创建的文件对象结构的指针
path:文件名指针,指定将创建或打开的文件名
mode:访问类型和打开方法,由一下标准的一个组合指定的
返回 操作结果 FR_OK 成功,其他失败。
模式 描述
FA_READ 指定读访问对象。可以从文件中读取数据。 与FA_WRITE 结 合可以进行读写访问。
FA_WRITE 指定写访问对象。可以向文件中写入数据。与FA_READ 结合 可以进行读写访问。
FA_OPEN_EXISTING 打开文件。如果文件不存在,则打开失败。(默认)
FA_OPEN_ALWAYS 如果文件存在,则打开;否则,创建一个新文件。
FA_CREATE_NEW 创建一个新文件。如果文件已存在,则创建失败。
FA_CREATE_ALWAYS 创建一个新文件。如果文件已存在,则它将被截断并覆盖。
1.3 f_close
功能 关闭一个打开的文件
函数定义 FRESULT f_close(FIL* fp)
参数 fp:指向将被关闭的已打开的文件对象结构的指针
返回 操作结果 FR_OK 成功,其他失败。
1.4 f_read
功能 从一个打开的文件中读取数据
函数定义 FRESULT f_read(FIL* fp, void* buff, UINT btr, UINT* br)
参数 fp:指向将被读取的已打开的文件对象结构的指针
buff:指向存储读取数据的缓冲区的指针
btr:要读取的字节数
br:指向返回已读取字节数的UINT变量的指针,返回为实际读取的字节数
返回 操作结果 FR_OK 成功,其他失败。
1.5 f_write
功能 写入数据到一个已打开的文件
函数定义 FRESULT f_write(FIL* fp, void* buff, UINT btw, UINT* bw)
参数 fp:指向将被写入的已打开的文件对象结构的指针
buff:指向存储写入数据的缓冲区的指针
btw:要写入的字节数
bw:指向返回已写入字节数的UINT变量的指针,返回为实际写入的字节数
返回 操作结果 FR_OK 成功,其他失败。
1.6 f_gets
功能:从文件中读取字符串
函数定义 TCHAR* f_gets(TCHAR* str, int size, FIL* fp)
参数 fp:指向将被写入的已打开的文件对象结构的指针
str:指向存储读字符串缓冲区的指针
size:读缓冲区的字节数
1.7 f_tell()
功能:获取文件的当前指针位置相对文件首地址的偏移。
函数定义:TCHAR* f_tell(FIL* fp)
参数 fp:指向将被写入的已打开的文件对象结构的指针
1.8 f_lseek()
功能:移动文件的读写指针
函数定义:FRESULT f_lseek(FIL* fp,DWORD offset)
参数 fp:指向将被写入的已打开的文件对象结构的指针
offset: 偏移文件起始地址的字节数。
1.9 f_eof()
功能:测试一个文件是否达到末尾
函数定义:FRESULT f_eof(FIL* fp)
参数fp:指向将被写入的已打开的文件对象结构的指针
返回值: 0:没有达到末尾
1:达到了末尾。
1.10 f_size()
功能;获取一个文件的大小
1.11 f_putc()
功能:写一个字符
1.12 f_puts()
功能:写一个字符串。
。。。这里就不一一列举了。
/* 在main前面添加如下代码*/
/* USER CODE BEGIN PTD */
FATFS fs; /* FatFs 文件系统对象 */
FIL file; /* 文件对象 */
FRESULT f_res; /* 文件操作结果 */
uint16_t fnum; /* 文件成功读写数量 */
BYTE ReadBuffer[1024] = {0}; /* 读缓冲区 */
BYTE WriteBuffer[] = /* 写缓冲区 */
"hello word\r\n";
uint16_t file_memory=0;
/* USER CODE END PTD */
/*在main里面添加如下代码*/
/* USER CODE BEGIN 2 */
printf("\r\n****** FatFs Example ******\r\n\r\n");
//在外部 SD 卡挂载文件系统,文件系统挂载时会对 SD 卡初始化
f_res = f_mount(&fs, "0:", 1);
if(f_res == FR_OK)
{
printf("挂载成功\r\n");
f_res = f_open(&file, "0:120_0811.wav", FA_OPEN_EXISTING | FA_READ);
if(f_res == FR_OK)
{
printf("文件打开成功\r\n");
file_memory=f_size(&file);
printf("文件大小:%d\r\n",file_memory);
}
}
/* USER CODE END 2 */
以上就是所有的配置过程,关于SD卡的介绍我这里就不做阐述了,大家感兴趣可以去看看其他博主写的。这里我借鉴了http://t.csdn.cn/dnIQU这篇文章,这位博主写的很好。