完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32输入捕获功能,使用TIM2和TIM3同时捕获8路波形。
工作上的一个需求,要采集两组控制步进电机的信号。就是采集8个通道的方波,测量频率和计脉冲个数。看起来简简单单的东西,磕磕碰碰搞了两天,走了一些弯路,这里写出来记录一下。顺便理解一下输入捕获个多种用法。 1. 硬件设计 首先看一下用到那些IO口。在STM32手册里找这样TIMx_CHx的就是输入捕获的口了。 这里用了TIM2的4个口和TIM3的4个口。 [tr]定义端口[/tr]
2. 定时器和输入捕获配置(初始化) 比较长,大概分为,初始化时钟,初始化端口,初始化定时器,配置中断优先级,设置上升沿,使能中断和定时器。 主程序里的调用 TIM2_Cap_Init(0XFFFF,72-1); //1MHz的频率计数 1 Q:定时器的时间如何计算呢? A:72000000/72=1000000 TIM_ICInitTypeDef TIM_ICInitStructure; void TIM2_Cap_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能定时器2时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能定时器3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能GPIOB时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成输入 并 全部拉低 GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0); GPIO_ResetBits(GPIOA,GPIO_Pin_1); GPIO_ResetBits(GPIOA,GPIO_Pin_2); GPIO_ResetBits(GPIOA,GPIO_Pin_3); GPIO_ResetBits(GPIOA,GPIO_Pin_6); GPIO_ResetBits(GPIOA,GPIO_Pin_7); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成输入 并 全部拉低 GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_ResetBits(GPIOB,GPIO_Pin_0); GPIO_ResetBits(GPIOB,GPIO_Pin_1); //初始化定时器2 TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装值 TIM_TimeBaseStructure.TIM_Prescaler = psc; //设置与分配器 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //配置TIM2 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //配置TIM3 //初始化输入捕获参数 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择输入端口1:CH1 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI1上 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置分配为不分配 TIM_ICInitStructure.TIM_ICFilter = 0x00;//配置输入滤波为不滤波 TIM_ICInit(TIM2,&TIM_ICInitStructure); TIM_ICInit(TIM3,&TIM_ICInitStructure); //下面的都一样,就不一一说明了。 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00; TIM_ICInit(TIM2,&TIM_ICInitStructure); TIM_ICInit(TIM3,&TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00; TIM_ICInit(TIM2,&TIM_ICInitStructure); TIM_ICInit(TIM3,&TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00; TIM_ICInit(TIM2,&TIM_ICInitStructure); TIM_ICInit(TIM3,&TIM_ICInitStructure); //中断分组优先级初始化 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //配置寄存器 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //配置寄存器 //8个通道都设置成,上升沿捕获 TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising); TIM_OC2PolarityConfig(TIM2,TIM_ICPolarity_Rising); TIM_OC3PolarityConfig(TIM2,TIM_ICPolarity_Rising); TIM_OC4PolarityConfig(TIM2,TIM_ICPolarity_Rising); TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Rising); TIM_OC2PolarityConfig(TIM3,TIM_ICPolarity_Rising); TIM_OC3PolarityConfig(TIM3,TIM_ICPolarity_Rising); TIM_OC4PolarityConfig(TIM3,TIM_ICPolarity_Rising); //允许更新中断,允许CCxIE捕获中断 TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABLE);// TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABLE);// //使能定时器 TIM_Cmd(TIM2,ENABLE); TIM_Cmd(TIM3,ENABLE); } 3. 中断函数 这里举一个例子,TIM2_CH1的,其他的复制粘贴改一下就行。 捕获方波的思路就是,捕获两个上升沿,两个上升沿的时间差就是周期。周期取倒数就是频率呗。 u8 TIMCH_STA[8] = {0}; //标志位数组 u16 TIMCH_VAL[8] = {0}; //计时器数组 void TIM2_IRQHandler(void) { if((TIMCH_STA[0]&0X80)==0)//还未捕获到一个完整的周期 { if(TIM_GetITStatus(TIM2,TIM_IT_CC1) != RESET)//捕获1发生捕获事件 { if(TIMCH_STA[0]&0X40) //捕获到第二个上升沿 { TIMCH_STA[0]|=0X80; //标记捕获到一个完整的周期,给主程序处理 TIMCH_VAL[0]=TIM_GetCapture1(TIM2);//获取事件 } else //捕获到第一个上升沿 { TIMCH_STA[0]=0; //清空标志位 TIMCH_VAL[0]=0; //清空计时器 TIM_SetCounter(TIM2,0); //清空定时器 TIMCH_STA[0]|=0X40; //标记捕获到第一个上升沿 } } } } 主程序里就很简单了 for(i=0;i<8;i++)//扫描8个通道的标志位 { if(TIMCH_STA&0X80)//成功捕获到脉冲 { temp = TIMCH_VAL; //获取周期时间 printf("HIGH[%d]:%d usrn",i,temp); //打印输出 TIMCH_STA=0; //复位标志位,开启下一次捕获 } } 4. 注意事项和扩展说明 1. 采样精度 输入一个1KHz的频率,采到的数是999us。也就是1.001KHz,四舍五入就是1KHz。由于电路也没滤波有误差也情有可原。 2. 采样范围 因为定时器的频率是1M,所以10KHz一下的采的才比较准。测试时候给了一个50KHz,采样的数据是19纳秒,也就是52.6KHz,就不太准了。而且计数器的数组也只是U16型,就是说如果频率小于15.25HZ,就溢出了。 所以这个程序的采样范围就是50Hz~5KHz,如果要大或者要小,就得调整程序。就像示波器不也是要调整频率的吗。 3. 如果要采占空比 第一个上升沿和第二个上升沿的时间是周期,那第一个上升沿和第一个下降沿的时间就是高电平的时间,算一下就是占空比了。 在采到上升沿的时候,把捕获改成捕获下降沿,采到下降沿的时候,改成捕获上升沿。就可以算出占空比了。但是实际测试中精度下检了,大概是因为,在中断里面改配置捕获会占用时间。 TIM_OC1PolarityConfig(TIM3,TIM_ICPolarity_Falling);//捕获下降沿。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1828 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1640 浏览 1 评论
1109 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
742 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1698 浏览 2 评论
1955浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
763浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
590浏览 3评论
608浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
575浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-1 23:14 , Processed in 0.641234 second(s), Total 44, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号