野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15288|回复: 9

求救:多路脉宽捕获,TIM通道出错

[复制链接]
发表于 2017-12-27 13:56:15 | 显示全部楼层 |阅读模式
火哥,我程序用两个TIM捕获6路脉宽信号,但配置的时候发现会有通道配置冲突问题,多次调整,也只能最多捕获5路信号。我现在只能屏蔽掉一路信号
static void GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //结构体定义
RCC_AHB1PeriphClockCmd (CH1_GPIO_CLK |
             CH2_GPIO_CLK |
             CH3_GPIO_CLK |
             CH4_GPIO_CLK |
             CH5_GPIO_CLK |
             CH6_GPIO_CLK ,ENABLE); //开启时钟
/*引脚通用配置*/
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;  //设置引脚模式为复用模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //设置引脚的输出类型为推挽输出
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN; //设置引脚为下拉模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚速率为50MHz
/*CH1引脚*/  
GPIO_InitStructure.GPIO_Pin   = CH1_PIN; //选择要控制的GPIO引脚  
GPIO_Init(CH1_GPIO_PORT , &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(CH1_GPIO_PORT,CH1_PINSOURCE,CH1_AF); //定时器复用引脚连接  
/*CH2引脚*/
GPIO_InitStructure.GPIO_Pin = CH2_PIN; //选择要控制的GPIO引脚
GPIO_Init(CH2_GPIO_PORT , &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(CH2_GPIO_PORT,CH2_PINSOURCE,CH2_AF); //定时器复用引脚连接
/*CH3引脚*/
GPIO_InitStructure.GPIO_Pin = CH3_PIN; //选择要控制的GPIO引脚
GPIO_Init(CH3_GPIO_PORT , &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(CH3_GPIO_PORT,CH3_PINSOURCE,CH3_AF); //定时器复用引脚连接
/*CH4引脚*/
GPIO_InitStructure.GPIO_Pin = CH4_PIN; //选择要控制的GPIO引脚
GPIO_Init(CH4_GPIO_PORT , &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(CH4_GPIO_PORT,CH4_PINSOURCE,CH4_AF); //定时器复用引脚连接
/*CH5引脚*/
GPIO_InitStructure.GPIO_Pin = CH5_PIN; //选择要控制的GPIO引脚
GPIO_Init(CH5_GPIO_PORT , &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(CH5_GPIO_PORT,CH5_PINSOURCE,CH5_AF); //定时器复用引脚连接
/*CH6引脚*/
GPIO_InitStructure.GPIO_Pin = CH6_PIN; //选择要控制的GPIO引脚
GPIO_Init(CH6_GPIO_PORT , &GPIO_InitStructure); //初始化GPIO
GPIO_PinAFConfig(CH6_GPIO_PORT,CH6_PINSOURCE,CH6_AF); //定时器复用引脚连接

}

/**
  * @brief  通用定时器中断优先级配置
  * @param  无
  * @retval 无
  */
static void TIMx_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //结构体定义
/* CH12中断 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 设置中断组为0
NVIC_InitStructure.NVIC_IRQChannel = CH12_TIM_IRQn; // 设置中断来源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 设置子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* CH3456中断 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 设置中断组为0
NVIC_InitStructure.NVIC_IRQChannel = CH3456_TIM_IRQn; // 设置中断来源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; // 设置子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}


/**
  * @brief  输入模式配置
  * @param  无
  * @retval 无
  */
static void TIM_INPUT_Config(void)
{
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_ICInitTypeDef  TIM_ICInitStructure;

  RCC_APB1PeriphClockCmd(CH12_TIM_CLK  |
             CH3456_TIM_CLK ,ENABLE); // 开启TIM时钟

/* 定时器初始化通用配置 */
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF-1;  //当定时器从0计数到0xFFFF,为一个定时周期
  TIM_TimeBaseStructure.TIM_Prescaler = 84-1; // 通用定时器时钟源TIMxCLK = HCLK/2=84MHz
                        // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=1MHz
  TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;  // 计数方式
/* CH12定时器初始化 */
TIM_TimeBaseInit(CH12_TIM, &TIM_TimeBaseStructure); // 初始化定时器
/* CH3456定时器初始化 */
TIM_TimeBaseInit(CH3456_TIM, &TIM_TimeBaseStructure); // 初始化定时器


/* 输入捕获通用配置 */
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //TIxFPx边沿触发
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //设置时钟分割:TDTS = Tck_tim
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //输入预分频/不分频
  TIM_ICInitStructure.TIM_ICFilter = 0x0;  //滤波设置,经历几个周期跳变认定波形稳定0x0~0xF/不滤波
/* CH1输入捕获配置 */
  TIM_ICInitStructure.TIM_Channel = CH1_IC_CHANNEL; //通道选择
  TIM_ICInit(CH12_TIM, &TIM_ICInitStructure);
TIM_ITConfig(CH12_TIM ,CH1_IT_CC ,ENABLE);
/* CH2输入捕获配置 */
TIM_ICInitStructure.TIM_Channel = CH2_IC_CHANNEL;//通道选择
TIM_ICInit(CH12_TIM, &TIM_ICInitStructure);
TIM_ITConfig(CH12_TIM ,CH2_IT_CC ,ENABLE);
/* CH3输入捕获配置 */
TIM_ICInitStructure.TIM_Channel = CH3_IC_CHANNEL;//通道选择
TIM_ICInit(CH3456_TIM, &TIM_ICInitStructure);
TIM_ITConfig(CH3456_TIM ,CH3_IT_CC ,ENABLE);
// /* CH4输入捕获配置 */
// TIM_ICInitStructure.TIM_Channel = CH4_IC_CHANNEL;//通道选择
// TIM_ICInit(CH3456_TIM, &TIM_ICInitStructure);
// TIM_ITConfig(CH3456_TIM ,CH4_IT_CC ,ENABLE);
/* CH5输入捕获配置 */
TIM_ICInitStructure.TIM_Channel = CH5_IC_CHANNEL;//通道选择
TIM_ICInit(CH3456_TIM, &TIM_ICInitStructure);
TIM_ITConfig(CH3456_TIM ,CH5_IT_CC ,ENABLE);
/* CH6输入捕获配置 */
TIM_ICInitStructure.TIM_Channel = CH6_IC_CHANNEL;//通道选择
TIM_ICInit(CH3456_TIM, &TIM_ICInitStructure);
TIM_ITConfig(CH3456_TIM ,CH6_IT_CC ,ENABLE);
              
TIM_Cmd(CH12_TIM, ENABLE);  //使能定时器
TIM_Cmd(CH3456_TIM, ENABLE);  //使能定时器
}


/**
  * @brief  初始控制定时器定时
  * @param  无
  * @retval 无
  */
void RC6GS_Init(void)
{
GPIO_Config();
TIMx_NVIC_Configuration();
TIM_INPUT_Config();

}

uint8_t   CH1_CAPTURE_STA = 0; //通道1输入捕获标志,高两位做捕获标志,低6位做溢出标志  
uint16_t  CH1_CAPTURE_UPVAL;
uint16_t  CH1_CAPTURE_DOWNVAL;
uint32_t  CH1_TempValue;
uint16_t  CH1_PulseWidth; //输出高电平时间

uint8_t   CH2_CAPTURE_STA = 0; //通道2输入捕获标志,高两位做捕获标志,低6位做溢出标志  
uint16_t  CH2_CAPTURE_UPVAL;
uint16_t  CH2_CAPTURE_DOWNVAL;
uint32_t  CH2_TempValue;
uint16_t  CH2_PulseWidth; //输出高电平时间

uint8_t   CH3_CAPTURE_STA = 0; //通道3输入捕获标志,高两位做捕获标志,低6位做溢出标志  
uint16_t  CH3_CAPTURE_UPVAL;
uint16_t  CH3_CAPTURE_DOWNVAL;
uint32_t  CH3_TempValue;
uint16_t  CH3_PulseWidth; //输出高电平时间

uint8_t  CH4_CAPTURE_STA = 0; //通道4输入捕获标志,高两位做捕获标志,低6位做溢出标志  
uint16_t  CH4_CAPTURE_UPVAL;
uint16_t  CH4_CAPTURE_DOWNVAL;
uint32_t  CH4_TempValue;
uint16_t  CH4_PulseWidth; //输出高电平时间

uint8_t  CH5_CAPTURE_STA = 0; //通道4输入捕获标志,高两位做捕获标志,低6位做溢出标志  
uint16_t  CH5_CAPTURE_UPVAL;
uint16_t  CH5_CAPTURE_DOWNVAL;
uint32_t  CH5_TempValue;
uint16_t  CH5_PulseWidth; //输出高电平时间

uint8_t  CH6_CAPTURE_STA = 0; //通道4输入捕获标志,高两位做捕获标志,低6位做溢出标志  
uint16_t  CH6_CAPTURE_UPVAL;
uint16_t  CH6_CAPTURE_DOWNVAL;
uint32_t  CH6_TempValue;
uint16_t  CH6_PulseWidth; //输出高电平时间

/**
  * @brief  中断服务,读取CH1~CH2的脉宽
  * @param  无
  * @retval 无
  */
void CH12_TIM_IRQHandler(void)
{
/* CH1高电平捕获时间 */
if ((CH1_CAPTURE_STA & 0X80) == 0)   //还未成功捕获
{
  if (TIM_GetITStatus(CH12_TIM, CH1_IT_CC) != RESET)   //捕获1发生捕获事件
  {
   TIM_ClearITPendingBit(CH12_TIM, CH1_IT_CC);   //清除中断标志位
   if (CH1_CAPTURE_STA & 0X40)  //捕获到一个下降沿
   {
    CH1_CAPTURE_DOWNVAL = TIM_GetCapture1(CH12_TIM);//记录下此时的定时器计数值
    if (CH1_CAPTURE_DOWNVAL < CH1_CAPTURE_UPVAL)
    {
     CH1_TempValue = 65535;
    }
    else
     CH1_TempValue = 0;
    CH1_PulseWidth = CH1_CAPTURE_DOWNVAL - CH1_CAPTURE_UPVAL + CH1_TempValue;  //得到总的高电平的时间
    CH1_CAPTURE_STA = 0;  //捕获标志位清零
    TIM_OC1PolarityConfig(CH12_TIM, TIM_ICPolarity_Rising); //设置为上升沿捕获   
   }
   else //发生捕获时间但不是下降沿,第一次捕获到上升沿,记录此时的定时器计数值
   {
    CH1_CAPTURE_UPVAL = TIM_GetCapture1(CH12_TIM);  //获取上升沿数据
    CH1_CAPTURE_STA |= 0X40;  //标记已捕获到上升沿
    TIM_OC1PolarityConfig(CH12_TIM, TIM_ICPolarity_Falling);//设置为下降沿捕获
   }
  }
}

/* CH2高电平捕获时间 */
if ((CH2_CAPTURE_STA & 0X80) == 0)   //还未成功捕获
{   
  if (TIM_GetITStatus(CH12_TIM, CH2_IT_CC) != RESET)   //捕获2发生捕获事件
  {
   TIM_ClearITPendingBit(CH12_TIM, CH2_IT_CC);   //清除中断标志位
   if (CH2_CAPTURE_STA & 0X40)  //捕获到一个下降沿
   {
    CH2_CAPTURE_DOWNVAL = TIM_GetCapture2(CH12_TIM);//记录下此时的定时器计数值
    if (CH2_CAPTURE_DOWNVAL < CH2_CAPTURE_UPVAL)
    {
     CH2_TempValue = 65535;
    }
    else
     CH2_TempValue = 0;
    CH2_PulseWidth = CH2_CAPTURE_DOWNVAL - CH2_CAPTURE_UPVAL + CH2_TempValue;  //得到总的高电平的时间
    CH2_CAPTURE_STA = 0;  //捕获标志位清零
    TIM_OC2PolarityConfig(CH12_TIM, TIM_ICPolarity_Rising); //设置为上升沿捕获   
   }
   else //发生捕获时间但不是下降沿,第一次捕获到上升沿,记录此时的定时器计数值
   {
    CH2_CAPTURE_UPVAL = TIM_GetCapture2(CH12_TIM);  //获取上升沿数据
    CH2_CAPTURE_STA |= 0X40;  //标记已捕获到上升沿
    TIM_OC2PolarityConfig(CH12_TIM, TIM_ICPolarity_Falling);//设置为下降沿捕获
   }
  }
}
}

/**
  * @brief  中断服务,读取CH3~CH6的脉宽
  * @param  无
  * @retval 无
  */
void CH3456_TIM_IRQHandler(void)
{
/* CH3高电平捕获时间 */
if ((CH3_CAPTURE_STA & 0X80) == 0)   //还未成功捕获
{
  if (TIM_GetITStatus(CH3456_TIM, CH3_IT_CC) != RESET)   //捕获1发生捕获事件
  {
   TIM_ClearITPendingBit(CH3456_TIM, CH3_IT_CC);   //清除中断标志位
   if (CH3_CAPTURE_STA & 0X40)  //捕获到一个下降沿
   {
    CH3_CAPTURE_DOWNVAL = TIM_GetCapture1(CH3456_TIM);//记录下此时的定时器计数值
    if (CH3_CAPTURE_DOWNVAL < CH3_CAPTURE_UPVAL)
    {
     CH3_TempValue = 65535;
    }
    else
     CH3_TempValue = 0;
    CH3_PulseWidth = CH3_CAPTURE_DOWNVAL - CH3_CAPTURE_UPVAL + CH3_TempValue;  //得到总的高电平的时间
    CH3_CAPTURE_STA = 0;  //捕获标志位清零
    TIM_OC1PolarityConfig(CH3456_TIM, TIM_ICPolarity_Rising); //设置为上升沿捕获   
   }
   else //发生捕获时间但不是下降沿,第一次捕获到上升沿,记录此时的定时器计数值
   {
    CH3_CAPTURE_UPVAL = TIM_GetCapture1(CH3456_TIM);  //获取上升沿数据
    CH3_CAPTURE_STA |= 0X40;  //标记已捕获到上升沿
    TIM_OC1PolarityConfig(CH3456_TIM, TIM_ICPolarity_Falling);//设置为下降沿捕获
   }
  }
}

/* CH4高电平捕获时间 */
if ((CH4_CAPTURE_STA & 0X80) == 0)   //还未成功捕获
{   

  if (TIM_GetITStatus(CH3456_TIM, CH4_IT_CC) != RESET)   //捕获2发生捕获事件
  {
   TIM_ClearITPendingBit(CH3456_TIM, CH4_IT_CC);   //清除中断标志位
   if (CH4_CAPTURE_STA & 0X40)  //捕获到一个下降沿
   {
    CH4_CAPTURE_DOWNVAL = TIM_GetCapture2(CH3456_TIM);//记录下此时的定时器计数值
    if (CH4_CAPTURE_DOWNVAL < CH4_CAPTURE_UPVAL)
    {
     CH4_TempValue = 65535;
    }
    else
     CH4_TempValue = 0;
    CH4_PulseWidth = CH4_CAPTURE_DOWNVAL - CH4_CAPTURE_UPVAL + CH4_TempValue;  //得到总的高电平的时间
    CH4_CAPTURE_STA = 0;  //捕获标志位清零
    TIM_OC2PolarityConfig(CH3456_TIM, TIM_ICPolarity_Rising); //设置为上升沿捕获   
   }
   else //发生捕获时间但不是下降沿,第一次捕获到上升沿,记录此时的定时器计数值
   {
    CH4_CAPTURE_UPVAL = TIM_GetCapture2(CH3456_TIM);  //获取上升沿数据
    CH4_CAPTURE_STA |= 0X40;  //标记已捕获到上升沿
    TIM_OC2PolarityConfig(CH3456_TIM, TIM_ICPolarity_Falling);//设置为下降沿捕获
   }
  }
}

/* CH5高电平捕获时间 */
if ((CH5_CAPTURE_STA & 0X80) == 0)   //还未成功捕获
{   
  if (TIM_GetITStatus(CH3456_TIM, CH5_IT_CC) != RESET)   //捕获3发生捕获事件
  {
   TIM_ClearITPendingBit(CH3456_TIM, CH5_IT_CC);   //清除中断标志位
   if (CH5_CAPTURE_STA & 0X40)  //捕获到一个下降沿
   {
    CH5_CAPTURE_DOWNVAL = TIM_GetCapture3(CH3456_TIM);//记录下此时的定时器计数值
    if (CH5_CAPTURE_DOWNVAL < CH5_CAPTURE_UPVAL)
    {
     CH5_TempValue = 65535;
    }
    else
     CH5_TempValue = 0;
    CH5_PulseWidth = CH5_CAPTURE_DOWNVAL - CH5_CAPTURE_UPVAL + CH5_TempValue;  //得到总的高电平的时间
    CH5_CAPTURE_STA = 0;  //捕获标志位清零
    TIM_OC3PolarityConfig(CH3456_TIM, TIM_ICPolarity_Rising); //设置为上升沿捕获   
   }
   else //发生捕获时间但不是下降沿,第一次捕获到上升沿,记录此时的定时器计数值
   {
    CH5_CAPTURE_UPVAL = TIM_GetCapture3(CH3456_TIM);  //获取上升沿数据
    CH5_CAPTURE_STA |= 0X40;  //标记已捕获到上升沿
    TIM_OC3PolarityConfig(CH3456_TIM, TIM_ICPolarity_Falling);//设置为下降沿捕获
   }
  }
}

/* CH6高电平捕获时间 */
if ((CH6_CAPTURE_STA & 0X80) == 0)   //还未成功捕获
{   
  if (TIM_GetITStatus(CH3456_TIM, CH6_IT_CC) != RESET)   //捕获4发生捕获事件
  {
   TIM_ClearITPendingBit(CH3456_TIM, CH6_IT_CC);   //清除中断标志位
   if (CH6_CAPTURE_STA & 0X40)  //捕获到一个下降沿
   {
    CH6_CAPTURE_DOWNVAL = TIM_GetCapture4(CH3456_TIM);//记录下此时的定时器计数值
    if (CH6_CAPTURE_DOWNVAL < CH6_CAPTURE_UPVAL)
    {
     CH6_TempValue = 65535;
    }
    else
     CH6_TempValue = 0;
    CH6_PulseWidth = CH6_CAPTURE_DOWNVAL - CH6_CAPTURE_UPVAL + CH6_TempValue;  //得到总的高电平的时间
    CH6_CAPTURE_STA = 0;  //捕获标志位清零
    TIM_OC4PolarityConfig(CH3456_TIM, TIM_ICPolarity_Rising); //设置为上升沿捕获   
   }
   else //发生捕获时间但不是下降沿,第一次捕获到上升沿,记录此时的定时器计数值
   {
    CH6_CAPTURE_UPVAL = TIM_GetCapture4(CH3456_TIM);  //获取上升沿数据
    CH6_CAPTURE_STA |= 0X40;  //标记已捕获到上升沿
    TIM_OC4PolarityConfig(CH3456_TIM, TIM_ICPolarity_Falling);//设置为下降沿捕获
   }
  }
}
}

回复

使用道具 举报

发表于 2017-12-27 14:13:55 | 显示全部楼层
检查下硬件引脚是不是共用了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-12-27 15:23:48 | 显示全部楼层
左丘冰 发表于 2017-12-27 14:13
检查下硬件引脚是不是共用了

没有共用,程序屏蔽通道CH3,也能正常。只要屏蔽通道1~4中的任何一个,都能正常运行,感觉是两个计数器的捕获通道有冲突
回复 支持 反对

使用道具 举报

发表于 2018-1-4 20:53:22 | 显示全部楼层
你指的冲突是什么表现,编译冲突还是运行时出错?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-1-8 09:23:42 | 显示全部楼层
usichhj6 发表于 2018-1-4 20:53
你指的冲突是什么表现,编译冲突还是运行时出错?

是6个输入通道同时用的时候,数据捕获不正常。不知道是溢出了还是什么其他原因
回复 支持 反对

使用道具 举报

发表于 2018-1-19 15:03:23 | 显示全部楼层
有可能是中断优先级的问题。407有14个定时器,试试一个定时器只负责一路捕获
回复 支持 反对

使用道具 举报

发表于 2018-1-19 15:13:27 | 显示全部楼层
这样就可用优先级来避免冲突的发生
回复 支持 反对

使用道具 举报

发表于 2018-1-29 20:50:28 | 显示全部楼层
于连 发表于 2018-1-8 09:23
是6个输入通道同时用的时候,数据捕获不正常。不知道是溢出了还是什么其他原因

你好,请问你的问题解决了吗?能给我个联系方式交流一下吗?我也想知道这个问题。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-4-28 14:46:21 | 显示全部楼层
问题解决了,是中断打开早了,把终端开启指令写在最后就好了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-4-28 14:46:59 | 显示全部楼层
TypeDef 发表于 2018-1-29 20:50
你好,请问你的问题解决了吗?能给我个联系方式交流一下吗?我也想知道这个问题。

解决了,中断开启的早了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2025-12-6 01:23 , Processed in 0.047190 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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