历史上的今天
返回首页

历史上的今天

今天是:2025年01月30日(星期四)

2019年01月30日 | 使用STM32CubeMx配置STM32输入捕获功能

2019-01-30 来源:eefocus

输入捕获原理


在输入捕获模式下,当检测到ICx信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(TIMx_CCRx)中。当发生捕获事件时,相应的CCxIF标志(TIMx_SR寄存器)被置1,如果开放了中断或者DMA操作,则将产生中断或者DMA请求。如果发生捕获事件时CCxIF标志已经为高,那么重复捕获标志CCxOF(TIMx_SR寄存器)被置1。写CCxIF=0可清除CCxIF,或读取存储在TIMx_CCRx寄存器中的捕获数据也可清除CCxIF。写CCxOF=0可清除CCxOF。

摘自《STM32参考手册中文》


简单解释:定时器一直在计数,如果检测到设置的极性边沿,会把当前的计数值存下来,并触发中断;


比如,定时器设置为TIM2,预分频719,计数周期0xFFFF,则TIM2 10us计数一次,计数到0xFFFF,重装载到0;现在设置的输入捕获极性为上升沿捕获,则当某通道捕获到一次上升沿后,触发中断,并将当前的计数值存在对应通道的CCR值;


所以无论是设置为上升沿捕获还是下降沿捕获,都只能得到整个脉冲的周期时间;如果是想获得高电平占整个周期的百分比呢?


那么我就需要在最开始设置为上升沿捕获,当捕获到一个上升沿后,把极性设置为下降沿捕获,依次类推,这样我们就可以得到高电平时间和周期时间了;注意要设置好标志位


这里的话会出现一个问题,比如我的上升沿时间点在上一个周期,下降沿时间点在下一个周期,那么在下降沿-上升沿之前还要再加上一个定时器周期


以下是我的STM32CubeMx配置


在这里插入图片描述
在这里插入图片描述在这里插入图片描述

8. 以下是比较重要的代码


/* Private variables ---------------------------------------------------------*/

uint16_t Channel1HighTime, Channel2HighTime, Channel3HighTime, Channel4HighTime;

uint16_t Channel1Period, Channel2Period, Channel3Period, Channel4Period;

uint8_t  Channel1Edge = 0, Channel2Edge = 0, Channel3Edge = 0, Channel4Edge = 0;

uint16_t Channel1Percent, Channel2Percent, Channel3Percent, Channel4Percent;

uint16_t Channel1PercentTemp[3] = {0, 0, 0};

uint8_t Channel1TempCount = 0;

uint16_t Channel1RisingTimeLast=0, Channel1RisingTimeNow, Channel1FallingTime;

uint16_t Channel2RisingTimeLast=0, Channel2RisingTimeNow, Channel2FallingTime;

uint16_t Channel3RisingTimeLast=0, Channel3RisingTimeNow, Channel3FallingTime;

uint16_t Channel4RisingTimeLast=0, Channel4RisingTimeNow, Channel4FallingTime;

/* USER CODE END PV */


int main(void)

{

  /* USER CODE BEGIN 1 */


  /* USER CODE END 1 */


  /* MCU Configuration----------------------------------------------------------*/


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();


  /* USER CODE BEGIN Init */


  /* USER CODE END Init */


  /* Configure the system clock */

  SystemClock_Config();


  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */


  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  MX_USART1_UART_Init();

  MX_TIM2_Init();

  /* USER CODE BEGIN 2 */

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);

  /* USER CODE END 2 */


  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);

HAL_Delay(500);

  /* USER CODE END WHILE */


  /* USER CODE BEGIN 3 */


  }

  /* USER CODE END 3 */


}


void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

  /* Prevent unused argument(s) compilation warning */

  UNUSED(htim);

  /* NOTE : This function Should not be modified, when the callback is needed,

            the __HAL_TIM_IC_CaptureCallback could be implemented in the user file

   */

if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)

{

if(Channel1Edge == 0)

{

Channel1RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);//获取上升沿时间点

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);//切换捕获极性

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);

Channel1Edge = 1;

if(Channel1RisingTimeLast == 0)

{

Channel1Period = 0;

}

else

{

if(Channel1RisingTimeNow > Channel1RisingTimeLast)

{

Channel1Period = Channel1RisingTimeNow - Channel1RisingTimeLast;

}

else

{

Channel1Period = Channel1RisingTimeNow + 0xffff - Channel1RisingTimeLast + 1;

}

}

Channel1RisingTimeLast = Channel1RisingTimeNow;

}

else if(Channel1Edge == 1)

{

Channel1FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);

if(Channel1FallingTime < Channel1RisingTimeNow)

{

Channel1HighTime = Channel1FallingTime + 0xffff - Channel1RisingTimeNow + 1;

}

else

{

Channel1HighTime = Channel1FallingTime - Channel1RisingTimeNow;

}

if(Channel1Period != 0)

{

Channel1Percent = (uint8_t)(((float)Channel1HighTime / Channel1Period) * 1000);

printf("Channel1 = %d ", Channel1Percent);

}

