上一篇介绍了IAP的实现。这里开始介绍主机的一个设计实例。
目标功能:STM32做主机,硬件接口主要包括SD card, USB,CAN, LCD,按键。
主要功能:
1,通过USB链接到PC,将用于更新的APP程序的BIN文件,放入SD中。
2,STM32通过FATFS读写SD卡中的文件。
3,通过CAN接口发送数据给从机。
4,LCD和按键用于人机交互。
PC通过STM32 USB读取SD卡的部分功能直接使用使用了神州三号开发板中的例程。移植FATFS参考了网上的一些例子,比较乱。
int main(void)
{
uint16_t Status = 0;
delay_init(); //延时初始化
NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init();
uart_init(9600);
if (KEY2==0&&KEY3==0)//按着组合按键启动,进入读卡器模式
{
sys_mode_flag = MODE_CARD_READ;
GPIO_Config();
/*MAL配置 */
MAL_Config();
/*中断配置 */
Interrupts_Config();
/*USB接口初始化*/
Set_USBClock();//设置USB接口时钟
USB_Init();//USB接口初始化
while (bDeviceState != CONFIGURED)
{
;//reserved
}
USB_Configured_LED();//设置USB接口的LED指示灯状态
while (1)
{
;
}
}
else
{
sys_mode_flag = MODE_IAP_DEVICE;
Status = SD_Init();
if (Status == SD_OK)
{
/*----------------- Read CSD/CID MSD registers ------------------*/
Status = SD_GetCardInfo(&SDCardInfo);
}
if (Status == SD_OK)
{
show_sdcard_info();
/*----------------- Select Card --------------------------------*/
Status = SD_SelectDeselect((u32) (SDCardInfo.RCA << 16));
}
if (Status == SD_OK)
{
Status = SD_EnableWideBusOperation(SDIO_BusWide_4b);
}
/* Set Device Transfer Mode to DMA */
if (Status == SD_OK)
{
Status = SD_SetDeviceMode(SD_DMA_MODE);
}
disk_initialize(0);
f_mount(0, &fs);
OSInit();
OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//创建起始任务
OSStart();
}
}
从main函数可以看出,上电如果按下组合按键,进入USB读卡器模式,可以在PC上将SD卡识别成可以移动磁盘。没按组合键,则将SD卡,通过FATFS文件系统挂载。
//扫描path录下的所有BIN文件
void scan_files(u8 *path)
{
OS_CPU_SR cpu_sr;
FRESULT res;
FILINFO finfo;
char lfn[50]; //用于存长文件名
DIR dirs;
char* result;
u8 i=0;
finfo.lfsize = sizeof(lfn);
finfo.lfname = lfn;
OS_ENTER_CRITICAL();
res = f_opendir(&dirs, (const TCHAR*)path); /* 打开工作目录 */
if(res == FR_OK)
{
printf("working directory:%s\r\n",path);
fcount = 0;
while( f_readdir(&dirs, &finfo) == FR_OK)/* 依次读取文件名 */
{
if ( finfo.fattrib & AM_ARC) /* 判断是否为存档型文档 */
{
if(finfo.lfname[0] == NULL && finfo.fname !=NULL) /*当长文件名称为空,短文件名非空时转换*/
{
finfo.lfname =finfo.fname;
}
/* 文件名为空即到达了目录的末尾,退出 */
if( !finfo.lfname[0] )
{
break;
}
result = strstr(finfo.lfname, ".bin");
if ( result != NULL)
{
printf("\r\n第%d个文件:\r\n",fcount);
printf("fname: %s \r\n",finfo.lfname );
printf("fsize: %d \r\n",finfo.fsize);
if ( fcount < MAX_FILE_COUNT)
{
strcpy((char*)fileList[fcount], finfo.lfname);
}
else//大于最多的存储量
{
break;
}
fcount++;
}
}
}
}
qsort(fileList, fcount, sizeof(fileList[0]), cmp);
printf("\r\n--------------------after sort--------------------\r\n");
for ( i = 0 ; i <fcount; i++ )
{
printf("\r\n第%d个文件:\r\n",i);
printf("fname: %s \r\n",(char*)fileList[i]);
}
OS_EXIT_CRITICAL();
}
这个函数用于扫描某个目录下面的文件,支持英文长文件名。关于FATFS的长文件名,只需配置ffconf.h中
#define _CODE_PAGE 437
#define _USE_LFN 1 /* 0 to 3 */
然后读取文件的时候使用finfo.lfname进行操作。
上面代码对读出来的文件名进行了排序。使用stdlib.H标准库中的函数qsort进行。
下面是串口调式的打印信息
剩下的就是读取文件,CAN发送数据的功能。