STM32__定时器与_PWM_快速使用入门

合集下载

STM32 TIM的PMW模式

STM32 TIM的PMW模式

STM32 TIM的PMW模式STM32开发板学习日记-[5]TIM的PMW模式脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。

在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1)或’111’(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。

必须设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄存器,最后还要设置TIMx_CR1寄存器的ARPE位使能自动重装载的预装载寄存器(在向上计数或中心对称模式中)。

因为仅当发生一个更新事件的时候,预装载寄存器才能被传送到影子寄存器,因此在计数器开始计数之前,必须通过设置TIMx_EGR寄存器中的UG位来初始化所有的寄存器。

OCx的极性可以通过软件在TIMx_CCER寄存器中的CCxP 位设置,它可以设置为高电平有效活或低电平有效。

TIMx_CCER寄存器中的CCxE位控制OCx输出使能。

在PWM模式(模式1或模式2)下,TIMx_CNT和TIM1_CCRx 始终在进行比较,(依据计数器的计数方向)以确定是否符合TIM1_CCRx≤TIM1_CNT或者TIM1_CNT≤TIM1_CCRx。

然而为了与OCREF_CLR的功能(在下一个PWM周期之前,ETR信号上的一个外部事件能够清除OCxREF)一致,OCxREF信号只能在下述条件下产生:●当比较的结果改变●当输出比较模式(TIMx_CCMRx寄存器中的OCxM位)从“冻结”(无比较,OCxM=’000’)切换到某个PWM模式(OCxM=’110’或’111’)。

STM32入门简易教程

STM32入门简易教程

器配置等详细信息。 3、 STM32F103RB 数据手册
a) 产品的基本配置(内置 FLASH 和 RAM 的容量、外设模块的种类和数量等); b) 管脚的数量和分配,电气特性,封装信息和订购代码等。 4、 STM32 开发板手册 与开发板配套的参考资料,有很多经验值得借鉴。 5、 stm32 固件库 a) 相关定义,文档约定和固件库规则; b) 库的架构,安装指南及使用实例; c) 每个外围模块的函数及解释。 6、 开发板原理图 必不可少的硬件电路参考。 7、 互联网 取之不尽的知识宝库。
意法半导体是市场上第一家提供基于 Cortex-M3 内核的无传感器的磁场定向电机控制
解决方案的厂商。这套工具证明 STM32 的内核和专用电机控制外设都有充足的处理能力来 优化驱动器的性能,最小化系统总体成本。STM 微控制器在 25 微秒内即可执行一整套无传 感器三相无刷永磁同步电机(PMSM)矢量控制算法,大多数应用任务占用 CPU 资源比率 小于 30%,为 CPU 执行其它应用任务(如需要)预留了充足的处理能力。永磁电机同步电 机控制解决方案的代码大小少于 16 千字节。
二、重要的参考资料
1、 Cortex-M3 权威指南 宋岩 译 权威资料的精简版,思路清晰,有条理,适合学 Cortex-M3 处理器的所有人。
2、 STM32 技术参考手册 a) STM32 微控制器产品的技术参考手册是讲述如何使用该产品的; b) 包含各个功能模块的内部结构、所有可能的功能描述、各种工作模式的使用和寄存
在性能方面,STM32 系列的处理速度比同级别的基于 ARM7TDMI 的产品快 30%,换 句话说,如果处理性能相同,STM32 产品功耗比同级别产品低 75%。同样地,使用新内核 的 Thumb 2 指令集,设计人员可以把代码容量降低 45%,几乎把应用软件所需内存容量降 低了一半。此外,根据 Dhrystones 和其它性能测试结果,STM32 的性能比最好的 16 位架构 至少高出一倍。

STM32L4定时器(TIMER)介绍

STM32L4定时器(TIMER)介绍
• No free-running timer management issues
10
• All channels connected to an I/O can be configured either as an input (capture) or an output (compare or PWM) • Beside basic operation, most timers are including extra features:
CH1
Capture Compare
CH1 CH1N
BK
TIM16/17
Basic timer
ClockΒιβλιοθήκη 16Trigger/Clock
• No Capture Compare channels • Counting period defined with autoreload register only • Trigger output serves for trigger and time base generation purpose
9
• Several derivatives existing with decreasing number of features
• Advanced-control • General-purpose (4, 2 or 1 channel) • Basic
• The Low-Power LPTIMER architecture changed because of the following characteristics:
17
Center Aligned
Up counting
Down counting

