Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
stm32F4
输入捕获
20
stm32 定时器输入捕获驱动求助
发布于 2023-01-13 09:37:07 浏览:1377
订阅该版
各位大佬好,打扰了。最近尝试在 stm32f413 是使用定时器输入捕获测试频率,主要参照网上的各种例程以及这个 PR: https://github.com/RT-Thread/rt-thread/pull/6009 用另一个定时器输出 PWM 来测试,结果发现不进中断。不知该如何改了,请问有用过此功能的大佬吗? 请帮忙看一下这样写的是否正确,谢谢! 目前参考各种例程杂糅得到代码如下: ```CXX #include
#define LOG_TAG "drv.drv.tcap" #include
#define MAX_PERIOD 65535 #define MAX_PULSE 1000 struct stm32_capture { TIM_HandleTypeDef tim_handle; const char *name; rt_uint8_t channel; IRQn_Type tim_irqn; }; extern void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim); static rt_uint64_t get_timer_clock(TIM_HandleTypeDef *htim) { rt_uint64_t tim_clock = 0; #if defined(SOC_SERIES_STM32F2) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) if (htim->Instance == TIM9 || htim->Instance == TIM10 || htim->Instance == TIM11 || htim->Instance == TIM1 || htim->Instance == TIM8) #elif defined(SOC_SERIES_STM32L4) if (htim->Instance == TIM15 || htim->Instance == TIM16 || htim->Instance == TIM17) #elif defined(SOC_SERIES_STM32MP1) if (htim->Instance == TIM4) #elif defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) if (0) #endif { #if !defined(SOC_SERIES_STM32F0) && !defined(SOC_SERIES_STM32G0) tim_clock = HAL_RCC_GetPCLK2Freq() * 2; #endif } else { #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) tim_clock = HAL_RCC_GetPCLK1Freq(); #else tim_clock = HAL_RCC_GetPCLK1Freq() * 2; #endif } return tim_clock; } static rt_err_t stm32_hw_capture_init(struct stm32_capture *device) { TIM_HandleTypeDef *tim = RT_NULL; TIM_IC_InitTypeDef ic_config = {0}; TIM_MasterConfigTypeDef master_config = {0}; TIM_ClockConfigTypeDef clock_config = {0}; rt_uint64_t tim_clock = 0; RT_ASSERT(device != RT_NULL); tim = (TIM_HandleTypeDef *)&device->tim_handle; tim_clock = get_timer_clock(tim) / 1000000; /* configure the timer to ic mode */ tim->Init.Prescaler = tim_clock-1; tim->Init.CounterMode = TIM_COUNTERMODE_UP; tim->Init.Period = MAX_PERIOD-1; tim->Init.AutoReloadPreload = MAX_PERIOD-1; tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; #if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4) tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; #else tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; #endif if (HAL_TIM_Base_Init(tim) != HAL_OK) { LOG_E("%s ic init failed", device->name); return -RT_ERROR; } if (HAL_TIM_IC_Init(tim) != HAL_OK) { LOG_E("%s ic init failed", device->name); return -RT_ERROR; } HAL_NVIC_SetPriority(device->tim_irqn, 0, 0); HAL_NVIC_EnableIRQ(device->tim_irqn); clock_config.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(tim, &clock_config) != HAL_OK) { LOG_E("%s clock init failed", device->name); return -RT_ERROR; } master_config.MasterOutputTrigger = TIM_TRGO_RESET; master_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(tim, &master_config) != HAL_OK) { LOG_E("%s master config failed", device->name); return -RT_ERROR; } ic_config.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; ic_config.ICSelection = TIM_ICSELECTION_DIRECTTI; ic_config.ICPrescaler = TIM_ICPSC_DIV1; ic_config.ICFilter = 0; /* config inputcapture channel */ if (HAL_TIM_IC_ConfigChannel(tim, &ic_config, TIM_CHANNEL_3) != HAL_OK) { LOG_E("%s channel3 config failed", device->name); return -RT_ERROR; } /* enable update request source */ __HAL_TIM_URS_ENABLE(tim); __HAL_TIM_ENABLE_IT(tim,TIM_IT_UPDATE); return RT_EOK; } static rt_err_t stm32_hw_capture_start(struct stm32_capture *device) { TIM_HandleTypeDef *tim = RT_NULL; RT_ASSERT(device != RT_NULL); tim = (TIM_HandleTypeDef *)&device->tim_handle; // HAL_TIM_Base_Start(tim); HAL_TIM_IC_Start_IT(tim, TIM_CHANNEL_3); return RT_EOK; } static struct stm32_capture _capture = { .tim_handle = TIM2, .name = "tc2ch3", .channel = 0x04, .tim_irqn = TIM2_IRQn, }; void TIM2_IRQHandler(void) { rt_kprintf("TIM2_IRQHandler\n"); /* enter interrupt */ rt_interrupt_enter(); HAL_TIM_IRQHandler(&_capture.tim_handle); /* leave interrupt */ rt_interrupt_leave(); } /* USER CODE BEGIN 1 */ //[7]:0,没有成功的捕获;1,成功捕获到一次. //[6]:0,还没捕获到低电平;1,已经捕获到低电平了. //[5:0]:捕获低电平后溢出的次数 uint8_t TIM2CH2_CAPTURE_STA; // 输入捕获状态 uint16_t TIM2CH2_CAPTURE_VAL; // 输入捕获值 // 溢出回调函数和捕获回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if ((TIM2CH2_CAPTURE_STA & 0x80) == 0) // 还未捕获成功 { if (TIM2CH2_CAPTURE_STA & 0x40) // 已捕获到一个上升沿 { if ((TIM2CH2_CAPTURE_STA & 0x3F) == 0x3F) // 高电平的时间太长 { TIM2CH2_CAPTURE_STA |= 0X80; // 标记为成功捕获一次 TIM2CH2_CAPTURE_VAL = 0XFFFF; } else TIM2CH2_CAPTURE_STA++; // 否则标记溢出数加1 } } } // 捕获中断发生时执行 上升沿复位开始计时,下降沿获取捕获值计算 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if ((TIM2CH2_CAPTURE_STA & 0X80) == 0) // 还未捕获成功 [7]:0,没有成功的捕获;1,成功捕获到一次. { if (TIM2CH2_CAPTURE_STA & 0X40) // 成功率捕获到1个下降沿 [6]:0,还没捕获到低电平;1,已经捕获到低电平了. { rt_kprintf("get down: %d\r\n", rt_tick_get()); TIM2CH2_CAPTURE_STA |= 0X80; // 标记成功,捕获到1次高电平完成 TIM2CH2_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&_capture.tim_handle, TIM_CHANNEL_3); // 捕获当前设置捕获值 TIM_RESET_CAPTUREPOLARITY(&_capture.tim_handle, TIM_CHANNEL_3); // 清除原来设置 TIM_SET_CAPTUREPOLARITY(&_capture.tim_handle, TIM_CHANNEL_3, TIM_ICPOLARITY_RISING); // 捕获到下降沿之后,将捕获到复位为上升沿 } else // 捕获到一个上升沿 { rt_kprintf("get up: %d\r\n", rt_tick_get()); TIM2CH2_CAPTURE_STA = 0; TIM2CH2_CAPTURE_VAL = 0; TIM2CH2_CAPTURE_STA |= 0X40; // 将STA置为0x40 当下一次触发中断时,会进入上面的if语句 __HAL_TIM_DISABLE(&_capture.tim_handle); // 关闭定时器 __HAL_TIM_SET_COUNTER(&_capture.tim_handle, 0); // 将定时器计数值清零 TIM_RESET_CAPTUREPOLARITY(&_capture.tim_handle, TIM_CHANNEL_3); // 清除输入捕获标志位 TIM_SET_CAPTUREPOLARITY(&_capture.tim_handle, TIM_CHANNEL_3, TIM_ICPOLARITY_FALLING); // 将输入捕获上升沿改为捕获下降沿 __HAL_TIM_ENABLE(&_capture.tim_handle); // 使能定时器,开启定时器 } } } int stm32_time_capture_init(void) { stm32_hw_capture_init(&_capture); stm32_hw_capture_start(&_capture); return 0; } INIT_APP_EXPORT(stm32_time_capture_init); ```
查看更多
潇潇熊
2023-01-15
这家伙很懒,什么也没写!
定时器同时捕获4个通道的PWM代码 ```c /* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-09-16 Administrator the first version */ #include
#include
#include
TIM_HandleTypeDef htim8; #define POWER1_CTRL GET_PIN(H,2) /** * @brief TIM8 Initialization Function * @param None * @retval None */ static void MX_TIM8_Init(void) { /* USER CODE BEGIN TIM8_Init 0 */ /* USER CODE END TIM8_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_IC_InitTypeDef sConfigIC = {0}; /* USER CODE BEGIN TIM8_Init 1 */ /* USER CODE END TIM8_Init 1 */ htim8.Instance = TIM8; htim8.Init.Prescaler = 180-1; htim8.Init.CounterMode = TIM_COUNTERMODE_UP; htim8.Init.Period = 65535; htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim8.Init.RepetitionCounter = 0; htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim8) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_Init(&htim8) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim8, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_ConfigChannel(&htim8, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_ConfigChannel(&htim8, &sConfigIC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_ConfigChannel(&htim8, &sConfigIC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } __HAL_TIM_DISABLE(&htim8); //关闭定时器8 __HAL_TIM_SET_COUNTER(&htim8,0); HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_1); //开启TIM8的捕获通道1,并且开启捕获中断 HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_2); //开启TIM8的捕获通道2,并且开启捕获中断 HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_3); //开启TIM8的捕获通道3,并且开启捕获中断 HAL_TIM_IC_Start_IT(&htim8,TIM_CHANNEL_4); //开启TIM8的捕获通道4,并且开启捕获中断 __HAL_TIM_ENABLE_IT(&htim8,TIM_IT_UPDATE); //使能更新中断 __HAL_TIM_ENABLE(&htim8);//使能定时器8 } /** * @brief TIM_Base MSP Initialization * This function configures the hardware resources used in this example * @param htim_base: TIM_Base handle pointer * @retval None */ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(htim_base->Instance==TIM8) { /* USER CODE BEGIN TIM8_MspInit 0 */ /* USER CODE END TIM8_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_TIM8_CLK_ENABLE(); __HAL_RCC_GPIOI_CLK_ENABLE(); /**TIM8 GPIO Configuration PI7 ------> TIM8_CH3 PI6 ------> TIM8_CH2 PI5 ------> TIM8_CH1 PI2 ------> TIM8_CH4 */ GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF3_TIM8; HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); /* TIM8 interrupt Init */ //HAL_NVIC_SetPriority(TIM8_BRK_TIM12_IRQn, 0, 0); //HAL_NVIC_EnableIRQ(TIM8_BRK_TIM12_IRQn); HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn); //HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 0, 0); //HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn); HAL_NVIC_SetPriority(TIM8_CC_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM8_CC_IRQn); /* USER CODE BEGIN TIM8_MspInit 1 */ /* USER CODE END TIM8_MspInit 1 */ } } /** * @brief TIM_Base MSP De-Initialization * This function freeze the hardware resources used in this example * @param htim_base: TIM_Base handle pointer * @retval None */ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) { if(htim_base->Instance==TIM8) { /* USER CODE BEGIN TIM8_MspDeInit 0 */ /* USER CODE END TIM8_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_TIM8_CLK_DISABLE(); /**TIM8 GPIO Configuration PI7 ------> TIM8_CH3 PI6 ------> TIM8_CH2 PI5 ------> TIM8_CH1 PI2 ------> TIM8_CH4 */ HAL_GPIO_DeInit(GPIOI, GPIO_PIN_7|GPIO_PIN_6|GPIO_PIN_5|GPIO_PIN_2); /* TIM8 interrupt DeInit */ //HAL_NVIC_DisableIRQ(TIM8_BRK_TIM12_IRQn); HAL_NVIC_DisableIRQ(TIM8_UP_TIM13_IRQn); //HAL_NVIC_DisableIRQ(TIM8_TRG_COM_TIM14_IRQn); HAL_NVIC_DisableIRQ(TIM8_CC_IRQn); /* USER CODE BEGIN TIM8_MspDeInit 1 */ /* USER CODE END TIM8_MspDeInit 1 */ } } void TIM8_UP_TIM13_IRQHandler(void) { HAL_TIM_IRQHandler(&htim8); } /** * @brief This function handles TIM8 capture compare interrupt. */ void TIM8_CC_IRQHandler(void) { HAL_TIM_IRQHandler(&htim8); } //捕获状态 //[7]:0,没有成功的捕获;1,成功捕获到一次. //[6]:0,还没捕获到低电平;1,已经捕获到低电平了. //[5:0]:捕获低电平后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:4294秒) rt_uint8_t TIM8CH3_CAPTURE_STA = 0; //输入捕获状态 rt_uint16_t TIM8CH3_CAPTURE_VAL; //输入捕获值(TIM8是16位) rt_uint16_t tim8ch3_cnt_zero; rt_uint8_t TIM8CH4_CAPTURE_STA = 0; //输入捕获状态 rt_uint16_t TIM8CH4_CAPTURE_VAL; //输入捕获值(TIM8是16位) rt_uint16_t tim8ch4_cnt_zero; rt_uint8_t TIM8CH2_CAPTURE_STA = 0; //输入捕获状态 rt_uint16_t TIM8CH2_CAPTURE_VAL; //输入捕获值(TIM8是16位) rt_uint16_t tim8ch2_cnt_zero; rt_uint8_t TIM8CH1_CAPTURE_STA = 0; //输入捕获状态 rt_uint16_t TIM8CH1_CAPTURE_VAL; //输入捕获值(TIM8是16位) rt_uint16_t tim8ch1_cnt_zero; //定时器更新中断(计数溢出)中断处理回调函数, 该函数在HAL_TIM_IRQHandler中会被调用 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断(溢出)发生时执行 { rt_interrupt_enter(); if((TIM8CH1_CAPTURE_STA & 0X80)==0)//还未成功捕获 { if(TIM8CH1_CAPTURE_STA & 0X40)//已经捕获到高电平了 { if((TIM8CH1_CAPTURE_STA & 0X3F) == 0X3F)//高电平太长了 { TIM8CH1_CAPTURE_STA |= 0X80; //标记成功捕获了一次 TIM8CH1_CAPTURE_VAL = 0XFFFF; } else TIM8CH1_CAPTURE_STA ++; } } if((TIM8CH2_CAPTURE_STA & 0X80)==0)//还未成功捕获 { if(TIM8CH2_CAPTURE_STA & 0X40)//已经捕获到高电平了 { if((TIM8CH2_CAPTURE_STA & 0X3F) == 0X3F)//高电平太长了 { TIM8CH2_CAPTURE_STA |= 0X80; //标记成功捕获了一次 TIM8CH2_CAPTURE_VAL = 0XFFFF; } else TIM8CH2_CAPTURE_STA ++; } } if((TIM8CH3_CAPTURE_STA & 0X80)==0)//还未成功捕获 { if(TIM8CH3_CAPTURE_STA & 0X40)//已经捕获到高电平了 { if((TIM8CH3_CAPTURE_STA & 0X3F) == 0X3F)//高电平太长了 { TIM8CH3_CAPTURE_STA |= 0X80; //标记成功捕获了一次 TIM8CH3_CAPTURE_VAL = 0XFFFF; } else TIM8CH3_CAPTURE_STA ++; } } if((TIM8CH4_CAPTURE_STA & 0X80)==0)//还未成功捕获 { if(TIM8CH4_CAPTURE_STA & 0X40)//已经捕获到高电平了 { if((TIM8CH4_CAPTURE_STA & 0X3F) == 0X3F)//高电平太长了 { TIM8CH4_CAPTURE_STA |= 0X80; //标记成功捕获了一次 TIM8CH4_CAPTURE_VAL = 0XFFFF; } else TIM8CH4_CAPTURE_STA ++; } } rt_interrupt_leave(); } //定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行 { rt_interrupt_enter(); if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//捕获1发生捕获事件 { if((TIM8CH1_CAPTURE_STA & 0X80) == 0)//还未成功捕获 { if(TIM8CH1_CAPTURE_STA & 0X40) //捕获到一个下降沿 { TIM8CH1_CAPTURE_STA |= 0X80; //标记成功捕获到一次高电平脉宽 TIM8CH1_CAPTURE_VAL = TIM8->CCR1; TIM8->CCER &= ~(1<<1);//配置TIM8通道2上升沿捕获 } else //还未开始,第一次捕获上升沿 { tim8ch1_cnt_zero = TIM8->CCR1; TIM8CH1_CAPTURE_STA = 0; TIM8CH1_CAPTURE_VAL = 0; TIM8CH1_CAPTURE_STA |= 0X40; //标记捕获到了上升沿 TIM8->CCER |= 1<<1;//定时器8通道2设置为下降沿捕获 } } } if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//捕获2发生捕获事件 { if((TIM8CH2_CAPTURE_STA & 0X80) == 0)//还未成功捕获 { if(TIM8CH2_CAPTURE_STA & 0X40) //捕获到一个下降沿 { TIM8CH2_CAPTURE_STA |= 0X80; //标记成功捕获到一次高电平脉宽 TIM8CH2_CAPTURE_VAL = TIM8->CCR2; TIM8->CCER &= ~(1<<5);//配置TIM8通道2上升沿捕获 } else //还未开始,第一次捕获上升沿 { tim8ch2_cnt_zero = TIM8->CCR2; TIM8CH2_CAPTURE_STA = 0; TIM8CH2_CAPTURE_VAL = 0; TIM8CH2_CAPTURE_STA |= 0X40; //标记捕获到了上升沿 TIM8->CCER |= 1<<5;//定时器8通道2设置为下降沿捕获 } } } if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)//捕获3发生捕获事件 { if((TIM8CH3_CAPTURE_STA & 0X80) == 0)//还未成功捕获 { if(TIM8CH3_CAPTURE_STA & 0X40) //捕获到一个下降沿 { TIM8CH3_CAPTURE_STA |= 0X80; //标记成功捕获到一次高电平脉宽 TIM8CH3_CAPTURE_VAL = TIM8->CCR3; TIM8->CCER &= ~(1<<9);//配置TIM8通道3上升沿捕获 } else //还未开始,第一次捕获上升沿 { tim8ch3_cnt_zero = TIM8->CCR3; TIM8CH3_CAPTURE_STA = 0; TIM8CH3_CAPTURE_VAL = 0; TIM8CH3_CAPTURE_STA |= 0X40; //标记捕获到了上升沿 TIM8->CCER |= 1<<9;//定时器8通道3设置为下降沿捕获 } } } if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)//捕获4发生捕获事件 { if((TIM8CH4_CAPTURE_STA & 0X80) == 0)//还未成功捕获 { if(TIM8CH4_CAPTURE_STA & 0X40) //捕获到一个下降沿 { TIM8CH4_CAPTURE_STA |= 0X80; //标记成功捕获到一次高电平脉宽 TIM8CH4_CAPTURE_VAL = TIM8->CCR4; TIM8->CCER &= ~(1<<13);//配置TIM8通道3上升沿捕获 } else //还未开始,第一次捕获上升沿 { tim8ch4_cnt_zero = TIM8->CCR4; TIM8CH4_CAPTURE_STA = 0; TIM8CH4_CAPTURE_VAL = 0; TIM8CH4_CAPTURE_STA |= 0X40; //标记捕获到了上升沿 TIM8->CCER |= 1<<13;//定时器8通道3设置为下降沿捕获 } } } rt_interrupt_leave(); } extern float robot_aims_speed; extern rt_uint8_t mknm4_fx; void forword_check_speed(rt_uint16_t spedd) { float sed_spd_f = 0; if(spedd > 550) { mknm4_fx = 0x09; sed_spd_f = (float)spedd; sed_spd_f = sed_spd_f - 550; robot_aims_speed = sed_spd_f * 0.001; } else if(spedd < 450) { mknm4_fx = 0x06; sed_spd_f = (float)spedd; sed_spd_f = 450 - sed_spd_f; robot_aims_speed = sed_spd_f * 0.001; } else { mknm4_fx = 0x00; robot_aims_speed = 0.0; } } void leftright_check_speed(rt_uint16_t lrdata) { float sed_spd_f = 0; if(lrdata > 550) { mknm4_fx = 0x0F; sed_spd_f = (float)lrdata; sed_spd_f = sed_spd_f - 550; robot_aims_speed = sed_spd_f * 0.001; } else if(lrdata < 450) { mknm4_fx = 0x00; sed_spd_f = (float)lrdata; sed_spd_f = 450 - sed_spd_f; robot_aims_speed = sed_spd_f * 0.001; } else { mknm4_fx = 0x00; robot_aims_speed = 0.0; } } void zhuanxiang_check_speed(rt_uint16_t lrdata) { float sed_spd_f = 0; if(lrdata > 550) { mknm4_fx = 0x00; sed_spd_f = (float)lrdata; sed_spd_f = sed_spd_f - 550; robot_aims_speed = sed_spd_f * 0.0005; } else if(lrdata < 450) { mknm4_fx = 0x0f; sed_spd_f = (float)lrdata; sed_spd_f = 450 - sed_spd_f; robot_aims_speed = sed_spd_f * 0.0005; } else { mknm4_fx = 0x00; robot_aims_speed = 0.0; } } void forback_leftright(rt_uint16_t fbdata,rt_uint16_t lrdata) { float sed_spd_f = 0; if(fbdata > 550) { if(lrdata > 550) { mknm4_fx = 0x52; sed_spd_f = (float)lrdata; sed_spd_f = sed_spd_f - 550; robot_aims_speed = sed_spd_f * 0.0005; rt_kprintf("1\n"); } else if(lrdata < 450) { mknm4_fx = 0x58; sed_spd_f = (float)lrdata; sed_spd_f = 450 - sed_spd_f; robot_aims_speed = sed_spd_f * 0.0005; rt_kprintf("2\n"); } } else if(fbdata < 450) { if(lrdata > 550) { mknm4_fx = 0xa1; sed_spd_f = (float)lrdata; sed_spd_f = sed_spd_f - 550; robot_aims_speed = sed_spd_f * 0.0005; rt_kprintf("3 = %d\n",lrdata); } else if(lrdata < 450) { mknm4_fx = 0xa4; sed_spd_f = (float)lrdata; sed_spd_f = 450 - sed_spd_f; robot_aims_speed = sed_spd_f * 0.0005; //rt_kprintf("4 = %d\n",lrdata); } } else { mknm4_fx = 0x00; robot_aims_speed = 0.0; } } extern rt_uint8_t mknm4_lock_flag; rt_uint32_t extern_tmp_ch3 = 0; #define CSB_PRIORITY 15//任务优先级 static char csb_stack[800]; static struct rt_thread csb_thread; static void csb_entry(void *parameter) { rt_uint8_t print_ct = 0; rt_uint32_t tmp_ch4 = 0; rt_uint32_t tmp_ch3 = 0; rt_uint32_t tmp_ch2 = 0; rt_uint32_t tmp_ch1 = 0; rt_thread_mdelay(2000); MX_TIM8_Init(); rt_pin_mode(POWER1_CTRL, PIN_MODE_OUTPUT); rt_pin_write(POWER1_CTRL, PIN_HIGH); while(1) { rt_thread_mdelay(10); if(TIM8CH1_CAPTURE_STA & 0X80) //成功捕获到了一次高电平 { if((TIM8CH1_CAPTURE_STA & 0X3F) == 0)//还没有溢出过 tmp_ch1 = TIM8CH1_CAPTURE_VAL - tim8ch1_cnt_zero; else tmp_ch1 = (0XFFFF - tim8ch1_cnt_zero) + TIM8CH1_CAPTURE_VAL; if(tmp_ch1 > 2000)//油门通道 { tmp_ch1 = 2000; } else if(tmp_ch1 < 1000) { tmp_ch1 = 1000; } tmp_ch1 = tmp_ch1 - 1000; if(tmp_ch1 < 100) tmp_ch1 = 0; TIM8CH1_CAPTURE_STA = 0; } if(TIM8CH2_CAPTURE_STA & 0X80) //成功捕获到了一次高电平 { if((TIM8CH2_CAPTURE_STA & 0X3F) == 0)//还没有溢出过 tmp_ch2 = TIM8CH2_CAPTURE_VAL - tim8ch2_cnt_zero; else tmp_ch2 = (0XFFFF - tim8ch2_cnt_zero) + TIM8CH2_CAPTURE_VAL; if(tmp_ch2 > 2000)//油门通道 { tmp_ch2 = 2000; } else if(tmp_ch2 < 1000) { tmp_ch2 = 1000; } tmp_ch2 = tmp_ch2 - 1000; if(tmp_ch2 < 100) tmp_ch2 = 0; TIM8CH2_CAPTURE_STA = 0; } if(TIM8CH3_CAPTURE_STA & 0X80) //成功捕获到了一次高电平 { if((TIM8CH3_CAPTURE_STA & 0X3F) == 0)//还没有溢出过 tmp_ch3 = TIM8CH3_CAPTURE_VAL - tim8ch3_cnt_zero; else tmp_ch3 = (0XFFFF - tim8ch3_cnt_zero) + TIM8CH3_CAPTURE_VAL; if(tmp_ch3 > 2000)//左右通道 { tmp_ch3 = 2000; } else if(tmp_ch3 < 1000) { tmp_ch3 = 1000; } tmp_ch3 = tmp_ch3 - 1000; TIM8CH3_CAPTURE_STA = 0; } if(TIM8CH4_CAPTURE_STA & 0X80) //成功捕获到了一次高电平 { if((TIM8CH4_CAPTURE_STA & 0X3F) == 0)//还没有溢出过 tmp_ch4 = TIM8CH4_CAPTURE_VAL - tim8ch4_cnt_zero; else tmp_ch4 = (0XFFFF - tim8ch4_cnt_zero) + TIM8CH4_CAPTURE_VAL; if(tmp_ch4 > 2000)//前后通道 { tmp_ch4 = 2000; } else if(tmp_ch4 < 1000) { tmp_ch4 = 1000; } tmp_ch4 = tmp_ch4 - 1000; TIM8CH4_CAPTURE_STA = 0; } //右手、前ch3-->1000,后ch3-->0,前后走 if(((tmp_ch3 < 450) || (tmp_ch3 > 550)) && ((tmp_ch2 < 450) || (tmp_ch2 > 550))) { //forback_leftright(tmp_ch2,tmp_ch3); mknm4_lock_flag = 0; } else if((tmp_ch3 < 450) || (tmp_ch3 > 550)) { //forword_check_speed(tmp_ch3); mknm4_lock_flag = 0; } /* if(tmp_ch3 < 100) { mknm4_lock_flag = 0; mknm4_fx = 0x0F; robot_aims_speed = 0.2; } */ if((tmp_ch3 < 200)) { //右手、左ch1-->1000,右ch1-->0,横走 if((tmp_ch1 < 450) || (tmp_ch1 > 550)) { leftright_check_speed(tmp_ch1); mknm4_lock_flag = 0; } else { mknm4_lock_flag = 1; mknm4_fx = 0x00; robot_aims_speed = 0.0; } } else { mknm4_lock_flag = 1; mknm4_fx = 0x00; robot_aims_speed = 0.0; } if(tmp_ch1 == 0 && tmp_ch2 == 0 && tmp_ch3 == 0 && tmp_ch4 == 0) { mknm4_lock_flag = 1; mknm4_fx = 0x00; robot_aims_speed = 0.0; } print_ct ++; if(print_ct > 100) { print_ct = 0; rt_kprintf("CH1 = %d,CH2 = %d,CH3 = %d,CH5 = %d\n",tmp_ch1,tmp_ch2,tmp_ch3,tmp_ch4); } extern_tmp_ch3 = tmp_ch3; } } static int csb_sample(void) { rt_thread_init(&csb_thread, "csbsample", csb_entry, RT_NULL, &csb_stack[0], sizeof(csb_stack), CSB_PRIORITY,100); rt_thread_startup(&csb_thread); return 0; } INIT_APP_EXPORT(csb_sample); ```
2
个回答
默认排序
按发布时间排序
用户名由3_15位
2023-01-15
这家伙很懒,什么也没写!
- 我在F767的芯片上用裸机跑过 - 我发现你的代码start函数中只开启了HAL_TIM_IC_Start_IT函数 如下是我开启时的步骤 ```c __HAL_TIM_CLEAR_FLAG(&htim9,TIM_IT_UPDATE);//清除中断标志位,防止一使能定时器就进入中断 HAL_TIM_IC_Start_IT(&htim9, TIM_CHANNEL_2); // 开启输入捕获中断 __HAL_TIM_ENABLE_IT(&htim9,TIM_IT_UPDATE); //使能更新中断 ``` - 另外附上我的输入捕获代码 - 参考代码 https://zhuanlan.zhihu.com/p/351996418 tim.c ```c /* TIM9 init function */ void MX_TIM9_Init(void) { /* USER CODE BEGIN TIM9_Init 0 */ /* USER CODE END TIM9_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_IC_InitTypeDef sConfigIC = {0}; /* USER CODE BEGIN TIM9_Init 1 */ /* USER CODE END TIM9_Init 1 */ htim9.Instance = TIM9; htim9.Init.Prescaler = 108-1; htim9.Init.CounterMode = TIM_COUNTERMODE_UP; htim9.Init.Period = 50000-1; htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim9.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim9) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim9, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_IC_Init(&htim9) != HAL_OK) { Error_Handler(); } sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 15; if (HAL_TIM_IC_ConfigChannel(&htim9, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM9_Init 2 */ /* USER CODE END TIM9_Init 2 */ } void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* TIM9 interrupt Init */ HAL_NVIC_SetPriority(TIM1_BRK_TIM9_IRQn, 1, 0); HAL_NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn); /* USER CODE BEGIN TIM9_MspInit 1 */ /* USER CODE END TIM9_MspInit 1 */ } } ``` ```c void Init(void) { { //输入捕获定时器初始化 __HAL_TIM_CLEAR_FLAG(&htim9,TIM_IT_UPDATE);//清除中断标志位,防止一使能定时器就进入中断 HAL_TIM_IC_Start_IT(&htim9, TIM_CHANNEL_2); // 开启输入捕获中断 __HAL_TIM_ENABLE_IT(&htim9,TIM_IT_UPDATE); //使能更新中断 } } ``` ```c /** * @brief Period elapsed callback in non-blocking mode * @param htim TIM handle * @retval None * @note 定时器中断回调函数 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { /* Prevent unused argument(s) compilation warning */ UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed, the HAL_TIM_PeriodElapsedCallback could be implemented in the user file */ if(htim == (&htim9)) { bldc[0].PW.period_cnt++;//中断计数 } } /** * @brief Input Capture callback in non-blocking mode * @param htim TIM IC handle * @retval None */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { /* Prevent unused argument(s) compilation warning */ UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed, the HAL_TIM_IC_CaptureCallback could be implemented in the user file */ if(htim == (&htim9)) { if(bldc[0].PW.tri_flag==0)//上升沿触发时进入(tri_flag 0 上升沿触发 / 1 下降沿触发) { bldc[0].PW.period_cnt=0;//中断次数清零 __HAL_TIM_SET_COUNTER(&htim9,0); //计数器清零 bldc[0].PW.ccr_cnt=0;//存捕获寄存器获取的值的变量清零 __HAL_TIM_SET_CAPTUREPOLARITY(&htim9, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING);//改变触发极性-下降沿触发 bldc[0].PW.tri_flag=1; } else//下降沿触发时进入 { bldc[0].PW.ccr_cnt = __HAL_TIM_GET_COMPARE(&htim9, TIM_CHANNEL_2);//获取捕获寄存器的值 //ccr_cnt=HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//功能同上 __HAL_TIM_SET_CAPTUREPOLARITY(&htim9, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);//改变触发极性-上降沿触发 bldc[0].PW.tri_flag = 0; bldc[0].PW.end_flag = 1;//捕获完成标志 } if(bldc[0].PW.end_flag==1)//结束捕获 { bldc[0].PW.FOL.Ai = (float)(bldc[0].PW.period_cnt * 50000+(bldc[0].PW.ccr_cnt+1));//脉宽给入FOL输入 if(bldc[0].D.direction == CW) //编码器反馈速度计算公式 V = 频率 * 分钟(60) / 电机每转脉冲个数 bldc[0].get_speed = 1000000 / First_Order_Lag(&bldc[0].PW.FOL,bldc[0].PW.FOL.Ai) *60 / bldc[0].PPR / bldc[0].reduction_ratio; else if(bldc[0].D.direction == CCW) bldc[0].get_speed = -1000000 / First_Order_Lag(&bldc[0].PW.FOL,bldc[0].PW.FOL.Ai) *60 / bldc[0].PPR / bldc[0].reduction_ratio; bldc[0].PW.end_flag=0; } } } ```
撰写答案
登录
注册新账号
关注者
0
被浏览
1.4k
关于作者
a1012112796
这家伙很懒,什么也没写!
提问
29
回答
233
被采纳
27
关注TA
发私信
相关问题
1
编译stm32F407动态模块报错
2
RTT-STUDIO STM32F4 如何配置 开启FPU功能
3
STM32F405RG CAN1发送波特率设置
4
STM32F401RC 用 RT-Thread Studio 烧写不了程序
5
为什么单片机STM32F405RG只能成功烧录一次?
6
rt-thread studio生成的程序写入stm32f405rg无法运行
7
MCU探索版+RT_Thread+Webnet的疑问
8
STM32F407VG启动硬件定时器系统忙类死机
9
STM32F4的虚拟串口 的USB时钟如何配置
10
stm32客户端TCP Client连接不上pc端的TCP Server
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
如何在master上的BSP中添加配置yml文件
2
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
3
RT-Thread 发布 EtherKit开源以太网硬件!
4
rt-thread使用cherryusb实现虚拟串口
5
《C++20 图形界面程序:速度与渲染效率的双重优化秘籍》
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部