我是靠谱客的博主 勤劳斑马,最近开发中收集的这篇文章主要介绍基于FreeRTOS与MQTT的物联网技术应用系列——步进电机控制(三)SD卡驱动、FatFS等的移植和ini配置文件读取的实现一、添加SD卡驱动代码、移植FatFS二、移植minIni库,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本文实现了基于STM32F107VC的金牛开发板的基于SPI模式的SD卡驱动和FatFS的移植,以及利用minini库对ini配置信息文件进行读取。

因为后面连接网络需要相关配置参数,而且可能随时发生变化,这些参数不可能固定在程序中,所以,我们现在把它放在sd卡中,以便随时更改。

IDE环境为: MDK v5.23
硬件环境:基于STM32F107VC的金牛开发板

一、添加SD卡驱动代码、移植FatFS

为了节省时间,就不造轮子了,直接使用网上共享的spi和sd驱动代码、FatFS源代码。
这部分源代码摘自:
STM32_SD_FATFS_LCD_TOUCH
备用地址:STM32_SD_FATFS_LCD_TOUCH

把这个源代码下来,解压。
把STM32_SD_FATFS_LCD_TOUCH.rarUserSD_CARDsrc 目录下的spi.c、sdcard.c文件和
STM32_SD_FATFS_LCD_TOUCH.rarUserSD_CARDinc 目录下的spi.h、sdcard.h文件都复制到我们工程的BSP目录下,并把spi.c、sdcard.c加入工程的BSP组。

在spi.h中加入:

#include "stm32f10x_spi.h"

然后下载FatFS官方源码:
http://elm-chan.org/fsw/ff/arc/ff13.zip

解压后重命名整个文件夹为FatFS,并把它复制到我们工程的third_party目录下。

在IDE上添加一个组,名字为:third_party/FatFS,添加third_party/FatFS/source目录下的diskio.c、ff.c这两个文件。
其中ff.c是具体fat文件系统的实现,diskio.c是文件系统硬件驱动接口实现。

接下来,把STM32_SD_FATFS_LCD_TOUCH.rarUserfatfs 目录下的diskio.h和diskio.c文件复制到third_party/FatFS/Source下面来,覆盖原同名文件。

这样就直接使用来源于网上的SD卡驱动接口实现了。

然后,把third_party/FatFS/source这个路径添加到IDE的包含路径中。
编译一下可以通过。

移植完了。写个demo测试一下。

首先参考网上的例程,写一个fatfs测试代码,主体放在common.h和common.c中:

common.h

#ifndef _COMMON_H_
#define _COMMON_H_  1

#include "stm32f10x.h"

#define FI 1
#define DI 2

/* Values magic to the Board keys */
#define  NOKEY  0
#define  KEY1   1
#define  KEY2   2
#define  KEY3   3
#define  KEY4   4

#define RCC_KEY1                                    RCC_APB2Periph_GPIOD
#define GPIO_KEY1_PORT                              GPIOD    
#define GPIO_KEY1                                   GPIO_Pin_3

#define RCC_KEY2                                    RCC_APB2Periph_GPIOA
#define GPIO_KEY2_PORT                              GPIOA  
#define GPIO_KEY2                                   GPIO_Pin_8

#define RCC_KEY3                                    RCC_APB2Periph_GPIOC
#define GPIO_KEY3_PORT                              GPIOC    
#define GPIO_KEY3                                   GPIO_Pin_13 

#define RCC_KEY4                                    RCC_APB2Periph_GPIOA
#define GPIO_KEY4_PORT                              GPIOA    
#define GPIO_KEY4                                   GPIO_Pin_0 

#define GPIO_KEY_ANTI_TAMP                          GPIO_KEY3
#define GPIO_KEY_WEAK_UP                            GPIO_KEY4


uint8_t GetKey(void);
void Sys_Soft_Reset(void);
void get_file_name(uint8_t *file_name,uint8_t length,uint8_t type);
uint8_t check_file_name(uint8_t *file_name,uint8_t length);

void format_disk(void);
void creat_file(void);
void delete_file(void);
void list_file(void);
void get_disk_info(void);
void creat_dir(void);
void edit_file(void);
void read_file(void);


int InitMQTTServerInfo(void);

#endif

common.c

#include "spi.h"
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include "ff.h"
#include "integer.h"
#include "diskio.h"
#include <string.h>
#include "FreeRTOS.h"
#include "serial.h"