at32单片机定时器加dma动态输出pwm波流程

at32单片机定时器加dma动态输出pwm波流程

at32单片机定时器加dma动态输出pwm波流

在使用at32单片机进行定时器加DMA动态输出PWM波时,我们需要按照以下流程进行操作:
1. 初始化定时器:选择合适的定时器模块,并设置相关的参数,如定时器的工作模式、计数范围和时钟源等。

通过设置定时器的相关寄存器来实现。

2. 初始化DMA:选择合适的DMA通道,并设置相关的参数,如数据传输方向、传输单位和传输长度等。

通过设置DMA的相关寄存器来实现。

3. 设置PWM参数:根据需求设置PWM波的相关参数,如频率、占空比和极性等。

可以通过修改PWM控制器的相关寄存器来实现。

4. 编写DMA传输缓冲区:根据需要生成PWM波形的数据,存储在DMA传输缓冲区中。

可以使用数组或者指针来定义和操作缓冲区。

5. 启动DMA传输:将DMA传输缓冲区的地址和大小配置给DMA通道,并启动DMA传输。

DMA传输将会按照设定的参数从缓冲区中读取数据,并将数据传输到PWM输出端口。

6. 启动定时器:启动定时器开始计数,根据设定的定时器参数,定时器将会产生中断触发DMA传输。

7. 中断处理:处理定时器中断,重新加载DMA传输缓冲区的地址和大小,以实现持续的数据传输,从而动态生成PWM波形。

以上就是使用at32单片机定时器加DMA动态输出PWM波的流程。

通过合理配置定时器和DMA参数,以及编写适当的数据传输缓冲区,可以实现精确的PWM波形输出,并且可以根据需要动态调整PWM波的频率和占空比。

STM32使用HAL库输出连续可调的PWM信号

STM32使用HAL库输出连续可调的PWM信号

STM32使用HAL库输出连续可调的PWM信号1.配置GPIO引脚作为PWM输出。

选择一个合适的GPIO引脚,并将其配置为复用模式,用于PWM输出。

例如,若使用TIM1作为PWM输出定时器,则可以选择GPIO引脚PA8,其复用功能为TIM1_CH12.配置定时器。

使用HAL库初始化和配置所选定的定时器(例如TIM1)作为PWM输出的时基。

设置定时器的时钟源、预分频因子和计数周期。

可以通过修改这些参数来调整PWM信号的频率。

3.配置PWM输出通道。

使用HAL库初始化和配置所选定的PWM输出通道(例如TIM1_CH1)。

设置通道的输出模式和占空比。

可以通过修改占空比来调整PWM信号的高电平时间,从而改变输出电压。

4.启动定时器。

通过调用HAL库中的相关函数,启动所选定的定时器开始计数。

定时器计数到达设定的计数周期后,将会产生一个PWM信号。

5.调整PWM信号的占空比。

通过修改PWM输出通道的占空比,可以改变PWM信号的高电平时间。

通过调整占空比的大小,可以控制PWM信号的输出电压。

6.实时调整PWM信号的频率和占空比。

通过修改定时器的预分频因子和计数周期,可以调整PWM信号的频率。

通过修改PWM输出通道的占空比,可以调整PWM信号的占空比。

可以根据特定的应用需求,实时调整这些参数,来实现连续可调的PWM信号输出。

