打印
[应用相关]

STM32CubeMX的FatFs中间件访问SD卡失败的解决笔记

[复制链接]
3225|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
在给IoT网关和复杂节点制作IoT开发框架时,打算把FatFs中间件加入到开发框架中,却发现老是在f_mount或f_open函数中出错,但FatFs的设置反复检查都没错,唯一就是更新了STM32CubeMX和STM32Cube库为最新版(2020-4-15)。


1)检查原理图
很多开发板都没有把该引脚连到GPIO上,所以硬件上是不能实现插卡检测功能的。



使用特权

评论回复
沙发
哈根达斯uz|  楼主 | 2022-2-27 23:35 | 只看该作者
2)MX(STUM32CubeMX)做的修改
很多开发板没有用GPIO连接卡座的检测插卡引脚,然后STM32CubeMX的前面的版本是OK的,但新的MX版本加入了一个名为”Platform Settings”,里面有一个关于“插卡检测引脚的设置”,因为没有实际的引脚连接,这里提示感叹号。

使用特权

评论回复
板凳
哈根达斯uz|  楼主 | 2022-2-27 23:43 | 只看该作者

使用特权

评论回复
地板
哈根达斯uz|  楼主 | 2022-2-27 23:43 | 只看该作者
选一个STM32F407ZGT6没用到的引脚,这里是PG15,设为GPIO Input,一定要设为下拉,如下图所示:

使用特权

评论回复
5
哈根达斯uz|  楼主 | 2022-2-27 23:44 | 只看该作者
)加入测试代码,并调试
3.1)插卡、对卡进行写入操作
MX生成代码,在MDK中加入一些测试代码,调试通过(在SD卡上写入字符串,拿到PC上读出正常,并且FatFs的API的返回值全部是FR_OK),如下图所示:

使用特权

评论回复
6
哈根达斯uz|  楼主 | 2022-2-27 23:45 | 只看该作者
3.2)拨卡、对卡进行写入操作
代码同上,测试结果如下:


使用特权