//#define _DEBUG
#include "dprintf.h"

/* Handle to the com port used by both tasks. */
static xComPortHandle xPort = NULL;

/* The Rx task will block on the Rx queue for a long period. */
#define comRX_BLOCK_TIME            ( ( TickType_t ) 0xffff )



void edit_file(void)
{
    FATFS fs;
    FIL file;
    FRESULT res; 
    DIR dirs;
    FILINFO finfo;
    signed char key = 0;
    char path[20];

    uint32_t index = 0x00;
    uint32_t reindex = 0x00;
    uint8_t file_buff[512] = {0};

    uint32_t files_num = 0;
    uint8_t length;
    res = f_mount(&fs,"",0);
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }
    res = f_opendir(&dirs,"/");
    printf("rn------------ÎļþÁбí------------");
    if (res == FR_OK) 
    {
        while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
        {
            if (finfo.fattrib & AM_DIR)//Èç¹ûÊÇÎļþ¼Ð 
            { 
                continue;
            } 
            else 
            {   
                files_num++;
                //ÏÔʾÎļþÃû,ÏÔʾÎļþʵ¼Ê´óС ,Îļþʵ¼Ê´óС²ÉÓÃËÄÉáÎåÈë·¨
                printf("rn/%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);
            }
        }
        if( files_num == 0 )//ÎÞÎļþ
        {
            printf("rnÎÞÎļþ!");    
        }
    }
    else
    {
        printf("rn´ò¿ª¸ùĿ¼ʧ°Ü!");
        printf("rn´íÎó´úÂë: %u",res);
    }
    printf("rnÊäÈëÒª±à¼­ÎļþÈ«Ãû,ÒԻسµ½áÊø...");
    get_file_name((uint8_t *)path,length,FI);
    res = f_open(&file,path,FA_READ | FA_WRITE);
    if (res == FR_OK)
    {   
        printf("rn´ò¿ªÎļþ %s ³É¹¦",path);
        printf("rnÏÖÔÚÊÇÎļþ±à¼­×´Ì¬,ÇëÊäÈëҪдÈëµÄÊý¾Ý!");       
        printf("rn°´ESC»òÕßCtrl+C½áÊø±à¼­!rn");

        while(1)
        {       
            if(xSerialGetChar( xPort, &key, comRX_BLOCK_TIME )== pdFALSE)  
            {
                continue;
            }

            if ((key == 0x1B) && (index == 0x00))//key ESC
            {
                printf("rnÊý¾Ý»¹Ã»ÓÐÊäÈë,ÏÖÔÚ´¦Óڱ༭ģʽ...");                               
                continue;
            }
            else if ((key == 0x1B)) //key ESC
            {
                printf("rn±£´æÊý¾Ý...");
                res = f_write(&file,file_buff,index,&reindex);
                if ((res == FR_OK) && (reindex == index))
                {
                    printf("rn±£´æÊý¾Ý³É¹¦!");
                    f_close(&file);
                    index = 0x00;
                    reindex = 0x00;                                 
                }
                else
                {
                    printf("rn±£´æÊý¾Ýʧ°Ü!");
                    printf("rn´íÎó´úÂë: %u",res);                                 
                }
                break;
            }
            else if (key == 0x03) //key Ctrl+C
            {
                printf("rn½áÊøÎļþ±à¼­!");
                printf("rn±£´æÊý¾Ý...");
                res = f_write(&file,file_buff,index,&reindex);
                if ((res == FR_OK) && (reindex == index))
                {
                    printf("rn±£´æÊý¾Ý³É¹¦!");
                    f_close(&file);
                    index = 0x00;
                    reindex = 0x00;                                 
                }
                else
                {
                    printf("rn±£´æÊý¾Ýʧ°Ü!");
                    printf("rn´íÎó´úÂë: %u",res);                                 
                }
                break;
            }
            else if ((key < 0x21) || (key > 0x80))
            {
                continue;
            }
            else
            {
                file_buff[index++] = key;
                printf("%c",key);
                if (index > 512)
                {
                    index = 0x00;
                }
            }
        }
    }
    else
    {
        printf("rn´ò¿ªÎļþʧ°Ü,´íÎó´úÂë: %u",res);
    }
}


