jsp做简单校园网站/排名点击软件怎样

jsp做简单校园网站,排名点击软件怎样,网站建设调研报告的前言,包装印刷脉冲信号用于设备控制是非常常见的,但在一些情况下,我们希望精确的控制脉冲的数量以实现对运动的精确控制。实现的方式也许有多种多样,但使用计时器来实现此类操作是人们比较容易想到的。 1、原理概述 我们知道在STM32平台上,使…

脉冲信号用于设备控制是非常常见的,但在一些情况下,我们希望精确的控制脉冲的数量以实现对运动的精确控制。实现的方式也许有多种多样,但使用计时器来实现此类操作是人们比较容易想到的。

1、原理概述

我们知道在STM32平台上,使用计时器来实现PWM操作是非常常见的用法。使用的是单一计时器,事实上通过主从两个计时器配合我们也可通过生成PWM波的方式精确控制输出脉冲的数量。接下来我们就来简单了解一下使用主从计时器实现精确数量脉冲输出的原理。

对于STM32平台一般都有TIM1和TIM8两个高级定时器和TIM2、TIM3、TIM、TIM5等几个通用定时器。STM32的这些定时器可以通过另外一个定时器的某一个条件被触发而启动。这里所谓某一个条件可以是定时到时、定时器超时、比较成功等各种条件。这种通过一个定时器触发另一个定时器的工作方式称为定时器的同步,发出触发信号的定时器工作于主模式,接受触发信号而启动的定时器工作于从模式。这些个计时器都可用作从计时器,但作为主计时器则是对应不同的触发源,它们的主从关系必须遵循设定不可随意配置。具体的配置关系如下:

当然要实现精确控制脉冲输出,就需要按照上述列表中的要求实现主从计时器的配置。对于主计时器来说,要将输出配置为PWM输出,并将触发输出的主从模式启用。而对于从计时器来说,需要启用从模式,并设为门控方式,触发源则根据上述表中的描述来选择。

可是为什么主从计时器就能实现精确数量的脉冲输出呢?我们借助下面的简单图示来说明这个问题。

首先按前面所述的主从计时器要求配置好主从计时器,这是最基本的要求。主计时器负责设置脉冲输出的频率以及输出脉冲,从计数器所控制输出的脉冲数。具体过程是这样的,主进程启动主从计时器,从计时器通过主计时器输出的触发信号开始脉冲计数,当达到指定的计数值后,产生中断停止主计时器输出,直到主进程再次开启这一过程。

2、系统设计

我们已经了解了通过主从计时器实现精确数量脉冲输出的基本原理。那究竟如何实际做呢?接下来我们就设计一个简单的系统实现它。

在这一系统中,我是使用STM32F407作为实现平台,以TIM1作为主计时器,TIM4作为从计时器,同时输出四路脉冲信号。四路的频率是相同的,但每一路的输出数量是可以设定的。具体的操作结构如下图所示:

主进程轮询控制计时器TIM1和TIM4工作,而TIM1主计时器给TIM4从计时器输出触发信号,而从计时器到达指定脉冲数后输出中断信号控制TIM1的输出通道停止。我们人为规定TIM4的通道1、2、3、4与TIM1的输出通道1、2、3、4相对应。

3、代码实现

我们已经说明了使用主从计时器实现精确输出脉冲数的原理,也设计了我们的我们想要实现的系统结构,接下来我们实现这一系统。

3.1、主计时器的配置

首先我们来看一看主计时器的配置,具体代码如下:

/*TIM1初始化配置*/
static void TIM1_Init_Configuration(uint32_t period)
{TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};htim1.Instance = TIM1;htim1.Init.Prescaler = 1;htim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = (period-1);htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter = 0;if (HAL_TIM_PWM_Init(&htim1) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK){Error_Handler();}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = (period/2);sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_4) != HAL_OK){Error_Handler();}sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;sBreakDeadTimeConfig.DeadTime = 0;sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK){Error_Handler();}HAL_TIM_MspPostInit(&htim1);
}

