amobbs.com 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
回复: 3

输入捕获获取信号不实时是怎么回事?求教~

[复制链接]
(3169985)

打赏出0元收入0元

发表于 2020-6-3 11:54:01 | 显示全部楼层 |阅读模式
使用STM32F401定时器3捕获输入信号,捕获信号的有效高电平,但是捕获的信号不完整,会漏掉几位。代码如下:

/***************************************  配置部分代码 ************************************************/
TIM_HandleTypeDef TIM3_Handler; //定时器 3 句柄
TIM_HandleTypeDef TIM5_Handler; //定时器 5 句柄

void TIM5_Init(unsigned int arr,unsigned short psc)
{
    __HAL_RCC_TIM5_CLK_ENABLE();
   
    TIM5_Handler.Instance = TIM5;                               //通用定时器5
    TIM5_Handler.Init.Prescaler = psc;                          //分频系数
    TIM5_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;         //向上计数
    TIM5_Handler.Init.Period = arr;                             //自动装载值
    TIM5_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   //时钟分频因子
    HAL_TIM_Base_Init(&TIM5_Handler);                           //初始化定时器5
   
    __HAL_TIM_ENABLE(&TIM5_Handler);                            //使能定时器5
}
/*********************
配置TIM3定时器输入捕获
*********************/
void TIM3_Cap_Init(unsigned int arr,unsigned short psc)
{
    TIM_IC_InitTypeDef TIM3_CH1Config;
      
   
    TIM3_Handler.Instance = TIM3;                               //通用定时器3
    TIM3_Handler.Init.Prescaler = psc;                          //分频系数
    TIM3_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;         //向上计数
    TIM3_Handler.Init.Period = arr;                             //自动装载值
    TIM3_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   //时钟分频因子
    HAL_TIM_IC_Init(&TIM3_Handler);                             //初始化输入捕获时基参数
   
    TIM3_CH1Config.ICPolarity = TIM_ICPOLARITY_RISING;          //设置上升沿捕获
    TIM3_CH1Config.ICSelection = TIM_ICSELECTION_DIRECTTI;      //映射到TI1上
    TIM3_CH1Config.ICPrescaler = TIM_ICPSC_DIV1;                //配置输入分频,不分频
    TIM3_CH1Config.ICFilter = 0;                                //设置输入滤波,不滤波
    HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_1);  //配置TIM3通道1
   
    HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_1);           //开启捕获通道,并开启捕获中断
    __HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE);           //使能更新中断
   
}

/**************************
定时器3 底层驱动,时钟使能,引脚配置
此函数会被HAL_TIM_IC_Init()调用
**************************/
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
   
    __HAL_RCC_TIM3_CLK_ENABLE();                                //使能 TIM3 时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();                               //开启 GPIOA 时钟   
      
   
    GPIO_Initure.Pin = GPIO_PIN_6;                              //PA6
    GPIO_Initure.Mode = GPIO_MODE_AF_OD;                        //复用推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;                            //上拉
    GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;             //高速
    GPIO_Initure.Alternate = GPIO_AF2_TIM3;                     //PA6复用为TIM3通道1
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
   
    HAL_NVIC_SetPriority(TIM3_IRQn,2,0);                        //设置中断优先级,抢占 2,子优先级 0
    HAL_NVIC_EnableIRQ(TIM3_IRQn);                              //开启 ITM3 中断通道
   
}


//捕获状态
//[7]:0,没有成功的捕获;1,成功捕获到一次.
//[6]:0,还没捕获到低电平;1,已经捕获到低电平了.
//[5:0]:捕获低电平后溢出的次数(对于 32 位定时器来说,1us 计数器加 1,溢出时间:4294 秒)
unsigned char TIM3CH1_CAPTURE_STA;  //输入捕获状态
unsigned int TIM3CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5 是 32 位)
unsigned int TIM3CH1_CAPTURE_OK = 0;
unsigned int TIM3CH1_CAPTURE_CNT = 0;
unsigned int TIM3CH1_CAPTURE_BIT_CNT = 0;
unsigned char TIM3CH1_CAPTURE_BUFF_LEN = 0;
unsigned char *TIM3CH1_CAPTURE = (unsigned char *)0x20000B00;



//定时器 3 中断服务函数
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TIM3_Handler);//定时器共用处理函数
}