void read_file(void)
{

    FATFS fs;
    FIL file;
    FRESULT res; 
    DIR dirs;
    FILINFO finfo;
    char path[20]={0};
    char buffer[512] = {0};
    uint32_t i;
    uint8_t length;
    uint32_t re,files_num = 0;

    res = f_mount(&fs,"",0);

    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }

    res = f_opendir(&dirs,"/");

    if (res == FR_OK) 
    {
        //i = strlen(path);
        printf("rn-----------ÎļþÁбí-------");
        while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
        {
            if (finfo.fattrib & AM_DIR)//Èç¹ûÊÇÎļþ¼Ð 
            { 
                continue;
            } 
            else 
            {   
                files_num++;
                //ÏÔʾÎļþÃû,ÏÔʾÎļþʵ¼Ê´óС
                printf("rn/%12s%7ld Byte ",  &finfo.fname[0],finfo.fsize);
            }
        }
        if( files_num == 0 )//ÎÞÎļþ
        {
            printf("rnÎÞÎļþ,Çë·µ»ØÏÈ´´½¨Îļþ!");
            return;
        }
    }
    else
    {
        printf("rn´ò¿ª¸ùĿ¼ʧ°Ü!");
        printf("rn´íÎó´úÂë: %u",res);
    }
    printf("rnÊäÈëÎļþÈ«Ãû,ÒԻسµ½áÊø...");
    get_file_name((uint8_t *)path,length,FI);
    res = f_open(&file,path,FA_READ);

    if (res == FR_OK)
    {
        printf("rnÕýÔÚ´ò¿ªÎļþ,ÒÔÏÂÊÇÎļþÊý¾Ý:rn");
        while (1)
        {
            for(i = 0;i < 512;i++)
            {
                buffer[i] = 0x00;
            }
            res = f_read(&file,buffer,512,&re);
            printf("%s",buffer);

            if (res || re == 0)
            {
                printf("rnÎļþ¶ÁÈ¡½áÊø,¹Ø±ÕÎļþ!");
                f_close(&file);
                break;  
            }   
        }
    }
    else
    {
        printf("rn´ò¿ªÎļþ %s ´íÎó£¡n",path);
    }
    f_mount(NULL,"",0);
}


void creat_dir(void)
{
    FATFS fs;        
    FRESULT res;     
    char path[20];
    uint8_t length;
    res = f_mount(&fs,"",0);
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }   
    printf("rnÇëÊäÈëÎļþ¼ÐÃû,»Ø³µÈ·ÈÏ...¸ñʽ 8 + 3...");
    get_file_name((uint8_t *)path,length,DI);
    res = f_mkdir(path);
    if (res == FR_OK)
    {
        printf("rn´´½¨ÎļþĿ¼³É¹¦!");
    }
    else
    {
        printf("rn´´½¨Ä¿Â¼Ê§°Ü...");
        printf("rn´íÎó´úÂë: %u",res);
    }
    f_mount(NULL,"",0);
}


