最近项目中用到了输入捕获。发现rtthread没有stm32的输入捕获驱动。
于是自己做了一个,基于TIM4,其他的TIMER应该没有太大区别,每个通道都可以独立捕获。
#include <board.h>
#define DRV_DEBUG
#define LOG_TAG "drv.tcap"
#include <drv_log.h>
#include <rtconfig.h>
#define BSP_USING_TIMER_CAPTURE
#if defined(BSP_USING_TIMER_CAPTURE)
#include <rtdevice.h>
#include "drv_config.h"
/* Private typedef --------------------------------------------------------------*/
typedef struct stm32_capture_device{
struct rt_inputcapture_device parent;
TIM_HandleTypeDef timer;
uint32_t u32LastCnt;
uint32_t u32PluseCnt;
uint8_t input_data_level;
uint8_t not_first_edge;
uint32_t over_under_flowcount;
IRQn_Type irq;
uint8_t ch;
char* name;
}stm32_capture_device;
/* Private functions ------------------------------------------------------------*/
static rt_err_t stm32_capture_init(struct rt_inputcapture_device *inputcapture);
static rt_err_t stm32_capture_open(struct rt_inputcapture_device *inputcapture);
static rt_err_t stm32_capture_close(struct rt_inputcapture_device *inputcapture);
static rt_err_t stm32_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us);
/* Private define ---------------------------------------------------------------*/
/* Public functions -------------------------------------------------------------*/
/* Private variables ------------------------------------------------------------*/
enum
{
#ifdef BSP_USING_TIMER4_CAPTURE
#ifdef TIMER4_CAPTURE_CHANNEL1
TIMER4_CAPTURE_CH1_INDEX,
#endif
#ifdef TIMER4_CAPTURE_CHANNEL2
TIMER4_CAPTURE_CH2_INDEX,
#endif
#ifdef TIMER4_CAPTURE_CHANNEL3
TIMER4_CAPTURE_CH3_INDEX,
#endif
#ifdef TIMER4_CAPTURE_CHANNEL4
TIMER4_CAPTURE_CH3_INDEX,
#endif
#endif
TIMER_CAPTURE_INDEX_MAX,
};
static struct stm32_capture_device stm32_capture_obj[] =
{
#ifdef BSP_USING_TIMER4_CAPTURE
#ifdef TIMER4_CAPTURE_CHANNEL1
TIMER4_CAPTURE_CH1_CONFIG,
#endif
#ifdef TIMER4_CAPTURE_CHANNEL2
TIMER4_CAPTURE_CH2_CONFIG,
#endif
#endif
};
static struct rt_inputcapture_ops stm32_capture_ops = {
.init = stm32_capture_init,
.open = stm32_capture_open,
.close = stm32_capture_close,
.get_pulsewidth = stm32_capture_get_pulsewidth,
};
/* Functions define ------------------------------------------------------------*/
void capture_updata_isr(struct stm32_capture_device* device)
{
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_UPDATE) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_UPDATE);
for(uint8_t i = 0; i < TIMER_CAPTURE_INDEX_MAX; i++)
device[i].over_under_flowcount++;
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_CC1) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_CC1);
#ifdef TIMER4_CAPTURE_CHANNEL1
uint32_t cnt = HAL_TIM_ReadCapturedValue(&device[TIMER4_CAPTURE_CH1_INDEX].timer, device[TIMER4_CAPTURE_CH1_INDEX].ch);//获取当前的捕获值.
if(!device[TIMER4_CAPTURE_CH1_INDEX].not_first_edge){ //first
device[TIMER4_CAPTURE_CH1_INDEX].not_first_edge = 1;
device[TIMER4_CAPTURE_CH1_INDEX].input_data_level = 0;
}else{
device[TIMER4_CAPTURE_CH1_INDEX].input_data_level = !device[TIMER4_CAPTURE_CH1_INDEX].input_data_level;
device[TIMER4_CAPTURE_CH1_INDEX].u32PluseCnt = cnt + 0xffff * device[TIMER4_CAPTURE_CH1_INDEX].over_under_flowcount - device[TIMER4_CAPTURE_CH1_INDEX].u32LastCnt;
rt_hw_inputcapture_isr(&device[TIMER4_CAPTURE_CH1_INDEX].parent, device[TIMER4_CAPTURE_CH1_INDEX].input_data_level);
}
if(device[TIMER4_CAPTURE_CH1_INDEX].input_data_level)
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH1_INDEX].timer, device[TIMER4_CAPTURE_CH1_INDEX].ch, TIM_INPUTCHANNELPOLARITY_FALLING); //切换捕获极性
else
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH1_INDEX].timer, device[TIMER4_CAPTURE_CH1_INDEX].ch, TIM_INPUTCHANNELPOLARITY_RISING); //切换捕获极性
device[TIMER4_CAPTURE_CH1_INDEX].over_under_flowcount = 0;
device[TIMER4_CAPTURE_CH1_INDEX].u32LastCnt = cnt;
HAL_TIM_IC_Start_IT(&device[TIMER4_CAPTURE_CH1_INDEX].timer, device[TIMER4_CAPTURE_CH1_INDEX].ch);
#endif
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_CC2) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_CC2);
#ifdef TIMER4_CAPTURE_CHANNEL2
uint32_t cnt = HAL_TIM_ReadCapturedValue(&device[TIMER4_CAPTURE_CH2_INDEX].timer, device[TIMER4_CAPTURE_CH2_INDEX].ch);//获取当前的捕获值.
if(!device[TIMER4_CAPTURE_CH2_INDEX].not_first_edge){ //first
device[TIMER4_CAPTURE_CH2_INDEX].not_first_edge = 1;
device[TIMER4_CAPTURE_CH2_INDEX].input_data_level = 0;
}else{
device[TIMER4_CAPTURE_CH2_INDEX].input_data_level = !device[TIMER4_CAPTURE_CH2_INDEX].input_data_level;
device[TIMER4_CAPTURE_CH2_INDEX].u32PluseCnt = cnt + 0xffff * device[TIMER4_CAPTURE_CH2_INDEX].over_under_flowcount - device[TIMER4_CAPTURE_CH2_INDEX].u32LastCnt;
rt_hw_inputcapture_isr(&device[TIMER4_CAPTURE_CH2_INDEX].parent, device[TIMER4_CAPTURE_CH2_INDEX].input_data_level);
}
if(device[TIMER4_CAPTURE_CH2_INDEX].input_data_level)
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH2_INDEX].timer, device[TIMER4_CAPTURE_CH2_INDEX].ch, TIM_INPUTCHANNELPOLARITY_FALLING); //切换捕获极性
else
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH2_INDEX].timer, device[TIMER4_CAPTURE_CH2_INDEX].ch, TIM_INPUTCHANNELPOLARITY_RISING); //切换捕获极性
device[TIMER4_CAPTURE_CH2_INDEX].over_under_flowcount = 0;
device[TIMER4_CAPTURE_CH2_INDEX].u32LastCnt = cnt;
HAL_TIM_IC_Start_IT(&device[TIMER4_CAPTURE_CH2_INDEX].timer, device[TIMER4_CAPTURE_CH2_INDEX].ch);
#endif
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_CC3) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_CC3);
#ifdef TIMER4_CAPTURE_CHANNEL3
uint32_t cnt = HAL_TIM_ReadCapturedValue(&device[TIMER4_CAPTURE_CH3_INDEX].timer, device[TIMER4_CAPTURE_CH3_INDEX].ch);//获取当前的捕获值.
if(!device[TIMER4_CAPTURE_CH3_INDEX].not_first_edge){ //first
device[TIMER4_CAPTURE_CH3_INDEX].not_first_edge = 1;
device[TIMER4_CAPTURE_CH3_INDEX].input_data_level = 0;
}else{
device[TIMER4_CAPTURE_CH3_INDEX].input_data_level = !device[TIMER4_CAPTURE_CH3_INDEX].input_data_level;
device[TIMER4_CAPTURE_CH3_INDEX].u32PluseCnt = cnt + 0xffff * device[TIMER4_CAPTURE_CH3_INDEX].over_under_flowcount - device[TIMER4_CAPTURE_CH3_INDEX].u32LastCnt;
rt_hw_inputcapture_isr(&device[TIMER4_CAPTURE_CH3_INDEX].parent, device[TIMER4_CAPTURE_CH3_INDEX].input_data_level);
}
if(device[TIMER4_CAPTURE_CH3_INDEX].input_data_level)
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH3_INDEX].timer, device[TIMER4_CAPTURE_CH3_INDEX].ch, TIM_INPUTCHANNELPOLARITY_FALLING); //切换捕获极性
else
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH3_INDEX].timer, device[TIMER4_CAPTURE_CH3_INDEX].ch, TIM_INPUTCHANNELPOLARITY_RISING); //切换捕获极性
device[TIMER4_CAPTURE_CH3_INDEX].over_under_flowcount = 0;
device[TIMER4_CAPTURE_CH3_INDEX].u32LastCnt = cnt;
HAL_TIM_IC_Start_IT(&device[TIMER4_CAPTURE_CH3_INDEX].timer, device[TIMER4_CAPTURE_CH3_INDEX].ch);
#endif
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_CC4) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_CC4);
#ifdef TIMER4_CAPTURE_CHANNEL4
uint32_t cnt = HAL_TIM_ReadCapturedValue(&device[TIMER4_CAPTURE_CH4_INDEX].timer, device[TIMER4_CAPTURE_CH4_INDEX].ch);//获取当前的捕获值.
if(!device[TIMER4_CAPTURE_CH4_INDEX].not_first_edge){ //first
device[TIMER4_CAPTURE_CH4_INDEX].not_first_edge = 1;
device[TIMER4_CAPTURE_CH4_INDEX].input_data_level = 0;
}else{
device[TIMER4_CAPTURE_CH4_INDEX].input_data_level = !device[TIMER4_CAPTURE_CH4_INDEX].input_data_level;
device[TIMER4_CAPTURE_CH4_INDEX].u32PluseCnt = cnt + 0xffff * device[TIMER4_CAPTURE_CH4_INDEX].over_under_flowcount - device[TIMER4_CAPTURE_CH4_INDEX].u32LastCnt;
rt_hw_inputcapture_isr(&device[TIMER4_CAPTURE_CH4_INDEX].parent, device[TIMER4_CAPTURE_CH4_INDEX].input_data_level);
}
if(device[TIMER4_CAPTURE_CH4_INDEX].input_data_level)
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH4_INDEX].timer, device[TIMER4_CAPTURE_CH4_INDEX].ch, TIM_INPUTCHANNELPOLARITY_FALLING); //切换捕获极性
else
__HAL_TIM_SET_CAPTUREPOLARITY(&device[TIMER4_CAPTURE_CH4_INDEX].timer, device[TIMER4_CAPTURE_CH4_INDEX].ch, TIM_INPUTCHANNELPOLARITY_RISING); //切换捕获极性
device[TIMER4_CAPTURE_CH4_INDEX].over_under_flowcount = 0;
device[TIMER4_CAPTURE_CH4_INDEX].u32LastCnt = cnt;
HAL_TIM_IC_Start_IT(&device[TIMER4_CAPTURE_CH4_INDEX].timer, device[TIMER4_CAPTURE_CH4_INDEX].ch);
#endif
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_BREAK) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_BREAK);
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_TRIGGER) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_TRIGGER);
}
if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_COM) != RESET)
{
__HAL_TIM_CLEAR_IT(&device->timer, TIM_FLAG_COM);
}
}
#ifdef BSP_USING_TIMER4_CAPTURE
void TIM4_IRQHandler(void)
{
rt_interrupt_enter();
capture_updata_isr(stm32_capture_obj);
rt_interrupt_leave();
}
#endif
static rt_err_t stm32_capture_get_pulsewidth(struct rt_inputcapture_device *inputcapture, rt_uint32_t *pulsewidth_us)
{
rt_err_t ret = RT_EOK;
struct stm32_capture_device *stm32_capture;
stm32_capture = (stm32_capture_device *)inputcapture;
return -(ret);
}
static rt_err_t stm32_timer_capture_init(struct stm32_capture_device* device)
{
rt_err_t ret = RT_EOK;
#if defined(BSP_USING_TIMER4_CAPTURE)
static uint8_t TIM4_INIT = 0;
if (device->timer.Instance == TIM4){
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
if(!TIM4_INIT){
device->timer.Init.Prescaler = 108-1;
device->timer.Init.CounterMode = TIM_COUNTERMODE_UP;
device->timer.Init.Period = 0xffff;
device->timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
device->timer.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&device->timer) != HAL_OK){
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&device->timer, &sClockSourceConfig) != HAL_OK){
Error_Handler();
}
if (HAL_TIM_IC_Init(&device->timer) != HAL_OK){
Error_Handler();
}
HAL_NVIC_SetPriority(device->irq, 3, 0);
HAL_NVIC_EnableIRQ(device->irq);
HAL_TIM_Base_Start_IT(&device->timer);
TIM4_INIT = 1;
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&device->timer, &sConfigIC, device->ch) != HAL_OK){
Error_Handler();
}
}
#endif
return -(ret);
}
static rt_err_t stm32_capture_init(struct rt_inputcapture_device *inputcapture)
{
rt_err_t ret = RT_EOK;
RT_ASSERT(inputcapture != RT_NULL);
if (stm32_timer_capture_init((struct stm32_capture_device *) inputcapture) != RT_EOK){
rt_kprintf("Failed to initialize TIMER.\n");
ret = RT_ERROR;
}
return -(ret);
}
static rt_err_t stm32_capture_open(struct rt_inputcapture_device *inputcapture)
{
rt_err_t ret = RT_EOK;
RT_ASSERT(inputcapture != RT_NULL);
struct stm32_capture_device* device = (struct stm32_capture_device*)inputcapture;
device->not_first_edge = 0;
device->input_data_level = 0;
device->over_under_flowcount = 0;
device->u32LastCnt = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(&device->timer, device->ch, TIM_INPUTCHANNELPOLARITY_FALLING);
HAL_TIM_IC_Start_IT(&device->timer, device->ch);
return ret;
}
static rt_err_t stm32_capture_close(struct rt_inputcapture_device *inputcapture)
{
rt_err_t ret = RT_EOK;
RT_ASSERT(inputcapture != RT_NULL);
struct stm32_capture_device* device = (struct stm32_capture_device*)inputcapture;
HAL_TIM_IC_Stop_IT(&device->timer, device->ch);
return ret;
}
/* Init and register timer capture */
static int stm32_timer_capture_device_init(void)
{
struct stm32_capture_device *device;
for (uint8_t i = 0; i < sizeof(stm32_capture_obj) / sizeof(stm32_capture_obj[0]); i++){
device = &stm32_capture_obj[i];
device->parent.ops = &stm32_capture_ops;
if (rt_device_inputcapture_register(&device->parent, stm32_capture_obj[i].name, device)!= RT_EOK){
LOG_E("%s register failed", stm32_capture_obj[i].name);
return -RT_ERROR;
}
}
return 0;
}
INIT_DEVICE_EXPORT(stm32_timer_capture_device_init);
#endif //#if defined(BSP_USING_TIMER_CAPTURE)
原作者:yushigengyu