本帖最后由 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只能读出高电平。按键没按或者按下读的都是高电平。
|