void get_file_name(uint8_t *file_name,uint8_t length,uint8_t type)
{
    signed char key;
    uint8_t name_leng = 0;
    printf("rn");

    while (1)
    {
        if(xSerialGetChar( xPort, &key, comRX_BLOCK_TIME )== pdFALSE)  
        {
            continue;
        }

        if ((key == 13) && (name_leng == 0))
        {
            printf("rn");
            continue;
        }
        else if ((key == 0x2F) || (key == 0x5C))
        {
            printf("%c",key);
            continue;
        }
        else if ((key == 13) && (name_leng > 0))
        {
            printf("rn");
            if (type == FI)
            {
                if (check_file_name(file_name,name_leng) == 0)
                {
                    break;
                }
            }
            else
            {
                break;
            }           

        }
        else
        {
            printf("%c",key);
            file_name[name_leng] = key;
            name_leng++;
            if (name_leng > 12)
            {
                printf("rnÎļþÃû¸ñʽ: 8 + 3£¬Ö»Ö§³Ö8¸ö×Ö·û,3¸öÀ©Õ¹Ãû!");
                printf("rnÇëÖØÐÂÊäÈë...");
                name_leng = 0;
                continue;
            }
        }
    }
}
void format_disk(void)
{
    FATFS fs;
    uint8_t res;
    BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */

    res = f_mount(&fs,"",0);
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }   
    printf("rnÕýÔÚ¸ñʽ»¯´ÅÅÌ,ÇëÉÔºò...");

    res = f_mkfs("", FM_ANY,0,work,sizeof(work));
    if (res == FR_OK)
    {
        printf("rn¸ñʽ»¯³É¹¦...");
    }
    else
    {
        printf("rn¸ñʽ»¯Ê§°Ü...");
        printf("rn´íÎó´úÂë: %urn",res);
    }
    f_mount(NULL,"",0);
}
void creat_file(void)
{
    FIL file;
    FIL *pf = &file;
    FATFS fs;
    uint8_t res;
    uint8_t name[16] = {0};
    uint8_t length = 0;
    printf("rnÇëÊäÈëÎļþÃû,»Ø³µÈ·ÈÏ...¸ñʽ 8 + 3...");
    printf("rnÀý:123.datrn");
    get_file_name(name,length,FI);  
    res = f_mount(&fs,"",0);                                   /* Mount a Logical Drive 0 */
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }   
    res = f_open(pf,(TCHAR *)name,FA_READ | FA_WRITE | FA_CREATE_NEW);
    if (res == FR_OK)
    {
        printf("rn´´½¨Îļþ³É¹¦!");
        res = f_close(pf);
        if (res != FR_OK)
        {
            printf("rn´´½¨Îļþ³É¹¦,µ«¹Ø±ÕÎļþʱ,ʧ°Ü!");
            printf("rn´íÎó´úÂë: %u",res);             
        }               
    }
    else
    {
        printf("rn´´½¨Îļþʧ°Ü!");
        printf("rn´íÎó´úÂë: %u",res); 
    }
    f_mount(NULL,"",0);
}
void delete_file(void)
{
    FATFS fs;
    FRESULT res;
    DIR dirs;
    FILINFO finfo;
    uint8_t name[16] = {0};
    uint8_t length = 0;
    uint32_t files_num = 0;

    res = f_mount(&fs,"",0);              /* Mount a Logical Drive 0*/   
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }

    res = f_opendir(&dirs,"/");      /* Create a Directroy Object */
    if (res == FR_OK) 
    {
        printf("rn-----------ÎļþÁбí-------");
        while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
        {
            if (finfo.fattrib & AM_DIR)//Èç¹ûÊÇÎļþ¼Ð 
            { 
                continue;
            } 
            else 
            {   
                files_num++;
                //ÏÔʾÎļþÃû,ÏÔʾÎļþʵ¼Ê´óС ,Îļþʵ¼Ê´óС²ÉÓÃËÄÉáÎåÈë·¨
                printf("rn/%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);
            }
        }
        if( files_num == 0 )//ÎÞÎļþ
        {
            printf("rnÎÞÎļþ,Çë·µ»ØÏÈ´´½¨Îļþ!");
            return;
        }
    }

    get_file_name(name,length,FI);    /* Get file name */

    res = f_unlink((TCHAR *)name);    /* Delete a File or Directory */

    if (res == FR_OK)
    {
        printf("rnɾ³ýÎļþ³É¹¦!");
    }
    else if (res == FR_NO_FILE)
    {
        printf("rnÕÒ²»µ½Îļþ»òĿ¼!");
    }
    else if (res == FR_NO_PATH)
    {
        printf("rnÕÒ²»µ½Â·¾¶!");
    }
    else
    {
        printf("rn´íÎó´úÂë: %u",res);
    }
    f_mount(NULL,"",0);
}
void list_file(void)
{
    FATFS fs;
    FILINFO finfo;
    FRESULT res;
    DIR dirs;
    int i;
    int files_num=0;
    res = f_mount(&fs,"",0);
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }   
    res = f_opendir(&dirs,"/");                         /* Create a Directroy Object */
    printf("rn------------ÎļþÁбí------------");
    if (res == FR_OK)
    {
        while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0])    /* Read Directory Entry in Sequense*/
        {
            i = strlen(finfo.fname);
            if (finfo.fattrib & AM_DIR)//Èç¹ûÊÇÎļþ¼Ð 
            {
                files_num++;
                printf("rn/%s", &finfo.fname[0]);
                switch(i)//×÷ÓãºÊä³öÎļþÃû×ó¶ÔÆë
                {
                case 1:printf(" ");
                case 2:printf(" ");
                case 3:printf(" ");
                case 4:printf(" ");
                case 5:printf(" ");
                case 6:printf(" ");
                case 7:printf(" ");
                case 8:printf("%15s"," ");
                }   
            } 
            else 
            {
                continue;
            }   
        }
    }
    else
    {
        printf("rn´ò¿ª¸ùĿ¼ʧ°Ü!");
        printf("rn´íÎó´úÂë: %u",res);
    }
    res = f_opendir(&dirs, "/");
    if (res == FR_OK) 
    {
        while ((f_readdir(&dirs, &finfo) == FR_OK) && finfo.fname[0]) 
        {
            if (finfo.fattrib & AM_DIR) 
            { 
                continue;
            } 
            else 
            {   
                files_num++;                
                printf("rn/.%12s%7ld KB ",  &finfo.fname[0],(finfo.fsize+512)/1024);              
            }
        }
        if( files_num==0 )//ÎÞÎļþ
        {
            printf("rnÎÞÎļþ!");    
        }
    }
    else
    {
        printf("rn´ò¿ª¸ùĿ¼ʧ°Ü!");
        printf("rn´íÎó´úÂë: %u",res);
    }
    f_mount(NULL,"",0);

}
void get_disk_info(void)
{
    FATFS fs;
    FATFS *fls = &fs;
    FRESULT res;
    DWORD fre_clust;    

    res = f_mount(&fs,"",0);                         /* Mount a Logical Drive 0 */
    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return;
    }   

    res = f_getfree("/",&fre_clust,&fls);        /* Get Number of Free Clusters */
    if (res == FR_OK) 
    {
                                                 /* Print free space in unit of MB (assuming 4096 bytes/sector) */
        printf("rn%d KB Total Drive Space.rn"
               "%d KB Available Space.rn",
               ((fls->n_fatent-2)*fls->csize)*4,(fre_clust*fls->csize)*4);
    }
    else
    {
        printf("rn»ñµÃ´ÅÅÌÐÅϢʧ°Ü!");
        printf("rn´íÎó´úÂë: %u",res);
    }                                                                                                      
    f_mount(NULL,"",0);                          /*Unmount a Logical Drive 0 */ 
}
uint8_t check_file_name(uint8_t *file_name,uint8_t length)
{
    uint8_t res;
    if (length > 13)
    {
        res = 1;
    }
    else
    {
        if (file_name[length - 4] == '.')
        {
            res = 0;
        }
        else
        {
            res = 2;
        }
    }
    return res;

}


