打印
[STM32F1]

VSCODE STM32 裸机之定时器

[复制链接]
978|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 zero949079783 于 2021-11-13 20:18 编辑

开发环境:VSCODE(gcc编译链)+STM32CubeMX(也可以使用HUAWEI-LiteOS-Studio) 。
代码:链接:https://pan.baidu.com/s/1uXfIR0GFQOBZPl1NfQP08w  
提取码:6b0c



Tout = ((arr+1)*(psc+1))/Tclk ;
其中:

Tclk:定时器的输入时钟频率(单位MHZ)

Tout:定时器溢出时间(单位为us)

  .TIM_Period = arr;                                 eg;4999

  .TIM_Prescaler = psc;                             eg:7199

   Tout = ((4999+1)×(7199+1))/72 = 500000us = 500ms    /*

* 初始化定时器的时候指定我们分频系数psc,这里是将我们的系统时钟(72MHz)进行分频

* 然后指定重装载值arr,这个重装载值的意思就是当 我们的定时器的计数值 达到这个arr时,定时器就会重新装载其他值.

例如当我们设置定时器为向上计数时,定时器计数的值等于arr之后就会被清0重新计数

* 定时器计数的值被重装载一次被就是一个更新(Update)

* 计算Update时间公式

Tout = ((arr+1)*(psc+1))/Tclk

公式推导详解:

Tclk是定时器时钟源,在这里就是72Mhz

我们将分配的时钟进行分频,指定分频值为psc,就将我们的Tclk分了psc+1,我们定时器的最终频率就是Tclk/(psc+1) MHz

这里的频率的意思就是1s中记 Tclk/(psc+1)M个数 (1M=10的6次方) ,每记一个数的时间为(psc+1)/Tclk ,很好理解频率的倒数是周期,这里每一个数的周期就是(psc+1)/Tclk 秒

然后我们从0记到arr 就是 (arr+1)*(psc+1)/Tclk

举例:比如我们设置arr=7199,psc=9999

我们将72MHz (1M等于10的6次方) 分成了(9999+1)等于 7200Hz

每记录一个数就是1/7200秒

定时器更新(7199+1)*(1/7200)=1s,也就是1s进入一次更新

void TIM_Config(void)
{
    HAL_TIM_Base_Start_IT(&htim1); //打开TIM1中断
    HAL_TIM_Base_Start_IT(&htim8); //开TIM8中断
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance  == TIM1)
    {
        LED_B_TOG();
        if(HAL_GPIO_ReadPin(LED_B_GPIO_Port,LED_B_Pin) == 0) //读取IO状态
        {
            printf("LED_B 开启\r\n");
        }
        else{
            printf("LED_B 关闭\r\n");
        }
    }

    if (htim->Instance  == TIM8)
    {
        LED_R_TOG();
        if(HAL_GPIO_ReadPin(LED_R_GPIO_Port,LED_R_Pin) == 0) //读取IO状态
        {
            printf("LED_R 开启\r\n");
        }
        else{
            printf("LED_R 关闭\r\n");
        }
    }
}









STM32中GPIO_ReadOutputDataBit及GPIO_ReadInputDataBit区别;上拉输入_IPU,下拉输入_IPD,模拟输入_AIN ;开漏输出_Out_OD, 推挽输出_Out_PP ,复用功能的推挽输出_AF_PP,复用功能的开漏输出_AF_OD。

一,GPIO_ReadOutputDataBit及GPIO_ReadInputDataBit区别

简单来讲:GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)读的是GPIOx_IDR,读的是当IO口设置为输入状态时候的IO口值

                GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)读的是GPIOx_ODR,读的是当IO口设置为输出状态时候的IO口值

如果你想详细一点了解这两个函数的区别的话,你可以这样试试,
  就拿那个按键控制LED灯的实验来说吧,
           (1)当你设置KEY为上拉输入,你用GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
            去读IO口状态的时候,若你没有按下按键,你读出来的IO值是1,(因为上拉输入把IO口拉高),当你按下按键的时候,你读出来的IO值是0,(因为按下按键把IO拉低) 。

            当你设置KEY为下拉输入,  去读IO口状态的时候,若你没有按下按键,你读出来的IO值是1,(因为上拉输入把IO口拉高),当你按下按键的时候,你读出来的IO值是0,(因为按下按键把IO拉低) 。下拉输入,GPIO_ReadInputDataBit,按键没按下来读的是高电平,按下读的是低电平。
          (2)当你设置KEY为上拉输入,你用 GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 去读IO口状态的时候, 无论你按不按下按键,你读出来的值都是1,因为用GPIO_ReadOutputDataBit去读IO口,它是可以忽略外部操作(按下按键)对它的影响 它只认可内部的操作(上拉电阻的影响)。
我用实际实验证明过上面的实验现象,我的理解就是这样,可能有错误,希望对你有帮助。
总结:

   (1)如果是端口设置成下拉输入GPIO_ReadInputDataBit,GPIO_ReadOutputDataBit,可以区分高低电平。

   (2)如果是端口设置成开漏输出GPIO_ReadInputDataBit,GPIO_ReadOutputDataBit,可以区分高低电平。GPIO_ReadInputDataBit,                       GPIO_ReadOutputDataBit,可以区分高低电平。

   (3)如果是端口设置成上拉输入GPIO_ReadOutputDataBit只能读出高电平。按键没按或者按下读的都是高电平。



使用特权

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

本版积分规则

33

主题

89

帖子

1

粉丝