3.2、从计时器的配置

接着我们再来看一看从计时器的配置,具体代码如下:

/*TIM4初始化配置*/
static void TIM4_Init_Configuration(void)
{TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_SlaveConfigTypeDef sSlaveConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};htim4.Instance = TIM4;htim4.Init.Prescaler = 0;htim4.Init.CounterMode = TIM_COUNTERMODE_UP;htim4.Init.Period = 0xFFFF;htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;if (HAL_TIM_Base_Init(&htim4) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK){Error_Handler();}sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;sSlaveConfig.InputTrigger = TIM_TS_ITR0;if (HAL_TIM_SlaveConfigSynchronization(&htim4, &sSlaveConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK){Error_Handler();}
}

3.3、主轮询函数实现

主轮询函数控制着主从计时器的启动,是实现脉冲输出的控制者,包括设置脉冲数并开启从计数器的计数和中断以及启动主计时器的输出。具体代码如下:

/*实现通讯数据的处理*/void HgraDataProcess(void)
{TIM_SET_CAPTUREPOLARITY(&htim1,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);  // 捕获比较1中断使能TIM_SET_CAPTUREPOLARITY(&htim1,TIM_CHANNEL_2,TIM_ICPOLARITY_RISING);  // 捕获比较2中断使能TIM_SET_CAPTUREPOLARITY(&htim1,TIM_CHANNEL_3,TIM_ICPOLARITY_RISING);  // 捕获比较3中断使能TIM_SET_CAPTUREPOLARITY(&htim1,TIM_CHANNEL_4,TIM_ICPOLARITY_RISING);  // 捕获比较4中断使能__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,6400);     // 输入通道1的捕获比较值CCR1__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_2,6400);     // 输入通道2的捕获比较值CCR2__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_3,6400);     // 输入通道3的捕获比较值CCR3__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,6400);     // 输入通道4的捕获比较值CCR4HAL_TIM_OC_Start_IT(&htim4,TIM_CHANNEL_1);    //开启定时器4通道1的输入捕获中断HAL_TIM_OC_Start_IT(&htim4,TIM_CHANNEL_2);    //开启定时器4通道2的输入捕获中断HAL_TIM_OC_Start_IT(&htim4,TIM_CHANNEL_3);    //开启定时器4通道3的输入捕获中断HAL_TIM_OC_Start_IT(&htim4,TIM_CHANNEL_4);    //开启定时器4通道4的输入捕获中断HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1);  //开启定时器1通道1的PWM输出中断        HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_2);  //开启定时器1通道2的PWM输出中断HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_3);  //开启定时器1通道3的PWM输出中断HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_4);  //开启定时器1通道4的PWM输出中断
}

3.4、中断处理函数的实现

从计时器产生中断后,会根据不同的中断调用不同的中断处理函数,这些回调函数是需要我们实现的,在这里要实现主计时器PWM输出的停止以及中断标志的复位等处理。具体实现代码如下:

/*PWM中断轮询回调函数*/
static void TIM1_PWM_PulseFinished(TIM_HandleTypeDef *htim)
{if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)                         //判断是否生成中断标志位SR{if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET)              //定时器中断使能是否开启{__HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC1);                   //清除中断标志位SRif(HAL_TIM_PWM_Stop_IT(&htim1, TIM_CHANNEL_1)==HAL_OK)         //关闭定时器1的通道1的PWM输出{HAL_TIM_OC_Stop_IT(&htim4,TIM_CHANNEL_1) ;                   //关闭定时器4的通道1的输入中断捕获flagStop[0] = 1;                                                //关闭标志置1}}}                                                                          //下面的通道2同理如此if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2) != RESET){if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC2) !=RESET){__HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC2);                       //清除标志位if(HAL_TIM_PWM_Stop_IT(&htim1, TIM_CHANNEL_2)==HAL_OK){    aHAL_TIM_OC_Stop_IT(&htim4,TIM_CHANNEL_2) ;   flagStop[1] = 1;           }}}if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3) != RESET){if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC3) !=RESET){__HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC3);                       //清除标志位if(HAL_TIM_PWM_Stop_IT(&htim1, TIM_CHANNEL_3)==HAL_OK){    HAL_TIM_OC_Stop_IT(&htim4,TIM_CHANNEL_3) ;   flagStop[2] = 1;           }}}if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4) != RESET){if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC4) !=RESET){__HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC4);                       //清除标志位if(HAL_TIM_PWM_Stop_IT(&htim1, TIM_CHANNEL_4)==HAL_OK){    HAL_TIM_OC_Stop_IT(&htim4,TIM_CHANNEL_4) ;   flagStop[3] = 1;            }}}if((flagStop[0]== 1)&&(flagStop[1] == 1)&&(flagStop[2] == 1)&&(flagStop[3] == 1)){flagStop[0]= 0;flagStop[1]= 0;flagStop[2]= 0;flagStop[3]= 0;__HAL_TIM_SET_COUNTER(&htim4,0);}
}