评论回复
7
哈根达斯uz|  楼主 | 2022-2-27 23:46 | 只看该作者
结论
新版的STM32MX给FatFs中间件的配置上进行了改动,主要是针对BSP API,新增了一个Platform Settings,并要求提供一个引脚来专门检测插卡(Detect_SDIO(GPIO:Input) , 为了解决MX生成代码中会在“检查卡状态函数中”总是失败导致的f_open函数失败,解决办法多种多样,比如可以直接改代码也是可行的,我这里是通过拉低一个没用引脚来告诉FatFs中间件的执行流程,卡永远是插入的。

使用特权

评论回复
8
童雨竹| | 2022-10-27 07:02 | 只看该作者

中断信号直接从各外部设备通知中断控制器

使用特权

评论回复
9
Pulitzer| | 2022-10-27 08:05 | 只看该作者

待向GPIO(通用I/O端口)的输入从0变为1时,程序可以一定的间隔来检查GPIO的状态

使用特权

评论回复
10
公羊子丹| | 2022-10-27 10:01 | 只看该作者

来自单 片机内部的定时器和GPIO、串行通信设备UART等外设机器的中断被称为外部设备中断

使用特权

评论回复
11
Wordsworth| | 2022-10-27 11:04 | 只看该作者

定时器输出引脚的设定

使用特权

评论回复
12
Clyde011| | 2022-10-27 12:07 | 只看该作者

多次检查也会给单片机带来负荷,对功耗不利

使用特权

评论回复
13
万图| | 2022-10-27 14:03 | 只看该作者

这样的设定只需在setup()中定义一次便能在整个程序中有效

使用特权

评论回复
14
Uriah| | 2022-10-27 15:06 | 只看该作者

在掌握对象的变化频度时是有效的

使用特权

评论回复
15
帛灿灿| | 2022-10-27 17:02 | 只看该作者

在GR-SAKURA中,从IO30引脚到IO35引脚接收来自外部的中断信号

使用特权

评论回复
16
Bblythe| | 2022-10-27 18:05 | 只看该作者

一种了解状态变化的简单方法

使用特权

评论回复
17
童雨竹| | 2023-9-25 07:02 | 只看该作者

使用的开关管数量多,且要求参数一致性好,驱动电路复杂,实现同步比较困难。这种电路结构通常使用在1KW以上超大功率开关电源电路中。

使用特权

评论回复
18
Pulitzer| | 2023-9-25 08:05 | 只看该作者

需要让电源热稳定,在稳定后再进行测试

使用特权

评论回复
19
Uriah| | 2023-9-25 09:03 | 只看该作者

//*************************************************************************************************
//  Copyright (c)         深圳市赛元微电子有限公司
//        文件名称        :  S_TouchKeyCFG.c
//        作者                :
//        模块功能        :  触控键配置文件
//         版本                :
//         更改记录        :
//        注意事项        :  用户需要配置的文件在S_TouchKeyCFG.h中
//  库版本标记        :
//************************************************************************************************
#include "S_TouchKeyCFG.h"
#include "TKDriver.h"
#include "stdio.h"
//*************************************************************************************
//                844 寄存器定义
//*************************************************************************************
/*PSW*/
sfr         TK_PSW            =         0xD0;        //程序状态字
sbit         TK_CY                =         TK_PSW^7;        //进位  

//===========================================================================
//全局变量定义
unsigned        char        xdata                SOCAPI_TouchKeyStatus;                                        //API接口状态:bit7-一轮扫描完成标志  1:完成         0:未完成
                                                                                                                                            //                           bit6-通道触摸计数溢出标志 1:溢出         0:未溢出
//===============================================================================
//全局变量声明:该区域不可修改
unsigned         int         xdata                RawData [SOCAPI_SET_TOUCHKEY_TOTAL];                       
unsigned         int                xdata                BaseLine[SOCAPI_SET_TOUCHKEY_TOTAL];
unsigned    int                 xdata                FilterData[SOCAPI_SET_TOUCHKEY_TOTAL];                                                                                               
unsigned        char    idata                RestAreaCnt[SOCAPI_SET_TOUCHKEY_TOTAL];                        
unsigned        char    idata                TouchCnt[SOCAPI_SET_TOUCHKEY_TOTAL];                               
unsigned        char    idata                NoTouchCnt[SOCAPI_SET_TOUCHKEY_TOTAL];                         
unsigned        char        xdata                CurrentChannel[SOCAPI_SET_TOUCHKEY_TOTAL];                                                     
unsigned    char    idata             LowFingerDataCnt[SOCAPI_SET_TOUCHKEY_TOTAL];
unsigned        char    xdata                FloatAreaCnt[SOCAPI_SET_TOUCHKEY_TOTAL];
unsigned         char         idata             BaseLineAdjusttmp[SOCAPI_SET_TOUCHKEY_TOTAL];         
int                 xdata             DifferAccum[SOCAPI_SET_TOUCHKEY_TOTAL];
char                    xdata                SetNoiseThreshold;
unsigned         char        idata                ConfirmTouchCnt;
unsigned         char        idata                MultipleDealTpye = 0;

//自定义变量
unsigned         int         idata              UpdateBaseLNum;                                                 // 单键长按计数器
unsigned         int         idata              MultipleLNum;                                                // 多按键干扰计数

//外部变量接口
extern         unsigned        char        data                CurrentChannelMax;                //当前选中的keysensor的个数
extern  bit  bMultiple;        //多按键标志       
extern         bit  GetIsNeedUpdateBaseline(void);
extern  void SetNeedUpdateBaseline(void);
extern  unsigned  int SensorKeyFlag(void);
extern  void MultipleDeal(unsigned char CycleCnt);
extern  void TouchKey_Service(void);

/***************弹簧库独有***************/
#define                SOCAPI_SET_CS_FUNCTION                                                1                //0:表示不进行CS测试,1: 表示进行CS测试,默认0
#define                SOCAPI_INHIBITION_ZONE                                            8                //抑制区间%,设置范围5-10,默认7,即(7*10)%=70% ,连水时加大该参数,对讲机设置小
#define                SOCAPI_MAX_KEY_MUTIPLE                                                300                //多少次干扰更新基线,默认300*5=1500
#define                SOCAPI_MAX_KEY_NUM_INVALID                                        3        //强制更新基线按键限制个数,默认3
/****************************************/

#define                  AppType                                                     0
#define                  IsDoubleKey                                                 1
#define                  AirSeparationDistance                     2
#define           CONFIRMTOUCHCNT                        3
#define           INIT_AUTO_UPDATE_TIME                     4
#define           SET_KEY_CONTI_TIME                     5  
#define           SET_SYNC_UPDATE                                  6
#define           SET_UPDATE_SPEED                                  7       
#define           AUTO_UPDATE_TIME                         8
#define                  FilteredKValue                                         9
#define                  SET_ANTIJAM                                             10
#define                  BAUD                                             11
#define                  DwellTime                                         12
#define           SaveTime                                            13
#define           NOISE                                  16

#define           SET_TOUCH_FREQ                                         0
#define                  SET_RESOLUTION                                         1
#define           SET_GAIN_CFG                                         2
#define           SCANTIME                                                 3
#define           SET_ICHA                                                 4
#define           FINGER_THRESHOLD_H                             6
#define           FINGER_THRESHOLD_L                             7

//**********************************************************************************       
//                                                                 函数接口调用部分                                                                  //
//**********************************************************************************
/**************************************************
*函数名称:unsigned int SetOneKeyPushResetTime(void)
*函数功能:按键最长的输出时间
*入口参数:void
*出口参数:unsigned int SOCAPI_SET_KEY_CONTI_TIME
*备注         :这个返回值的设置, 是根据有多长时间启动TouchKeyRestart()一次
例如10ms 启动一次, 那SOCAPI_SET_KEY_CONTI_TIME*10ms,超过时间后此按键无效。
**************************************************/
unsigned int SetOneKeyPushResetTime(void)   
{          
        return  TKCFG[SET_KEY_CONTI_TIME];
}
/**************************************************
*函数名称:unsignedint  GetBaselineUpdateThreshold(void)
*函数功能:更新速度
*入口参数:void
*出口参数:unsigned  int
*备注         :
**************************************************/
int  GetBaselineUpdateThreshold(void)
{
        return TKCFG[SET_UPDATE_SPEED];
}

/**************************************************
*函数名称:unsigned char GetInitAutoUpdateTime(void)
*函数功能:初始化自动校准次数
*入口参数:void
*出口参数:unsigned  char
*备注         :
**************************************************/
unsigned char GetInitAutoUpdateTime(void)
{
        return  TKCFG[INIT_AUTO_UPDATE_TIME];
}
/**************************************************
*函数名称:unsigned char GetCsFunction(void)
*函数功能:进行CS 测试
*入口参数:void
*出口参数:char SOCAPI_SET_CS_FUNCTION
*备注         :
**************************************************/
char GetCsFunction(void)
{
        return SOCAPI_SET_CS_FUNCTION;
}
/**************************************************
*函数名称:int  GetCurrFingerValue(unsigned char i)
*函数功能:获取当前的finger 值
*入口参数:unsigned char
*出口参数:int
*备注         :
**************************************************/
unsigned int   GetCurrFingerValue(unsigned char i)
{
        return        TKChannelCfg[i][FINGER_THRESHOLD_H]*256+TKChannelCfg[i][FINGER_THRESHOLD_L] ;
}

/**************************************************
*函数名称:unsigned char  GetScanTimeValue(unsigned char i)
*函数功能:获取当前通道的扫描时间
*入口参数:unsigned char
*出口参数:unsigned char
*备注         :
**************************************************/
unsigned char  GetScanTimeValue(unsigned char i)
{
        return TKChannelCfg[i][SCANTIME];
}
/**************************************************
*函数名称:unsigned char IsDoubleKeyOrSlideKey(void)
*函数功能:检测是否是弹簧滑条或者双键
*入口参数:void
*出口参数:unsigned char
*备注         :
**************************************************/
unsigned char IsDoubleKeyOrSlideKey(void)
{
    return TKCFG[IsDoubleKey];
}
/**************************************************
*函数名称:unsigned char  GetBaseLineAdjustValue(unsigned char i)
*函数功能:获取当前通道的基线调整
j
*入口参数:unsigned char
*出口参数:unsigned char
*备注         :
**************************************************/
unsigned char  GetBaseLineAdjustValue(unsigned char i)
{       
     return BaseLineAdjusttmp[i];
}
/**************************************************
*函数名称:unsigned char GetUpConfirmCnt(void)
*函数功能:检测按键弹起次数
*入口参数:void
*出口参数:返回按键弹起确认次数
*备注         :
**************************************************/
unsigned char GetUpConfirmCnt(void)
{
        return ConfirmTouchCnt>>1;
}
/**************************************************
*函数名称:unsigned char GetTKYzCnt(void)
*函数功能:获取按键抑制确认次数
*入口参数:void
*出口参数:返回抑制次数
*备注         :
**************************************************/

unsigned char GetTKYzCnt(void)
{
        return (ConfirmTouchCnt/3);
}

/**************************************************
*函数名称:int GetTKYzThreshold(unsigned char i)
*函数功能:获取按键抑制区间
*入口参数:unsigned char i
*出口参数:返回抑制区间
*备注         :
**************************************************/
int GetTKYzThreshold(unsigned char i)
{       
        unsigned int SetFingerThresholdtmp;
       
        SetFingerThresholdtmp = GetCurrFingerValue(i);
    SetFingerThresholdtmp = SetFingerThresholdtmp*SOCAPI_INHIBITION_ZONE/10;

        return SetFingerThresholdtmp;
}
/**************************************************
*函数名称:void CurrentSensorChoose(void)
*函数功能:当前通道选择
*入口参数:void
*出口参数:void
*备注         :
**************************************************/
void CurrentSensorChoose(void)
{
        unsigned char          i ;
        unsigned char          Ctk_Channel_mark = 0;
        unsigned  int        CurrentSensorKey  ;
       
        CurrentSensorKey = SOCAPI_SET_TOUCHKEY_CHANNEL;
               
        for(i=0;i<16;i++)
        {
                CurrentSensorKey=CurrentSensorKey>>1;
                if(TK_CY)
                {
                        CurrentChannel[Ctk_Channel_mark] = i;                                                //选择触摸当前的通道
                        Ctk_Channel_mark++;
                        if(Ctk_Channel_mark >= SOCAPI_SET_TOUCHKEY_TOTAL)
                                break;
                }               
        }
        CurrentChannelMax = Ctk_Channel_mark;                                                        //当前选择的按键数
}

/**************************************************
*函数名称:unsigned char  GetCfgMsg(unsigned char i)
*函数功能:获取Touch KEY 配置信息
*入口参数:void
*出口参数:int
*备注         :
**************************************************/
unsigned char  GetCfgMsg(unsigned char i)
{
        switch(i)
        {
                 case 0:  return TKChannelCfg[0][SET_TOUCH_FREQ];
                 case 1:  return TKChannelCfg[0][SET_RESOLUTION];
                 case 2:  return TKChannelCfg[0][SET_GAIN_CFG];
                 case 3:  return TKChannelCfg[0][SET_GAIN_CFG];
                 case 4:  return TKCFG[SET_ANTIJAM];
                 default:return 0;                 
        }
}

/**************************************************
*函数名称:void CurrentSensorChoose(void)
*函数功能:初始化TK寄存器
*入口参数:void
*出口参数:void
*备注         :
**************************************************/
void TouchKeyCFGInit(void)
{
        unsigned char          i;
        ConfirmTouchCnt = TKCFG[CONFIRMTOUCHCNT];
        SetNoiseThreshold = TKCFG[NOISE];
        CurrentSensorChoose();
        for(i=0;i<CurrentChannelMax;i++)
        {
          BaseLineAdjusttmp[i] =TKChannelCfg[i][SET_ICHA];;       
        }  
        UpdateBaseLNum = 0;
}

/**************************************************
*函数名称:unsigned int TouchKeyScan(void)
*函数功能:检测按键接口
*入口参数:void
*出口参数:按键通道, 返回的是一个int , 通道数
*备注         :1,  调用触控库检测函数SensorKeyFlag()
                   2,  分析得出16个通道,哪个通道有按下,按下bit 位设置为1,否则为0
                   3,  检测是否需要立即更新baseline:  大于MAX_KEY_RESET_BASELINE 个按键按下时立即更新baseline
                   4,  双键或者单键按下时, 时间大于SetOneKeyPushResetTime()结果时更新baseline
**************************************************/
unsigned  int TouchKeyScan(void)
{
        unsigned char t;
    unsigned char MultipleCnt = 0;//按键计数
        unsigned  int Keyvalue ;
        unsigned  int KeyData = 0;        
       
        if(GetIsNeedUpdateBaseline() == 0)                                //检测是否需要更新baseline
        {
                Keyvalue = SensorKeyFlag();                                        //Sensor判断, 这里如果bMultiple = 1 表示中间有干扰         //分析按键,得出标准的16通道bit 位                                                                               
                for(t=0;t<CurrentChannelMax;t++)
                {
                        Keyvalue = Keyvalue>>1;
                        if(TK_CY)
                        {
                                KeyData |= (0x01 << (CurrentChannel[t]));              
                                MultipleCnt++;                                                       
                        }
                }               
                if(MultipleCnt >= 2)                                                                                  //进入多按键处理
                {                       
                        bMultiple = 1;                       
                        if(MultipleCnt >= SOCAPI_MAX_KEY_NUM_INVALID)
                        {
                                SetNeedUpdateBaseline();                                                         // 立即更新baseline ,例如亚克力板盖上去
                        }
                        else
                        {                                       
                                if(IsDoubleKeyOrSlideKey())
                                {
                                        bMultiple = 0;
                                }                                  
                        }                       
                }                       

                if(bMultiple == 0)                                                        //进入按键判断
                {               
                        if(KeyData != 0x0)                                            //单个按键达到多长时间就update baseline ,松手检测
                        {                       
                                UpdateBaseLNum++;
                        }
                        else       
                        {
                                UpdateBaseLNum = 0;        
                        }
                }       
                else
                {   
                    //考虑基线更新               
                        MultipleLNum++;
                        KeyData = 0x00;
                }

                if(UpdateBaseLNum > SetOneKeyPushResetTime())          //按键超出最长输出时间更新基线
                {
                        SetNeedUpdateBaseline();
                        UpdateBaseLNum = 0;
                }
                               
                if(MultipleLNum >SOCAPI_MAX_KEY_MUTIPLE)                  //干扰计数大于最大计数更新基线
                {
                        SetNeedUpdateBaseline();
                        MultipleDealTpye = 1;
                        MultipleLNum = 0;
                }  
        }                       
        else
        {
                MultipleDeal(TKCFG[AUTO_UPDATE_TIME]);                                                                                //基线复位处理
        }  
       
        return KeyData;
}

/**************************************************
*函数名称:void CTK_ISR(void) interrupt        11
*函数功能:触摸中断服务函数
*入口参数:void
*出口参数:void
*备注         :
**************************************************/
void CTK_ISR(void) interrupt        11
{
   TouchKey_Service();
}



使用特权

评论回复
20
公羊子丹| | 2023-9-25 09:08 | 只看该作者

确保在开关管导通,

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

325

帖子

0

粉丝