//定时器更新中断(溢出)中断处理回调函数, 在 HAL_TIM_IRQHandler 中会被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断发生时执行
{
    if((TIM3CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
    {
        if(TIM3CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
        {
            if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
            {
                TIM3CH1_CAPTURE_STA|=0X80;  //标记成功捕获了一次
                TIM3CH1_CAPTURE_VAL=65535;
            }
            else
                TIM3CH1_CAPTURE_STA++;
        }
    }
}


//定时器输入捕获中断处理回调函数,该函数在 HAL_TIM_IRQHandler 中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
    if((TIM3CH1_CAPTURE_STA&0X80)==0)                               //还未成功捕获
    {
        if(TIM3CH1_CAPTURE_STA&0X40)                                //捕获到一个下降沿
        {
            TIM3CH1_CAPTURE_STA|=0X80;                              //标记成功捕获到一次高电平脉宽
            TIM3CH1_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1);       //获取当前的捕获值
            TIM_RESET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1); //清除设置
            TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,
            TIM_ICPOLARITY_RISING);                                 //上升沿捕获
        }
        else                                                        //还未开始,第一次捕获上升沿
        {
            TIM3CH1_CAPTURE_STA=0;                                  //清空
            TIM3CH1_CAPTURE_VAL=0;
            TIM3CH1_CAPTURE_STA|=0X40;                              //标记捕获到了上升沿
            __HAL_TIM_DISABLE(&TIM3_Handler);                       //关闭定时器 3
            __HAL_TIM_SET_COUNTER(&TIM3_Handler,0);
            TIM_RESET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1); //清除原来设置
            TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,
            TIM_ICPOLARITY_FALLING);                                //下降沿捕获
            __HAL_TIM_ENABLE(&TIM3_Handler);                        //使能定时器 3
            
        }
    }
}

/************************************************    捕获信号处理代码  ****************************************************************/
unsigned char RecvData(unsigned char *byBuff)
{
    unsigned char byCmdLen = 0;
   
    if( TIM3CH1_CAPTURE_STA & 0x80 )                                            //捕获一次高电平
    {
        if( TIM3CH1_CAPTURE_VAL > 100 && TIM3CH1_CAPTURE_VAL < 600)             //捕获有效高电平:0 小于400微秒 600 * 48 / 72000000
        {
            byTIM3CH1[TIM3CH1_CAPTURE_CNT] = TIM3CH1_CAPTURE_VAL;
            byCap[TIM3CH1_CAPTURE_CNT] = 0;
            TIM3CH1_CAPTURE_CNT++;
            TIM3CH1_CAPTURE_OK = 1;
            TIM3CH1_CAPTURE_BIT_CNT = 0;
        }
        else if( TIM3CH1_CAPTURE_VAL > 600 && TIM3CH1_CAPTURE_VAL < 800 )      //捕获有效高电平:1
        {
           
            byTIM3CH1[TIM3CH1_CAPTURE_CNT] = TIM3CH1_CAPTURE_VAL;
            byCap[TIM3CH1_CAPTURE_CNT] = 1;
            TIM3CH1_CAPTURE_CNT++;
            TIM3CH1_CAPTURE_OK = 1;
            TIM3CH1_CAPTURE_BIT_CNT = 0;
        }
        if( TIM3CH1_CAPTURE_OK == 1 ){
            TIM3CH1_CAPTURE_BIT_CNT++;
            __HAL_TIM_SET_COUNTER(&TIM5_Handler,0);
        }
        TIM3CH1_CAPTURE_STA = 0;
    }
    if( __HAL_TIM_GET_COUNTER(&TIM5_Handler) > 2000 && TIM3CH1_CAPTURE_OK == 1 )
    {
        SLK_OUT(0);                                                         //拉低,方便查看结束标志
        TIM3CH1_CAPTURE_OK = 0;
        TIM3CH1_CAPTURE_BIT_CNT = 0;
        byCmdLen = Toyato_Decode(byBuff,TIM3CH1_CAPTURE_CNT);
        TIM3CH1_CAPTURE_CNT = 0;
        memset(byCap,0,256);
        memset(byTIM3CH1,0,128);
    }
    return byCmdLen;
}

我想获取有效的高电平值得时候,只读到了一段信号,前后的信号丢失了,请大家帮忙看看是什么原因。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
(3169897)

打赏出0元收入0元

 楼主| 发表于 2020-6-3 11:55:29 | 显示全部楼层
只读到了红色方框内的4个高电平,剩下的都没有读到
(3167780)

打赏出0元收入0元

发表于 2020-6-3 12:30:46 | 显示全部楼层
直接TIM中断服务函数里边处理,不要用HAL库这种回调函数处理方式试试看。
(3166370)

打赏出0元收入0元

发表于 2020-6-3 12:54:16 | 显示全部楼层
你看看你的最小时钟脉宽
回帖提示: 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号-1 )

GMT+8, 2020-7-10 04:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表