4、小结

我们设计了一个四路输出的脉冲输出,每一路的输出数量可以精确单独控制,在输出的频率相对较低而且数量不大的情况下我们验证是没有问题的。当然在数量特别多时,是否有偏差我们没有测试。而在我们使用的平台,时钟为168MHz,根据我们的简单测试在输出8MHz的脉冲时还是比较精确的,不过这已经完全满足一般的应用需求。

其实从STM32的手册我可以知道,输出指定脉冲数的方法有多种,但使用主从计时器方式是比较好的一种。这种方式虽然多用了一个定时器,但因为不需要频繁中断大大减少了CPU的处理资源。

欢迎关注:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

外设驱动库开发笔记0:EPD总体设计

在产品开发过程中,不可避免需要使用很多外部的元件及传感器,这些元器件也许是板载的,也许是板外的,但不管怎样,为其开发驱动程序都是必须的。每次都需要为这些元器件编写驱动程序。但每次重复编写调试很麻烦&#xff0…

外设驱动库开发笔记1:AD56xx系列DAC驱动

DAC在我们的项目中经常使用到,而使用最多的就是AD56xx系列,包括有单通道的AD5662、双通道的AD5623和AD5663、以及四通道的AD5624和AD5664等。出于方便复用的原因,我们设计并实现AD56xx系列DAC的驱动。 1、功能概述 AD56xx系列DAC属于nanoDA…

外设驱动库开发笔记2:AD8400系列数字电位器驱动

一些时候我们需要在系统使用过程中改变某些电路电阻值以达到改变设定的目的,这时候我们就会使用电位器。在我们使用数字控制电路时多选择数字电位器。在这一篇我们就来设计AD8400系列数字电位器的驱动。 1、功能概述 AD8400/AD8402/AD8403分别是单通道/双通道/四通…

外设驱动库开发笔记3:AD527x系列数字电位器驱动

在一些时候我们需要使用精度更高的数字电位器来实现我们的应用。我们经常使用AD527x系列数字电位器来实现这类应用。在通常情况下,AD527x系列数字电位器完全能够满足要求。为了减少重复工作,在这里我们将分系并实现AD527x系列数字电位器的驱动。 1、功能…

PID控制器改进笔记之一:改进PID控制器之参数动态调整

前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。所以在这篇中我们来讨论改进…

外设驱动库开发笔记4:AD9833函数发生器驱动

很多时候我们需要输出某种函数信号,如方波、三角波、正弦波等,但想要获得这样的函数信号,不论是硬件电路还是软件实现,却并不是一件简单的事情。不过AD9833这类函数生成芯片可以简化这方面的操作,这一节我们就来设计并…

PID控制器改进笔记之二:改进PID控制器之手自动切换

前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。所以在这篇中我们来讨论改进…

外设驱动库开发笔记5:AD7705系列ADC驱动

