courses:embedded_system:输入捕获
输入捕获实验
实验目的
1. 了解输入捕获; 2. 学会配置输入捕获。
实验内容
用TIM5的通道1(PA0)来做输入捕获,捕获PA0上高电平的脉宽,通过串口打印高电平脉宽时间。
实验说明
- main.c
/******************************************************************************* * -------------------------------------------------------------------------------- * 实 验 名 : 输入捕获实验 * 实验说明 : 按键k_up是在定时器5通道1上,通过配置好定时器5输入捕获通道, 按下按键k_up或者连接脉冲发生器即可在串口上打印输出捕获高电平的时间, 在串口助手上显示其输出 ,按下复位开关重新运行 见文件内截图 ,程序设计中所有中断函数都放在中断stm32f10x_it.c文件 * 连接方式 : * 注 意 : 所用函数在头文件.c文件内 *******************************************************************************/ #include "public.h" #include "printf.h" #include "systick.h" #include "input.h" #include "key.h" /**************************************************************************** * Function Name : main * Description : Main program. * Input : None * Output : None * Return : None ****************************************************************************/ int main() { u32 temp; key_init(); // 按键初始化 input_init(); // 输入捕获初始化 printf_init(); // printf初始化 while(1) { if((TIM5CH1_CAPTURE_STA&0x80)) // 成功捕获到了一次完整的高电平 { temp = TIM5CH1_CAPTURE_STA&0x3f; // 取出总共溢出的次数 temp = temp*65536; // 计算溢出时间总和 = 溢出次数 * 每次溢出的计数值65536 temp = temp + TIM5CH1_CAPTURE_VAL; // 得到总的高电平时间,TIM5CH1_CAPTURE_VAL为未溢出那一次的计数值 printf("高电平持续时间为:%d us\r\n", temp); TIM5CH1_CAPTURE_STA = 0; // 开启下一次捕获 } delay_ms(10); } }
- input.c
#include "input.h" u8 TIM5CH1_CAPTURE_STA; // 输入捕获状态(全局变量) u16 TIM5CH1_CAPTURE_VAL; // 输入捕获值(全局变量) /******************************************************************************* * 函 数 名 : input_init * 函数功能 : 输入捕获配置初始化,定时器5通道1输入捕获配置 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void input_init() { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; // 声明一个结构体变量,用来初始化定时器 TIM_ICInitTypeDef TIM5_ICInitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* 开启定时器5时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); // 使能TIM5时钟 TIM_ClearITPendingBit(TIM5,TIM_IT_Update|TIM_IT_CC1); // 清除中断和捕获标志位 TIM_TimeBaseInitStructure.TIM_Period = 0xffff; // 设定计数器自动重装值 TIM_TimeBaseInitStructure.TIM_Prescaler = 71; // 以1Mhz的频率计数 一次即是1us TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 设置时钟分割:TDTS = Tck_tim TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数模式 TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);// 根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 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_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn; // 打开TIM5的全局中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; // 抢占优先级为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; // 响应优先级为1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 中断使能 NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM5,ENABLE); // 使能或者失能TIMx外设 TIM_ITConfig(TIM5, TIM_IT_Update|TIM_IT_CC1, ENABLE ); // 使能或者失能指定的TIM中断 }
中断函数在 stm32f10x_it.c 中
- 中断函数.c
// 当边沿触发器检测到边沿时,进入定时器中断程序 void TIM5_IRQHandler() // 定时器5输入捕获中断函数 { if((TIM5CH1_CAPTURE_STA&0X80)==0) // 还未成功捕获一次完整的高电平(上升沿+下降沿) { if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) // 判断是否为更新中断 { if(TIM5CH1_CAPTURE_STA&0X40) // 第6位为1:已经捕获到高电平了(上升沿) { if((TIM5CH1_CAPTURE_STA&0x3f)==0x3f) // 低5位全为1:高电平太长了 { TIM5CH1_CAPTURE_STA|=0x80; // 强制标记成功捕获了一次完整的高电平 TIM5CH1_CAPTURE_VAL=0xffff; } else { TIM5CH1_CAPTURE_STA++; // 否则让溢出次数加1 } } } } if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET) // 捕获1发生捕获事件 { if(TIM5CH1_CAPTURE_STA&0X40) // 捕获到一个下降沿 { TIM5CH1_CAPTURE_STA|=0X80; // 标记成功捕获到一次上升沿(本次捕获完毕) TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); // 获得TIM5输入捕获1的值 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); // 清除中断标志位 }
注:以上用到的全局变量 TIM5CH1_CAPTURE_STA
功能描述如下
tablelayout
TIM5CH1_CAPTURE_STA | ||
---|---|---|
bit 7 | bit 6 | bit 5~bit 0 |
=1:捕获完成的标志 | =1:捕获到边沿的标志 | 捕获指定电平后定时器溢出的次数,若=11111:溢出次数满,强制结束捕获 |
其中,捕获上升沿/下降沿,高电平/低电平,具体取决于极性的配置。
实验步骤
1. 使用1根1P杜邦线连接核心板PA0连接“自主脉冲发生”单元的J72; 2. 使用1根2P杜邦线连接核心板PA2连接“两路串行通信”单元的TXD1,PA3与RXD1连接;(printf输出定义在USART2上面) 3. “两路串行通信”单元中的卧式开关打在“串行”上,串口线DB1同电脑连接; 4. 在KEIL软件中调试运行“输入捕获”工程文件; 5. 实验现象:打开PC端串口调试助手选择连接串口,设置波特率为9600,字符串显示; 调节脉冲调节电位器,查看不同的高电平时间。
实验任务
1. 按上述步骤调试出结果; 2. 改用独立按键发送高电平,按下按键后观察高电平持续时间的变化; 3. 将程序功能修改为捕获低电平及持续时间; 4. 通过调节自主脉冲发生器模组的占空比,观察并验证两次实验成功捕获的分别是高电平与低电平; 试通过结果估算占空比的值。
任务解答
任务2:
1). 用1p杜邦线连接 PA0 和任意一个独立按键,如K8。 2). 按下按键发送高电平脉冲后被成功捕获,并且显示电平持续时间。 3). 每次按下显示高电平持续时间不一样,整体接近,个别持续时间很短。
任务3:
改为低电平捕获时只需要修改定时器TIM5通道1配置边沿检测的极性。即依次将 input_init() 和 TIM5_IRQHandler() 中的
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; \\ 初始化上升沿捕获 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); \\ 设置为上升沿捕获 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); \\ 设置为下降沿捕获
改为
TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; \\ 初始化下降沿捕获 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); \\ 设置为下降沿捕获 TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); \\ 设置为上升沿捕获
任务4:
高电平捕获结果(自主脉冲发生器占空比调到最大)
高电平持续时间为:98816 us 高电平持续时间为:98738 us 高电平持续时间为:98826 us 高电平持续时间为:98774 us 高电平持续时间为:98818 us 高电平持续时间为:98776 us 高电平持续时间为:98836 us 高电平持续时间为:98785 us 高电平持续时间为:98792 us 高电平持续时间为:98812 us 高电平持续时间为:98332 us 高电平持续时间为:98809 us 高电平持续时间为:98773 us 高电平持续时间为:98834 us 高电平持续时间为:98736 us 高电平持续时间为:98790 us
低电平捕获结果(自主脉冲发生器占空比同上)
低电平持续时间为:450 us 低电平持续时间为:450 us 低电平持续时间为:449 us 低电平持续时间为:449 us 低电平持续时间为:449 us 低电平持续时间为:450 us 低电平持续时间为:450 us 低电平持续时间为:450 us 低电平持续时间为:450 us 低电平持续时间为:449 us 低电平持续时间为:449 us 低电平持续时间为:450 us 低电平持续时间为:449 us 低电平持续时间为:450 us 低电平持续时间为:449 us 低电平持续时间为:450 us
可以验证: \begin{align} \text{占空比 } = \frac{1580247}{1580247+7193} \approx 99.55\% \end{align}