当前位置: 首页 > news >正文

公司网站自己创建东莞建站多少钱

公司网站自己创建,东莞建站多少钱,单县网站建设,杭州建筑网页设计目录 定时器基本定时功能实现 CubeMX设置 手动书写代码部分 定时器启动 实现溢出回调函数 HAL_Delay介绍 HAL_Delay实现原理 HAL_Delay的优点 HAL_Delay的缺点 利用滴答定时器(SysTick)实现微秒级延时 PWM PWM介绍 通用定时器中的重要寄存器 PWM中的捕获比较通道 …目录 定时器基本定时功能实现 CubeMX设置 手动书写代码部分 定时器启动 实现溢出回调函数 HAL_Delay介绍 HAL_Delay实现原理 HAL_Delay的优点 HAL_Delay的缺点 利用滴答定时器(SysTick)实现微秒级延时 PWM PWM介绍 通用定时器中的重要寄存器 PWM中的捕获比较通道 什么是定时器通道 定时器通道如何工作 为什么需要定时器通道 PWM实现呼吸灯 CubeMX配置 关于TIMx_PSC和TIMx_ARR的计算 几种不同方式实现设定PWM的周期 如何选择不同PSC与ARR的组合 代码编写 定时器基本定时功能实现 CubeMX设置 注意这里只是对定时器配置实现一个很简单的定时功能。 时钟来源 定时器中断使能  定时器预分频值计数模式计数周期 手动书写代码部分 定时器启动 下面主要介绍一下关于定时器的简单运用 关于下面图片中的初始化函数我们可以不用过于在意因为在我们上面CUBEMX中已经配置过了而且定时器的初始化相比于外部中断要复杂的多所以就不推荐手动书写代码配置了主要掌握CubeMX中的定时器初始化配置方式就行。 在main.c中让定时器开始运行 尽管我们在CubeMX或类似的配置工具中配置了定时器并生成了代码但生成代码仅仅是设置了定时器的参数如时钟源、预分频器、自动重载值、中断使能等。这些配置通常在 MX_TIMx_Init() 或类似的初始化函数中完成。 然而这些初始化函数并不会自动启动定时器或启用中断需要我们调用相应的启动函数来手动对定时器开启。这是一种设计哲学记住就好也就是多了一行开启时钟代码。 启动定时器函数需要一个参数接受一个TIM_HandleTypeDef类型的地址 这个参数在我们的TIM2_Init函数中有是在tim.c中定义的是一个全局变量。 由于我们的main.c文件中包含了tim.h头文件并且tim.h中对于这个变量进行了extern声明所以在main中可以直接使用htim2了 htim2 用于表示特定定时器实例在这里是 TIM2 的一个句柄 (Handle) 结构体变量包含了管理特定定时器所需的所有配置信息和状态我们对定时器进行配置的时候主要就是对这个变量进行配置。 它是全局的通常定义在文件作用域可以在程序的任何地方只要包含了定义它的文件或声明它的头文件访问和修改它。  它是访问点所有针对 TIM2 定时器的 HAL 库函数如 HAL_TIM_Base_Start_IT(htim2)、HAL_TIM_PeriodElapsedCallback(htim) 等都需要通过这个 htim2 句柄来知道它们正在操作的是哪个定时器。 实现溢出回调函数 由于我们使用了CubeMX配置了定时器所以关于定时器的TIM6_DAC_IRQHander()不需要我们来声明并实现这里的逻辑和中断处理那块的逻辑差不多不过定时器这里有很多回调函数对于简单的定时功能我们需要实现的是溢出回调函数——HAL_TIM_PeriodElapsedCallback()。 通过HAL_TIM_PeriodElapsedCallback()可以实现周期性任务 LED 闪烁 每隔 500ms 翻转一次 LED 的状态。数据采样 每隔 10ms 读取一次传感器数据。任务调度 以固定的频率触发一个任务的执行。 关于HAL_TIM_PeriodElapsedCallback这个弱定义函数可以放main.c函数中进行实现。 补充一下main.c文件中函数声明和实现的写法         声明在 main() 函数之前 在 main.c 中确实经常看到用户编写的函数在 main() 函数之前进行声明原型声明。         实现通常在 main() 函数之后 而这些函数的实现函数体则经常放在 main() 函数的后面通常是在 /* USER CODE BEGIN 4 */ 和 /* USER CODE END 4 */ 这样的用户代码区域内。 其他模块的文件一般我们的选择是在.h中进行函数的声明在.c文件中进行函数的实现。  HAL_Delay介绍 HAL_Delay实现原理 HAL_Delay() 的实现方式主要基于 SysTick 定时器 和一个全局的滴答计数变量 (uwTick)。 如果是使用CubeMX进行的配置那么默认会在main()中调用HAL_Init()里面会自动帮我们启动滴答定时器SysTick。 SysTick 是 Cortex-M 系列处理器包括 STM32内置的一个 24 位倒计时定时器。它直接集成在 CPU 核心内部。 工作方式 我们会配置 SysTick 的重装载值Reload Value。一旦启用SysTick 计数器会从这个重装载值开始递减SysTick 计数器一般直接使用系统的主时钟频率HCLK。当计数器递减到 0 时它会产生一个 SysTick 中断然后自动重新装载并再次开始递减。所以 每过 1msSysTick 计数器递减到 0触发一次 SysTick 中断。执行 ISR 处理器响应 SysTick 中断执行相应的 ISR。调用 HAL_IncTick() 在 SysTick 的 ISR 内部HAL_IncTick() 被执行。更新 uwTick HAL_IncTick() 将全局变量 uwTick 加 1。HAL_GetTick() 函数的实现非常直接它只是简单地返回当前 uwTick 变量的值 HAL_Delay的伪代码如下 void HAL_Delay(uint32_t Delay) {uint32_t tickstart HAL_GetTick(); // 获取当前系统滴答值uint32_t wait tickstart Delay; // 计算目标滴答值// 等待直到达到目标滴答值并处理uwTick可能溢出的情况while((HAL_GetTick() wait) ((HAL_GetTick() - tickstart) Delay)) {// 空循环CPU在此处忙等待} } HAL_Delay的优点 1. 使用简单易于上手 HAL_Delay() 的接口非常直观你只需要传入一个你想要延时的毫秒数函数就会阻塞相应的时长。对于嵌入式编程的初学者来说这是最容易理解和使用的延时方式能够快速实现一些简单的功能 2. 无需额外配置 一旦 HAL 库和 SysTick 定时器被初始化这通常在项目启动时自动完成HAL_Delay() 就可以直接调用无需进行额外的定时器配置也不需要编写中断服务程序。这大大简化了开发流程尤其是在快速原型开发或对延时精度要求不高的场景下。 HAL_Delay的缺点 1. 阻塞式操作 (Blocking): 这是最主要的缺点。当调用 HAL_Delay() 时CPU 会进入一个忙等待循环不执行任何其他有用的任务直到延时结束。 2. 不适用于精确的微秒级延时 HAL_Delay() 的精度是毫秒级因为它依赖于 1ms 的 SysTick 中断。对于需要微秒us甚至纳秒ns级别的精确延时HAL_Delay() 无法满足要求。 3.不适用于中断服务程序 (ISR) 中使用 严重问题 绝对不能在中断服务程序 (ISR) 中直接调用 HAL_Delay()。 HAL_Delay() 依赖于 SysTick 中断来更新 uwTick 变量。如果 SysTick 中断的优先级低于数值上大于当前执行的 ISR那么 SysTick 中断将无法抢占当前 ISR 并执行导致 uwTick 无法更新。这样一来HAL_Delay() 就会陷入无限循环使系统彻底崩溃。 HAL_Delay()中的SysTick定时器默认的优先级是最低的所以在ISR中调用HAL_Delay不可能调用成功会持续阻塞在这里除非我们手动调整SysTick定时器优先级让其变得更高但是这也是非常非常非常不推荐的 4. 与 RTOS 的兼容性问题 如果您的项目使用了实时操作系统 (RTOS)如 FreeRTOS直接使用 HAL_Delay() 是不推荐的。 RTOS 有自己的任务调度机制它提供的延时函数例如 FreeRTOS 的 osDelay() 或 vTaskDelay()会在任务延时期间将当前任务挂起并允许调度器切换到其他任务执行从而充分利用 CPU 资源。 利用滴答定时器(SysTick)实现微秒级延时 上面说到了使用滴答定时器(SysTick)实现的延迟函数HAL_Delay只能实现ms级别延时对于更精确的微秒级别是不支持的下面我们自己来使用SysTick实现微秒级延时。 下面实现的delay_us 函数是一个典型的忙等待busy-waiting 实现也就是基于查询方式实现的没有用到中断。 void delay_us(uint32_t nus){uint32_t ticks;uint32_t told, tnow, tcnt 0;uint32_t reload SysTick-LOAD 1; //计数个数为重装载值加1ticksnus*(SystemCoreClock/1000000); //nus 微秒总共需要的 SysTick 节拍数told SysTick-VAL; //初始计数器值while(1){tnowSysTick-VAL;if(tnow! told){if(tnowtold) tcnt told- tnow; //SysTick递减的计数器else tcnt reload- tnow told;told tnow;if(tcntticks) break; //延时时间已到退出}}} 这段代码通过不断读取 SysTick 的值并巧妙地处理了 SysTick 递减计数和溢出绕回的特性来精确地累加流逝的节拍数。当累加的节拍数达到预设的目标值时就完成了微秒级的延时。 PWM 下面这个视频是对pwm比较专业一点的介绍 【STM32】输出比较模式讲解以及STM32CUBEMXMDK代码实现_哔哩哔哩_bilibili 下面这篇文章是对pwm比较通俗一点的介绍更易理解 PWM原理 PWM频率与占空比详解-CSDN博客 PWM介绍 PWM全称是脉冲宽度调制它通过数字方式来模拟出模拟信号的效果简单来说PWM的原理就是通过快速开关一个数字信号比如电源并且控制它在一个周期内“开”的时间长短来达到目的。 脉冲宽度通常就是指在一个完整的 PWM 周期内信号处于高电平ON 状态的持续时间长度。 下面是一些关键点 PWM周期一个PWM完整波需要的时间Period这是指一个完整的PWM波形所需的时间也就是说信号从“开”到“关”再回到“开”的总时间。 占空比Duty Cycle这是PWM的核心。它表示在一个周期内信号处于“开”状态的时间所占的比例。占空比越高信号“开”的时间就越长。 PWM频率Frequency这是指每秒钟有多少个PWM周期。频率越高信号切换得越快看起来就越平滑越像一个真正的模拟信号。PWM 的频率是由 ARR 和 PSC 共同决定的 PWM是如何工作的 想象一下你有一个灯泡你想控制它的亮度。 如果你一直给灯泡供电100%占空比它就会全亮。 如果你完全不给灯泡供电0%占空比它就会熄灭。 如果你以很快的速度比如每秒钟开关1000次每次只让灯泡亮一半的时间50%占空比那么因为你的眼睛无法分辨这么快的开关灯泡看起来就会是半亮的状态。 这就是PWM的工作原理。通过调整“开”的时间比例占空比我们就可以控制灯泡的亮度、电机的转速、音频信号的音量等等。 通用定时器中的重要寄存器 预分频器寄存器 (TIMx_PSC) 这个寄存器用于设置定时器时钟的预分频值从而设置了定时器的时钟频率。 PSC (Prescaler Value)定时器时钟源会通过这个预分频器进行分频从而得到计数器实际使用的时钟频率。计算方式计数器时钟频率 定时器时钟源频率 / (PSC 1)。 自动重载寄存器 (TIMx_ARR) 这个寄存器定义了计数器达到多少时会溢出并重新开始计数或改变计数方向。   ARR (Auto-Reload Value)当计数器达到 ARR 的值时会发生更新事件。  计算方式PWM 的频率是由 ARR 和 PSC 共同决定的。PWM 频率 计数器时钟频率 / (ARR 1) 定时器时钟源频率 / ((PSC 1) * (ARR 1))。  作用设置 PWM 信号的周期和频率。ARR 值越大PWM周期越长频率越低。 捕获/比较寄存器 (TIMx_CCRx) 每个 PWM 通道都有一个对应的 CCRx 寄存器如 TIMx_CCR1, TIMx_CCR2 等。 CCRx (Capture/Compare Register Value)这个寄存器存储的值与计数器 CNT 的值进行比较从而决定 PWM 信号的占空比。 计算方式占空比 CCRx / (ARR 1)。  例如如果 ARR 999CCRx 500那么占空比就是 500 / 1000 50%。  作用设置 PWM 信号的脉冲宽度进而控制占空比。 当然通用定时器中还有一些其他寄存器很多这些寄存器由CubeMX帮我们自动设置好了所以不需要很关注。 PWM中的捕获比较通道 什么是定时器通道 你可以把一个微控制器里的定时器想象成一个多功能的厨房定时器总机。这个总机本身可以计时例如设定每秒滴答一次。而通道就是这个总机上独立的定时器插口或功能模块。 每个通道都可以独立地配置来完成特定的任务例如 捕获输入Input Capture 测量外部信号的脉冲宽度、频率或边沿之间的时间间隔。 比较输出Output Compare 在定时器计数到预设值时改变输出引脚的状态高/低电平用于产生PWM波形、延时输出脉冲等。 PWM 生成PWM Generation 最常见的用途之一生成可调占空比的脉冲宽度调制信号用于电机调速、LED调光等。 单脉冲模式One-Pulse Mode 在事件发生后产生一个固定宽度的脉冲。 一个定时器通常会有2个、4个或更多个通道这意味着这个定时器可以同时处理2个、4个或更多个上述的独立任务。 定时器通道如何工作 每个定时器通道内部都有一组专门的寄存器来配置它的行为其中最重要的就是比较/捕获寄存器 (Capture/Compare Register, CCR)。 作为输出Output Compare/PWM 当定时器的内部计数器通常是TIMx_CNT寄存器的值与某个通道的CCR寄存器的值相等时定时器就会触发该通道预设的动作例如翻转输出电平、生成PWM脉冲。你可以为每个通道设置不同的CCR值从而产生不同的输出波形或在不同时间点触发事件。一旦配置好通道会根据定时器计数器的值自动在引脚上生成PWM波形无需CPU干预。 作为输入Input Capture 当外部引脚上的信号例如上升沿或下降沿发生变化时定时器会将当前内部计数器TIMx_CNT的值“捕获”到对应通道的CCR寄存器中。通过读取不同边沿捕获到的CCR值就可以计算出脉冲宽度、周期等。 为什么需要定时器通道 多任务并行 如果一个应用需要同时生成两个不同频率或占空比的PWM波形或者同时测量两个不同信号的频率那么使用一个多通道定时器会比使用两个独立的单功能定时器更高效、更节省资源。 资源优化 微控制器内部的硬件定时器是有限的宝贵资源。多通道设计允许单个定时器模块完成多种定时/计数相关的任务从而节省了片上定时器模块的数量。 灵活性 每个通道都可以独立配置其工作模式极大地增加了定时器模块的灵活性使其能够适应各种复杂的应用需求。 硬件实现 定时器通道通常通过硬件逻辑实现这意味着一旦配置完成它们就能自动、精确地工作无需CPU干预从而减轻了CPU的负担提高了系统的实时性。 PWM实现呼吸灯 CubeMX配置 PB10 引脚配置成 TIM2_CH3定时器2的通道3 的操作正是属于 STM32 微控制器中的 输出复用功能模式。 复用功能 (Alternate Function, AF) 一个GPIO引脚除了其通用IO功能外还可以“复用”为某个片内外设如定时器、SPI、I2C、USART等的专用功能引脚。 这样配置之后的效果 引脚功能特化 PB10 不再是简单的 GPIO它变成了一个由硬件定时器控制的专用引脚。 作为 PWM 输出 PB10 引脚将输出一个脉冲宽度调制PWM波形。  作为 输出比较当 TIM2 的计数器值与 TIM2_CH3 的比较值CCR3相等时PB10 引脚的电平状态会按照预设的模式发生变化例如翻转、置高、置低。  作为 输入捕获PB10 引脚将作为一个输入引脚。当外部信号在这个引脚上发生预设的边沿上升沿、下降沿或双边沿时TIM2 定时器的当前计数值会被立即“捕获”并存储到 TIM2_CH3 对应的捕获/比较寄存器CCR3中。 我想要让LED1变成呼吸灯在我的电路板上LED1对应的是PB10然后右键查看对应的多路复用模式中对应的正好是TIM2_CH3我们选择定时器2的通道3然后我们需要去配置 TIM2 具体的参数配置主要是要计算分频系数TIMx_PSC和自动重载寄存器 (TIMx_ARR) 通过设置这两个寄存器就实现了设置PWM的周期和频率 这里我们的主时钟频率为100Mhz假如我想要让输入TIM2的时钟频率变为100Khz让PWM的周期变成20ms那么此时TIMx_PSC和TIMx_ARR计算方式如下 TIMx_PSC  100Mhz/100Khz - 1 999 由于TIM2的时钟频率为100Khz所以一个节拍对应的为1/1000000.00001s0.01ms 20ms/0.01ms2000所以TIMx_ARR2000-11999 关于TIMx_PSC和TIMx_ARR的计算 几种不同方式实现设定PWM的周期 在上面的例子中要达到 PWM 周期为 20ms 这个目标TIMx_PSC (分频系数) 和 TIMx_ARR (自动重载寄存器) 的设置并非只有一种固定组合。它们是相互关联的我们可以通过调整其中一个来相应地调整另一个以达到相同的周期。 定时器时钟频率这是输入到特定定时器例如 TIM2的时钟频率通常是主时钟频率经过 APB 分频器后得到的。在我们的例子中假设主时钟是 100MHz。   TIMx_PSC (Prescaler Value)分频系数。它决定了定时器计数器实际的计数频率。计数器每经过 (TIMx_PSC 1) 个定时器时钟周期才递增/递减一次。   TIMx_ARR (Auto-Reload Register)自动重载值。它决定了定时器计数器的上限。计数器从 0 数到 TIMx_ARR或从 TIMx_ARR 数到 0表示一个完整的计数周期共 (TIMx_ARR 1) 个节拍。 方法一我们之前的方法 (分频后的时钟频率为 100 KHz) 选择分频系数 TIMx_PSC 999 此时 (PSC 1) 1000 分频后的定时器计数频率 100 MHz/1000100 KHz 计算 TIMx_ARR  (TIMx_ARR 1) \times 1000 2,000,000  (TIMx_ARR 1) 2,000,000 / 1000 2000 TIMx_ARR1999 这种组合是PSC 999, ARR 1999。  方法二让分频后的时钟频率为 1 MHz 选择分频系数 TIMx_PSC 99 此时 (PSC 1) 100 分频后的定时器计数频率 100 MHz/1001 MHz 计算 TIMx_ARR (TIMx_ARR 1) \times 100 2,000,000 (TIMx_ARR 1) 2,000,000 / 100 20000 TIMx_ARR19999 这种组合是PSC 99, ARR 19999。  方法三让分频后的时钟频率为 50 KHz 选择分频系数 TIMx_PSC 1999 此时 (PSC 1) 2000 分频后的定时器计数频率 100 MHz/200050 KHz 计算 TIMx_ARR (TIMx_ARR 1) \times 2000 2,000,000  (TIMx_ARR 1) 2,000,000 / 2000 1000 TIMx_ARR999 这种组合是PSC 1999, ARR 999。 如何选择不同PSC与ARR的组合 虽然有多种组合可以达到相同的 PWM 周期但在实际应用中选择哪种组合通常取决于以下因素 占空比精度 (Duty Cycle Resolution) ARR 值越大表示在一个 PWM 周期内有更多的计数节拍。 这意味着您可以更精细地调整占空比。例如如果 ARR 19999您可以将占空比设置为 (0/20000) 到 (19999/20000) 之间的任何值有 20000 个可能的占空比级别。 如果 ARR 999您只有 1000 个占空比级别。 因此通常会选择较大的 ARR 值以获得更高的占空比精度前提是 ARR 不超过寄存器的最大值如 16位定时器 ARR 最大为 6553532位定时器更大。 PSC 和 ARR 的寄存器大小限制 大多数通用定时器的 PSC 和 ARR 寄存器是 16 位的这意味着它们的值不能超过 65535。 有些高级定时器或较新的微控制器可能有 32 位的定时器。在选择 PSC 和 ARR 时需要确保它们不超过对应寄存器的最大值。 在我们的例子中2,000,000 这个乘积超出了 16 位定时器的单个寄存器范围所以必须进行分频即 PSC 和 ARR 都不能为 0除非定时器频率非常低。 计算方便性/可读性 有时会选择整数倍的分频使得计数频率成为一个“整”的 KHz 或 MHz 值方便理解和计算。 综上所述我们通常会选择较大的 ARR 值以获得更高的占空比精度但是同时也要注意PSC 和 ARR 设置的值不能超过寄存器大小限制 代码编写 由于CubeMX依旧已经帮我们做了很多工作所以这里我们需要修改的很少。 呼吸灯的效果是通过 PWM (脉冲宽度调制) 来实现的。我们通过周期性地改变 PWM 波形的占空比即高电平持续时间与整个周期的比值来控制 LED 的亮度。 当占空比从 0% 逐渐增加到 100% 时LED 会从灭逐渐变亮当占空比从 100% 逐渐减小到 0% 时LED 会从亮逐渐变灭。 这个过程循环往复就形成了“呼吸”的效果。 下面是启动 PWM 输出的关键函数。它告诉定时器 TIM2 的通道3 开始生成 PWM 波形。请务必在进入 while(1) 循环之前调用它。 HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_3); 这个函数会启动定时器如果它尚未运行并使其 PWM 输出开始在指定的通道引脚上生成波形。 关于调节占空比其实就是在调节比较捕获寄存器的值 计算方式占空比 CCRx / (ARR 1)。例如如果 ARR 999CCRx 500那么占空比就是 500 / 1000 50%。 设置比较捕获寄存器TIMx_CCRx的值 __HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_3, duty); 这是一个 HAL 库的宏本质上是直接操作寄存器用于设置指定定时器通道的比较值CCR 寄存器。 duty_cycle 的值直接决定了 PWM 的占空比。当 duty_cycle 接近 0 时LED 灭接近 PWM_MAX_DUTY 时LED 最亮。 /* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(htim2, TIM_CHANNEL_3); /* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */uint32_t duty;while (1){/* USER CODE END WHILE */for(duty0; duty2000; duty 20){__HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_3, duty);HAL_Delay(20);}for(duty2000; duty0; duty-20){__HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_3, duty);HAL_Delay(20);}/* USER CODE BEGIN 3 */} 推荐好文 STM32定时器详解原理、配置与应用实战-CSDN博客 STM32 定时器TIM-CSDN博客
http://www.zqtcl.cn/news/357721/

相关文章:

  • 烟台网站建设服务专业的企业智能建站制造厂家
  • 网站信息查询制作闹钟网站
  • 永久免费个人网站申请注册禁止 wordpress ajax
  • 建设网站江西一个简单的游戏网站建设
  • 织梦大气婚纱影楼网站源码优化大师电脑版
  • 衡水企业网站制作报价怎么通过局域网建设网站
  • 服装网站建设课程知道ip怎么查域名
  • 上海政务网站建设上行10m企业光纤做网站
  • 杭州做公司网站aso搜索优化
  • 南京越城建设集团网站网站空间续费多少钱
  • 深圳nft网站开发公司如何制作微信公众号里的小程序
  • 做网站美工要学什么聊城网站建设电话
  • 南通个人网站建设快手秒刷自助网站
  • html5 做网站网站开发找工作
  • 聚成网站建设艺术公司网站定制中心
  • 阿里云上可以做网站吗十六局集团门户网
  • 门户网站建设询价函有哪些网站可以做设计挣钱
  • 如何建立自己网站奔奔网站建设
  • 自由做图网站做网站所用的工具
  • 广西南宁做网站专业网站建设案例
  • 视屏网站的审核是怎么做的群辉 搭建wordpress
  • 嘉兴网站快速排名优化衡阳网站建设制作
  • 建设公共资源交易中心网站成都APP,微网站开发
  • dede网站地图修改厦门百度seo
  • 可以做行程的网站网站详情怎么做的
  • 网站建设心得8000字营销型网站建设的注意事项
  • 织梦购物网站整站源码哈尔滨网站建设技术托管
  • 做推广的网站微信号企业免费网站制作
  • 做旅游网站的引言上海公司网站建设哪家好
  • 找项目去哪个网站网站建设一条龙全包