STM32 PWM输出实验
- 格式:ppt
- 大小:1003.00 KB
- 文档页数:13
今天对AFIO有了正确的认识。
在使用引脚的重映射功能和外部中断时需要使用AIFO时钟。
贴一段官方手册对AFIO的解释:为了优化64脚或100脚封装的外设数目,可以把一些复用功能重新映射到其他引脚上。
设置复用重映射和调试I/O配置寄存器(AFIO_MAPR)实现引脚的重新映射。
这时,复用功能不再映射到它们的原始分配上。
这次PWM实验要实验的功能就是呼吸灯。
配置步骤如下:1:使能GPIO和TIM1时钟;2:配置GPIO,MODE查中文参考手册确定为为AF_PP;3:配置定时器;4:配置TIM1_CH1输出比较函数;5:因为TIM1为高级定时器,普通定时器在完成以上设置了之后,就可以输出 PWM 了,但是高级定时器,我们还需要使能刹车和死区寄存器( TIM1_BDTR)的 MOE 位,以使能整个 OCx(即 PWM)输出。
库函数的设置函数为:TIM_CtrlPWMOutputs(TIM1,ENABLE);// MOE 主输出使能6:使能预装载;7:使能自动重装载;(区别仅在于是否是本次还是下一个周期进行改变,可写,可不写)8:使能定时器。
贴出timer.cvoid PWM_Init(u16 arr,u16 psc){GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period=arr;TIM_TimeBaseInitStructure.TIM_Prescaler=psc;TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_Pulse=0;(初值)TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;TIM_OC1Init(TIM1,&TIM_OCInitStructure);TIM_CtrlPWMOutputs(TIM1,ENABLE);TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);TIM_ARRPreloadConfig(TIM1,ENABLE);TIM_Cmd(TIM1,ENABLE);}然后在主函数中只需调用TIM_SetCompare1(TIM1,led0val);就可以完成占空比的变化。
#include "STM32Lib\\"#include ""/******************************************************************************** Function Name : GPIO_Configuration* 设置PD3,PD4,PD5,PD6为键盘输入* 设置PB0,5,8,9; PC5,7; PD7 ;PA8 为输出LED灯*******************************************************************************/void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;/*允许总线CLOCK,在使用GPIO之前必须允许相应端的时钟.从STM32的设计角度上说,没被允许的端将不接入时钟,也就不会耗能,这是STM32节能的一种技巧,*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);/* PC8按键输入*/= GPIO_Pin_8;= GPIO_Mode_IPU; //上拉输入GPIO_Init(GPIOC, &GPIO_InitStructure);/* PC9按键输入*/= GPIO_Pin_9;= GPIO_Mode_IPU; //上拉输入GPIO_Init(GPIOC, &GPIO_InitStructure);}#ifndef HAL_H#define HAL_H//硬件初始化extern void ChipHalInit(void);extern void ChipOutHalInit(void);//输入宏定义#define GET_LEFT() (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_8)) #define GET_RIGHT() (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9))extern void USART1_Putc(u8 c);extern void USART_Configuration(void);extern void USART1_Puts(char * str);#endif#include "STM32Lib\\"void Tim1_Configuration(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;GPIO_InitTypeDef GPIO_InitStructure;/* PA8设置为功能脚(PWM) */= GPIO_Pin_8;= GPIO_Mode_AF_PP;= GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);TIM_DeInit(TIM1);/*TIM1时钟配置*/= 72; //预分频(时钟分频)72M/72=1000K= TIM_CounterMode_Up; //向上计数= 2000; //装载值 1000k/2000=500hz= TIM_CKD_DIV1;= 0x0;TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);/* Channel 1 Configuration in PWM mode */= TIM_OCMode_PWM2; //PWM模式2= TIM_OutputState_Enable; //正向通道有效= TIM_OutputNState_Disable;//反向通道无效= 300; //占空时间= TIM_OCPolarity_Low; //输出极性= TIM_OCNPolarity_High; //互补端的极性= TIM_OCIdleState_Set;= TIM_OCIdleState_Reset;TIM_OC1Init(TIM1,&TIM_OCInitStructure); //通道1/* TIM1 counter enable */TIM_Cmd(TIM1,ENABLE);/* TIM1 Main Output Enable */TIM_CtrlPWMOutputs(TIM1,ENABLE);}//设置捕获寄存器1void SetT1Pwm1(u16 pulse){TIM1->CCR1=pulse;}/**************************************************************实验名称:PWM**功能:是PA8产生PWM输出,按键调节占空比*************************************************************/#include "STM32Lib\\"#include ""#define SIZE 0u8 table[11]={"09 "};char buffer[10]={"0000000000"};void Delay(u16 n);void d_2_char(u32 x){buffer[SIZE+0]=table[x%/100000];buffer[SIZE+1]=table[x%00/100000];buffer[SIZE+2]=table[x%0/100000];buffer[SIZE+3]=table[x%/10000];buffer[SIZE+4]=table[x%1000000/10000];buffer[SIZE+5]=table[x%100000/10000];buffer[SIZE+6]=table[x%10000/1000];buffer[SIZE+7]=table[x%1000/100];buffer[SIZE+8]=table[x%100/10];buffer[SIZE+9]=table[x%10];}//延迟函数void Delay(u16 speed){u16 i;while(speed!=0){speed--;for(i=0;i<400;i++);}}extern void SetT1Pwm1(u16 pulse);int main(void){u16 pulse=300; ChipHalInit(); //片内硬件初始化ChipOutHalInit(); //片外硬件初始化for(;;){if(GET_LEFT()==0){while(GET_LEFT()==0);if(pulse<=2000){pulse+=30;// SetT1Pwm1(pulse);}else{pulse=300;}d_2_char(pulse);USART1_Puts(buffer);USART1_Puts("\r\n");}if(GET_RIGHT()==0){while(GET_RIGHT()==0);if(pulse<=2000){pulse-=60;}else{pulse=1800;}d_2_char(pulse); USART1_Puts(buffer); USART1_Puts("\r\n");}SetT1Pwm1(pulse);}}。
基于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输出与捕获。
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 这⾥就不对STM32的PWM进⾏讲解了,想要了解的可以百度⼀下,这⾥主要说怎么实现。
1、建⽴⼯程,我选的是STM32F103zet6芯⽚,选择定时器的PWM功能 2、配置时钟,我这⾥配的是内部时钟,没有配外部时钟,⽽且不是最⼤时钟,有需要的可以⾃⼰改 3、配置定时器,这⾥的话默认就可以,因为代码⾥⾯需要对配置的初始化代码进⾏修改的,⽽修改后才可以实现该功能 4、⽣成代码后,修改代码,找到PWM初始化函数,修改为如下代码,注意要把初始化函数前⾯的static关键字也去掉,⽽且函数声明也要跟着修改void MX_TIM4_Init(uint16_t pre,uint16_t pul) //修改初始化函数,改变频率与PWM{//占空⽐=Pulse/Period;频率:f=48M/pre/perTIM_MasterConfigTypeDef sMasterConfig;TIM_OC_InitTypeDef sConfigOC;htim4.Instance = TIM4;htim4.Init.Prescaler =pre; //分频(关键)htim4.Init.Period = 100-1;//计数周期(关键,若100的计数周期对于⼀些频率跟占空⽐误差⼤的话,可以⾃⼰计算更改调试计数周期⼤⼩)htim4.Init.CounterMode = TIM_COUNTERMODE_UP;htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;if (HAL_TIM_PWM_Init(&htim4) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}sConfigOC.OCMode = TIM_OCMODE_PWM1;sConfigOC.Pulse = pul;//脉冲计数(关键)sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK){_Error_Handler(__FILE__, __LINE__);}HAL_TIM_MspPostInit(&htim4);} 5、接着在⾃⼰需要的代码⾥插⼊,PWM开始停⽌函数就可以啦HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); //PWM开启函数MX_TIM4_Init(uint16_t pre,uint16_t pul);//改变参数就可实现改变占空⽐跟频率的⽬的了HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_1);//停⽌PWM 这⾥我说⼀下核⼼部分:占空⽐ = (Pulse/Period)*100%;频率: f = 48M/Prescaler/Period;影响PWM占空⽐跟频率的参数这主要是 Pulse、Prescaler、Period这3个;频率跟占空⽐都与Period(计数周期)有关,只要我们把计数周期定下来,修改Prescaler、跟Pulse 这两个值,就可以直接修改PWM的频率跟占空⽐了。
Main,c#include "stm32f10x.h"#include "string.h"/***********************************************************************外设时钟使能************************************************************************/void RCC_Configuration(void){/* 使能外设时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);}/****************************************************************************** *全部用到的引脚将在在配置******************************************************************************* /void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;/* Configure Pb.8-11 as output push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOC, &GPIO_InitStructure);/* 配置串口1引脚*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);}/****************************************************************************** *全部中断在此配置******************************************************************************* /void NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure;/* Configure the NVIC Preemption Priority Bits */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);/* Enable the USART1 Interrupt */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //TIM3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级3级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //TIM3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级3级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器}void EXTI_Configuration(void){EXTI_InitTypeDef EXTI_InitStructure;GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource4);EXTI_ClearITPendingBit(EXTI_Line0);EXTI_ClearITPendingBit(EXTI_Line1);EXTI_ClearITPendingBit(EXTI_Line2);EXTI_ClearITPendingBit(EXTI_Line3);EXTI_ClearITPendingBit(EXTI_Line4);EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3 | EXTI_Line4;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);}///***************************************************************************** **//// 外部中断在此配置////***************************************************************************** **///void EXTI_Configuration(void)//{// EXTI_InitTypeDef EXTI_InitStructure;// GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource8); // S4中断// GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource9);// GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource10);// GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource11);// EXTI_ClearITPendingBit(EXTI_Line8);// EXTI_ClearITPendingBit(EXTI_Line9);// EXTI_ClearITPendingBit(EXTI_Line10);// EXTI_ClearITPendingBit(EXTI_Line11);// EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;// EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;// EXTI_InitStructure.EXTI_Line=EXTI_Line8|EXTI_Line9|EXTI_Line10|EXTI_Line11;// EXTI_InitStructure.EXTI_LineCmd = ENABLE;// EXTI_Init(&EXTI_InitStructure);//}///****************************************************************************** *初始化时钟晶振72MHZ******************************************************************************* /void SysClock_Init(void){ErrorStatus HSEStartUpStatus;RCC_DeInit();RCC_HSEConfig(RCC_HSE_ON);HSEStartUpStatus = RCC_WaitForHSEStartUp();if(HSEStartUpStatus == SUCCESS){FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);FLASH_SetLatency(FLASH_Latency_2);RCC_HCLKConfig(RCC_SYSCLK_Div1);RCC_PCLK2Config(RCC_HCLK_Div1);RCC_PCLK1Config(RCC_HCLK_Div2);RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);RCC_PLLCmd(ENABLE);while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){;}RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);while(RCC_GetSYSCLKSource() != 0x08){;}}}/*****************************************************************USART1 初始化baud 波特率*****************************************************************/void USART1_Init(unsigned int baud){USART_InitTypeDef USART_InitStructure;USART_ART_BaudRate = baud; //信息传输速率USART_ART_WordLength = USART_WordLength_8b; //在一个帧中传输或者接收到的数据位数USART_ART_StopBits = USART_StopBits_1;USART_ART_Parity = USART_Parity_No;USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);USART_Cmd(USART1, ENABLE);}/*****************************************************************从USART1 发送一个字节*****************************************************************/void USART1_SendByte(unsigned char temp){USART_SendData(USART1, temp);while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);}/***************************************************************** 从USART1 发送字符串*****************************************************************/ void USART1_Printf(char *pch){while(*pch != '\0'){USART1_SendByte(*(unsigned char *)pch);pch++;}}/******************************************** 延时程序ms*****************************************/void Delay(unsigned short time){unsigned short i, j;for(; time > 0; time--){for(j = 0; j < 10; j++){for(i = 0; i < 1000; i++);}}}/*******************************************************MAIN 函数*******************************************************/int main(void){SysClock_Init(); // 初始化系统时钟72MHZRCC_Configuration(); // 使能外设GPIO_Configuration(); // 配置引脚NVIC_Configuration(); // 配置中断USART1_Init(9600); // 配置串口1,波特率9600EXTI_Configuration();USART1_Printf("");while(1){;}// return(0);}STM32f10x_it.c/******************************************************************************** * @file Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c* @author MCD Application Team* @version V3.4.0* @date 10/15/2010* @brief Main Interrupt Service Routines.* This file provides template for all exceptions handler and* peripherals interrupt service routine.****************************************************************************** * @copy** THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONL Y AIMS AT PROVIDING CUSTOMERS* WITH CODING INFORMA TION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SA VE* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.** <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>*//* Includes ------------------------------------------------------------------*/#include "stm32f10x_it.h"/** @addtogroup STM32F10x_StdPeriph_Template* @{*//* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*//* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*//* Private function prototypes -----------------------------------------------*//* Private functions ---------------------------------------------------------*//****************************************************************************** //* Cortex-M3 Processor Exceptions Handlers *//****************************************************************************** //*** @brief This function handles NMI exception.* @param None* @retval None*/void NMI_Handler(void){}/*** @brief This function handles Hard Fault exception.* @param None* @retval None*/void HardFault_Handler(void){/* Go to infinite loop when Hard Fault exception occurs */while (1){}}/*** @brief This function handles Memory Manage exception.* @param None* @retval None*/void MemManage_Handler(void){/* Go to infinite loop when Memory Manage exception occurs */ while (1){}}/*** @brief This function handles Bus Fault exception.* @param None* @retval None*/void BusFault_Handler(void){/* Go to infinite loop when Bus Fault exception occurs */while (1){}}/*** @brief This function handles Usage Fault exception.* @param None* @retval None*/void UsageFault_Handler(void){/* Go to infinite loop when Usage Fault exception occurs */ while (1){}}/*** @brief This function handles SVCall exception.* @param None* @retval None*/void SVC_Handler(void){}/*** @brief This function handles Debug Monitor exception.* @param None* @retval None*/void DebugMon_Handler(void){}/*** @brief This function handles PendSVC exception.* @param None* @retval None*/void PendSV_Handler(void){}extern USART1_Printf(char *pch);// extern EXTI0_IRQHandler(void);// extern EXTI1_IRQHandler(void);// extern EXTI2_IRQHandler(void);//extern EXTI3_IRQHandler(void);// extern EXTI4_IRQHandler(void);/*** @brief This function handles SysTick Handler.* @param None* @retval None*/void SysTick_Handler(void){}extern Delay(unsigned short time);/****************************************************************************** ** Function Name : USART1_IRQHandler* Description : This function handles USART1 global interrupt request.* Input : None* Output : None* Return : None******************************************************************************* /extern void USART1_SendByte(unsigned char temp); // 声明外部函数void USART1_IRQHandler(void){if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ // 如果是串口接收中断USART1_SendByte(USART_ReceiveData(USART1)); // 将接收到的字节发送出去}}void EXTI0_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line0) != RESET){Delay(200);EXTI_ClearITPendingBit(EXTI_Line0);USART1_Printf("ff\n");}}void EXTI1_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line1) != RESET){Delay(200);EXTI_ClearITPendingBit(EXTI_Line1);USART1_Printf("ff\n");}}void EXTI2_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line2) != RESET){Delay(200);EXTI_ClearITPendingBit(EXTI_Line2);USART1_Printf("ff\n");}}void EXTI3_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line3) != RESET){Delay(200);EXTI_ClearITPendingBit(EXTI_Line3);USART1_Printf("ff\n");}}void EXTI4_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line4) != RESET) {Delay(100);EXTI_ClearITPendingBit(EXTI_Line4);USART1_Printf("ff\n");}}。
基于STM32定时器产生PWM的研究报告一、引言PWM(Pulse Width Modulation,脉宽调制)技术是一种常用的控制技术,通过调整脉冲的宽度来控制输出信号的平均功率。
在嵌入式系统中,利用单片机的定时器模块可以方便地实现PWM输出功能。
本研究报告将重点研究基于STM32定时器产生PWM信号的原理和实现方法,并对应用案例进行详细描述和分析。
二、基于STM32定时器的PWM原理1.STM32定时器的工作模式STM32单片机中的定时器模块具有多种工作模式,常用的有基本定时器模式和高级定时器模式。
基本定时器模式适用于简单的定时与计数任务,而高级定时器模式则具有更多的功能和灵活性。
2.PWM信号的产生原理PWM信号的产生需要频率控制和占空比控制两个参数。
频率控制由定时器的时钟频率和预分频系数来决定,占空比控制则由定时器的计数值和比较值来决定。
基本上,定时器模块会自动地进行预分频和计数,并在满足条件时翻转输出比较寄存器的值,从而产生PWM输出信号。
三、PWM信号的应用案例1.LED灯控制PWM信号广泛应用于LED灯的亮度控制。
通过改变PWM信号的占空比,可以控制LED的亮度,实现调光的功能。
具体步骤为:配置定时器的时钟频率和预分频系数,设置计数值和比较值以控制占空比,将PWM信号输出到LED灯。
2.直流电机控制PWM信号也可以被用于直流电机的速度控制。
通过改变PWM信号的频率和占空比,可以控制电机的转速和输出功率。
具体步骤为:配置定时器的时钟频率和预分频系数,设置计数值和比较值以控制频率和占空比,将PWM信号输出到电机驱动模块。
四、实验结果与分析以LED灯控制为例进行实验,使用STM32F1系列的单片机,通过定时器2产生PWM信号控制LED灯的亮度。
实验结果表明,PWM信号的占空比越大,LED灯的亮度越高。
此外,通过改变PWM信号的频率,可以感知到灯光的闪烁频率。
在实验过程中,还需要注意定时器的时钟频率和预分频系数的选择,以及计数值和比较值的设置。
微控制器综合设计与实训实验名称:实验八PWM输出实验实验八:PWM输出实验1 实训任务(1) 开启TIM时钟,配置定时器通道对应IO口为复用输出;(2) 利用定时器的PWM输出功能产生波;(3) 通过调节占空比调节LED的亮度。
1.1 实验说明脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
简单一点,就是对脉冲宽度的控制。
STM32的定时器除了TIM6和7。
其他的定时器都可以用来产生PWM输出。
其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。
而通用定时器也能同时产生多达4路的PWM输出。
要使STM32的通用定时器TIMx产生PWM输出,除了上一实验的寄存器外,我们还会用到3个寄存器,分别是:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)。
本实验仅利用TIM3的CH2产生一路PWM输出。
通过重映射TIM_CH2到PB5上,由TIM_CH2输出PWM来控制LED1的亮度。
1.2 实验步骤(1)在实训平台上将PB5连接LED灯;(2)编写timer.c与timer.h文件,实现通过重映射TIM_CH2到PB5上,由TIM_CH2输出PWM来控制LED1的亮度。
(3)编写main文件,编译成功;(4) 程序编译无误后下载到实训平台,观察LED亮度的变化:通过示波器观察输出的波形。
2 程序设计(1) 新建文件夹并命名为PWM输出实验,复制粘贴上一章的实验文件,将工程文件改名为PWM.uvprojx。
(2)timer.h文件只需再添加TIM3_PWM_Init的声明即可。
(3) 编写timer.c文件。
a. 开启TIM3时钟以及复用功能时钟置,配置PB5为复用输出要使用TIM3,必须先开启TIM3的时钟,使能GPIO外设和AFIO复用功能模块时钟。
定时器实验一、实验要求编程序利用STM32的通用定时器TIM2和TIM3产生六路PWM输出。
二、实验原理实验主要考察对STM32F10X系列单片机定时器的使用。
STM32F103系列的单片机一共有11个定时器,其中:✧2个高级定时器✧4个普通定时器✧2个基本定时器✧2个看门狗定时器✧1个系统嘀嗒定时器出去看门狗定时器和系统滴答定时器的八个定时器列表;八个定时器分成3个组TIM1和TIM8是高级定时器TIM2-TIM5是通用定时器TIM6和TIM7是基本的定时器这8个定时器都是16位的,它们的计数器的类型除了基本定时器TIM6和TIM7都支持向上,向下,向上/向下这3种计数模式。
本次试验主要用到通用定时器TIM2和TIM3。
通用定时器(TIM2~TIM5)的主要功能:除了基本的定时器的功能外,还具有测量输入信号的脉冲长度( 输入捕获) 或者产生输出波形( 输出比较和PWM)。
通用定时器的时钟来源;a:内部时钟(CK_INT)b:外部时钟模式1:外部输入脚(TIx)c:外部时钟模式2:外部触发输入(ETR)d:内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器通用定时期内部时钟的产生:通用定时器(TIM2-5)的时钟不是直接来自APB1,而是通过APB1的预分频器以后才到达定时器模块。
当APB1的预分频器系数为1时,这个倍频器就不起作用了,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1时钟频率的两倍。
PWM输出模式;STM32的PWM输出有两种模式:模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。
区别如下:110:PWM模式1,在向上计数时,一旦TIMx_CNT在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
STM32定时器PWM输出总结STM32是意法半导体(STMicroelectronics)公司推出的一系列32位微控制器(MCU)的产品,相较于传统的8位和16位MCU,STM32具有更强的处理能力和更多的外设资源。
其中,定时器是STM32系列MCU的重要外设之一,可以用于实现各种定时、计数和PWM输出等功能。
定时器是STM32系列MCU中一个非常重要的外设,可以提供一些基本的定时、计数和计时功能。
除了基本功能外,定时器还可以通过配置不同的工作模式、输入捕获和输出比较等功能来实现更多的应用。
在STM32中,每个定时器可以被划分为多个通道,每个通道可以配置为不同的工作模式。
其中,PWM输出功能通常使用定时器的输出比较模式来实现,通过配置不同的占空比来实现不同的PWM波形输出。
使用STM32定时器的PWM输出功能,一般需要进行以下步骤:1.选择合适的定时器和通道:在STM32系列MCU中,一般会有多个定时器可供选择,根据实际需求选择合适的定时器和通道。
2.配置定时器的工作模式:定时器的工作模式取决于具体的应用需求,可以选择定时模式、计数模式、输入捕获模式或者输出比较模式。
3.配置输出比较模式:输出比较模式是实现PWM输出的关键,通过配置不同的比较值和占空比来实现不同的PWM波形输出。
4.配置GPIO引脚:将定时器的输出引脚与GPIO引脚相连,实现PWM波形的输出。
使用STM32定时器的PWM输出功能,可以实现多种应用。
比如:-控制电机的转速和方向:通过调整PWM波形的占空比,可以控制电机的转速和方向。
-LED灯的亮度调节:通过调整PWM波形的占空比,可以实现LED灯的亮度调节。
-蜂鸣器的声音控制:通过调整PWM波形的频率,可以实现蜂鸣器的声音控制。
总结起来,STM32定时器的PWM输出功能是一种非常有用且灵活的功能,可以通过配置不同的定时器和通道,实现多种不同的应用。
通过控制输出比较模式和占空比,可以实现精确的PWM波形输出。