嵌入式系统设计课程设计 课题名称:基于stm32的呼吸灯设计说明书 学 院: 机械与自动控制学院 专 业: 机械电子工程 3班 设计成员:胡* 学 号:201530300139 指导老师: 张* 日 期: 2018年6月20日
目录 一、 呼吸灯简介2 二、 PWM呼吸灯原理3 1.PWM简介3 2.PWM程序编写5 三、呼吸灯的设计9 1.程序设计9 2. 呼吸灯电路图设计14 3.呼吸灯实验实物图 14 四、结论与心得15 五、参考文献16
基于stm32的呼吸灯 1、呼吸灯简介呼吸灯是指灯光在微电脑的控制之下完成由亮到暗的逐渐变化,感觉好像是人在呼吸。其广泛应用于手机之上,并成为各大品牌新款手机的卖点之一,起到一个通知提醒的作用。当你的手机里面有未处理的通知,比如说未接来电,未查收的短信等等,呼吸灯就会由暗到亮的变化,像呼吸一样那么有节奏,起到一个通知提醒的作用。 要使用数字器件控制灯光的强弱,我们很自然就想到PWM(脉冲宽度调制)技术。假如以LED作为灯光设备,且由控制器输出的PWM信号可以直接驱动LED,PWM信号中的低电平可点亮LED灯。由于视觉暂留效应,人眼可以看不到LED灯的闪烁现象,反应到人眼中的是亮度的差别,因此我们需要LED以较高的频率进行开关(亮灭)切换。因此我们可以使用高频率的PWM信号,通过调制信号的占空比,控制LED灯的亮度。根据以上思路,根据上课和实验所学知识利用PWM实现呼吸灯设计。 2、PWM呼吸灯原理1.PWM简介Pulse Width Modulation: 脉冲宽度调制(PWM) 脉冲:频率 ,方波 脉冲宽度:占空比, 高电平的宽度:在同一个时间内,高电平所占比例 频率与周期:f = 1/T f:频率(主频) T:周期 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制,PWM原理如图: 图中,我们假定定时器工作在向上计数PWM模式,且当CNT<CCRx时,输出0,CNT>=CCRx时输出1。那么就可以得到如上的PWM示意图:当CNT值小于CCRx的时候IO输出低电平(0),当CNT值大于等于CCRx的时候,IO输出高电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环。改变CCRx的值,就可以改变PWM输出的占空比,改变ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。 控制PWM的三个寄存器:捕获/比较模式寄存器(TIMx_CCMR1/2),捕获/比较使能寄存器(TIMx_CCER),捕获/比较寄存器(TIMx_CCR1~4)。这三个寄存器针对不同的定时器不同的输出模式设置各不相同。 本次实验主要用到捕获/比较寄存器( TIMx_CCR1~4),该寄存器总共有 4 个,对应 4 个输通道 CH1~4。 TIMX_CCR包括捕获输入部分(数字滤波、多路复用和预分频器)和比较输出部分(比较器和输出控制)。 - 捕获输入。在输入时,捕获/比较寄存器TIMx_CCR被用于党捕获(存储)输入脉冲在电平发生翻转时加载脉冲计数器TIMx_CNT的当前计数值,从而实现脉冲的频率测量。
- 比较输出。在输出时,捕获/比较寄存器TIMx_CCR用来存储一个脉冲数值,把这个数值与脉冲计数器TIMx_CNT的当前计数值进行比较,根据比较结果进行不同的电平输出。
在输出模式下,该寄存器的值与 CNT 的值比较,根据比较结果产生相应动作。通过修改这个寄存器的值,就可以控制 PWM 的输出脉宽了。 在呼吸灯设计过程中使用的是 TIM3的通道 1和2,需要修改 TIM3_CCR2 以实现脉宽控制 A6和A7的亮度。 2.PWM程序编写1)开启TIM3和GPIO时钟,配置PA6、PA7选择复用功能AF9(TIM3)输出。RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能定时器TIM3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能引脚PA6和PA7的时钟 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //选择输出模式为复用推挽输出 2)初始化TIM3,设置TIM3的ARR和PSC等参数。在开启了 TIM3 的时钟之后,要设置 ARR 和 PSC 两个寄存器的值来控制输出 PWM 的周期。当 PWM 周期太慢(低于 50Hz)的时候,就会明显感觉到闪烁了。因此, PWM 周期在这里不宜设置的太小。 这在库函数是TIM_TimeBaseInit 函数实现的,调用的格式为: TIM_TimeBaseStructure.TIM_Period=1000-1; //设置自动重装载寄存器周期的值。 TIM_TimeBaseStructure.TIM_Prescaler=0; //设置用来作为TIMx时钟频率除数的预分频数。 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分割。 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //选择计数器模式,向上计数。 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //将设置好的参数初始化。 3)设置TIM3_CHX的PWM模式,使能TIM3的输出。要设置 TIM3_CH2 为 PWM 模式(默认是冻结的),因为 LED是低电平亮,而当 CCR2 的值小的时候,D9 就暗,CCR2 值大的时候, D9 就亮,所以通过配置 TIM3_CCMR1 的相关位来控制 TIM3_CH2 的模式。在库函数中,PWM 通道设置是通过函数TIM_OC1Init()~TIM_OC4Init()来设置的, 不同的通道的设置函数不一样,通道 1时,使用的函数为TIM_OC1Init();通道2时,使用的函数为TIM_OC2Init()。 结构体TIM_OCInitTypeDef的定义: typedef struct { uint16_t TIM_OCMode; / uint16_t TIM_OutputState; / uint16_t TIM_OutputNState; / uint16_t TIM_Pulse; / uint16_t TIM_OCPolarity; / uint16_t TIM_OCNPolarity; / uint16_t TIM_OCIdleState; / uint16_t TIM_OCNIdleState; / } TIM_OCInitTypeDef; 参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
参数 TIM_OCPolarity 用来设置极性是高还是低。
其他的参数 TIM_OutputNState, TIM_OCNPolarity, TIM_OCIdleState 和 TIM_OCNIdleState 是高级定时器 TIM1 和 TIM8 才用到的。 主函数中设置如下: TIM_OCInitTypeDef TIM_OCInitStructure; //设置一个TIM_OCInitStructure结构体来初始化外设 TIMx。 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //设置TIM输出模式为PWM1。 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //比较输出使能。
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;; //TIM输出比较级极性高。
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //将设定好的参数初始化给通道1。 TIM_OC2Init(TIM3,&TIM_OCInitStructure); //初始化通道2。 4)使能TIM3.TIM_Cmd(TIM3,ENABLE); //使能 TIM3的外设。 5)修改TIM14_CCR1来控制占空比。通过修改 TIM3_CCR1和TIM3_CCR2 可以控制通道1和通道2的输出占空比。继而控制 PA6和PA7 的亮度。 TIM_OCInitStructure.TIM_Pulse=CCR1_Val; //设置了待装入捕获比较寄存器的脉冲值。 TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR1上的预装载寄存器 TIM_OCInitStructure.TIM_Pulse=CCR2_Val; //设置了待装入捕获比较寄存器的脉冲值。 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器。
呼吸灯电路图设计

