目录

问题描述:

(1)捕获timer初始化

(2)捕获中断处理函数

(3)速度计算公式

原因查找:

(1)库函数的原因

(2)timer_channel_capture_value_register()位置的原因


问题描述:

四个脉冲捕获通道均给1000Hz 的脉冲,运行一段时间后,四个通道捕获的脉冲数差距
较大,增加相邻脉冲差值计算代码后,发现同一通道的采集的两个脉冲之间的时钟计数差值
可能是正常情况下的2 倍/3 倍/4 倍/5 倍/6 倍。

排查了一两个月,怀疑单板,怀疑芯片,怀疑测试台,怀疑软件,怀疑人生....

我原来的程序是下面这样的:

(1)捕获timer初始化

void initialize_CAP_IN_timer(void)
{uint32_t timer = TIMER1;uint32_t timer_clk = RCU_TIMER1;timer_parameter_struct timer_initpara;timer_ic_parameter_struct timer_icinitpara;rcu_periph_clock_enable(timer_clk);rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);timer_deinit(timer);timer_initpara.prescaler = 199u;timer_initpara.alignedmode = TIMER_COUNTER_EDGE;timer_initpara.counterdirection = TIMER_COUNTER_UP;timer_initpara.period = 0xFFFFFFFFu;timer_initpara.clockdivision = TIMER_CKDIV_DIV1;    timer_initpara.repetitioncounter = 0u;timer_init(timer, &timer_initpara);timer_auto_reload_shadow_enable(timer);timer_channel_input_struct_para_init(&timer_icinitpara);timer_input_capture_config(timer, TIMER_CH_0, &timer_icinitpara);timer_input_capture_config(timer, TIMER_CH_1, &timer_icinitpara);timer_input_capture_config(timer, TIMER_CH_2, &timer_icinitpara);timer_input_capture_config(timer, TIMER_CH_3, &timer_icinitpara);timer_interrupt_flag_clear(TIMER1,TIMER_INT_CH0);timer_interrupt_enable(timer, TIMER_INT_CH0);timer_interrupt_flag_clear(TIMER1,TIMER_INT_CH1);timer_interrupt_enable(timer, TIMER_INT_CH1);timer_interrupt_flag_clear(TIMER1,TIMER_INT_CH2);timer_interrupt_enable(timer, TIMER_INT_CH2);timer_interrupt_flag_clear(TIMER1,TIMER_INT_CH3);timer_interrupt_enable(timer, TIMER_INT_CH3);timer_enable(timer);timer_interrupt_flag_clear(timer, TIMER_INT_FLAG_UP);return;
}

(2)捕获中断处理函数

void TIMER1_IRQHandler(void)
{if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH0)){gw_CAP_NUM_INT[0]++;timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH0);}if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH1)){gw_CAP_NUM_INT[1]++;timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH1);}if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH2)){gw_CAP_NUM_INT[2]++;timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH2);}if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH3)){gw_CAP_NUM_INT[3]++;timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH3);}
}

(3)速度计算公式

简单来说,就是看20ms内发生了多少个脉冲。

static void CALC_velocity_and_FRQ(void)
{UINT_8  i, j;UINT_32 sum[4] = {0, 0, 0, 0};UINT_32 every_pulse_tick_avg[4];.../* 获得速度脉冲计数和时钟脉冲计数 */for (i=0; i<=3; i++){gw_CAP_NUM_last[i] = gw_CAP_NUM[i];gl_CAP_TCNT_last[i] = gl_CAP_TCNT[i];/* 读取速度捕获脉冲中断计数值 */gw_CAP_NUM[i] = gw_CAP_NUM_INT[i];gl_CAP_TCNT[i] = timer_channel_capture_value_register_read(TIMER1, i); }/* for (i=0; i<=3; i++) *//* 计算速度脉冲计数和时钟脉冲计数的差值,并计算各轴速度 */for (i=0; i<=3; i++){/* 备份上个周期计算的差值 */gw_CAP_NUM_delta_backup[i]  = gw_CAP_NUM_delta[i];gl_CAP_TCNT_delta_backup[i] = gl_CAP_TCNT_delta[i];/* 计算本周期的差值 */gw_CAP_NUM_delta[i]  = gw_CAP_NUM[i] - gw_CAP_NUM_last[i];gl_CAP_TCNT_delta[i] = gl_CAP_TCNT[i] - gl_CAP_TCNT_last[i];if (gl_CAP_TCNT_delta[i] > 0)       /* 除数为0处理 */{gw_velocity_value[i] = (gl_wheel_with_COEF[i] * gw_CAP_NUM_delta[i])/ gl_CAP_TCNT_delta[i];}...}   /* for (i=0; i<=3; i++) */return;
}   /* CALC_velocity_and_FRQ() */

原因查找:

经过代码排查,最后发现是下面两个原因导致的,芯片售后没有给出具体解释,我也搞不懂。

(1)库函数的原因

这版有问题的程序用的是V2.0.0

/*!\file    gd32f4xx_timer.c\brief   TIMER driver\version 2016-08-15, V1.0.0, firmware for GD32F4xx\version 2018-12-12, V2.0.0, firmware for GD32F4xx
*/...void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt)
{TIMER_INTF(timer_periph) &= (~(uint32_t)interrupt);
}...

需要用新版的库,V2.1.0以后好像都把上面那个“&”给去掉了,中断标志是硬件置位的,软件写0清标志,写1没有影响。按理来讲两种写法没有区别,但是不知道官方为什么会修正这个函数,可能有硬件设计方面的原因?

/*!\file    gd32f4xx_timer.c\brief   TIMER driver\version 2016-08-15, V1.0.0, firmware for GD32F4xx\version 2018-12-12, V2.0.0, firmware for GD32F4xx\version 2020-09-30, V2.1.0, firmware for GD32F4xx\version 2022-03-09, V3.0.0, firmware for GD32F4xx
*/void timer_interrupt_flag_clear(uint32_t timer_periph, uint32_t interrupt)
{TIMER_INTF(timer_periph) = (~(uint32_t)interrupt);
}

(2)timer_channel_capture_value_register()位置的原因

读取脉冲发生时刻timer_count寄存器值的函数timer_channel_capture_value_register()放在中断里,而不能放在20ms中断里。也是搞不懂。。。

uint32_t gl_timer_channel_capture_value[i]; /*用来存放触发时刻timer寄存器的值*/void TIMER1_IRQHandler(void)
{if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH0)){gw_CAP_NUM_INT[0]++;gl_timer_channel_capture_value[0] = timer_channel_capture_value_register_read(TIMER1, 0);   timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH0);}if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH1)){gw_CAP_NUM_INT[1]++;gl_timer_channel_capture_value[1] = timer_channel_capture_value_register_read(TIMER1, 1);   timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH1);}if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH2)){gw_CAP_NUM_INT[2]++;gl_timer_channel_capture_value[2] = timer_channel_capture_value_register_read(TIMER1, 2);   timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH2);}if (timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH3)){gw_CAP_NUM_INT[3]++;gl_timer_channel_capture_value[3] = timer_channel_capture_value_register_read(TIMER1, 3);   timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH3);}
}
static void CALC_velocity_and_FRQ(void)
{UINT_8  i, j;UINT_32 sum[4] = {0, 0, 0, 0};UINT_32 every_pulse_tick_avg[4];.../* 获得速度脉冲计数和时钟脉冲计数 */for (i=0; i<=3; i++){gw_CAP_NUM_last[i] = gw_CAP_NUM[i];gl_CAP_TCNT_last[i] = gl_CAP_TCNT[i];/* 读取速度捕获脉冲中断计数值 */gw_CAP_NUM[i] = gw_CAP_NUM_INT[i];gl_CAP_TCNT[i] = gl_timer_channel_capture_value[i]; /*这里改用全局变量读取*/}/* for (i=0; i<=3; i++) *//* 计算速度脉冲计数和时钟脉冲计数的差值,并计算各轴速度 */for (i=0; i<=3; i++){/* 备份上个周期计算的差值 */gw_CAP_NUM_delta_backup[i]  = gw_CAP_NUM_delta[i];gl_CAP_TCNT_delta_backup[i] = gl_CAP_TCNT_delta[i];/* 计算本周期的差值 */gw_CAP_NUM_delta[i]  = gw_CAP_NUM[i] - gw_CAP_NUM_last[i];gl_CAP_TCNT_delta[i] = gl_CAP_TCNT[i] - gl_CAP_TCNT_last[i];if (gl_CAP_TCNT_delta[i] > 0)       /* 除数为0处理 */{gw_velocity_value[i] = (gl_wheel_with_COEF[i] * gw_CAP_NUM_delta[i])/ gl_CAP_TCNT_delta[i];}...}   /* for (i=0; i<=3; i++) */return;
}   /* CALC_velocity_and_FRQ() */

有人遇到同样的问题吗?