我们的经常需要采集一些精度要求较高的模拟信号,使用MCU集成的ADC难以达到要求、所以我们需要独立的ADC芯片。这一节我们就来设计并实现AD7705芯片的驱动、并探讨驱动的使用方法。 1、功能概述 AD7705/AD7706是用于低频测量的完整模拟前端。可以直接从传感器接收低…

PID控制器改进笔记之三:改进PID控制器之正反作用

前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。所以在这篇中我们来讨论改进…

PID控制器改进笔记之四:改进PID控制器之设定值响应

前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。所以在这篇中我们来讨论改进…

PID控制器改进笔记之五:改进PID控制器之串级设定

前面我们发布了一系列PID控制器相关的文章,包括经典PID控制器以及参数自适应的PID控制器。这一系列PID控制器虽说实现了主要功能,也在实际使用中取得了良好效果,但还有很多的细节部分可以改进以提高性能和灵活性。所以在这篇中我们来讨论改进…

滤波器开发之一:基于算数平均的平滑滤波器

信号采集是非常常见的需求,我们也总是希望采集到的数据是纯净而真实的,但这只是我们的希望。环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响,于是就有了滤波器的用…

外设驱动库开发笔记6:AD719x系列ADC驱动

前面我们讨论了AD7705这种ADC器件的驱动开发,在实际中我们使用更多的是AD719x系列的ADC芯片、包括有AD7191、AD7192和AD7193等。接下来我们就来设计并开发AD719x的驱动程序。 1、功能概述 AD7192是一款适合高精密测量应用的低噪声完整模拟前端,内置一个…

滤波器开发之二:基于算数平均的带阻平滑滤波器

信号采集是非常常见的需求,我们也总是希望采集到的数据是纯净而真实的,但这只是我们的希望。环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响,于是就有了滤波器的用…

滤波器开发之三:基于算数平均的阶进平滑滤波器

信号采集是非常常见的需求,我们也总是希望采集到的数据是纯净而真实的,但这只是我们的希望。环境中存在太多的干扰信号,为了让我们得到的数据尽可能地接近实际值,我们需要降低这些干扰信号的影响,于是就有了滤波器的用…

外设驱动库开发笔记7:LTC2400系列ADC驱动

有些时候我们需要对高精度的ADC来处理一些要求较高的模拟量采集。在处理温控器的过程中我们就使用到了LTC2400这款ADC。接下来我们就来设计并实现LTC2400的驱动。 1、功能概述 LTC2400是一个供电电压2.7V到5.5V的微功率24位转换器,集成了振荡器、4ppm INL和0.3ppm…

外设驱动库开发笔记8:GPIO模拟I2C驱动

I2C总线简单方便,是我们经常使用的一种总线。但有时候我们的MCU没有足够多的I2C控制器来实现我们的应用,所幸我可以使用普通的GPIO引脚来模拟低速的I2C总线通信。这一节我们就来实现使用软件通过普通GPIO操作I2C设备的驱动。 1、功能概述 I2C总线使用两…

嵌入式IAP开发笔记之一:面向STM32的BootLoader程序

对于很多人来说,BootLoader并不是一个陌生的词,甚至会经常用到它。因为在很多情况下我们都需要BootLoader程序,比如我们需要对系统在线升级时就需要它,还有当我们需要在外部存储器中运行程序时也需要用到它。在这里我们就来设计一…

外设驱动库开发笔记9:SHT1x系列温湿度传感器驱动

在我们的产品中,经常需要检测温湿度数据。有很多检测温湿度的方法和模块,其中SHT1x系列温湿度传感器就是一种成本较低使用方便的温湿度检测模块。下面我们就来说一说如何实现SHT1x系列温湿度传感器的驱动。 1、功能概述 SHT1x包括 SHT10, S…

Modbus协议栈应用实例之一:Modbus RTU主站应用

自从开源了我们自己开发的Modbus协议栈之后,有很多朋友建议我针对性的做几个示例。所以我们就基于平时我们的应用整理了几个简单但可以说明基本的应用方法的示例,在这一篇中我们先来使用协议栈实现Modbus RTU主站的示例。 1、何为RTU主站 Modbus协议是…