嵌入式系统应用PWM呼吸灯综合性实验电子信息科学与技术物理与电子科学学院2015-06-04电工电子中心2015年6月绘制湖北师范学院电工电子实验教学省级示范中心电子版实验报告第2页,共8页STM32呼吸灯设计(研究)一.任务解析呼吸灯就是让LED灯的闪烁像呼吸一样,灯光在微电脑控制之下完成由亮到暗再由暗到亮的逐渐变化。通过程序代码实现PWM(脉宽调制)输出驱动LED,逐渐改变PWM的占空比从而实现LED模拟呼吸的过程,即渐亮再渐暗再渐亮再渐暗……如此往复,再利用LED的余辉和人眼的暂留效应,看上去就和人的呼吸一样。二.方案论证实现STM32呼吸灯设计有不同方法,通过看STM32培训视频和STM32不完全手册等资料,分析总结了如下所示的两种方案。方案一:利用先实现PWM分模块实现呼吸灯的方案根据STM32不完全手册资料,先编写好PWM输出的程序代码,然后编写实现呼吸灯的主函数并在在主函数程序中调用PWM输出的程序和LED灯的程序,从而通过stm32的pwm输出驱动LED实现呼吸灯。方案二:利用一个总程序实现呼吸灯的方案根据STM32不完全手册资料,编写一个程序代码,在这个程序代码中包含实现呼吸灯的主体程序,及配置系统时钟、配置GPIO口、配置TIMER等设置,从而通过PWM输出占空比实现呼吸灯。上述两种方案,从程序的难易程度来说,无论是库函数版本还是寄存器版本去编写程序,两个方案的程序代码编写难度相当;但是,就程序调试的难度而言,库函数版本的程序代码更易让人懂,且方案一更容易查找程序代码的错误,更利于程序的调试。所以,选择方案一编写库函数版本程序代码去实现STM32呼吸灯设计。三.方案实施由方案一编写库函数版本程序代码去实现STM32呼吸灯设计,即通过看过的视频和库函数版本的STM32手册资料先编写LED灯控制的程序代码led.c;再编写PWM输出的程序代码pwm.c;最后编写呼吸灯的主体程序main.c,并在主函数中调用led.c和pwm.c程序代码,从而实现呼吸灯。1、STM32呼吸灯的主函数流程图如下所示:湖北师范学院电工电子实验教学省级示范中心电子版实验报告第3页,共8页2、STM32呼吸灯的关键程序代码如下所示:①配置系统时钟模块:RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);②配置GPIO口模块:GPIO_InitTypeDefGPIO_InitStructure;//设置一个GPIO_InitStructure结构体。GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//选择引脚8。GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//选择输出模式为复用推挽输出。GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//设置引脚最高输出速率为50MHz。GPIO_Init(GPIOA,&GPIO_InitStructure);//将设定好的参数初始化。③配置TIMER模块:TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;延时、IO口初始化定时器初始化结束main函数LED灯DS0由暗到亮输出0;从亮到输出1延时PWM的输出占空比递增(递减)湖北师范学院电工电子实验教学省级示范中心电子版实验报告第4页,共8页TIM_OCInitTypeDefTIM_OCInitStructure;TIM_TimeBaseStructure.TIM_Period=arr;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值72M/(900)=80KTIM_TimeBaseStructure.TIM_Prescaler=psc;//设置用来作为TIMx时钟频率除数的预分频值不分频TIM_TimeBaseStructure.TIM_ClockDivision=0;//设置时钟分割:TDTS=Tck_timTIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//TIM向上计数模式TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;//选择定时器模式:TIM脉冲宽度调制模式2TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能TIM_OCInitStructure.TIM_Pulse=0;//设置待装入捕获比较寄存器的脉冲值TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出极性:TIM输出比较极性高TIM_OC1Init(TIM1,&TIM_OCInitStructure);//根据TIM_OCInitStruct中指定的参数初始化外设TIMxTIM_CtrlPWMOutputs(TIM1,ENABLE);//MOE主输出使能TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//CH1预装载使能TIM_ARRPreloadConfig(TIM1,ENABLE);//使能TIMx在ARR上的预装载寄存器TIM_Cmd(TIM1,ENABLE);//使能TIM1④配置LED模块:#includeled.h//初始化PB5和PE5为输出口.并使能这两个口的时钟//LEDIO初始化voidLED_Init(void){GPIO_InitTypeDefGPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD,ENABLE);//使能PA,PD端口时钟GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//LED0--PA.8端口配置GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出湖北师范学院电工电子实验教学省级示范中心电子版实验报告第5页,共8页GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHzGPIO_Init(GPIOA,&GPIO_InitStructure);//根据设定参数初始化GPIOA.8GPIO_SetBits(GPIOA,GPIO_Pin_8);//PA.8输出高GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//LED1--PD.2端口配置,推挽输出GPIO_Init(GPIOD,&GPIO_InitStructure);//推挽输出,IO口速度为50MHzGPIO_SetBits(GPIOD,GPIO_Pin_2);//PD.2输出高}⑤实现呼吸灯主体程序:intmain(void){u16led0pwmval=0;u8dir=1;delay_init();//延时函数初始化LED_Init();//初始化与LED连接的硬件接口TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khzwhile(1){delay_ms(10);if(dir)led0pwmval++;elseled0pwmval--;if(led0pwmval300)dir=0;if(led0pwmval==0)dir=1;//if(led0pwmval==0)delay_ms(50000);TIM_SetCompare1(TIM1,led0pwmval);}}3、STM32呼吸灯的所有程序:#includepwm.h#includeled.h//arr:自动重装值//psc:时钟预分频数voidTIM1_PWM_Init(u16arr,u16psc){GPIO_InitTypeDefGPIO_InitStructure;湖北师范学院电工电子实验教学省级示范中心电子版实验报告第6页,共8页TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;TIM_OCInitTypeDefTIM_OCInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIO外设时钟使能//设置该引脚为复用输出功能,输出TIM1CH1的PWM脉冲波形GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;//TIM_CH1GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);TIM_TimeBaseStructure.TIM_Period=arr;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值72M/(900)=80KTIM_TimeBaseStructure.TIM_Prescaler=psc;//设置用来作为TIMx时钟频率除数的预分频值不分频TIM_TimeBaseStructure.TIM_ClockDivision=0;//设置时钟分割:TDTS=Tck_timTIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//TIM向上计数模式TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;//选择定时器模式:TIM脉冲宽度调制模式2TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//比较输出使能TIM_OCInitStructure.TIM_Pulse=0;//设置待装入捕获比较寄存器的脉冲值TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出极性:TIM输出比较极性高TIM_OC1Init(TIM1,&TIM_OCInitStructure);//根据TIM_OCInitStruct中指定的参数初始化外设TIMxTIM_CtrlPWMOutputs(TIM1,ENABLE);//MOE主输出使能TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//CH1预装载使能TIM_ARRPreloadConfig(TIM1,ENABLE);//使能TIMx在ARR上的预装载寄存器湖北师范学院电工电子实验教学省级示范中心电子版实验报告第7页,共8页TIM_Cmd(TIM1,ENABLE);//使能TIM1}#includeled.h#includedelay.h#includesys.h#includepwm.hintmain(void){u16led0pwmval=0;u8dir=1;delay_init();//延时