1.接线原理图:
LED正极接PA0,负极接GND,即高电平电亮,低电平熄灭。占空比越大,LED越亮;占空比越小,LED越暗。
实物图:
LED在不断的改变亮度,实现呼吸灯效果。(是LED完全亮完全灭的进阶版)
2.代码部分:
主函数部分代码如下:
#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "PWM.h" //现象:有条件的可以买示波器观察PWM波形(矩形波,占空比50%)调节CCR,占空比越高,高电平占比越大,LED越亮 uint8_t i; int main(void) { OLED_Init(); PWM_Init(); //如果没有下面while循环的进一步操作,则LED为常亮(实际是1KHz闪烁) while(1) { for(i=0;i<=100;i++) { PWM_SetCompare1(i);//完成占空比从0%~100%,亮灭逐渐变亮,达到呼吸灯效果 Delay_ms(10); } for(i=0;i<=100;i++) { PWM_SetCompare1(100-i);//完成占空比从0%~100%,亮灭逐渐变暗,达到呼吸灯效果 Delay_ms(10); } } }
PWM(PWM驱动LED部分)代码如下:
//操作思路可参考:(图PWM基本结构)
//1.RCC开启时钟,把TIM外设和GPIO外设的时钟打开。
//2.初始化时基单元,选择内部时钟-----使用的还是TIM2,所以直接复制粘贴内部时钟部分代码
//3.初始化输出比较单元,(重要函数TIM_OC1Init)包括CCR的值,输出比较模式,极性选择,输出使能。(结构体)
//4.初始化GPIO,(第三步的输出比较模式的值需要GPIO输出展示)TIM_OC1Init,GPIO口初始化为复用推挽输出
//5.运行控制,启动计数器。
//注:两个重要函数:
//用结构体初始化输出比较单元函数:TIM_OC1Init(在初始化PWM第三步)
//更改占空比,实现LED呼吸现象需要用的函数:PWM_SetCompare1(单独封装)
#include "stm32f10x.h" // Device header void PWM_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//第一步:开启APB1时钟,因为TIM2是APB1总线的外设 TIM_InternalClockConfig(TIM2);//第二步:选择内部时钟 //第二步:初始化时基单元----TIM_TimeBaseInit的第二个参数是结构体,配置结构体 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //TIM_CKD_DIV1,1分频,不分配;TIM_CKD_DIV2,2分频;TIM_CKD_DIV4,4分频----要求不高时,随意选择 TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //TIM_CounterMode_Up向上计数;TIM_CounterMode_Down向下计数;TIM_CounterMode_CenterAligned1等为中央对齐 TIM_TimeBaseInitStructure.TIM_Period=100-1;//自动重装器的值,在10K频率下记10K个数,即1s一个。---ARR的值 TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//预分频,对72M进行7200分频----PSC的值 TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器用到,通用定时器选0 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//结构体 //第三步:初始化输出比较单元,总共有四个,需要哪个通道(此处选PA0口,使用TIM_OC1Init),初始化哪个函数 TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值 //TIM_OCInitStructure.TIM_OCIdleState=;//高级定时器才会用到 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式,此处选择PWM模式1. //TIM_OCInitStructure.TIM_OCNIdleState=;//高级定时器 //TIM_OCInitStructure.TIM_OCNPolarity=;//高级定时器才会用到 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出比较极性,TIM_OCPolarity_High有效电平为高电平 //TIM_OCInitStructure.TIM_OutputNState=;//高级定时器才会用到 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//设置输出使能,TIM_OutputState_Enable使能 TIM_OCInitStructure.TIM_Pulse=50;//设置CCR寄存器的值。占空比为50%---占空比越高,高电平占比越大,LED越亮 TIM_OC1Init(TIM2, &TIM_OCInitStructure);//初始化OC1通道,输出波形,使之在GPIO口中输出波形 //第四步:初始化GPIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//选择复用推挽输出,使外设控制引脚(参照复用开漏/推挽输出图) GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //第五步:启动定时器 TIM_Cmd(TIM2,ENABLE); } //现象:有条件的可以买示波器观察PWM波形(矩形波,占空比50%)调节CCR,占空比越高,高电平占比越大,LED越亮 //单独更改CCR的值,在运行中更改CCR,使之亮度变化,变为呼吸灯 //更改占空比需要用的PWM_SetCompare1 void PWM_SetCompare1(uint16_t Compare) { TIM_SetCompare1(TIM2,Compare); }
PWM.h代码部分如下:
#ifndef __PWM_H #define __PWM_H void PWM_Init(void); void PWM_SetCompare1(uint16_t Compare); #endif
3.补充:
//补充:PWM处给出的函数重要的有两类:
//用结构体初始化输出比较单元函数:TIM_OC1Init
//更改占空比,实现LED呼吸现象需要用的函数:PWM_SetCompare1
//补充:TIM2的OC1选择使用某一个GPIO口时,需要查找引脚定义表
//如TIM2的引脚复用在PA0上,使用TIM2的OC1也就是CH1通道输出PWM时,
//只能在PA0引脚输出,不能在其他引脚输出.CH2只能在PA1输出...
//在引脚说明手册里,默认复用功能对应的引脚不能更改,
//但是,如果两个外设接在同一引脚,有重定义/重映射功能时,且需要同时使用时,可更改外设的引脚。
//如需要用TIM的CH1通道输出PWM.则能在PA0引脚输出,或在重映射改为PA15,因此需要初始化GPIO的PA0
//补充:ARR,PSC,CCR是分别用来计算频率,占空比和分辨率的(参考参数计算图)
//公式如下:PWM频率: Freq = CK_PSC / (PSC + 1) / (ARR + 1)
//PWM占空比: Duty = CCR / (ARR + 1)
//PWM分辨率: Reso = 1 / (ARR + 1)
//计算时,频率,占空比,分辨率是自己设置的,是已知的,因此,变为解方程组,(一般频率为1KHz,占空比50%,分辨率1%)
//解的ARR=100-1 PSC=720-1 CCR=50