一、环境
keil5,使用库函数
二、移植对象
stm32f103zet6 >> stm32f103c8t6
三、连接方式
硬件SPI1(PA5,6,7)
四、主函数代码
#include "stdio.h"
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "malloc.h"
#include "MMC_SD.h"
#include "ff.h"
#include "exfuns.h"
void SD_Read_Sectorx(u32 sec);
int main(void)
{
u32 total,free;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 LED_Init(); //LED端口初始化
OLED_Init(); //初始化OLED
OLED_Clear();
OLED_ShowString(0,0,"OLED ready",12);
delay_ms(1000);
OLED_Fill(0,0,127,7,0);//清除显示
delay_ms(1000);
exfuns_init(); //为fatfs相关变量申请内存
mem_init(); //初始化内存池
while(SD_Initialize()) //检测SD卡
{
OLED_ShowString(0,0,"SD Card Error!",12);
delay_ms(200);
OLED_Fill(0,0,127,7,0);//清除显示
delay_ms(200);
//LED0=!LED0;//DS0闪烁
}
exfuns_init(); //为fatfs相关变量申请内存
f_mount(fs[0],"0:",1); //挂载SD卡
while(exf_getfree("0",&total,&free)) //得到SD卡的总容量和剩余容量
{
OLED_ShowString(0,0,"Fatfs Error!",12);
delay_ms(200);
OLED_Fill(0,0,127,7,0);//清除显示
delay_ms(200);
//LED0=!LED0;//DS0闪烁
}
OLED_ShowString(0,0,"FATFS OK!",12);
OLED_ShowString(0,1,"Total: MB",12);
OLED_ShowString(0,2,"Free : MB",12);
OLED_ShowNum(48,1,total>>10,5,12); //显示SD卡总容量 MB
OLED_ShowNum(48,2,free>>10,5,12);
while(1)
{
}
}
四、问题
0.移植准备
①修改device为STM32F103C8
②将C/C++中define“STM32F10X_HD,USE_STDPERIPH_DRIVER”改为“STM32F10X_HD,USE_STDPERIPH_DRIVER”
③更换相应的启动文件(.s)
1.编译报错内存不足
①从工程中删除cc936.c等文件,c8t6装不下
②mallco.h中#define MEM_MAX_SIZE 421024改小,测试101024可用,需保证编译结果后面两个size的和小于20k
③#define _CODE_PAGE 936 改为 #define _CODE_PAGE 1 使用ascii码减少存储开销
④相应#define _LFN_UNICODE 0 和 #define _STRF_ENCODE 0 ,使用ascii
2.程序死在while(SD_Initialize())中
①强烈建议检查连线,特别是SLK
②最好单片机单独供电而不是使用仿真器供电,可能由于供电不足导致spi初始化的高电平不符合要求
③如果使用仿真器调试时卡在此处,可能是卡在以下代码
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET)
{
//...
}
百度到的解释是“rxne只能读一次,如果调试器读取了,那么程序就永远读不到了”,此外SPI运行时有一定几率程序会卡死在检查接受标志位处RXNE,论坛上的解决方案是将检查接受标志位改为检查忙状态,所以可以换成
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
{
//...
}
经测试此方案可行。
④如果改为SPI2,可能是SPI2时钟初始化的问题。SPI1的时钟在APB2上而SPI2的在APB1上,初始化需调用不同的函数。如:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //硬件SPI1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); //硬件SPI2
3.程序死在while(exf_getfree(“0”,&total,&free))中
①一般来说不会在这句话中卡住,卡住了检查下连线吧
②设置SPI为高速模式时可能由于时钟太快导致初始化不成功(也可能是初始化之后的部分导致无法正常使用,ZET6没有这个问题而C8T6存在),可以适当降低高速模式的时钟
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{
//SPI1_SetSpeed(SPI_BaudRatePrescaler_2);//原函数
SPI1_SetSpeed(SPI_BaudRatePrescaler_4);//修改
}
五、资料
1.SPI存储器W25X16,Debug时卡在SPI_I2S_GetFlagStatus(SPI1, 2.SPI_I2S_FLAG_RXNE
3.SPI调试小结
4.fatfs文件系统移植 读写时莫名出现FR_DISK_ERR问题
5.死循环了:while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET);
6.SPI/I2S调试总结
7.F103C8T6移植Fatfs文件系统时编译报错空间不够