地址:http://bbs.5imx3g.com/forum.php?mod=viewthread&tid=70
OP: Ok, I've got it (mostly) worked out thanks to a post here and a post elsewhere. The key is changing polarity of the signal in the IRQ handler. Here, I am assuming that the PWMs are phase aligned, so I only need to check for rising/falling edges of the Channel 1 signal. But this could easily be adapted to allow for PWMs that are not phase-aligned.
Here is my current code, reading 4 PWM signals with a single timer (the ccr[] array holds the current PWM pulse widths):
- // Hold onto the Channel 1 init structure -- we will use it to reverse
- // polarity on every edge interrupt.
- static TIM_ICInitTypeDef TIM_CH1_ICInitStructure;
- #define GPIO_AF_TIM2 GPIO_AF_2
- void ConfigPwmIn() {
- GPIO_InitTypeDef GPIO_InitStructure;
- TIM_ICInitTypeDef TIM_ICInitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- TIM_DeInit(TIM2 );
- /* TIM2 clock enable */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
- /* GPIOC clock enable */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
- /* TIM2 GPIO pin configuration : CH1=PD3, C2=PD4, CH3=PD7, CH4=PD6 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7 | GPIO_Pin_6;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- /* Connect pins to TIM3 AF2 */
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_TIM2 );
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_TIM2 );
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_TIM2 );
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_TIM2 );
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- /* Enable capture*/
- TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
- TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
- TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
- TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
- TIM_CH1_ICInitStructure.TIM_ICFilter = 0;
- TIM_ICInit(TIM2, &TIM_ICInitStructure);
- TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
- TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
- TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
- TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
- TIM_ICInitStructure.TIM_ICFilter = 0;
- TIM_ICInit(TIM2, &TIM_ICInitStructure);
- TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
- TIM_ICInit(TIM2, &TIM_ICInitStructure);
- TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
- TIM_ICInit(TIM2, &TIM_ICInitStructure);
- /* Enable TIM2 */
- TIM_Cmd(TIM2, ENABLE);
- /* Enable CC1-4 interrupt */
- TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
- /* Clear CC1 Flag*/
- TIM_ClearFlag(TIM2, TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4 );
- }
- static volatile uint32_t ccr[4];
- static volatile char pulseState = 0;
- void TIM2_IRQHandler() {
- if (TIM2 ->SR & TIM_IT_CC1 ) {
- TIM2 ->SR &= (~TIM_IT_CC1 );
- if (pulseState == 0) {
- TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
- // Any time we get a rising edge on CH1, we reset the counter. All channels are
- // phase aligned, so they all use this as a reference.
- TIM_SetCounter(TIM2, 0);
- } else {
- TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
- // Pull the value on the falling edge.
- ccr[0] = TIM_GetCapture1(TIM2 );
- }
- pulseState = !pulseState;
- // Reverse polarity.
- TIM_ICInit(TIM2, &TIM_CH1_ICInitStructure);
- }
- if (TIM2 ->SR & TIM_IT_CC2 ) {
- TIM2 ->SR &= (~TIM_IT_CC2 );
- ccr[1] = TIM_GetCapture2(TIM2 );
- }
- if (TIM2 ->SR & TIM_IT_CC3 ) {
- TIM2 ->SR &= (~TIM_IT_CC3 );
- ccr[2] = TIM_GetCapture3(TIM2 );
- }
- if (TIM2 ->SR & TIM_IT_CC4 ) {
- TIM2 ->SR &= (~TIM_IT_CC4 );
- ccr[3] = TIM_GetCapture4(TIM2 );
- }
- }
相关推荐
在STM32中,计时器是一个关键的组件,用于执行定时和计数任务。本文将深入探讨基于STM32的计时器以及如何通过C语言编写相关的智能提醒器代码。 1. **STM32计时器类型** STM32系列芯片提供了多种类型的计时器,包括...
- **输出使能**:使能TIM3计时器,开始输出PWM信号。 ### 总结 本程序通过STM32的TIM3定时器实现了PWM信号的生成,并且支持占空比和频率的调节。通过合理配置时钟系统、GPIO引脚以及定时器参数,可以灵活地控制PWM...
对于初学者来说,这是一个很好的学习资源,能够帮助他们掌握STM32F407的超声波测距和多路PWM输出应用。通过修改程序,不仅可以实现避障小车,还可以应用于舵机控制、伺服电机驱动等多种场合,具有很高的实用性。 ...
本主题将深入探讨如何利用STM32的定时器功能来捕获输入信号的高电平持续时间,这对于计算脉冲宽度、频率测量或任何与时间间隔相关的工作至关重要。 首先,我们需要了解STM32定时器的基本结构。STM32系列微控制器...
输入捕获是微控制器中的一个常见功能,它允许我们精确地测量外部信号的上升沿或下降沿,并根据这些事件触发中断或读取时间戳,从而计算信号的周期和占空比。 首先,我们需要了解STM32F103ZET6这款芯片。它是STM32...
* 输出重定向o配置I/Os o计时器——打断事件给快速PWM关闭,逐周期电流控制,输入捕获给时间测量o输出 blanking 源 STM32H7模拟比较器(COMP)工作模式 * COMP窗口模式:比较器的目的是指示,如果模拟电压比阈值...
通用定时器具备多个捕获/比较通道,能够对输入信号的上升沿或下降沿进行检测,从而捕获当前定时器的值并存储到对应的捕获/比较寄存器(TIMx_CCRx)。 输入捕获的工作过程可以概括为:当TIMx_CHx通道上的信号边沿...
当发送一个脉冲后,计时器开始计时,直到接收到反射回波为止。通过计算时间差乘以声速(大约343m/s在空气中),可以得到与目标物体的距离。 2. STM32微控制器介绍: STM32是意法半导体公司推出的一系列基于ARM ...
STM32F103C8T6 器件具有七个计时器,包括三个 16 位计时器,每个计时器最多支持 4 个输入捕获/输出比较/PWM 或脉冲计数器和四象限编码器输入,一个 16 位电机控制 PWM 计时器,两个看门狗计时器和一个 SysTick 计时...
当TIM2_CNT=TIM2_ARR的值时,TIM2_CNT重新回到0继续计数,PA0电平翻转,输出高电平,此时一个完整的PWM信号就诞生了。 程序分析 在程序中,我们使用定时器配置函数TIM_PWM_Init()来配置TIM2和TIM3。首先,使能TIM2...
### STM32通用定时器学习总结 #### 一、引言 STM32微控制器以其高性能和丰富的外设资源在嵌入式系统开发领域占据着重要地位。...希望通过对本篇文章的学习,能够让大家对STM32通用定时器有一个更加深入的认识。
STM32H750是意法半导体(STMicroelectronics)推出的一款高性能的微控制器,属于STM32 H7系列,具有强大的双核ARM Cortex-M7处理器,适用于高精度的实时应用。本项目主要涉及STM32H750的定时器输入捕获功能,通过...
以计时器API为例,它们按照IP功能被分为基本计时器、捕获、脉宽调制(PWM)等多个类别。 HAL驱动层还实现了运行时故障检测,通过检查所有函数的输入值来确保软件的健壮性。这种动态检测同样适用于用户应用开发和...
在本文中,我们将深入探讨如何基于STM32微控制器实现PWM呼吸灯效果。STM32是一种广泛应用的32位微控制器系列,具有丰富的外设接口和高性能,非常适合于各种嵌入式项目,包括我们的PWM呼吸灯。 首先,我们需要了解...
比如定时器API被分为几个类别,包括基本计时器、捕获、脉冲宽度调制(PWM)等,每个类别都对应硬件的某些功能。 HAL驱动层的源代码是严格按照ANSI-C标准开发的,这意味着它的独立于特定的开发工具。源代码经过...
在本学习笔记中,我们将深入探讨STM32 F103C8T6型号芯片中的三个关键概念:时钟树、滴答计时器(也称为系统定时器)以及定时器定时中断。这些知识点对于理解和有效地使用STM32进行实时控制至关重要。 首先,时钟树...
总之,STM32F103ZE通过巧妙地配置两个定时器,可以有效地实现四路输入捕捉和四路输出功能,这对于资源有限但又需高精度时间控制的项目来说是一个实用的解决方案。实际操作时,开发者需要深入理解STM32定时器的工作...
HAL驱动层是面向功能的而非面向IP(知识产权)的,这意味着其API根据提供功能的不同被分为多个类别,如定时器API被分为基本计时器、捕获或PWM(脉宽调制)类别。HAL驱动层还实现了运行时故障检测功能,通过检查函数...
STM32超声波测距系统是嵌入式开发中的一个常见应用,它结合了微控制器(如STM32F103)的功能与超声波传感器的技术,用于精确测量物体的距离。在这个项目中,STM32F103芯片被用作核心处理器,负责控制超声波传感器并...
例如,定时器API被分为基础计时器、捕获、脉宽调制(PWM)等类别,方便开发者针对不同功能进行操作。 4. 低层APIs(LL):这个API层提供了一个快速、轻量级的、面向专家的硬件接近层。LL API仅适用于一组外设,基于...