图 部分硬件仿真电路图 3.呼吸灯实验实物图
 四、结论与心得1.一开始老师布置作业时是无限制的自由发挥,一头雾水不知道自己该从哪里下手该干什么,后来因为在机电传动控制实验中正好学习了直流电机PWM调速实验,由此得到启发觉得可以通过PWM控制灯泡的闪烁频率来实现灯光的亮度变化,进而实现呼吸灯的效果。 2.编写程序过程中还存在许多问题,一开始是直接在实验例程PWM输出实验中修改,因为没有硬件设备,只能通过仿真,仿真一直不成功,后经过在网上搜集资料、查看相关书籍和询问同学完成本次实验的程序,实验程序中没有LED程序,而是直接在输出引脚输出高低电平从而实现灯泡的闪烁。对实验中出现的诸多问题,一定要认真分析其原因之所在,然后查阅资料通过各种方法解决实验中出现的这些问题,做完实验之后要做好相关总结,这样才能把一个实验做完美,对以后的实验也有着一定的帮助作用。 - 在本次实验中当决定好做什么内容时,一定要先仔细分析整个实验要达到的目标要求,然后做出总体设计方案将程序编写细化到每一部分,这样就不容易出错,而且在检查错误问题时也会稍微容易一点。
- 通过这次综合实验让我对stm32有了更进一步的熟悉和了解,一个看似很简单的东西,到动手把它设计出来就比较困难了,所以在今后的学习中我们要注意这一点,要把课堂上所学到的知识和实际联系起来,同时通过本次实验让我对课本理论知识有了深入实际的理解,也会在调试中出现的错误结合理论知识寻找问题所在的原因,一步步检查调试,直到完成实验最终目的。
- 通过设计大作业,让我明白任何实验都是基于理论的,理论知识学扎实了,才能在程序编写上和调试上快速准确的完成实验,以此警示自己在后期的学习中一定要注意理论知识的学习。
三、呼吸灯的设计
1.程序设计
- /*延时函数*/
- void Delay(__IO u32 nCount)
- {
- while(nCount--);
- }
- u16 CCR1_Val=1000;
- u16 CCR2_Val=0;
- u8 a=0;
- /*主函数*/
- int main(void)
- {
- RCC_Config();
- TIM3_GPIO_Config();
- TIM3_Mode_Config();
- while(1)
- {
- if(CCR1_Val>0&&a<40&&CCR2_Val<1000)
- {
- CCR1_Val-=25; //通过改变脉冲值,实现灯泡的亮度
- CCR2_Val+=25;
- TIM3_Mode_Config();
- a++;
- Delay(0XFFFF);
- Delay(0XFFFF);
- Delay(0XFFFF);
- Delay(0XFFFF);
- }
- else
- {
- CCR1_Val+=25;
- CCR2_Val-=25;
- TIM3_Mode_Config();
- Delay(0XFFFF);
- Delay(0XFFFF);
- a++;
- if(a==80)a=0;
- }
- }
- }
- /*使能时钟*/
- void RCC_Config(void)
- {
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能定时器TIM3时钟。
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能引脚PA的时钟。
- }
- /*配置 GPIO 的模式和 IO 口*/
- void TIM3_GPIO_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure; //设置一个GPIO_InitStructure结构体。
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7; //选择引脚PA6和PA7。
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //选择输出模式为复用推挽模式。
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置引脚最高输出速率为50MHZ。
- GPIO_Init(GPIOA,&GPIO_InitStructure); //将设定好的参数初始化。
- }
- /* 设置TIM3 */
- void TIM3_Mode_Config(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //设置一个TIM_TimeBaseStructure结构体。
- TIM_OCInitTypeDef TIM_OCInitStructure; //设置一个TIM_OCInitStructure结构体 。 TIM_TimeBaseStructure.TIM_Period=1000-1; //设置自动重装载寄存器周期的值。
- TIM_TimeBaseStructure.TIM_Prescaler=0; //设置用来作为TIMx时钟频率除数的预分频值。 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分割 。 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //选择了计数器模式,向上计数。
- TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //将设置好的参数初始化 。
- TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //设置TIM输出模式为PWM1。
- TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //使能输出比较
- TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; /TIM输出比较剂型高
- TIM_OCInitStructure.TIM_Pulse=CCR1_Val; //设置了待装入捕获比较寄存器的脉冲值
- TIM_OC1Init(TIM3, &TIM_OCInitStructure); //将设定好的参数初始化给通道1
- TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR1上的预装载寄存器
- TIM_OCInitStructure.TIM_Pulse=CCR2_Val;
- TIM_OC2Init(TIM3,&TIM_OCInitStructure); //通道2
- TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
- TIM_ARRPreloadConfig(TIM3,ENABLE); //使能TIM3在ARR上的预装载寄存器
- TIM_Cmd(TIM3,ENABLE); //使能TIM3的外设
- }
复制代码
完整的Word格式文档51黑下载地址:
教学模板-库函数操作.rar
(460.43 KB, 下载次数: 53)
|