下面是一个示例代码,演示如何利用HAL库配置和控制STM32的PWM输出:```c#include "stm32f4xx_hal.h"TIM_HandleTypeDef htim1;void SystemClock_Config(void);static void MX_GPIO_Init(void);static void MX_TIM1_Init(void);int main(void)HAL_Init(;SystemClock_Config(;MX_GPIO_Init(;MX_TIM1_Init(;HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);while (1)uint16_t dutyCycle = 500; // 设置占空比为50%__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle); HAL_Delay(1000); // 延时1sdutyCycle = 1000; // 设置占空比为100%__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle); HAL_Delay(1000); // 延时1s}void SystemClock_Config(void)RCC_OscInitTypeDef RCC_OscInitStruct;RCC_ClkInitTypeDef RCC_ClkInitStruct;__HAL_RCC_PWR_CLK_ENABLE(;__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1 );RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 336;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 7;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)Error_Handler(;}RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK ,RCC_CLOCKTYPE_PCLK1RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct,FLASH_LATENCY_5) != HAL_OK)Error_Handler(;}void MX_GPIO_Init(void)GPIO_InitTypeDef GPIO_InitStruct;__HAL_RCC_GPIOA_CLK_ENABLE(;GPIO_InitStruct.Pin = GPIO_PIN_8;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);void MX_TIM1_Init(void)TIM_MasterConfigTypeDef sMasterConfig;TIM_OC_InitTypeDef sConfigOC;htim1.Instance = TIM1;htim1.Init.Prescaler = 0;htim1.Init.CounterMode = TIM_COUNTERMODE_UP;htim1.Init.Period = 1000; // 设置计数周期为1000htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)Error_Handler(;}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim1,&sMasterConfig) != HAL_OK)Error_Handler(;}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = 0; // 初始化占空比为0sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC,TIM_CHANNEL_1) != HAL_OK)Error_Handler(;}```这是一个基本的示例,演示了如何使用HAL库配置和控制STM32的PWM输出。

基于STM32CubeMX配置PWM输出和输入捕获

基于STM32CubeMX配置PWM输出和输入捕获

基于STM32CubeMX配置PWM输出和输⼊捕获PWM输出和输⼊捕获1、试验⽬标 1.输出2路PWM脉冲信号 2.捕获1路PWM脉冲信号 本次试验会使⽤到2个定时器,⼀个⾼级定时器⽤于脉冲捕获,⼀个普通定时器⽤于PWM脉冲输出。

2、准备材料 1. STM32F103C8 2. STM32CubeMX2、STM32CubeMX配置 2.1时钟树 系统时钟为72M,APB1 和APB2 的定时器时钟都为72MHZ。

2.2 PWM输出配置 PWM的输出配置⽐较简单,这⾥我们使⽤到了TIM2普通定时器控制输出,具体参数如下图。

在 Parameter Settings 页配置预分频系数为 72-1,计数周期(⾃动加载值)为 10000-1,定时器溢出频率,即PWM的周期,就是72MHz/(71+1)/(9999+1) = 100Hz 2.3 PWM输⼊捕获配置 PWM捕获,本次试验使⽤到了STM32F103C8的⾼级定时器TIM1。

配置如下图。

中断配置勾线这⾥,因为我们需要使⽤中断回调函数来计算频率占空⽐。

2.4 配置中断分组和中断使能2.5串⼝输出2.6⽣成⼯程 这⾥选择分离C.h⽂件,IDE 根据⾃⼰的环境选择,这⾥我使⽤的GUN编译⽅式的IDE所以选择了SW4SEM32。

以上CubeMX的PWM配置就完成了。

配置完毕后,⽣成⼯程打开。

下⾯我们来分析代码和如何使⽤。

3、代码实现 3.1 tim.c 该代码主要配置了Tim1 和Tim2 的相关配置,为什么要这么配置,在接下来的第4⼤点会详细说明。

这⾥主要了解HAL_TIM_IC_CaptureCallback 捕获中断回调函数这⾥函数主要处理计算占空⽐和频率。