void Sys_Soft_Reset(void)
{   
    SCB->AIRCR =0X05FA0000|(u32)0x04;     
}

main.c


#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "utils.h"
#define _DEBUG
#include "dprintf.h"


void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Configure IO connected to LD1, LD2, LD3 and LD4 leds *********************/  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
}

//??????
void NVIC_Configuration(void)
{ 
    /* Configure the NVIC Preemption Priority Bits */  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

    #ifdef  VECT_TAB_RAM  
      /* Set the Vector Table base location at 0x20000000 */ 
      NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
    #else  /* VECT_TAB_FLASH  */
      /* Set the Vector Table base location at 0x08000000 */ 
      NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
    #endif
}


void RCC_Configuration(void)
{
    SystemInit();   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA 
                           |RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
                           |RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE
                           |RCC_APB2Periph_ADC1  | RCC_APB2Periph_AFIO 
                           |RCC_APB2Periph_SPI1, ENABLE );
  // RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL ,ENABLE );
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 
                           |RCC_APB1Periph_USART3|RCC_APB1Periph_TIM2                              
                           , ENABLE );
     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}


void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
    /* This function will get called if a task overflows its stack.   If the
    parameters are corrupt then inspect pxCurrentTCB to find which was the
    offending task. */

    ( void ) pxTask;
    printf("ÈÎÎñ£º%s ·¢ÏÖÕ»Òç³ön", pcTaskName);
    for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationTickHook( void )
{
}

static void prvSetupHardware( void )
{
    /* Start with the clocks in their expected state. */
    RCC_DeInit();

    /* Enable HSE (high speed external clock). */
    RCC_HSEConfig( RCC_HSE_ON );

    /* Wait till HSE is ready. */
    while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET )
    {
    }

    /* 2 wait states required on the flash. */
    *( ( unsigned long * ) 0x40022000 ) = 0x02;

    /* HCLK = SYSCLK */
    RCC_HCLKConfig( RCC_SYSCLK_Div1 );

    /* PCLK2 = HCLK */
    RCC_PCLK2Config( RCC_HCLK_Div1 );

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config( RCC_HCLK_Div2 );

    /* Enable PLL. */
    RCC_PLLCmd( ENABLE );

    /* Wait till PLL is ready. */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source. */
    RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK );

    /* Wait till PLL is used as system clock source. */
    while( RCC_GetSYSCLKSource() != 0x08 )
    {
    }

    /* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE and AFIO clocks */
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
                            | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE );

    /* Set the Vector Table base address at 0x08000000 */
    NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );

    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );

    /* Configure HCLK clock as SysTick clock source. */
    SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );

    GPIO_Configuration();
}



