1、实验目的
PWM编程;
测试波形;逻辑分析仪
2、实验器材
反客核心板和例程,
逻辑分析仪
dap下载器;
3、原理和注意事项
PWM波形,这里需要是高电平的时间。
注意定时器9和定时器1的频率是168Mhz。看时钟线。看正点原子的教程
可能配置和正点原子不太一样,看下设置一些系数。
实际,用逻辑分析仪,测到我们的频率和原子的例子有些出入,弄清楚问题就好了。
正点的例子是定时器14。
结论,
**
定时器9和定时器1的频率的计算:
**
我们的定时器9和定时器1的频率是168Mhz,从这两个定时器产生的PWM的PWM的频率,是分频之后的,比如我们是168分频,那么就是168M/168=1M hz.。。然后我们再在这个基础上,分一次,得到实际的PWM的频率。比我我们分1000次,那么就是1Mhz/1000=1000hz。所以实际我们如果要确定PWM的频率,那么固定前面的分配系数是168-1,将后面的分配系数作为变量,那么就能改变这个变量,得到我们想要的pwm的频率。
定时器1和定时器9的占空比的计算。
改变这个函数的第二个参数,就可以改变占空比了。比如是1000hz频率,那么计算100次,占空比就是百分之10;计算300次,就是百分之30,最大计算到1000次。
第几个通道的PWM,就是setcompare1改为compare2…
初始电平是高电平,然后从0—arr是高电平,arr到最大值是0.
配合结构体成员TIM_OCInitTypeDef.TIM_OCPolarity来一起使用。
现在假定TIM_OCInitTypeDef.TIM_OCPolarity = TIM_OCPolarity_High,则起始波形为高电位。
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位。
代码:
pwm.h
#ifndef __PWM_H
#define __PWM_H
#include "stm32f4xx.h"
void TIM9_PWM_Init(u32 arr,u32 psc);//E5--ch2
void TIM1_PWM_Init(u32 arr,u32 psc);//E9 11 13 14
#endif //__DELAY_H
pwm.c
#include "pwm.h"
#include "led.h"
//TIM9 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
//注意,定时器9的频率,经过测量和分析,是168M,所以main函数中500-1,84-1,得到频率应该是
//168/84=2M ,再除以500,等于4Khz,注意,要用
void TIM9_PWM_Init(u32 arr,u32 psc)
{
//此部分需手动修改IO口设置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE); //TIM9时钟使能 168M=84M*2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //使能PORTe时钟 GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1); //========GPIOE5复用为定时器14
GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_TIM9); //e5复用为定时器14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //GPIOE5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化PE5
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM9,&TIM_TimeBaseStructure);//初始化定时器14
//初始化TIM9 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //*********************************输出极性:初始高电平,小于arr,则是高电平
TIM_OC1Init(TIM9, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable); //使能TIM14在CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM9,ENABLE);//ARPE使能
TIM_Cmd(TIM9, ENABLE); //使能TIM9
TIM_CtrlPWMOutputs(TIM9,ENABLE);
}
//TIM9 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数--------------PE9 11 13 14
void TIM1_PWM_Init(u32 arr,u32 psc)//E9 11 13 14
{
//此部分需手动修改IO口设置
int ccr1=500,ccr2=500,ccr3=500,ccr4=500;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//注意,定时器1用APB2时钟线
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //=====TIM10时钟使能
//在那个引脚产生PWM?设定对应PWM口的时钟打开,这里用B8
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //======使能PORTB时钟
//引脚复用A---6===GPIO_AF_TIM13
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1); //========GPIOE5复用为定时器14
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1); //========GPIOE5复用为定时器14
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1); //========GPIOE5复用为定时器14
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1); //========GPIOE5复用为定时器14
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13|GPIO_Pin_14; //=======GPIOE5 E6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOE,&GPIO_InitStructure); //==============初始化PF9
//Timer clock = sysclock /(TIM_Prescaler+1) = 168M
TIM_TimeBaseStructure.TIM_Prescaler=psc; //==============定时器分频0000
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
//Period = (TIM counter clock / TIM output clock) - 1 = 20K
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//=======初始化定时器1
//初始化TIM9 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//输出同相,TIM_OCNPolarity_High时输出反相
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//初始高电平
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
// TIM_OC1Init(TIM1, &TIM_OCInitStructure); //=========根据T指定的参数初始化外设TIM1 4OC1
TIM_OCInitStructure.TIM_Pulse = ccr1; //设置待装入捕获比较寄存器的脉冲值
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //=============根据指定的参数初始化外设 TIMx
//TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //==========CH1 预装载使能
// TIM_ARRPreloadConfig(TIM13,ENABLE);//==============ARPE使能
TIM_OCInitStructure.TIM_Pulse = ccr2; //设置待装入捕获比较寄存器的脉冲值
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //=============根据指定的参数初始化外设 TIMx
TIM_OCInitStructure.TIM_Pulse = ccr3; //设置待装入捕获比较寄存器的脉冲值
TIM_OC3Init(TIM1, &TIM_OCInitStructure); //=============根据指定的参数初始化外设 TIMx
TIM_OCInitStructure.TIM_Pulse = ccr4; //设置待装入捕获比较寄存器的脉冲值
TIM_OC4Init(TIM1, &TIM_OCInitStructure); //=============根据指定的参数初始化外设 TIMx
TIM_Cmd(TIM1, ENABLE); //==============使能TIM1
TIM_CtrlPWMOutputs(TIM1,ENABLE);
}
main.c
#include "stm32f4xx.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include "beep.h"
#include "exti.h"
#include "timer.h"
#include "pwm.h"
//第一个,修改头文件led.h,配置硬件的IO对应
//修改led.c文件
int main(void)
{
u8 key_flag = 0; //按键标志
u8 i=0;
int led0val=0;
int led1val=0;
Delay_Init(); //延时函数初始化
LED_Init(); //LED初始化
BEEP_Init(); //LED初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
EXTIX_Init();
TIM3_Int_Init(5000-1,8400-1);
TIM4_Int_Init(5000-1,8400-1);
TIM9_PWM_Init(1000-1,168-1);//E5--ch1---------PWM波形的频率是168M/168再除以1000,1M/1000=1000hz
TIM1_PWM_Init(1000-1,168-1);//E9--
TIM_Cmd(TIM9, ENABLE); //使能TIM9的PWM1/
TIM_Cmd(TIM1, ENABLE); //使能TIM9的PWM
while (1)
{
// for(i=0;i<10;i++)
// {
// LED1_ON;LED2_ON;LED3_ON;LED4_ON;BEEP_ON;
// Delay_ms(1000);
// LED1_OFF;LED2_OFF;LED3_ON;LED4_ON;BEEP_OFF;
// Delay_ms(1000);
// }
TIM_SetCompare1(TIM9,100);
Delay_ms(10);
TIM_SetCompare1(TIM9,300);
Delay_ms(10);
TIM_SetCompare1(TIM9,600);
Delay_ms(10);
TIM_SetCompare1(TIM9,850);
Delay_ms(10);
TIM_SetCompare1(TIM1,100);
Delay_ms(10);
TIM_SetCompare1(TIM1,300);
Delay_ms(10);
TIM_SetCompare1(TIM1,600);
Delay_ms(10);
TIM_SetCompare1(TIM1,850);
Delay_ms(10);
// TIM_SetCompare1(TIM9,led0val); //修改比较值,修改占空比 pe5---T9CH1
// led0val++;
// if(led0val==400)//最大是499
// led0val=0;
//
// TIM_SetCompare1(TIM1,led1val); //修改比较值,修改占空比
// TIM_SetCompare2(TIM1,led1val); //修改比较值,修改占空比
// TIM_SetCompare3(TIM1,led1val); //修改比较值,修改占空比
// TIM_SetCompare4(TIM1,led1val); //修改比较值,修改占空比
// led1val++;
// if(led1val==400)//最大是499
// led1val=0;
// Delay_ms(10);
}
}