嵌入式开发之STM32学习笔记day10

STM32F103C8T6 TIM定时器输出比较

1 定时器输出比较基础概念

  • OC(Output Compare)输出比较
  • 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
  • 每个高级定时器和通用定时器都拥有4个输出比较通道
  • 高级定时器的前3个通道额外拥有死区生成和互补输出的功能

2 PWM 的基本概念

PWM(Pulse Width Modulation,脉宽调制)是一种通过调节脉冲信号的占空比来控制模拟信号的技术。其核心是通过快速开关数字信号,改变高电平与低电平的时间比例,从而模拟不同的电压或功率输出。

2.1 PWM 的工作原理

  • 占空比:高电平时间与整个周期的比值,通常以百分比表示。例如,50%占空比表示高电平和低电平时间相等。
  • 频率:单位时间内脉冲信号的周期数(Hz)。高频 PWM 可减少输出波动,但可能受硬件限制。
  • PWM 参数:

公式: 频率 = 1 / TS 占空比 = TON / TS 分辨率 = 占空比变化步距

描述: 这是一个简单的PWM原理图,假设定时器工作模式是向上计数,当计数值小于阈值时,就会输出一个电平状态,比如高电平,反之输出低电平。高电平持续时间(脉冲宽度)和周期时间的比值为占空比,范围是0-100%。上图是生成的是占空比为40%的pwm波。

**案例场景分析:**在智能家居的客厅中,一盏嵌入式LED灯正通过PWM(脉冲宽度调制)技术展现出细腻的光影魔法。通过微控制器精准调节PWM的占空比,灯光从清晨的柔和暖黄渐变为午后的明亮白光,仿佛自然光线在室内流动。当夜晚观影模式开启时,灯光瞬间调至10%的暗调,既营造出沉浸式氛围,又避免了直视光源的刺眼。PWM的高频脉冲控制让亮度变化丝滑无频闪,配合智能系统还能联动音乐节奏,让灯光随着旋律明暗起伏,如同无声的舞者用光影演绎科技与艺术的交融。

3 输出比较通道(高级)

4 输出比较通道(通用)

5 输出比较模式

模式 描述
冻结 CNT=CCR时,REF保持为原状态
匹配时置有效电平 CNT=CCR时,REF置有效电平
匹配时置无效电平 CNT=CCR时,REF置无效电平
匹配时电平翻转 CNT=CCR时,REF电平翻转
强制为无效电平 CNT与CCR无效,REF强制为无效电平
强制为有效电平 CNT与CCR无效,REF强制为有效电平
PWM模式1 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平 向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平
PWM模式2 向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平 向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平

6 PWM基本结构

分析说明:

这张图展示了一个定时器PWM信号输出的内部工作机制,其主要流程如下:

时基单元:

  • 包括 PSC(预分频器)CNT(计数器)ARR(自动重装器),它们共同决定了PWM的周期。

  • PSC将主时钟频率进行分频,决定了CNT计数的速度。

  • CNT是计数器,按设定频率进行计数,从0开始递增到ARR设置的最大值,然后重新从0计数。

  • ARR决定了PWM的周期(CNT最大值)。

输出比较单元(CCR)

  • CCR(捕获/比较寄存器) 用于设定PWM的占空比,即高电平的持续时间。

  • 当CNT小于CCR时,输出为高电平;CNT大于等于CCR时,输出为低电平。

REF极性与GPIO输出:

  • 通过设置极性选择器,可以决定输出为正向PWM(高电平有效)还是反向PWM(低电平有效)。

  • 最终的PWM信号通过GPIO引脚输出。

图示解读:

  • 上方折线图表示CNT计数器从0到ARR(如9)不断循环计数。

  • 红线是CCR的值,例如3。

  • 下方绿色方波表示PWM输出波形:当计数值小于CCR时为高电平,超过后为低电平。


简要概括:

STM32定时器通过PSC分频后由CNT计数器递增计数,周期由ARR设置决定。当计数器CNT的值小于CCR时,输出为高电平,否则为低电平,从而形成PWM波形。通过调整CCR值可以控制PWM的占空比。极性选择电路还可以决定PWM信号的有效电平方向,最终由GPIO口输出PWM信号,实现对外设的精确控制。

7 PWM参数计算

  • PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
  • PWM占空比: Duty = CCR / (ARR + 1)
  • PWM分辨率: Reso = 1 / (ARR + 1)

8 使用PWM精准控制LED亮度:从原理到代码实现