/********************************************************************************* @file tim.c* @brief This file provides code for the configuration* of the TIM instances.******************************************************************************* @attention** <h2><center>© Copyright (c) 2021 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:* /licenses/BSD-3-Clause********************************************************************************//* Includes ------------------------------------------------------------------*/#include "tim.h"/* USER CODE BEGIN 0 *//// 计算占空⽐时使⽤__IO uint16_t IC2Value = 0;__IO uint16_t IC1Value = 0;__IO float DutyCycle = 0;__IO float Frequency = 0;/* USER CODE END 0 */TIM_HandleTypeDef htim1; // ⾼级定时器捕获PWMTIM_HandleTypeDef htim2; // 普通定时器输出PWM/* TIM1 init function */void MX_TIM1_Init(void){TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_SlaveConfigTypeDef sSlaveConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_IC_InitTypeDef sConfigIC = {0};htim1.Instance = TIM1;htim1.Init.Prescaler = 72-1;htim1.Init.CounterMode = TIM_COUNTERMODE_UP; /* 计数⽅式上计数 */htim1.Init.Period = 65535; /* 计数器更新上限值 */htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 采样时钟分频 */htim1.Init.RepetitionCounter = 0; /* 重装值=0 */htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /* ⾃动装载值软件使能 */ if (HAL_TIM_Base_Init(&htim1) != HAL_OK) /* 初始定时器 */{Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; /* 内部时钟源 */if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_IC_Init(&htim1) != HAL_OK){Error_Handler();}///选择从模式: 复位模式sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; /* 选择定时器输⼊触发: TI1FP1 */ sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;sSlaveConfig.TriggerFilter = 0;if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK){Error_Handler();}///IC1捕获上升沿触发 TI1FP1sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;sConfigIC.ICFilter = 0;if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK){Error_Handler();}///IC2捕获下降沿捕获 TI1FP2sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_2) != HAL_OK){Error_Handler();}}/* TIM2 init function */void MX_TIM2_Init(void){TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};TIM_OC_InitTypeDef sConfigOC = {0};htim2.Instance = TIM2;/** htim2.Init.Prescaler 分频计算* 定时器时钟源TIMxCLK = 2 * PCLK1* PCLK1 = HCLK / 2* => TIMxCLK = HCLK/2 = SystemCoreClock / 2 *2=72MHz (APB1)* 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10KHz* */htim2.Init.Prescaler = 72-1;htim2.Init.CounterMode = TIM_COUNTERMODE_UP; /* 计数⽅式上升沿有效 */htim2.Init.Period = 10000-1; /* 累计 TIM_Period个后产⽣⼀个更新或者中断当定时器从0计数到10000,即为10000次,为⼀个定时周期*/ htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(&htim2) != HAL_OK){Error_Handler();}sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; /* 内部时钟源 */if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK){Error_Handler();}if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK){Error_Handler();}///PWM模式配置sConfigOC.OCMode = TIM_OCMODE_PWM1; /* 配置为PWM模式1*/sConfigOC.Pulse = 5000; /* 默认占空⽐为50%*/sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; /* 当定时器计数值⼩于CCR1_Val时为⾼电平*/sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) /* 配置PWM通道*/{Error_Handler();}if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK){Error_Handler();}HAL_TIM_MspPostInit(&htim2); /* 外置GPIO初始化 */}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle){GPIO_InitTypeDef GPIO_InitStruct = {0};if(tim_baseHandle->Instance==TIM1){/* USER CODE BEGIN TIM1_MspInit 0 *//* USER CODE END TIM1_MspInit 0 *//* TIM1 clock enable */__HAL_RCC_TIM1_CLK_ENABLE(); /*定时器时钟使能*/__HAL_RCC_GPIOA_CLK_ENABLE(); /*GPIO时钟使能*//**TIM1 GPIO ConfigurationPA8 ------> TIM1_CH1*/GPIO_InitStruct.Pin = GPIO_PIN_8; /* 36脚的F103 不能改变引脚编号*/GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /* 输⼊模式*/GPIO_InitStruct.Pull = GPIO_NOPULL; /* ⽆上下拉*/HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* TIM1 interrupt Init */HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0); /* 配置中断分组*/HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); /* 使能中断*//* USER CODE BEGIN TIM1_MspInit 1 *//* USER CODE END TIM1_MspInit 1 */}else if(tim_baseHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspInit 0 *//* USER CODE END TIM2_MspInit 0 *//* TIM2 clock enable */__HAL_RCC_TIM2_CLK_ENABLE();/* USER CODE BEGIN TIM2_MspInit 1 *//* USER CODE END TIM2_MspInit 1 */}}void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle){GPIO_InitTypeDef GPIO_InitStruct = {0};if(timHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspPostInit 0 *//* USER CODE END TIM2_MspPostInit 0 */__HAL_RCC_GPIOA_CLK_ENABLE();/**TIM2 GPIO ConfigurationPA0-WKUP ------> TIM2_CH1PA1 ------> TIM2_CH2*/GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; /* 这⾥定义了2路PMW输出⽤PA0 和PA1*/ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/* USER CODE BEGIN TIM2_MspPostInit 1 *//* USER CODE END TIM2_MspPostInit 1 */}}void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle){if(tim_baseHandle->Instance==TIM1){/* USER CODE BEGIN TIM1_MspDeInit 0 *//* USER CODE END TIM1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM1_CLK_DISABLE();/**TIM1 GPIO ConfigurationPA8 ------> TIM1_CH1*/HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8);/* TIM1 interrupt Deinit */HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);/* USER CODE BEGIN TIM1_MspDeInit 1 *//* USER CODE END TIM1_MspDeInit 1 */}else if(tim_baseHandle->Instance==TIM2){/* USER CODE BEGIN TIM2_MspDeInit 0 *//* USER CODE END TIM2_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM2_CLK_DISABLE();/* USER CODE BEGIN TIM2_MspDeInit 1 *//* USER CODE END TIM2_MspDeInit 1 */}}/* USER CODE BEGIN 1 *//*** @brief Conversion complete callback in non blocking mode 捕获回调函数* @param htim : hadc handle* @retval None*/void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){/* 获取输⼊捕获值 */IC1Value = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);IC2Value = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_2);if (IC1Value != 0){/* 占空⽐计算 */DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);/* 频率计算 */Frequency = 72000000/72/(float)(IC1Value+1);}else{DutyCycle = 0;Frequency = 0;}}}/* USER CODE END 1 *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/3.2 main.c ⽤于计算的变量//计算占空⽐时的全局表变量extern __IO uint16_t IC2Value;extern __IO uint16_t IC1Value;extern __IO float DutyCycle;extern __IO float Frequency; 使能和输出PWM/// 使能捕获/⽐较2中断请求HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);/// 开始输出PWMHAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); 打印调试输出while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */printSwo("IC1Value =",IC1Value,LINE_FEED_EN);printSwo("IC2Value =",IC2Value,LINE_FEED_EN);printSwo("占空⽐:",DutyCycle,LINE_FEED_EN);printSwo("频率:",Frequency,LINE_FEED_EN);HAL_Delay(500);}3.3 输出结果短接任意⼀路输出 PA0与PA8 PWM输出与捕获,或 PA1与PA8 PWM输出与捕获。