#define ledSTACK_SIZE       configMINIMAL_STACK_SIZE
#define ledFLASH_RATE_BASE  ( ( TickType_t ) 333 )

static TaskHandle_t xHandleTaskLED=NULL;


static void vTaskLED(void* pvParameters)
{
    TickType_t xFlashRate, xLastFlashTime;
    xFlashRate = ledFLASH_RATE_BASE + ( ledFLASH_RATE_BASE * ( TickType_t ) 2 );
    xFlashRate /= portTICK_PERIOD_MS;
    xFlashRate /= ( TickType_t ) 2;
    xLastFlashTime = xTaskGetTickCount();

    while(1)
    {
        /* Turn on LD1 */
        GPIO_SetBits(GPIOD, GPIO_Pin_2);
        /* Insert delay */
        //vTaskDelay(300);
        vTaskDelayUntil( &xLastFlashTime, xFlashRate );

        /* Turn off LD1 */
        GPIO_ResetBits(GPIOD, GPIO_Pin_2);
        /* Insert delay */
        //vTaskDelay(300);
        vTaskDelayUntil( &xLastFlashTime, xFlashRate );
    }
}


#include "serial.h"
#include "integer.h"
#include "diskio.h"
#include "ff.h"
#include "sdcard.h" 
#include "common.h"
#include <stdio.h>

#define SYSTEM_INIT_TASK_PRIO    ( tskIDLE_PRIORITY )

/* Handle to the com port used by both tasks. */
static xComPortHandle xPort = NULL;

/* The Rx task will block on the Rx queue for a long period. */
#define comRX_BLOCK_TIME            ( ( TickType_t ) 0xffff )

static void sd_card_task(void* pvParameters)
{ 
    signed char  key = 0;

  GPIO_ResetBits(GPIOF,  GPIO_Pin_6);                                   //LED1 on

  while(1)
  {
        printf("rn============ ÇëÑ¡Ôñ...===============rnn");
        printf("¸ñ ʽ »¯------------------------------- 1rnn");
        printf("´´½¨Îļþ------------------------------- 2rnn");
        printf("ɾ³ýÎļþ ------------------------------ 3rnn");
        printf("ÁбíÎļþ------------------------------- 4rnn");
        printf("ÖØÆôϵͳ ------------------------------ 5rnn");
        printf("´ÅÅÌÐÅÏ¢------------------------------- 6rnn");
        printf("´´½¨Ä¿Â¼------------------------------- 7rnn");
        printf("±à¼­Îļþ------------------------------- 8rnn");
        printf("¶ÁÈ¡Îļþ------------------------------- 9rnn");
        printf("========================================rnn");



        xSerialGetChar( xPort, &key, comRX_BLOCK_TIME );

        if (key == 0x31)        //Format FS
        {
            printf("rn----1----");
            format_disk();
        }
        else if (key == 0x32)   //Creat File
        {
            printf("rn----2----");
            creat_file();       
        }
        else if (key == 0x33)   //Delete File
        {
            printf("rn----3----");
            delete_file();      
        }
        else if (key == 0x34)   //List File
        {
            printf("rn----4----");
            list_file();
        }
        else if (key == 0x35)   //Reset FS
        {
            printf("rn----5----");
            Sys_Soft_Reset();
        }
        else if (key == 0x36)   //Disk info
        {
            printf("rn----6----");
            get_disk_info();    
        }
        else if (key == 0x37)   //Creat Dir
        {
            printf("rn----7----");
            creat_dir();
        }
        else if (key == 0x38)   //Edit File
        {
            printf("rn----8----");
            edit_file();
        }
        else if (key == 0x39)   //Read File
        {
            printf("rn----9----");
            read_file();    
        }
        else
        {
            printf("rn----%c----",key);
            printf("rnÖ»½ÓÊÜ1-9ÃüÁÇëÖØÐÂÊäÈë");
        }           
    }       
}


