这个实验是用 TIM5 的通道 1( PA0) 来做输入捕获, 捕获 PA0 上高电平的脉宽(用 WK_UP 按键输入高电平),通过串口打印高电平脉宽时间。
初始化里边先设置上升沿为输入捕捉,进入捕捉中断后,记录TIM5_CNT的值,然后配置捕获信号为下降沿捕获,当下降沿到来时,发生捕获,并记录此时的 TIM5_CNT 值。这样,前后两次 TIM5_CNT 之差,就是高电平的脉宽,
同时 TIM5 的计数频率我们是知道的,从而可以计算出高电平脉宽的准确时间。
相应的配置步骤为:
(1)开启TIM5时钟和GPIO时钟,设置PA0为下拉输入- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //使能 TIM5 时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能 GPIOA 时钟
(2)
初始化 TIM5,设置 TIM5 的 ARR 和 PSC。(3)设置TIM5 的输入比较参数,开启输入捕获。(4)使能捕获和更新中断(设置TIM5 的 DIER 寄存器) (5)设置中断分组,编写中断服务函数 。- if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET){}//判断是否为更新中断
- if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET){}//判断是否发生捕获事件
- TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update);//清除中断和捕获标志位
(6)使能定时器(设置TIM5 的 CR1 寄存器)- TIM_Cmd(TIM5,ENABLE ); //使能定时器 5
timer.c中:
- //定时器 5 通道 1 输入捕获配置
- TIM_ICInitTypeDef TIM5_ICInitStructure;
- void TIM5_Cap_Init(u16 arr,u16 psc)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //①使能 TIM5 时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //①使能 GPIOA 时钟
- 215
- //初始化 GPIOA.0 ①
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 设置
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入
- GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0
- GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉
- //②初始化 TIM5 参数
- TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
- TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
- TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //初始化 TIMx
- //③初始化 TIM5 输入捕获通道 1
- TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端 IC1 映射到 TI1 上
- TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
- TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到 TI1 上
- TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
- TIM5_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 配置输入滤波器 不滤波
- TIM_ICInit(TIM5, &TIM5_ICInitStructure); //初始化 TIM5 输入捕获通道 1
- //⑤初始化 NVIC 中断优先级分组
- NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM3 中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级 2 级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级 0 级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
- NVIC_Init(&NVIC_InitStructure); //初始化 NVIC
- TIM_ITConfig( TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//④允许更新中断捕获中断
- TIM_Cmd(TIM5,ENABLE ); //⑥使能定时器 5
- }
- u8 TIM5CH1_CAPTURE_STA=0; //输入捕获状态
- u16 TIM5CH1_CAPTURE_VAL;//输入捕获值
- //⑤定时器 5 中断服务程序
- void TIM5_IRQHandler(void)
- {
- if((TIM5CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
- {
- if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
- {
- 216
- if(TIM5CH1_CAPTURE_STA&0X40) //已经捕获到高电平了
- {
- if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
- {
- TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次
- TIM5CH1_CAPTURE_VAL=0XFFFF;
- }else TIM5CH1_CAPTURE_STA++;
- }
- }
- if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET) //捕获 1 发生捕获事件
- {
- if(TIM5CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
- {
- TIM5CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
- TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
- TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //设置为上升沿捕获
- }else //还未开始,第一次捕获上升沿
- {
- TIM5CH1_CAPTURE_STA=0; //清空
- TIM5CH1_CAPTURE_VAL=0;
- TIM_SetCounter(TIM5,0);
- TIM5CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
- TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //设置为下降沿捕获
- }
- }
- }
- TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //清除中断标志位
- }
其中重要的是TIM5 的中断服务函数,TIM5CH1_CAPTURE_STA,是用来记录捕获状态:
设置 TIM5_CH1 捕获上升沿,这在TIM5_Cap_Init 函数执行的时候就设置好了,然后等待上升沿中断到来, 当捕获到上升沿中断,此时如果 TIM5CH1_CAPTURE_STA 的第 6 位为 0, 则表示还没有捕获到新的上升沿, 就先把TIM5CH1_CAPTURE_STA、 TIM5CH1_CAPTURE_VAL 和 TIM5->CNT 等清零,然后再设置TIM5CH1_CAPTURE_STA 的第 6 位为 1, 标记捕获到高电平, 最后设置为下降沿捕获,等待下降沿到来。如果等待下降沿到来期间,定时器发生了溢出,就在 TIM5CH1_CAPTURE_STA里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记捕获完成(虽然此时还没有捕获到下降沿)。当下降沿到来的时候,先设置 TIM5CH1_CAPTURE_STA 的第 7 位为 1,标记成功捕获一次高电平,然后读取此时的定时器值到 TIM5CH1_CAPTURE_VAL 里面,最后设置为上升沿捕获,回到初始状态。
main.c:
- <span style="font-size:14px;">extern u8 TIM5CH1_CAPTURE_STA; //输入捕获状态
- extern u16 TIM5CH1_CAPTURE_VAL; //输入捕获值
- int main(void)
- {
- u32 temp=0;
- delay_init(); //延时函数初始化
- NVIC_Configuration(); //设置 NVIC 中断分组 2
- uart_init(9600); //串口初始化波特率为 9600
- LED_Init(); //LED 端口初始化
- TIM3_PWM_Init(899,0); //不分频。 PWM 频率=72000/(899+1)=80Khz
- TIM5_Cap_Init(0XFFFF,72-1); //以 1Mhz 的频率计数
- while(1)
- {
- delay_ms(10);
- TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1);
- if(TIM_GetCapture2(TIM3)==300)
- TIM_SetCompare2(TIM3,0);
- if(TIM5CH1_CAPTURE_STA&0X80)//成功捕获到了一次上升沿
- {
- temp=TIM5CH1_CAPTURE_STA&0X3F;
- 218
- temp*=65536;//溢出时间总和
- temp+=TIM5CH1_CAPTURE_VAL;//得到总的高电平时间
- printf("HIGH:%d us\r\n",temp); //打印总的高点平时间
- TIM5CH1_CAPTURE_STA=0; //开启下一次捕获
- }
- }
- }</span>
如果用杜邦线把PB5和PA0连起来,就会看到串口助手里以固定的时间宽度输出。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。