STM32F103增强型系列产品包含:2个高级控制定时器、4个通用定时器、2个基本定时器、1个实时时钟、2个看门狗定时器和1个系统滴答定时器。
4个通用定时器(TIM2、3、4、5):每个定时器都有一个16位的自动加载递增/递减计数器、一个16位的预分频器和4个独立的通道。它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获),或者产生需要的输出波形(输出比较、产生PWM、单脉冲输出等)。
2个16位高级控制定时器(TIM1、8):由一个可编程预分频器驱动的16位自动装载计数器组成,与通用定时器有许多共同之处,但其功能强大,适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输出比较,产生PWM,具有带死区插入的互补PWM输出、单脉冲输出等)。
2个基本定时器(TIM6、7)主要用于产生DAC触发信号,也可做通用的16位时基计数器。
定时器计数模式:向上计数模式、向下计数模式、中央对齐模式。
向上计数模式:计数器从0计数到设定的数值,然后重新从0开始计数并且产生一个计数器溢出事件。
向下计数模式:计数器从设定的数值开始向下计数到0,然后自动从设定的数值重新向下计数,并产生一个向下溢出事件。
中央对齐模式(向上/向下计数):计数器从0开始计数到设定的数值-1,产生一个计数器溢出事件,然后向下计数到0并且产生一个计数器下溢事件;再从0开始重新计数。
定时器的工作频率:CK_CNT 表示定时器工作频率,TIMx_PSC 表示分频系数
则定时器的工作频率计算公式为:
CK_CNT=定时器时钟/ (TIMx_PSC +1)
由此可得到STM32单片机1个时钟周期为: T=1/ CK_CNT
定时时间的计算:定时时间由TIM_TimeBaseInitTypeDef中的TIM_Prescaler和TIM_Period设定。TIM_Period表示经过TIM_Period次计数后才会发生一次更新或中断。TIM_Prescaler是时钟预分频数。
设脉冲频率为TIMxCLK,定时公式为:
T = (TIM_Period + 1)× (TIM_Prescaler + 1)/ TIMxCLK
假设系统时钟是72MHz,时钟系统部分初始化程序如下所述:
TIM_TimeBaseStructure.TIM_Prescaler = 35999; //分频35999
TIM_TimeBaseStructure.TIM_Period = 1999; //计数值1999
定时时间为
T = (TIM_Period + 1)× (TIM_Prescaler + 1)/ TIMxCLK = (1999 + 1)× (35999 + 1)/ 72M = 1s
实现功能:用定时器2,以中断方式实现PA3口LED灯闪烁功能,闪烁频率1Hz。
实现步骤:
void GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void Tim2_Init(void)
{
TIM_TImeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器外设时钟
TIM_TimeBaseStructure.TIM_Period = 10000 - 1; //设置定时器初值为9999
TIM_TImeBaseStructure.TIM_Prescaler = 7200 - 1; //设置定时器分频为7199
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_up; //向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除TIM2中断标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能定时器2的中断功能
TIM_Cmd(TIM2, ENABLE); //使能定时器2
}
void NVIC_Configuration()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道使能
NVIC_Init(&NVIC_InitStructure)
}
void TIM2_IRQHandler(void)
{
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) == 0)
GPIO_SetBits(GPIOA, GPIO_Pin_3);
else
GPIO_ResetBits(GPIOA, GPIO_Pin_3);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
}
int main()
{
GPIO_Init();
Tim2_Init();
NVIC_Configuration();
while(1);
}