定时器学习笔记(嵌入式)

定时器学习笔记一、STM32F103定时器STM32F103的定时器为工业控制应用度量身定做,具有延时、信号的频率测量、信号的PWM测量、PWM输出、三相六步电机控及编码接口等功能,STM32F103微控制器内部集成了多个可编程定时器,可分为基本定时器、通用定时和高级定时器3种类型,从功能上看,基本定时器的功能是通用定时器的子集,而通用定时器的功能又是高级定时器的一个子集。

二、STM32F103定时器类型1.基本定时器TIM6和TIM72.通用定时器TM2-TIM53.高级定时器TIM1和TIM8三、PWM的实现(1)传统的数字电路方式。

用传统的数字电路实现PWM,电路设计较复杂,体积大,抗于扰能力差,系统的控制周期较长。

(2)微控制器普通1/0模拟方式。

对于微控制器中无PWM输出功能的情况,可以通过CPU操控普通1/O口来实现PWM输出。

但这样实现PWM将消耗大量的时间大大降低了CPU的效率,而且得到的PWM信号精度不太高。

(3)微控制器的PWM直接输出方式。

对于具有PWM输出功能的微控制器,在进行简单的配置后即可在微控制器的指定引脚上输出PWM脉冲。

四、PWM输出模式的工作过程(1)若配置脉冲计数器TIMx_CNT为向上计数模式,自动重装载寄存器TIMx_ARR的预设值为N,则脉冲计数器TIMx_CNT的当前计数值X在时钟CK_CNT的驱动下从0开始不断累加计数(2)在脉冲计数器TIMx_CNT随着时钟CK_CNT触发进行累加计数的同时,脉冲计数器LMx_CNT的当前计数值X与捕获/比较寄存器TIMx_CCR的预设值A进行比较:如果X<A.输出高电平(或低电平);如果X=A,输出低电平(或高电平)。

(3)当脉冲计数器TIMx_CNT的计数值X大于自动重装载寄存器TIMx_ARR的预设值N时,脉冲计数器TIMx_CNT的计数值清零并重新开始计数。