Channel1Edge = 0;

}

}

else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)

{

if(Channel2Edge == 0)

{

Channel2RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);

Channel2Edge = 1;

if(Channel2RisingTimeLast == 0)

{

Channel2Period = 0;

}

else

{

if(Channel2RisingTimeNow > Channel2RisingTimeLast)

{

Channel2Period = Channel2RisingTimeNow - Channel2RisingTimeLast;

}

else

{

Channel2Period = Channel2RisingTimeNow + 0xffff - Channel2RisingTimeLast + 1;

}

}

Channel2RisingTimeLast = Channel2RisingTimeNow;

}

else if(Channel2Edge == 1)

{

Channel2FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_2);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);

if(Channel2FallingTime < Channel2RisingTimeNow)

{

Channel2HighTime = Channel2FallingTime + 0xffff - Channel2RisingTimeNow + 1;

}

else

{

Channel2HighTime = Channel2FallingTime - Channel2RisingTimeNow;

}

if(Channel2Period != 0)

{

Channel2Percent = (uint8_t)(((float)Channel2HighTime / Channel2Period) * 1000);

printf("Channel2 = %d ", Channel2Percent);

}

Channel2Edge = 0;

}

}

else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_3)

{

if(Channel3Edge == 0)

{

Channel3RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_3);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_FALLING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);

Channel3Edge = 1;

if(Channel3RisingTimeLast == 0)

{

Channel3Period = 0;

}

else

{

if(Channel3RisingTimeNow > Channel3RisingTimeLast)

{

Channel3Period = Channel3RisingTimeNow - Channel3RisingTimeLast;

}

else

{

Channel3Period = Channel3RisingTimeNow + 0xffff - Channel3RisingTimeLast + 1;

}

}

Channel3RisingTimeLast = Channel3RisingTimeNow;

}

else if(Channel3Edge == 1)

{

Channel3FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_3);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_3, TIM_INPUTCHANNELPOLARITY_RISING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);

if(Channel3FallingTime < Channel3RisingTimeNow)

{

Channel3HighTime = Channel3FallingTime + 0xffff - Channel3RisingTimeNow + 1;

}

else

{

Channel3HighTime = Channel3FallingTime - Channel3RisingTimeNow;

}

if(Channel3Period != 0)

{

Channel3Percent = (uint8_t)(((float)Channel3HighTime / Channel3Period) * 1000);

printf("Channel3 = %d ", Channel3Percent);

}

Channel3Edge = 0;

}

}

else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_4)

{

if(Channel4Edge == 0)

{

Channel4RisingTimeNow = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_FALLING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);

Channel4Edge = 1;

if(Channel4RisingTimeLast == 0)

{

Channel4Period = 0;

}

else

{

if(Channel4RisingTimeNow > Channel4RisingTimeLast)

{

Channel4Period = Channel4RisingTimeNow - Channel4RisingTimeLast;

}

else

{

Channel4Period = Channel4RisingTimeNow + 0xffff - Channel4RisingTimeLast + 1;

}

}

Channel4RisingTimeLast = Channel4RisingTimeNow;

}

else if(Channel4Edge == 1)

{

Channel4FallingTime = HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_4);

__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_RISING);

HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);

if(Channel4FallingTime < Channel4RisingTimeNow)

{

Channel4HighTime = Channel4FallingTime + 0xffff - Channel4RisingTimeNow + 1;

}

else

{

Channel4HighTime = Channel4FallingTime - Channel4RisingTimeNow;

}

if(Channel4Period != 0)

{

Channel4Percent = (uint8_t)(((float)Channel4HighTime / Channel4Period) * 1000);

printf("Channel4 = %d\n", Channel4Percent);

}

Channel4Edge = 0;

}

}

}

推荐阅读

史海拾趣

Crystek公司的发展小趣事

随着科技的快速发展和市场的不断变化,Crystek公司意识到只有不断创新才能保持竞争优势。因此,公司加大了研发投入,积极引进先进技术,推出了一系列具有创新性和竞争力的新产品。其中,温度补偿晶体振荡器(TCXO)和压控晶体振荡器(VCXO)等产品的推出,不仅提升了Crystek公司的技术实力,也进一步巩固了其在行业中的领先地位。同时,公司还不断优化生产工艺和质量控制体系,确保产品的高性能和可靠性。

CINCH公司的发展小趣事

在快速发展的同时,CINCH公司也注重质量管理体系的建设。公司引进了国际先进的质量管理理念和方法,建立了完善的质量管理体系,并通过了ISO9001等质量管理体系认证。这一举措不仅提升了公司的产品质量和服务水平,还增强了客户对公司的信任度和满意度。

ETL semiconductor公司的发展小趣事

英特尔(Intel)的成立与发展与微处理器的发明密不可分。在20世纪70年代初,英特尔的工程师们开始研发一种能够将计算机的中央处理器(CPU)集成到单一芯片上的技术。经过数年的努力,他们成功推出了世界上第一款微处理器——Intel 4004。这一创新不仅改变了计算机行业,也为英特尔的崛起奠定了坚实基础。