本文将手把手教你通过PWM(脉冲宽度调制)技术控制LED灯的亮度,涵盖硬件连接、代码编写及原理分析,适用于STM32等常见开发板。通过调节占空比,实现灯光从暗到亮的平滑过渡,并附赠呼吸灯效果代码!

所需材料

  • 开发板(STM32)

  • LED灯(不同颜色需注意正向电压)

  • 220Ω限流电阻

  • 杜邦线若干

接线方式

  • LED正极 → PWM引脚(如STM32的PA0)

  • LED负极 → 电阻 → GND

8.1 PWM初始化

8.1.1 开启时钟
cs 复制代码
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
8.1.2 GPIO初始化
cs 复制代码
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);	//将PA0引脚初始化为复用推挽输出	
										//受外设控制的引脚,均需要配置为复用模式
8.1.3 配置时钟源

在这里外面选择时钟源为内部时钟TIM2

cs 复制代码
/*配置时钟源*/
TIM_InternalClockConfig(TIM2);	//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
8.1.4 时基单元初始化
cs 复制代码
/*时基单元初始化*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;			//定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;					//计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;				//预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
8.1.5 输出比较初始化
cs 复制代码
/*输出比较初始化*/
TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量
TIM_OCStructInit(&TIM_OCInitStructure);							//结构体初始化,若结构体没有完整赋值    //则最好执行此函数,给结构体所有成员都赋一个默认值  //避免结构体初值不确定的问题
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//输出比较模式,选择PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//输出极性,选择为高,若选择极性为低,则输出高低电平取反
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出使能
TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值
TIM_OC1Init(TIM2, &TIM_OCInitStructure);//将结构体变量交给TIM_OC1Init,配置TIM2的输出比较通道1
	
8.1.6 TIM使能------重要
cs 复制代码
/*TIM使能*/
TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行

8.2 占空比设置

cs 复制代码
/**
  * 函    数:PWM设置CCR
  * 参    数:Compare 要写入的CCR的值,范围:0~100
  * 返 回 值:无
  * 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
  *           占空比Duty = CCR / (ARR + 1)
  */
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);		//设置CCR1的值
}

这里,我们可以通过上面的PWM_SetCompare1函数来设置GPIO输出占空比为Compare的信号。因为我们起初设置ARR为100-1 , PSC为720-1,从而可以通过以下公式计算:

  • PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1) = 72*10^6 / 720000 = 100
  • PWM占空比: Duty = CCR / (ARR + 1) = CCR%
  • PWM分辨率: Reso = 1 / (ARR + 1) = 0.01

8.3 main主函数

cs 复制代码
int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	PWM_Init();			//PWM初始化
	
    OLED_ShowString(1, 1, "PWM contral led0");
	while (1)
	{
		for (i = 0; i <= 100; i++)
		{
			PWM_SetCompare1(i);			//依次将定时器的CCR寄存器设置为0~100,PWM占空比逐渐增大,LED逐渐变亮
			Delay_ms(10);				//延时10ms
		}
		for (i = 0; i <= 100; i++)
		{
			PWM_SetCompare1(100 - i);	//依次将定时器的CCR寄存器设置为100~0,PWM占空比逐渐减小,LED逐渐变暗
			Delay_ms(10);				//延时10ms
		}
	}
}

分析:

这里,我们就使用两个for循环,先将led占空比从0到100递增,然后又从100到0递减,我们就可以清晰的看见led亮度由暗变亮,由亮变暗,循环往复。

关注我

相关推荐
村头的猫1 分钟前
如何通过 noindex 阻止网页被搜索引擎编入索引?
前端·经验分享·笔记·搜索引擎
麦德泽特11 分钟前
超高速总线CDCTL01A 芯片在机器人领域的应用解析
人工智能·嵌入式硬件·物联网·机器人·信息与通信
逝水如流年轻往返染尘18 分钟前
CSS基础学习1
前端·css·学习
Resurgence031 小时前
建造者模式Builder Pattern
笔记·建造者模式
运维小杨1 小时前
linux云计算学习第八周,第九周
linux·学习·云计算
nenchoumi31191 小时前
UE5 学习系列(八)材质基础认知
学习·游戏·ue5·机器人·材质
vicorv252 小时前
电流传感器在汽车中的应用:从BMS电池管理到电机控制的工程解析
stm32·单片机·嵌入式硬件
物联网嵌入式小冉学长2 小时前
3.TCP回响服务器实现及源码分析上
stm32·网络协议·tcp/ip·嵌入式
z2014z2 小时前
第11章 结构 笔记
笔记·c#
jarenyVO3 小时前
Nginx全面深入学习目录
运维·学习·nginx