如此循环往复得到的PWM输出信号的周期为(N+1)×XTCK_CNT,其中,N为自动重装载寄存TIMx_ARR的预设值,TCK_CNT为时钟CK_CNT的周期。

STM3日记2之高级定时器TIM1和TIM8

STM32 高级定时器-PWM简单使用高级定时器与通用定时器比较类似,下面是一个TIM1 的PWM 程序,TIM1是STM32唯一的高级定时器。

共有4个通道有死区有互补。

先是配置IO脚:GPIO_InitTypeDef GPIO_InitStructure;/* PA8设置为功能脚(PWM) */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);/*PB13 设置为PWM的反极性输出*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);/*开时钟PWM的与GPIO的*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);/*配置TIM1*/TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;void Tim1_Configuration(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;TIM_DeInit(TIM1); //重设为缺省值/*TIM1时钟配置*/TIM_TimeBaseStructure.TIM_Prescaler = 4000; //预分频(时钟分频)72M/4000=18KTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数TIM_TimeBaseStructure.TIM_Period = 144; //装载值18k/144=125hz 就是说向上加的144便满了TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置了时钟分割不懂得不管TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0; //周期计数器值不懂得不管TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); //初始化TIMx的时间基数单位/* Channel 1 Configuration in PWM mode 通道一的PWM */TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM模式2TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //正向通道有效PA8TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //反向通道也有效PB13 TIM_OCInitStructure.TIM_Pulse = 40; //占空时间144 中有40的时间为高,互补的输出正好相反TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //互补端的极性TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; //空闲状态下的非工作状态不管TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //先不管TIM_OC1Init(TIM1,&TIM_OCInitStructure); //数初始化外设TIMx通道1这里2.0库为TIM_OCInit/* TIM1 counter enable开定时器*/TIM_Cmd(TIM1,ENABLE);/* TIM1 Main Output Enable 使能TIM1外设的主输出*/TIM_CtrlPWMOutputs(TIM1,ENABLE);}//设置捕获寄存器1void SetT1Pwm1(u16 pulse){TIM1->CCR1=pulse;}/*操作寄存器改变占空时间*//*************************************************************************** **************************************TIM1的定时器通道时间1到4 分别为PB8 PA9 PA10 PA11 而互补输出分别为PB13 PB14 PB15中止PB12 。

如何采用STM32中的控制定时器Tim1实现计数器功能


16 位上下,自动装载计数器。 16 位可编程预分频器,计数器时钟频率的分频率的分频系数为 个独立通道: 输入捕获 输出比较
1-65535 之间任意数值, 4
PWM 生成 单脉冲模式输出 死区时间可编程的互补输出 使用外部信号控制定时器和定时器互连的同步电路 在指定数目的计数器周期之后更新定时器寄存器 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态 如下事件发生时产生中断: 更新:计数器向上溢出或者向下溢出,计数器初始化。 触发事件(计数器启动,停止,初始化) 输入捕获 输出比较 刹车信号输入
GPIO_SetBits(GPIOB, GPIO_Pin_12); delay_nms(100); // 闪灯 GPIO_ResetBits(GPIOC, GPIO_Pin_8); TIM_ClearITPendingBi(t TIM1, TIM_FLAG_Update) ; // 清中断 } 将所有的准备工作的做好了,我们开始写 main 函数() 如下: RCC_Configuration() ; ledGPIO_init() ; //key_init () ; tim1_on () ; TIM_Configuration() ; NVIC_Configuration() ; while (1) { } 这样就完成了定时器 1 的计数器功能。
下面介绍一下采用 TIm1 实现计数器的功能: 步骤一:进行定时器时钟启CC_APB2PeriphClockCm(d RCC_APB2Periph_TIM,1 ENABLE); } 步骤二:实现对定时器的配置(对其内部寄存器进行配置初始化) 断 NVIC 设置:允许中断,设置优先级
如何采用 STM32 中的控制定时器 Tim1 实现计数器功能
STM32中的高级控制定时器( Tim1)是由一个 16 位的自动装载计数器组成, 它由一个可编程预分频器驱动。 用途在于:测量输入信号的脉冲宽度(输入捕获) ,或者产生输出波形(输出比较, PWM, 嵌入死区时间的互补 PWM 等)。 使用定时器预分频器和 RCC时钟控制预分频器, 可以实现脉冲宽度和波形周期从几个微秒 到几个毫秒的调节。 具体如下:

stm32单片机设计定时器中断实现1s的led灯闪烁知识应用

stm32单片机设计定时器中断实现1s的led灯闪烁知识应用要实现1s的LED灯闪烁,可以使用STM32单片机的定时器中断来控制LED的开关。

以下是实现的步骤:1. 配置定时器:选择一个定时器(如TIM2)并设置适当的预分频和计数值,以实现1s的定时周期。

2. 配置中断:使能定时器中断,并将中断优先级设置为适当的值(较高优先级)。

3. 初始化LED引脚:将LED引脚设置为输出,并初始化为高电平(LED关闭)。

4. 编写中断处理程序:在中断处理程序(如TIM2_IRQHandler)中,切换LED引脚的状态。

例如,如果LED引脚当前为高电平,则将其设置为低电平,反之亦然。

5. 启动定时器:启动定时器以开始定时。

整个步骤如下所示的代码示例:```c#include "stm32fxx.h"void TIM2_IRQHandler(void){if(TIM2->SR & TIM_SR_UIF){TIM2->SR &= ~TIM_SR_UIF; // 清除中断标志位// 切换LED引脚状态if(GPIOC->ODR & GPIO_ODR_ODR0)GPIOC->ODR &= ~GPIO_ODR_ODR0; // 关闭LEDelseGPIOC->ODR |= GPIO_ODR_ODR0; // 打开LED}}int main(){// 初始化LED引脚RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // 使能GPIOC时钟GPIOC->MODER |= GPIO_MODER_MODER0_0; // 将PC0设置为输出模式GPIOC->OSPEEDR |= GPIO_OSPEEDR_OSPEED0; // 设置PC0输出速度// 配置定时器RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // 使能TIM2时钟TIM2->PSC = 8399; // 将预分频设置为8400-1,得到10kHz 的计数频率TIM2->ARR = 9999; // 将计数值设置为10000-1,得到1s的定时周期// 配置中断TIM2->DIER |= TIM_DIER_UIE; // 使能更新中断NVIC_EnableIRQ(TIM2_IRQn); // 使能TIM2中断NVIC_SetPriority(TIM2_IRQn, 0); // 设置TIM2中断优先级为最高// 启动定时器TIM2->CR1 |= TIM_CR1_CEN; // 启动TIM2定时器while(1){// 程序主循环}return 0;}```以上代码使用了TIM2定时器和PC0引脚作为LED灯的控制。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

STM32 定时器与 PWM 快速使用入门
要求:在 万利的开发板 EK-STM32F 上产生 周期为1秒,占空比分别为 50% 10%的 PWM
并且点亮 板上的 LD1,LD2 灯闪烁。

做法很简单。

STM32的PWM是由 定时器来产生的。

可以看出 。定时器3的通道1至4在GPIO端口的映像。如果是完全映射。
各通道的连接引脚如下:
CH1=PC6, CH2=PC7, CH3=PC8, CH4=PC9

这样,刚好与板上的LD1,LD2灯符合,因为LD1连接到PC7,LD2连接到PC6引脚。

关于PWM一些知识.

STM32的TIMx 是 TIMx_ARR 寄存器确定频率(周期)、由TIMx_CCRx 寄存器确定占空比的
信号


使用定时器3。而TIM2、3、4的时钟源是 APB1 即是 PCLK1 ( APB1 对应 PCLK1 )
PCLK1 = APB1 = HCLK/2 = SYSCLK/2 = 36MHZ (36,000,000 HZ)
但是注意: 倍频器会自动倍2, 即是 【72MHZ】!

代码如下:

void
STM32_PWM_GPIO_Configuration(void)
{
// 11:完全映像
STM32_Afio_Regs->mapr.bit.TIM3_REMAP=3;

// LD1 =P7 LD2=PC6
/*GPIOA Configuration: ( PC6 PC7 ) TIM3 channel 1 and 2 as alternate function push
-pull */
STM32_Gpioc_Regs->crl.bit.CNF6=Output_Af_push_pull; // PC.06 复用功能推挽
输出

模式
STM32_Gpioc_Regs->crl.bit.MODE6=Output_Mode_50mhz; // PC.06 输出模式,最大速
度50MHz

STM32_Gpioc_Regs->crl.bit.CNF7=Output_Af_push_pull; // PC.07 复用功能推挽输出模

STM32_Gpioc_Regs->crl.bit.MODE7=Output_Mode_50mhz; // PC.07 输出模式,最大速
度50MHz

}//end sub