Amphenol RF公司的发展小趣事

台积电(TSMC)是全球最大的半导体代工企业之一。其发展历程可以追溯到上世纪80年代。当时,台积电看准了半导体代工市场的巨大潜力,决定专注于这一领域。通过不断的技术创新和市场拓展,台积电逐渐在代工领域树立了领先地位。如今,台积电已与全球众多知名芯片设计企业建立了紧密的合作关系,为全球半导体产业的发展做出了重要贡献。

First Silicon Co., Ltd公司的发展小趣事

随着全球电子市场的不断扩张,First Silicon公司意识到单一市场已无法满足其长远发展需求。于是,公司制定了全球化战略,通过设立海外研发中心、生产基地和销售网络,实现了从研发、生产到销售的全球化布局。这一战略不仅有效降低了公司的运营成本,还极大地提升了其品牌影响力和市场份额。在全球化进程中,First Silicon还积极与当地企业开展合作,共同推动电子技术的进步和应用。

Amplitronix LLC公司的发展小趣事

Amplitronix LLC的创立,源于两位年轻工程师对电子技术的热爱与执着。他们发现市场上存在一种需求,即高性能、高精度的电子测量仪器。于是,他们决定携手创业,将这个想法付诸实践。初创时期,资金短缺、技术难题、市场竞争激烈,每一道关卡都考验着他们的决心和毅力。但他们凭借着对技术的热情和对市场的敏锐洞察,不断研发创新,最终成功推出了首款产品,赢得了市场的初步认可。

问答坊 | AI 解惑

电子控制技术在汽车发动机中的应用

1.  引言1)汽车发动机基本原理和构造当今世界上的汽车发动机工作过程基本上都由四个冲程组成,即进气、压缩、膨胀和排气。利用燃料和空气的混合气在气缸内燃烧产生的高温高压气体的膨胀,发动机借助于曲柄连杆机构通过曲轴对外输出扭矩 ...…

查看全部问答>

25美分能买到什么MCU?

不可否认的是,TI还是有钱人~~ 说做MCU,这回又砸向了8位单片机市场: 起价仅 25 美分的 MSP430G2xx 系列 旨在用16位MCU的性能、8位MCU的价格攻城略地。 据称第一批产品现在已经可以提供样片了。昨天还和朋友聊,朋友也觉得:16位机这样的价 ...…

查看全部问答>

企业虚拟化项目十个重要技术问题中国IDC圈

企业虚拟化项目十个重要技术问题中国IDC圈 利用虚拟化技术,把软件从硬件当中抽取出来,创建灵活、动态的环境,这样的好处很吸引人。不过能 否成功实施该项技术则取决于所需技能、安全和管理工具以及业务驱动因素是否到位。因为,在有些情 况下 ...…

查看全部问答>

MPC8321 目标板寄存器文件

哪位仁兄大大,有vision Click 仿真器关于MPC8321 目标板寄存器文件? 小弟急需,谢谢啦…

查看全部问答>

降采样后的AD值与原先AD值差别较大,如何解决

大家好,小弟最近在做一个关于ADC的滑动平均的算法,遇到问题,还请指教。 先说下正常情况,将ADC数据传送到终端的步骤如下: ADC连续转换模式,每转换一个ADC数据,就触发一次中断。随后交给UART送到终端。 但后来发现,当ADC的转换频率为8KHZ ...…

查看全部问答>

请教烧写系统到开发板的问题

大家好,我在往开发板里烧写NK文件的时候在到达99%的时候,超级终端出现了: OEMVerifyMemory FAILED !OEMVERIFYMEMORY: Invalid image 然后烧写进度就停留在了99%,请问是什么错误啊?应该如何修改呢?…

查看全部问答>

嵌入式开发概念问题,请前辈引路

请问嵌入式系统移植是怎样的一个概念? 和原来我们所说的单片机对比来说 在系统上编程又有什么不同,如果是否需要学习vc,我只会c 还有驱动编程,又是怎么一回事,和单片机的IO口控制,flash读写,uart控制有什么区别 谢谢各位指导…

查看全部问答>

这些分类:电子/电器/半导体/仪表仪器 是有下面这些分支吗?

集成电路IC设计/应用工程师 电子工程师 电路工程师 电器工程师 电声/音响工程师 自动控制工程师 仪器/仪表/计量 …

查看全部问答>

win ce 下的串口的问题

  我想在win ce 下开发一个串口通信的控制软件 不知道怎么下手。请高手们指点迷精。。。。。。。。。。。。。。。。。。。。。。 用什么编程软件,等等;…

查看全部问答>

【我给XILINX资源中心做贡献】设计小技巧--Xilinx公司内部资料

设计小技巧--Xilinx公司内部资料这是一个在设计中常犯的错误列表,这些错误使得你的设计不可靠或者速度较慢。为了提高你的设计性能和提高速度的可靠性,你必须确定你的设计通过所有的这些检查。…

查看全部问答>