int main(void)
{  
    __set_PRIMASK(1);//½ûֹȫ¾ÖÖжÏ
    prvSetupHardware(); 

    FreeRTOS_printf_service_init();

    printf("###############################################rn");
    printf("##    hello! welcome to FreeRTOS v9.0.0      ##rn");
    printf("###############################################rn");

    printf("rnrn");

    SD_Init(); 

    xTaskCreate(vTaskLED,"vTaskLED",ledSTACK_SIZE,NULL,3,&xHandleTaskLED);

    xTaskCreate(sd_card_task,"vTaskSDCard",1024,NULL,SYSTEM_INIT_TASK_PRIO,NULL);

    vTaskStartScheduler();//Æô¶¯ÈÎÎñµ÷¶ÈÆ÷
}

/******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/


到此,文件系统已经基本OK,需要说明的是,此次移植没有加上对unicode的支持,因此,也就不支持中文,需要支持中文的读者请参考其他移植文章。

下面写一个ini文件,保存为ipcfg.ini,里面内容:

[server]
ip=10.0.0.105
port=1883
name=
password=

关于server是域名(feild),ip是关键字(key),“=”后面是该关键字参数的值(value)。
关于这部分请自行搜索参考有关文章。

把ipcgf.ini放到SD卡上,进行读取操作。

以下是一些展示:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

以上完整源代码:
STM32F107_FreeRTOS_v9.0.0_SDCard-FatFS.rar

二、移植minIni库

本项目使用了minIni库来读取ini文件解析配置参数,版本为minini_12b。

minIni官方网站:
https://www.compuphase.com/minini.htm

minini_12b官方源码地址:
https://www.compuphase.com/software/minini_12b.zip

下载下来,解压到minini_12b文件夹,把minini_12b整个文件夹复制到third_party目录下。
然后,在IED上添加一个组,命名为third_party/minIni,把third_party/minini_12b下的minIni.c文件加入到工程里面。

并把third_party/minini_12b加入到包含路径中。

此时编译会出现两个错误:

..OutputFreeRTOS_v9.0.0.: Error: L6218E: Undefined symbol __aeabi_assert (referred from minini.o).
..OutputFreeRTOS_v9.0.0.: Error: L6218E: Undefined symbol strnicmp (referred from minini.o).

这是链接找不到这两个函数。

所以,minIni.c需要修改。

对于__aeabi_assert,我们需要自定义实现,我们编写一个头文件bsp_assert.h,实现它:
bsp_assert.h:


#undef assert

#ifdef    __cplusplus
extern "C" {
#endif

#ifdef NDEBUG
/*
 * If not debugging, assert does nothing.
 */
#define assert(x)    ((void)0)

#else /* debugging enabled */

/*
 * CRTDLL nicely supplies a function which does the actual output and
 * call to abort.
 */
extern void _assert(const char *mesg, const char *file, int line);

/*
 * Definition of the assert macro.
 */
#define assert(e)       ((e) ? (void)0 : _assert(#e, __FILE__, __LINE__))

#endif    /* NDEBUG */

#ifdef    __cplusplus
}
#endif

并把它放在BSP目录下。
然后把minIni.c中的

 #include <assert.h>

换成我们的

#include "bsp_assert.h"

对于strnicmp,我们只需要在#include “bsp_assert.h”下面加一行宏:

#define PORTABLE_STRNICMP

这一部分代码改后如下:

#if defined NDEBUG
  #define assert(e)
#else
  //#include <assert.h>
    #include "bsp_assert.h"  //added @2017.09.25
  #define PORTABLE_STRNICMP  //added @2017.09.25
#endif

接下来,要配置一下FatFS函数接口配置:
把minIni.h中的

#include "minGlue.h"
#include "minGlue-FatFs.h"

此时编译会出错:

..third_partyminini_12bminGlue-FatFs.h(34): error:  #144: a value of type "int" cannot be used to initialize an entity of type "char *"
..third_partyminini_12bminGlue-FatFs.h(35): error:  #20: identifier "NULL" is undefined
D:Program Files (x86)Keil_v5ARMARMCCBin..includestring.h(209): error:  #159: declaration is incompatible with previous "strchr"  (declared at line 34 of "..third_partyminini_12bminGlue-FatFs.h")

打开minGlue-FatFs.h文件,在文件顶端加入:

#include <string.h>

修改ini_rename函数,在char *drive定义前面加const:

