STM32定时器实现100毫秒保存一次数据到SD卡

假设使用定时器3每1毫秒定时;保存至SD卡的函数是StartSave();

第一种情况:定时器快,主循环慢

1、代码设计1(错误的设计

int cnt = 0; //计数
//TIM3中断处理函数
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) 
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  
        cnt ++;   
    }
}
void main(void)
{
   代码段1
   while(1)
   {
     代码段2
     if(cnt %100 == 0)
     {
	StartSave();
     }
     代码段3
   }
}

分析:第一种设计经测试发现并没有按照预期的100毫秒间隔保存;原因何在呢?
很明显后台程序运行较快,当cnt 变为100的倍数时,主循环可能到达“代码段3”,当主循环再次到达
“代码段2”时,定时器中断已经改变了cnt的值。

2、代码设计2(在这种情况下正确)

int cnt = 0; //计数
unsigned char isOK = 0;
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) 
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  
        if(cnt++ % 100 == 0)
             isOK = 1;
    }
}
void main(void)
{
   代码段1
   while(1)
   {
     代码段2
     if(isOK == 1)
     {
	isOK = 0;
        StartSave();
     }
     代码段3
   }
}

设计2避免了1中所出现的问题。
第二种情况:定时器慢,主循环快
在这种情况下上面的代码设计2就出现问题了。出现保存多了的情况。
原因很明显,isOK这个变量的变化相对于主循环来说变化太慢了。会出现isOK一直为1 的情况。
假设定时器定时1ms,主循环0.5ms周期
1、代码设计1(错误的设计)

void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) 
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  
        cnt++;//该值理论保持时间仅1ms
    }
}
void main(void)
{
   unsigned char saveFin = 0;
   代码段1
   while(1)
   {
     代码段2
     if(cnt%100 )
     {
        StartSave();//明显出现100ms内多次保存的情况,因为主循环快
     }
     代码段3
   }
}

2、代码设计2(正确的设计)

unsigned char saveFin = 0;
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) 
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  
        cnt++;//该值理论保持时间仅1ms
    }
}
void main(void)
{
   unsigned char saveFin = 0;
   代码段1
   while(1)
   {
     代码段2
     if(cnt%100 == 0 && saveFin == 0 )
     {
        saveFin = 1;
        StartSave();
     }
     else
     {
        saveFin = 0; 
     }
     代码段3
   }
}

第三种情况:不能确定定时器和main循环周期哪个快的设计
当然主循环的周期不能大于保存周期100ms

unsigned char isOK = 0;
unsigned int clkCnt = 0;
void TIM3_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) 
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  ); 
        if(clkCnt++ % 10 == 0)
             cnt++;//该值理论保持时间10ms,需要在主循环中清零
    }
}
void main(void)
{
   unsigned char saveFin = 1;//注意这里的初始值为1,与前面设计不同
   代码段1
   while(1) //循环周期不能大于10ms,否则丢失对cnt的判断
   {
     代码段2
     if(cnt%10 == 0) //例如在100ms--110ms之间时将“保存标志”清零
     {
	saveFin = 0; 
     }
     else  //例如在110ms--200ms之间时完成保存
     {
        if(saveFin == 0)//在110ms--200ms之间只能保存一次的代码设计
        {
           startSave();
           saveFin = 1;
        }
     }
     代码段3
   }
}

 

如果有设计缺陷,欢迎大家参与讨论!

 

### 如何在STM32CubeMX中配置定时器中断 #### 一、硬件与软件准备 为了成功配置定时器中断,需准备好以下软硬件环境: - **硬件平台**:基于目标MCU(如STM32F1、STM32U5等)的开发板。 - **软件工具**:STM32CubeMX 和 Keil MDK 或其他兼容IDE。 确保调试接口已正确设置为Serial Wire模式[^5]。对于某些型号(如STM32U5),未正确配置可能导致设备无法被ST-Link识别。 --- #### 二、创建项目并启用定时器 1. 打开STM32CubeMX,新建一个针对目标MCU的工程。 2. 在Pinout & Configuration界面中,导航至“Timer”选项,选择所需的定时器模块(例如 TIM2 或 TIM3)。 启用该定时器,并将其Mode设置为“Output Compare PWM Mode”。这一步骤适用于需要PWM功能的应用场景;如果是纯计时需求,则可保留默认模式[^4]。 --- #### 三、配置定时器参数 进入Clock Configuration页面调整系统时钟频率后,在Configuration标签页完成如下操作: 1. 设置Prescaler预分频系数以及Period周期值来定义时间基准单位。例如,假设输入时钟为72MHz,希望获得毫秒级精度,则计算公式如下: \[ \text{实际间隔 (ms)} = (\text{Prescaler} + 1) \times (\text{Auto Reload Register Value} + 1) / f_{\text{CLK}} \] 若设定`Prescaler=9000`, `ARR=999`,最终得到约每秒钟触发一次中断[^1]。 2. 切换到Advanced Parameters部分,勾选Update Request Source下的Interrupt Enable项以激活更新事件产生的中断请求源[^3]。 --- #### 四、生成代码及修改回调函数 点击Generate Code按钮让STM32CubeMX自动生成初始化脚本文件夹结构。随后打开生成好的工程项目所在路径下的stm32fxxx_it.c文件定位到对应处理例程位置——即`HAL_TIM_IRQHandler()`方法内部实现逻辑定制化业务流程控制语句序列片段示例如下所示: ```c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if(htim->Instance==TIM2){ //判断是否来自指定定时器号 Toggle_LED(); //调用切换LED状态的方法作为演示动作 } } ``` 上述代码展示了如何利用定时器溢出中断去定期执行某特定任务的操作方式。 --- #### 五、编译下载验证效果 最后回到集成开发环境中完成整个项目的构建过程并将固件镜像烧写入单片机存储空间内即可观察预期现象表现情况啦! --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值