GD32F450ZIT6脉冲捕获会丢失脉冲的问题相关推荐

  1. ltspice 双脉冲_焊烟脉冲布袋式除尘器制作

    菲翔环保为您详细解读SAQutg焊烟脉冲布袋式除尘器制作的相关知识与详情,锅炉滤筒除尘器停机时,若停机时间短,不宜将滤袋清灰,应留意除尘器的保温,若停机时间长,应将所有滤袋清灰,并用引风机将滤袋内残留 ...

  2. 伺服电机脉冲控制的多种方式(AB相脉冲,方向脉冲,CW/CCW脉冲)

    脉冲信号可以分为AB相脉冲,脉冲+方向,CW/CCW脉冲. 这三种信号格式,在十几年前或者还有明显的相对优缺点和适用场合,现在就已经无所谓了,即使在使用上还是有所区分,也基本上是由于历史习惯. 1.A ...

  3. 脉冲电子围栏系统介绍_脉冲电子围栏系统介绍

    脉冲电子围栏大家在生活中经常见,但对于电子围栏系统介绍,大家肯定都不是很了解,下面通过电子围栏系统介绍希望能帮助到您. 电子围栏系统知识的构造,有利于您更好的利用身边的资源.脉冲电子围栏是电子围中的一 ...

  4. 脉冲电子围栏系统介绍_脉冲电子围栏系统构成及原理

    脉冲电子围栏系统构成及原理 电子围栏系统主要由脉冲高压前端围栏系统.脉冲电子围栏主机.布线系统(市电.通讯).控制系统等四个子系统组成,脉冲电子围栏主机是构成整个电子围栏系统的核心,其完成高压脉冲的发 ...

  5. 脉冲电子围栏系统介绍_脉冲电子围栏系统构成原理及优势分析

    脉冲电子围栏系统构成原理及优势分析 您现在的位置:首页 > 新闻中心 > 行业新闻 脉冲电子围栏系统构成及原理 电子围栏系统主要由脉冲高压前端围栏系统.脉冲电子围栏主机.布线系统(市电.通 ...

  6. java的编辑框丢失焦点_java – 捕获EditText丢失焦点

    我是一名长期,自学成才的业余VB程序员,现在正在尝试自学 Java和 Android.我这样说,所以你会知道我不会说好语言,而且对这两种追求都是非常新的. 我开发了一个Android表单,其中包含一系 ...

  7. 【SNN脉冲神经网络】SNN脉冲神经网络的工作原理演示MATLAB仿真带GUI界面

    clc;clear all;close all; % 初始参数I = 10; sigma = 0.04;beta = 5;gamma = 140; a = 0.02;b = 0.2; c = -65; ...

  8. 脉冲列输入型脉冲比较数字伺服系统的原理图

    声明:本文非原创,文末声明出处,侵权必删!!! 参考来源: 北京交通大学 硕士学位论文 基于脉冲串控制的含位置反馈和前馈补偿的位置控制算法的研究  赵旺升

  9. stm8s103k3 周期 捕获_STM8S003K3如何用定时器中断处理捕获脉冲?

    如果用STM8S的一个IO口检测一个脉冲电平,用在电话机上面,比方说是GPIO3用来检测脉冲电平变化后,MCU将接通电话的GPIO1置高,接通电话.当挂断电话后,GPIO3脉冲再次变化,GPIO1置低 ...

最新文章

  1. 谷歌不更新android studio,彻底迈向64位:谷歌宣布 Android Studio 将停止 32 位版本更新...
  2. python基础(part4)--语句
  3. vertex shader(5)
  4. 传三星Galaxy S10将推出Lite版本 搭载骁龙855处理器
  5. RequestDispatcher对象的应用-请求包含
  6. 机器学习实战(MachineLearinginAction) 第三章 决策树
  7. 微型计算机发展方向网络化,第二章 会计电算化工作环境
  8. 样条曲面_SolidWorks肥皂块曲面建模,你的肥皂掉了
  9. Mozilla Firefox 66 将使用更少的内存,提高扩展性能
  10. 翻书插件:bookblock.js
  11. jsp+ssh+mysql Java web学生考勤管理系统源码附视频指导运行教程
  12. 智能生活雷达应用,微波雷达技术发展,微波雷达感应模块方案
  13. Web实现:仿大学英语四级成绩查询 html css 含效果图
  14. 如何优化前端页面的LCP?
  15. [Java教程 00] 计算机基础
  16. Staring into the Abyss: An Evaluation of Concurrency Control with One Thousand Cores 论文阅读
  17. 传奇引擎注册服务器,GeeM2引擎架设传奇不能注册账号 进不去游戏
  18. 推荐一本书——半小时漫画中国史
  19. web前端简介 | 什么是前端
  20. Oracle删表报错ora00054,【Oracle】ORA-00054 错误解决方法

热门文章

  1. J9数字论:现阶段Web3.0存在的问题有哪些
  2. 【CSA STAR 对标分析】BCR-业务连续性管理与操作恢复
  3. 微信小程序自定义组件数据、方法和属性
  4. python编写我的世界
  5. markdown图片左对齐问题
  6. 假设有一条绳子长3000m,每天剪去一半,请问需要几天时间,绳子的长度会短于五米?
  7. 应用层协议 HTTP HTTPS
  8. 广州市计算机应用能力考试地点,【广东】全国计算机等级考试考点查询(汇总)...
  9. 《刨根问底系列》:序言
  10. 网络通信之传输层协议