static int ini_rename(TCHAR *source, const TCHAR *dest)
{
  /* Function f_rename() does not allow drive letters in the destination file */
  const char *drive = strchr(dest, ':');
  drive = (drive == NULL) ? dest : drive + 1;
  return (f_rename(source, drive) == FR_OK);
}

F7编译通过了。

下面写一个程序来读取上面ipcfg.ini中的参数。
在common.c中最下面加入以下代码:

#include "minIni.h"
#define sizearray(a)  (sizeof(a) / sizeof((a)[0]))

const char inifile[] = "ipcfg.ini";

static char MQTTServerIP[16]={0};
static int MQTTServerPort;
static char MQTTServerName[32]={0};
static char MQTTServerPassword[32]={0};

const char * getMQTTServerIP(void)
{
    return MQTTServerIP;
}


int getMQTTServerPort(void)
{
     return  MQTTServerPort;
}

char * getMQTTServerName(void)
{
    return MQTTServerName;
}

char * getMQTTServerPassword(void)
{
    return MQTTServerPassword;
}

int InitMQTTServerInfo(void)
{
    FATFS fs;
    FRESULT res; 
    char str[32+1]={0};
    long n;
    //int s, k;
    //char section[50];
    res = f_mount(&fs,"",0);

    if (res != FR_OK)
    {
        printf("rn¹ÒÔØÎļþϵͳʧ°Ü,´íÎó´úÂë: %u",res);
        return -1;
    }


    n = ini_gets("server", "ip", "192.168.1.1", str, sizearray(str), inifile);  
    printf("nserver ip:[ %s ]n",str);
    memcpy(MQTTServerIP,str,n);

    n = ini_gets("server", "port", "1883", str, sizearray(str), inifile);   
    printf("server port:[ %s ]n",str);
    MQTTServerPort = atoi(str);


    n = ini_gets("server", "name", "", str, sizearray(str), inifile);   
    printf("server name:[ %s ]n",str);
    memcpy(MQTTServerName,str,n);
    //dprintf("%sn",MQTTServerName);
    if(strcmp(MQTTServerName,"")==0)
    {
        dprintf("MQttServerName=""n");
    }

    n = ini_gets("server", "password", "", str, sizearray(str), inifile);   
    printf("server password:[ %s ]n",str);
    memcpy(MQTTServerPassword,str,n);
    //dprintf("%sn",MQTTServerPassword);
    if(strcmp(MQTTServerPassword,"")==0)
    {
        dprintf("MQTTServerPassword=""n");
    }   

    f_mount(NULL,"",0);
    return 0;
}

在common.h中加入:

extern int InitMQTTServerInfo(void);
extern const char * getMQTTServerIP(void); 
extern int getMQTTServerPort(void);
extern char * getMQTTServerName(void);
extern char * getMQTTServerPassword(void);

其中,InitMQTTServerInfo(void)函数读取了ipcfg.ini文件,并把参数解析出来放在缓存中。
剩下的几个函数是从缓存中读取参数出来。
ini_gets(“server”, “ip”, “192.168.1.1”, str, sizearray(str), inifile); 是读取server域中的ip关键字,如果没有该关键字,则设置成默认值(此处为”192.168.1.1”)。
在程序中如果ipcfg.ini文件读取出错则会设置成以下默认值:

ip=192.168.1.1
port=1883
name=""
password=""

在mian函数中的SD_Init(); 下面添加一行:
InitMQTTServerInfo();

然后,编译链接,烧到板子上运行,可以看到:
这里写图片描述

参数已经读取出来了。

修改一下参数,把sd卡的ipcfg.ini内容改成如下:

[server]
ip=10.0.0.108
port=10000
name=admin
password=123456

上电再试:
这里写图片描述

oK,完成!

完整源代码:
STM32F107_FreeRTOS_v9.0.0_SDCard-FatFS-ini.rar

下一篇将移植LwIP-1.4.1。

最后

以上就是勤劳斑马为你收集整理的基于FreeRTOS与MQTT的物联网技术应用系列——步进电机控制(三)SD卡驱动、FatFS等的移植和ini配置文件读取的实现一、添加SD卡驱动代码、移植FatFS二、移植minIni库的全部内容,希望文章能够帮你解决基于FreeRTOS与MQTT的物联网技术应用系列——步进电机控制(三)SD卡驱动、FatFS等的移植和ini配置文件读取的实现一、添加SD卡驱动代码、移植FatFS二、移植minIni库所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部