赞
踩
定时器是一种可以计数内部/外部时钟的外设
经过处理后的内部/外部时钟每产生一个方波,定时器内部的寄存器+1
当定时器计数到程序设定值后清零,同时产生中断
定时器可以将时钟分频,并产生中断或驱动其他外设
功能:基础定时器<通用定时器<高级定时器
例如:
先打开Cube进行外设以及时钟树的配置
把红灯的引脚PH12打开
然后可以在旁边外设列表的Timers设置定时器
先激活TIM6,根据公式设置TIM6的PSC(Prescaler)和ARR(Counter Period)
PSC设为84-1(即基础定时器只有主频168MHz一半(即84MHz)的输入)
ARR设为1000-1
最终输出1kHz
然后在TIM6的NVIC Settings中将TIM6的中断启动
然后GENERATE CODE生成代码
先在主函数循环里面加入HAL_Delay,防止程序卡死
/* USER CODE BEGIN 3 */
HAL_Delay(100);
/* USER CODE END 3 */
主函数的代码中
HAL_Init();//启动HAL库
SystemClock_Config();//启动高速时钟
//程序执行完这个函数后芯片工作频率便可达到168MHz
//在此之前只有16MHz
MX_GPIO_Init();
MX_TIM6_Init();//初始化Cube初始化外设
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */ //之间进行初始化代码的编写
然后我们需要先启动定时器在USER CODE BEGIN 2/END 2之间编写,即:
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);//启动TIM6,并使能它的中断
/* USER CODE END 2 */
其中htim6的类型是TIM_HandleTypeDef
TIM_HandleTypeDef是结构体,它的定义如下
typedef struct
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
{
TIM_TypeDef *Instance; /*!< Register base address */
TIM_Base_InitTypeDef Init; /*!< TIM Time Base required parameters */
HAL_TIM_ActiveChannel Channel; /*!< Active channel */
DMA_HandleTypeDef *hdma[7]; /*!< DMA Handlers array
This array is accessed by a @ref DMA_Handle_index */
HAL_LockTypeDef Lock; /*!< Locking object */
__IO HAL_TIM_StateTypeDef State; /*!< TIM operation state */
__IO HAL_TIM_ChannelStateTypeDef ChannelState[4]; /*!< TIM channel operation state */
__IO HAL_TIM_ChannelStateTypeDef ChannelNState[4]; /*!< TIM complementary channel operation state */
__IO HAL_TIM_DMABurstStateTypeDef DMABurstState; /*!< DMA burst operation state */
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
void (* Base_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Base Msp Init Callback */
void (* Base_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Base Msp DeInit Callback */
void (* IC_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM IC Msp Init Callback */
void (* IC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM IC Msp DeInit Callback */
void (* OC_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM OC Msp Init Callback */
void (* OC_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM OC Msp DeInit Callback */
void (* PWM_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Msp Init Callback */
void (* PWM_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Msp DeInit Callback */
void (* OnePulse_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM One Pulse Msp Init Callback */
void (* OnePulse_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM One Pulse Msp DeInit Callback */
void (* Encoder_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Encoder Msp Init Callback */
void (* Encoder_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Encoder Msp DeInit Callback */
void (* HallSensor_MspInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Hall Sensor Msp Init Callback */
void (* HallSensor_MspDeInitCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Hall Sensor Msp DeInit Callback */
void (* PeriodElapsedCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Period Elapsed Callback */
void (* PeriodElapsedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Period Elapsed half complete Callback */
void (* TriggerCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Trigger Callback */
void (* TriggerHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Trigger half complete Callback */
void (* IC_CaptureCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Input Capture Callback */
void (* IC_CaptureHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Input Capture half complete Callback */
void (* OC_DelayElapsedCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Output Compare Delay Elapsed Callback */
void (* PWM_PulseFinishedCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Pulse Finished Callback */
void (* PWM_PulseFinishedHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM PWM Pulse Finished half complete Callback */
void (* ErrorCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Error Callback */
void (* CommutationCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Commutation Callback */
void (* CommutationHalfCpltCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Commutation half complete Callback */
void (* BreakCallback)(struct __TIM_HandleTypeDef *htim); /*!< TIM Break Callback */
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
} TIM_HandleTypeDef;
可以把htim6简单理解为tim6抽象化的外设
由于该结构体参数都是结构体指针
因此我们得取输入参数的地址
然后在USER CODE BEGIN 4/END 4之间写回调函数
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint8_t counter = 0;//额外数数的变量,在函数中只初始化一次
counter++;//进行计数
if(counter==100)//即每100ms将counter清零
{
counter =0;
HAL_GPIO_TogglePin(GPIOH,GPIO_PIN_12);//翻转PH12的电平
}
};
/* USER CODE END 4 */
//函数作用就是每100ms闪灯一次
//HAL_TIM_PeriodElapsedCallback是定时器的回调函数(必须与hal库中的一致)
//该回调函数的参数一定是指针
默认情况下,Cube外设配置栏里的NVIC按照中断向量的先后顺序排序中断
靠上的中断具有更小的中断向量,即更高的中断向量优先级
抢占优先级和次要优先级可以自行设置
Priority Group可以设置两种优先级位数,默认没有次要优先级,4位抢占优先级
位数越大,能设置的级别越多
两种优先级共享4位
HAL内部使用kHz的时钟,很多库函数都会用到这个时钟
该时钟可由系统定时器SYSTICK或者其他定时器产生
一般都不使用系统定时器SYSTICK产生HAL时基
(SYSTICK是内核定时器,一般用于操作系统)
HAL时基由定时器中断产生
回到Cube,在sys中把Timebase Source从SYSTICK改为TIM7(改为以TIM7为时基)
然后在NVIC中配置中断优先级,无论什么时候HAL时基都必须被配置为最低优先级
设置好后生成代码
在main.c中自动生成一个回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM7) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
htim->Instance == TIM7//代表传入参数的寄存器(Instance)是TIM7
//如果传入参数的寄存器(Instance)是TIM7,那么会执行HAL_IncTick()函数
但是由于我们在上面USER CODE BEGIN 4/ END 4之间重新定义了一个同名的回调函数
因此程序在这里会报错
所以我们需要把上面定义的函数剪切到系统生成的回调函数中的
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */之间
并且判断一下是否为TIM6产生的中断
修改后代码如下
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM7) //判断是否为TIM7产生的中断
{
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
if (htim->Instance == TIM6) //判断是否为TIM6产生的中断
{
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint8_t counter = 0;
counter++;
if(counter==100)
{
counter =0;
HAL_GPIO_TogglePin(GPIOH,GPIO_PIN_12);
}
};
}
/* USER CODE END Callback 1 */
}
编译烧录后现象跟之前一样。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。