
参考了一下源代码
02600 void TIM_ClearFlag(TIM_TypeDef TIMx, uint16_t TIM_FLAG)
02601 {
02602 / Check the parameters /
02603 assert_param(IS_TIM_ALL_PERIPH(TIMx));
02604 assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG));
02605
02606 / Clear the flags /
02607 TIMx->SR = (uint16_t)~TIM_FLAG;
02676 void TIM_ClearITPendingBit(TIM_TypeDef TIMx, uint16_t TIM_IT)
02677 {
02678 / Check the parameters /
02679 assert_param(IS_TIM_ALL_PERIPH(TIMx));
02680 assert_param(IS_TIM_IT(TIM_IT));
02681 / Clear the IT pending Bit /
02682 TIMx->SR = (uint16_t)~TIM_IT;
02683 }
都是对同一个寄存器进行相同 *** 作。。完全一样的……
就是说。。两个函数实现的功能是一样的。。
大概是为了适应不同的编程风格写成了两个函数吧。。我的理解……
读者们,大家好!
接着上一章多功能时钟(绪论)的内容,在这一章中,我将介绍多功能时钟的时钟显示部分。话不多说,我们正式开始吧~
多功能时钟,时钟显示功能是必不可少的。所以,我们利用stm32的定时器来计时。本来打算采用stm32的RTC实时时钟,但后来想,刚开始弄得时候,尽量简单一些,别一开始就给自己出难题,毕竟RTC实时时钟要配置的东西还挺多的。如果此次做得不错的话,后面可以再加RTC实时时钟。
stm32不同于51,共有11个定时器,其中2个高级控制定时器(TIM1和TIM8),4个普通定时器(TIM2~TIM5)和2个基本定时器(TIM6和TIM7),以及2个看门狗定时器和1个系统滴答定时器。这里,我们采用普通定时器TIM2,并且开启定时器的中断,中断时间为1s,并且在中断函数里,模拟时钟的计时功能。
(1)配置嵌套中断控制器NVIC
void tim2_nvic_config(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructNVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructNVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2
NVIC_InitStructNVIC_IRQChannelSubPriority = 0;//子优先级为0
NVIC_InitStructNVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
这里,我们只需对NVIC_InitStruct结构体的每个元素赋值,其中TIM2_IRQn为定时器TIM2中断线,设置优先级组为2,即抢占优先级组为4组,这里抢占优先级为2,子优先级为0,然后使能NVIC(优先级不能理解上网查询)。
(2)定时器初始化配置
void tim2_config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
tim2_nvic_config(); //配置NVIC
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启时钟
TIM_DeInit(TIM2); //定时器2复位
TIM_TimeBaseInitStructTIM_Period = 2000-1; //自动重装载寄存器值
TIM_TimeBaseInitStructTIM_Prescaler = 36000-1; //时钟预分频数
TIM_TimeBaseInitStructTIM_ClockDivision = TIM_CKD_DIV1; //采样分频
TIM_TimeBaseInitStructTIM_CounterMode = TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); //初始化TIM2
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除溢出中断标志
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE); //使能时钟
}
TIM2初始化,首先配置NVIC,打开TIM2时钟,复位TIM2。然后对TIM_TimeBaseInitStruct结构体的每个元素赋值。这里,主要阐述如何计算定时中断时间。定时器的溢出中断时间由TIM_Period和TIM_Prescaler来决定的。这里,我直接给出公式:发生中断时间=(TIM_Period+1)(TIM_Prescaler+1)/FCLK,而FCLK为72M,所以定时1s,可以这样:TIM_Period=2000-1,TIM_Prescaler=36000-1;最后清除溢出中断标志,使能时钟即可计时。
(3)编写中断计时函数
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2 ,TIM_IT_Update)!=RESET)
{
sec++;
if(sec>=60)
{
sec = 0;
min++;
if(min>=60)
{
min = 0;
hour++;
if(hour>=24)
{
hour = 0;
}
}
}
}
TIM_ClearITPendingBit(TIM2 ,TIM_FLAG_Update);
}
这里,先定义时、分、秒三个变量,然后在中断函数里,对时间变量的关系进行换算即可。
(4)编写时钟显示函数
这里,我们采用LCD12864实时显示。LCD12864的相关内容,我后面在LCD库函数章节中,会专门介绍的。这里,只将时间显示即可。
lcd_display_num_m(2, 16, hour/10);
lcd_display_num_m(2, 24, hour%10);
lcd_display_string(2,32,"时");
lcd_display_num_m(2, 48, min/10);
lcd_display_num_m(2, 56, min%10);
lcd_display_string(2,64,"分");
lcd_display_num_m(2, 80, sec/10);
lcd_display_num_m(2, 88, sec%10);
lcd_display_string(2,96,"秒");
LCD12864的驱动函数,我跟着黄老师的视频后面写的,在老师的基础上,增加了汉字字符串显示函数。这里,看成库函数即可,只需简单的调用,显示时间就行。
(5)按键调整时间
成功显示时间后,我们需要按键来调整时间。 我们需要设置时钟启/停键(K1),时间位选择键(K2),数值增加键(K3),数值减小键(K4)。
1我们先对按键的GPIO进行配置,开启相应的时钟,选择相关引脚,设置浮空输入模式等。
void key_gpio_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/使能GPIO的RCC时钟/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
/配置PB11~PB14引脚/
GPIO_InitStructureGPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;
GPIO_InitStructureGPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructureGPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
2配置好按键的GPIO口后,编写按键扫描函数,从而达到调整时间的功能。
u8 flag,mark;//flag为定时器启停标志位,mark为位选择标志位
//mark为0表示未选中,mark为1表示选择时位,mark为2表示选择分位,mark为3表示选择秒位
void keyscan(void)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)
{
flag = ~flag;
if(!flag)
{
TIM_Cmd(TIM2, ENABLE);
}
else
{
TIM_Cmd(TIM2, DISABLE);
mark = 0;
}
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)
{
mark = mark>=30:mark+1;
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)
{
if(flag)
{
switch(mark)
{
case 1:hour = hour<23hour+1:0;break;
case 2:min = min<59min+1:0;break;
case 3:sec = sec<59sec+1:0;break;
default:break;
}
}
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)
{
if(flag)
{
switch(mark)
{
case 1:hour = hour>0hour-1:23;break;
case 2:min = min>0min-1:59;break;
case 3:sec = sec>0sec-1:59;break;
default:break;
}
}
}while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET);
}
}
至此,我们完成了时钟显示的功能,当然,后期如果可以的话,我们可以使用stm32的RTC实时时钟资源,还可以设置闹钟、整点报时的功能。
本章,我主要介绍了如何利用stm32的TIM定时器和GPIO资源,实现时钟显示和按键调整的功能。下一章中,我将介绍如何利用DHT11模块来测量温度和湿度,从而实现系统对环境参量的获取。
注:一开始在无线传输模块的选材上有串口wifiESP8266和NRF24L01两个,先选择了ESP8266进行测试,这个wifi模块传输距离,面对阻隔物体的传输比NRF24L01强,但是经过深入学习总结,这个模块传输速度很慢,因为限制在了串口的速率上,比如115200的波特率计算下来10kb/s左右的传输速率,而NRF24L01则是115kb/s的传输速率,所以最后放弃了ESP8266局限于各方面因素只能选择NRF24L01,如果有后生的话,有能力的话,建议选择sdio接口的WIFI模块。这个模块是我在正点原子论坛上了解到的,速度很块。
1利用定时器公式计算出TIMx_ARR(计数个数(自动重载寄存器(TIMx_ARR)))和TIMx_psc(分频系数)(例如:72Mhz ARR=9999,PSC=7199)
2初始化定时器:TIM_TimeBaseInit()
3打开时钟RCC
4清除标志位 :TIM_ClearFlag() (时间由高电平到低电平)
5使能定时器:TIM_Cmd() (打开定时器)
6判断是否定时完毕:TIM_GetFlagStatus() (判断是否高电平)
例如:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);//打开TIM6的外设时钟 改时钟在这里改,改成要求的时钟
TIM_TimeBaseStructureTIM_Prescaler = 4799;
TIM_TimeBaseStructureTIM_CounterMode = TIM_CounterMode_Up;//向上计数 改计数模式在这里改 改为 TIM_CounterMode_Down 向下计数
TIM_TimeBaseStructureTIM_Period = 1999;//秒数在这里改 05秒对应4999 1秒对应9999 两秒对应19999
TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);//这里改为对应的TIM
TIM_ClearFlag(TIM7, TIM_FLAG_Update);//这里改为对应的TIM
TIM_ITConfig(TIM7, TIM_IT_Update,ENABLE);//这里改为对应的TIM使能定时器中断
TIM_Cmd(TIM7, ENABLE);//使能或者失能TIMx外设
TIM_GetFlagStatus(TIM7, TIM_FLAG_Update);//检查指定的TIM标志位设置与否
注意:mainc文件中一定要添加头文件名 #include"stm32f10xh"
1设置外部中断初始化函数 :EXTI_Init()
2打开复用功能时钟(AFIO)(AFIO属于APB2)
3设置管脚中断函数:GPIO_EXTILineConfig()
4设置优先级初始化函数NVIC_Config()
5设置中断信号输入管脚初始化函数:GPIO_con()
6编写中断服务函数
中断服务函数列表:
1EXTI0_IRQHandler
2EXTI2_IRQHandler
3EXTI3_IRQHandler
4EXTI4_IRQHandler
5EXTI9_5_IRQHandler
1EXTI15_10_IRQHandler
以上就是关于STM32的TIM_ClearFlag TIM_ClearITPendingBit 区别全部的内容,包括:STM32的TIM_ClearFlag TIM_ClearITPendingBit 区别、基于stm32的多功能时钟1——时钟显示、用stm32F407捕获遥控器的PWM值,程序烧录进去后一直只运行到中断函数的config函数之前,什么原因附源码等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)