1.认识定时器
定时器是一种用于计时的机械或电子装置,广泛应用于各种领域。它的基本原理是通过计数来实现计时功能。定时器内部通常包含一个计数器,该计数器根据输入的时钟信号进行计数,从而计算出时间。
另外定时器还可以用于构造PWM脉冲调制信号,用于电机以及LED等等电子设备的电压控制等等。
定时器的定时周期:
T = (重装载值寄存器的值+1)* (预分频值寄存器的值+1)/ 时钟频率;
2.PWM的构造及定义
PWM(Pulse Width Modulation)控制是一种常见的电子技术,通过调整信号的脉冲宽度来实现对电路或设备的精确控制。这项技术在各个领域都有广泛的应用,从电机控制到照明调光,再到通信信号传输,都发挥着重要作用。
可以通过定时器构造相应的PWM脉冲,通过设置定时器通道的占空比,控制对应通道输出高电平或者低电平的时间。占空比指的是,在定时器的定时周期内,定时器的通道输出高电平或者低电平的时间在定时周期的时间占比。
3.基本定时器的软件驱动
3.1 SDK下载
这里采用国民官网提供的SDK包,以示例工程带领各位道友理解基本定时器的实现。SDK对应的下载链接如下:
- 半导体解决方案--国民技术|官方网站https://www.nationstech.com/support/dow/
资源有中文版本和英文版本的,大家可以根据需求自行下载.
3.2 软件实现
示例工程的路径如下:
该工程的功能可以参考工程中DOC/的readme文件查看,这里不做过多的解释.
/**
* @brief Configures the different system clocks.
*/
void RCC_Configuration(void)
{
/* PCLK1 = HCLK/4 */
RCC_ConfigPclk1(RCC_HCLK_DIV4);//这里选择的时钟频率为4分频,即定时器2的系统时钟为36MHz
/* TIM2 clock enable */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);//开启定时器2的时钟
/* GPIOC clock enable */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);//开启定时器2通道对应IO的时钟
}
/**
* @brief Configure the GPIO Pins.
*/
void GPIO_Configuration(void)//这里就是配置了IO口
{
GPIO_InitType GPIO_InitStructure;
/* GPIOC Configuration:Pin6, 7, 8 and 9 as alternate function push-pull */
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure);
}
/**
* @brief Configure the nested vectored interrupt controller.
*/
void NVIC_Configuration(void)//配置定时器的中断结构体,向中断控制器中注册中断
{
NVIC_InitType NVIC_InitStructure;
/* Enable the TIM2 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
/* System Clocks Configuration */
RCC_Configuration();
/* NVIC Configuration */
NVIC_Configuration();
/* GPIO Configuration */
GPIO_Configuration();
/* ---------------------------------------------------------------
TIM2 Configuration: Output Compare Timing Mode: 定时器的输出频率为6MHz
TIM2 counter clock at 6 MHz
CC1 update rate = TIM2 counter clock / CCR1_Val = 146.48 Hz
CC2 update rate = TIM2 counter clock / CCR2_Val = 219.7 Hz
CC3 update rate = TIM2 counter clock / CCR3_Val = 439.4 Hz
CC4 update rate = TIM2 counter clock / CCR4_Val = 878.9 Hz
--------------------------------------------------------------- */
/* Compute the prescaler value */
PrescalerValue = (uint16_t)(SystemCoreClock / 12000000) - 1;//计算重装载值
/* Time base configuration */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = 65535;//设置预分频值
TIM_TimeBaseStructure.Prescaler = 0;
TIM_TimeBaseStructure.ClkDiv = 0;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);初始化定时器的结构体
/* Prescaler configuration */
TIM_ConfigPrescaler(TIM2, PrescalerValue, TIM_PSC_RELOAD_MODE_IMMEDIATE);//这里设置了定时器2的重装载值
/* Output Compare Timing Mode configuration: Channel1 */
TIM_InitOcStruct(&TIM_OCInitStructure);
TIM_OCInitStructure.OcMode = TIM_OCMODE_TIMING;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR1_Val;//设置定时器2通道1的比较值
TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_HIGH;
TIM_InitOc1(TIM2, &TIM_OCInitStructure);
TIM_ConfigOc1Preload(TIM2, TIM_OC_PRE_LOAD_DISABLE);//这里失能2通道1的重载功能
/* Output Compare Timing Mode configuration: Channel2 */
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR2_Val;//设置定时器2通道2的比较值
TIM_InitOc2(TIM2, &TIM_OCInitStructure);
TIM_ConfigOc2Preload(TIM2, TIM_OC_PRE_LOAD_DISABLE);//这里失能2通道2的重载功能
/* Output Compare Timing Mode configuration: Channel3 */
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR3_Val;//设置定时器2通道3的比较值
TIM_InitOc3(TIM2, &TIM_OCInitStructure);
TIM_ConfigOc3Preload(TIM2, TIM_OC_PRE_LOAD_DISABLE);//这里失能2通道3的重载功能
/* Output Compare Timing Mode configuration: Channel4 */
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = CCR4_Val;//设置定时器2通道4的比较值
TIM_InitOc4(TIM2, &TIM_OCInitStructure);
TIM_ConfigOc4Preload(TIM2, TIM_OC_PRE_LOAD_DISABLE);//这里失能2通道4的重载功能
/* TIM IT enable */
TIM_ConfigInt(TIM2, TIM_INT_CC1 | TIM_INT_CC2 | TIM_INT_CC3 | TIM_INT_CC4, ENABLE);//配置定时器2的中断
/* TIM2 enable counter */
TIM_Enable(TIM2, ENABLE);//使能定时器
while (1)
;
}
上述代码中采用的时钟源为HCLK,即下图所示的时钟频率为72M,所以4分频后对应的APB总线对应的时钟频率为18M,但当APB分频系数为2、4、8时,TIMxCLK=APB总线频率×2,由此定时器的时钟频率为18*2=36MHz,由此得到定时器当前软件配置的定时器的定时周期为:
T = (65535+1)*1 / 36000000 = 0.0018204444444444
约为0.0018秒即1毫秒左右的时间。
工程功能如下图所示:
即代码中设置的CCR寄存器的值与定时器的计数值进行比较,当定时器的计数值大于CCR寄存器的值时就会触发定时器的CCR1,CCR2,CCR3,CCR4的中断,在中断中,则会检测这些中断的标记为,当标记被置为后,定时器对应的通道将会将会输出与未触发中断前相反的电平状态。
中断的处理代码具体如下:
/******************************************************************************/
/* N32G45X Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_n32g45x.s). */
/******************************************************************************/
void TIM2_IRQHandler(void)
{
if (TIM_GetIntStatus(TIM2, TIM_INT_CC1) != RESET)
{
TIM_ClrIntPendingBit(TIM2, TIM_INT_CC1);
/* Pin PC.06 toggling with frequency = 73.24 Hz */
GPIO_WriteBit(GPIOC, GPIO_PIN_6, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_PIN_6)));
capture = TIM_GetCap1(TIM2);
TIM_SetCmp1(TIM2, capture + CCR1_Val);
}
else if (TIM_GetIntStatus(TIM2, TIM_INT_CC2) != RESET)
{
TIM_ClrIntPendingBit(TIM2, TIM_INT_CC2);
/* Pin PC.07 toggling with frequency = 109.8 Hz */
GPIO_WriteBit(GPIOC, GPIO_PIN_7, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_PIN_7)));
capture = TIM_GetCap2(TIM2);
TIM_SetCmp2(TIM2, capture + CCR2_Val);
}
else if (TIM_GetIntStatus(TIM2, TIM_INT_CC3) != RESET)
{
TIM_ClrIntPendingBit(TIM2, TIM_INT_CC3);
/* Pin PC.08 toggling with frequency = 219.7 Hz */
GPIO_WriteBit(GPIOC, GPIO_PIN_8, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_PIN_8)));
capture = TIM_GetCap3(TIM2);
TIM_SetCmp3(TIM2, capture + CCR3_Val);
}
else
{
TIM_ClrIntPendingBit(TIM2, TIM_INT_CC4);
/* Pin PC.09 toggling with frequency = 439.4 Hz */
GPIO_WriteBit(GPIOC, GPIO_PIN_9, (Bit_OperateType)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_PIN_9)));
capture = TIM_GetCap4(TIM2);
TIM_SetCmp4(TIM2, capture + CCR4_Val);
}
}
4.PWM脉冲调制信号的构造,博主在下篇文章中更新