stm32的输入捕获驱动

发布于 2020-08-23 14:36:44

最近项目中用到了输入捕获。发现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)
{
    /* TIM Update event */
    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++;
    }
    
    /* Capture compare 1 event */
    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
    }
    /* Capture compare 2 event */
    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
    }
    /* Capture compare 3 event */
    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
    }
    /* Capture compare 4 event */
    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
    }
    /* TIM Break input event */
    if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_BREAK) != RESET)
    {
        __HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_BREAK);
    }
    /* TIM Trigger detection event */
    if (__HAL_TIM_GET_FLAG(&device->timer, TIM_FLAG_TRIGGER) != RESET)
    {
        __HAL_TIM_CLEAR_IT(&device->timer, TIM_IT_TRIGGER);
    }
    /* TIM commutation event */
    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)
{
    /* enter interrupt */
    rt_interrupt_enter();
    capture_updata_isr(stm32_capture_obj);
    /* leave interrupt */
    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;
    *pulsewidth_us = stm32_capture->u32PluseCnt;
    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)
0 条评论

发布
问题

分享
好友