void
STM32_TIM3_Configuration(void)
{
// TIM_DeInit( TIM3);//复位TIM3定时器
STM32_Rcc_Regs->apb1rstr.all |= RCC_TIM3RST;
STM32_Rcc_Regs->apb1rstr.all &= ~RCC_TIM3RST;
//时钟使能
STM32_Rcc_Regs->apb1enr.all |=RCC_TIM3EN;

/* TIM3 base configuration */
//TIM_TimeBaseStructure.TIM_Period = 9999;
//TIM_TimeBaseStructure.TIM_Prescaler = 7200;
//TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
//TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

STM32_Tim3_Regs->arr.all=9999; // 定时周期,PWM频率! 10毫秒*100=1秒
STM32_Tim3_Regs->psc.all=720; // 7200分
频 72MHZ/72,00 72,000,000/72,00=10,000
STM32_Tim3_Regs->cr1.bit.CKD=0; // 时钟分频因子
STM32_Tim3_Regs->cr1.bit.DIR=0; // 0:计数器向上计数

/* Clear TIM3 update pending flag[清除TIM3溢出中断标志] */
//TIM_ClearFlag(TIM3, TIM_FLAG_Update);
STM32_Tim3_Regs->sr.bit.UIF=0; //更新中断标记 由软件清0 ,例如当上溢或下溢时,软件
对CNT重新初始化

/* PWM1 Mode configuration: Channel1 Channel2 */
//TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
//TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//TIM_OC1Init(TIM3, &TIM_OCInitStructure);

// timer3 的 通道1 是 PC6 引脚, AFIO完全映射
STM32_Tim3_Regs->ccer.bit.CC1P=0; // 输入/捕获1输出极性 0:OC1高电平有效 1:
OC1低电平有效
STM32_Tim3_Regs->ccer.bit.CC1E=1; // 输入/捕获1输出使能 1: 开启- OC1信号输出到
对应的输出引脚。

STM32_Tim3_Regs->ccer.bit.CC2P=0; // 输入/捕获2输出极性 0:OC1高电平有效 1:OC1
低电平有效
STM32_Tim3_Regs->ccer.bit.CC2E=1; // 输入/捕获2输出使能 1: 开启- OC2信号输出到
对应的输出引脚。

STM32_Tim3_Regs->ccmr1.ou_bit.CC1S=0;//00:输出比较1 通道1 被配置为输出
STM32_Tim3_Regs->ccmr1.ou_bit.CC2S=0;//00:输出比较2 通道2 被配置为输出

STM32_Tim3_Regs->ccmr1.ou_bit.OC1M=6;//0110:PWM模式1
STM32_Tim3_Regs->ccmr1.ou_bit.OC2M=6;//0110:PWM模式1

STM32_Tim3_Regs->ccr1.all=5000;// 占空比 50%
STM32_Tim3_Regs->ccr2.all=1000;// 10%

// TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
STM32_Tim3_Regs->ccmr1.ou_bit.OC1PE=1; //OC1PE:输出比较1预装载使能1:开启
TIMx_CCR1寄存器的预装载功能
STM32_Tim3_Regs->ccmr1.ou_bit.OC2PE=1; //OC1PE:输出比较2预装载使能1:开启
TIMx_CCR2寄存器的预装载功能


//TIM_ARRPreloadConfig(TIM3, ENABLE);
STM32_Tim3_Regs->cr1.bit.ARPE=1; // 7 自动重装载预装载允许位 0:
TIM1_ARR寄存器没有缓冲

// TIM3 enable counter
//TIM_Cmd(TIM3, ENABLE);
STM32_Tim3_Regs->cr1.bit.CEN=1;// 开启计数器

STM32_Tim3_Regs->egr.bit.UG=1; //触发一次事件中断。
STM32_Tim3_Regs->sr.bit.UIF=0;

}//end sub

希望对各位初学者了解STM32的TIMx和PWM有帮助。

相关文档
最新文档