基于STM32的智能灯光亮度调节器【正点原子】(一)

系列文章目录

第一章 PWM调节

第二章 ADC采样

第三章 光敏传感器

第四章 智能灯光亮度调节器(终)


目录

前言

一、PWM是什么?

二、如何产生一个PWM信号?

总结


前言

本文实现的是一个智能灯光亮度调节器的设计,使用STM32F103ZE的单片机,可以手动调节灯光档位,也可以自动根据环境亮度进行切换灯光档位。这需要用到PWM调光、ADC采集、光敏传感器,本文将会将设计路线呈现出来。


提示:以下是本篇文章正文内容,下面案例可供参考

一、PWM是什么?

我们要调节板子上的LED灯光档位,需要用到PWM(Pulse Width Modulation),全称是脉冲宽度调制,使用PWM时,我们需要关注一下两个参数:
(1)PWM占空比

PWM信号的占空比指该PWM信号的一个周期中高电平所占时间的百分比,若信号始终是高电平,则该信号的占空比为100%,反之若信号始终是低电平,则该信号的占空比为0%,如下图所示,T是整个PWM周期,T1代表占空比:

 (2)PWM频率

PWM信号频率有多快,决定了PWM信号走完一个周期的速度。

二、如何产生一个PWM信号?

我们了解完PWM大概是个什么东西后,就要学习如何产生它和使用它。通过STM32的单片机,我们有两个方式去产生PWM信号,第一种是使用普通IO输出PWM,第二种是使用定时器的PWM的IO口:

(1)普通IO口

我们可以翻看手册去看普通IO口的主要功能:(下图转载自其他博主),如果这个IO口的主要功能那一栏出现CHx的标志,则是可以输出PWM的端口,上面的红框中的普就是普通定时器。

 (2)PWM端口

STM32的定时器除了TIM6、TIM7,其他的定时器都可以用来产生PWM,高级定时器TIM1与TIM8可同时产生7路的PWM,通用定时器则可以同时产生4路的PWM输出。

 (3)普通IO产生PWM方法

我们使用的是定时器中断去实现的,PWM的产生,我们需要去确定两个参数:周期占空比,而如何确定周期呢,我们知道T=1/f,所以只要把频率确定下来,周期就知道啦。而我们确定了时间后,占空比就是这个这段时间中高电平所占的时间的百分比就是我们想要的占空比啦。

例如,我们现在要去产生一个1KHz的占空比为50%的PWM,我们知道了频率为1KHz,那么周期根据T=1/f,就可以知道T=1ms,那么一个周期就是1ms。那占空比为50%,说明在一个1ms的周期中高电平所占的时间为0.5ms。那我们使用定时器中断,每0.1ms产生一次中断,每次进入中断时计数,中断服务函数前五次中断给高电平就可以实现占空比50%。

(4)PWM口产生PWM

我们使用PWM口时需要先了解一下相关的定时器:ARR、PSC、CNT、CR1

自动重装载寄存器ARR:

 该寄存器用于配置自动重装载值ARR

预分频寄存器PSC:

该寄存器用于配置预分频系数

 计数器CNT:

该寄存器用于配置计数值

 控制寄存器CR1:

根据控制寄存器位4的设定,分为两种计数模式:

 

 

 了解完上面的寄存器后,我们开始学习产生PWM的过程:举例一种情况,定时器的重装载值为ARR,比较值为CCR,每次计数时,都会将CNT计数值与CCR进行比较,若计数值CNT小于CCR,则输出低电平,若计数值CNT大于CCR,则输出高电平,那么这时占空比就是可以通过调整CCR的值去改变,而PWM的频率就可以通过调整ARR与PSC去调整。我们的配置过程为:

①初始化TIMx,设置TIMx的ARRPSC。

②设置TIMx_CHx的PWM模式使能TIMx的CHx输出。

使能TIMx

④修改TIMx_CCRx来控制占空比。

timer.c:

//TIM3 PWM 部分初始化
//PWM 输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{ 
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①使能定时器 3 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
RCC_APB2Periph_AFIO, ENABLE); //①使能 GPIO 和 AFIO 复用功能时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //②重映射 TIM3_CH2->PB5 
//设置该引脚为复用输出功能,输出 TIM3 CH2 的 PWM 脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //①初始化 GPIO
//初始化 TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在自动重装载周期值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //③初始化 TIMx
//初始化 TIM3 Channel2 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //④初始化外设 TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
}

mian.c:

int main(void)
{
    TIM3_PWM_Init(899,0);

    while(1)
    {
        ...
    }
}


总结

以上是PWM的学习与产生过程,后面的文章会说明如何使用PWM调节灯光档位,下面给一个正点原子的例程,是一个呼吸灯,可以烧录进自己的板子上看看,让自己更好的理解PWM的用处。

链接:https://pan.baidu.com/s/1UkNmRrqFlHx0dCuAHHDfRA?pwd=hxdg 
提取码:hxdg

  • 13
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
nrf51822并没有PWM模块,但是如果巧妙的结合PPI模块,并加上一个定时器中断就可以轻松的实现了PWM,思路是这样的: 定时器使用三个比较器 cc0、cc1和cc2,当三个比较器任何一产生比较事件的时候都会通过PPI去翻转GPIO的引脚,在初始化的时候这样设置这三个比较器: NRF_TIMER2->CC[0] = MAX_SAMPLE_LEVELS + next_sample_get(); NRF_TIMER2->CC[1] = MAX_SAMPLE_LEVELS; // CC2 will be set on the first CC1 interrupt. NRF_TIMER2->CC[2] = 0; 这是初始化的配置,到这里会有一个思考,这样的话计数器技术到cc0的时候依然会继续的往下计数,那这样的话他的再溢出的值就将回到cc2的时候也就是归零的时候,那这样的波形就分为了三段了,这不是我们所需要的,那这样要实现PWM就要把cc2的比较值往后挪,让他超过cc0,并且cc2到之前的一个比较值是固定的,这样就需要从新设置cc2的值,还有一个办法就是当计数器到cc0的时候请求中断重置计数器,但是这样做有一个问题就是进入中断是需要时间的,而当计数器到达cc0的时候就需要重置,同时计数器的下一个值就是cc2,这样就会造成冲突,所以我们使用了第一种方案。 具体实现是这样的,使能cc1比较中断,在第一次中断中重新设置cc1,让他的值变成了两倍,同时从新设置cc2,让他的值变成了cc1+N,N就是占空比参数,在第二次中断中,也是从新设置cc1,但是和上一次中断不同的是这时候设置的是cc0,而不是cc2 这样造成的计数器溢出值是这样的:
STM32F103正点原子精英版战舰是一款基于ARM Cortex-M3内核的微控制器开发板,配备了丰富的外设资源,包括多个通信接口、GPIO口、模数转换器等。正点原子公司给出了开源的固件库和示例代码,方便开发者使用。 在该开发板上实现示波器功能需要利用其中的ADC模数转换器、DMA控制器、LCD显示等资源。示波器的原理是通过采样输入信号并将其转换为数字信号后,通过DMA传输到内存中,再通过LCD实时绘制波形图。 首先,需要使用开发板上的ADC模块对输入信号进行采样。可以通过设置ADC控制寄存器来配置采样精度、采样速率等参数。采样数据可以通过DMA控制器直接传输到内存中,减少了CPU的负担。 然后,利用采样得到的数据,在LCD上绘制波形图。可以使用开发板上的TFT LCD模块,通过驱动程序将数据转换为对应的像素点,并实时刷新到LCD屏幕上,从而形成波形图。可以选择不同的显示方式,例如线性、点阵等,以适应不同的需求。 对于更高级的示波器功能,例如闭锁显示、触发功能、自动测量等,还需要进一步的算法和逻辑设计。可以通过编写相应的软件程序,结合硬件资源,实现这些功能。 总之,基于STM32F103正点原子精英版战舰的示波器的实现涉及到采样、数字信号处理和波形绘制等多个方面。通过充分利用该开发板的硬件资源和开源的固件库,可以实现一个功能强大的示波器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值