STM32 定时器产生PWM彻底应用

STM32 定时器产生PWM彻底应用
STM32 定时器产生PWM彻底应用

STM32 定时器产生PWM彻底应用

这次的任务是:用STM32的一个定时器在四个通道上产生四路频率可调占空比可调的PWM波。

看到这个题,我先看STM32的数据手册,把STM32的定时器手册看完就花了一天,但是看了一遍任然不知道所云,就看库函数,略有点理解,就想一哈把这个程序调出来,于是就花了一天多时间仿照网上别人的程序来写,花了一天多写出来调试,结果行不通,做了无用功,于是静下心来想想,还是一步一步的来。

我先用STM32的通用定时器用PWM模式产生四路相同占空比,不同频率的PWM波,配置如下:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM2时钟TIM_InternalClockConfig(TIM2);//使用内部时钟

TIM_BaseInitStructure.TIM_Prescaler=3; //设置TIM时钟频率除数的预分频值

TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择计数器模式TIM_BaseInitStructure.TIM_Period=1799;//设置下一个更新事件装入活动的自动重装载寄存器周期的值

TIM_BaseInitStructure.TIM_ClockDivision=0;//设置时钟分割

TIM_TimeBaseInit(TIM2,&TIM_BaseInitStructure);

//通道1

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择定时器模式

TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//选择输出比较状态TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Disable;//选择互补输出比较状态

TIM_OCInitStructure.TIM_Pulse=CCR1_Val;//设置了待装入捕获比较器的脉冲值

TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出极性

TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low;//设置互补输出极性TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;//选择空闲状态下得非工作状态

TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset;//选择互补空闲状态下得非工作状态

TIM_OC1Init(TIM2,&TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);

//通道2

TIM_OCInitStructure.TIM_Pulse=CCR2_Val;//设置了待装入捕获比较器的脉冲值

TIM_OC2Init(TIM2,&TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);

//通道3

TIM_OCInitStructure.TIM_Pulse=CCR3_Val;//设置了待装入捕获比较器的脉冲值

TIM_OC3Init(TIM2,&TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);

//通道4

TIM_OCInitStructure.TIM_Pulse=CCR4_Val;//设置了待装入捕获比较器的脉冲值

TIM_OC4Init(TIM2,&TIM_OCInitStructure);

TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);

TIM_Cmd(TIM2, ENABLE);

TIM_CtrlPWMOutputs(TIM2,ENABLE);

用pwm模式输出的频率和占空比是固定的,不可调,要想输出频率可调,占空比可调,必须得使用比较输出模式。这点资料是在STM32全国巡回研讨会上看到的,如图:

所以,接下来我就写了一个程序通过输出比较模式产生一路PWM波,这个波的频率和占空比都由自己确定,函数配置如下:

TIM_BaseInitStructure.TIM_Prescaler=3; //设置TIM时钟频率除数的预分频值(18M) TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择计数器模式TIM_BaseInitStructure.TIM_Period=1800;//设置下一个更新事件装入活动的自动重装载寄存器周期的值

TIM_BaseInitStructure.TIM_ClockDivision=0;//设置时钟分割

TIM_TimeBaseInit(TIM2,&TIM_BaseInitStructure);

//通道1

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;//选择定时器模式

TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//选择输出比较状态

TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Disable;//选择互补输出比较状态

TIM_OCInitStructure.TIM_Pulse=CCR1_Val1;//设置了待装入捕获比较器的脉冲值

TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出极性

TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low;//设置互补输出极性TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set;//选择空闲状态下得非工作状态

TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset;//选择互补空闲状态下得非工作状态

TIM_OC1Init(TIM2,&TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_ARRPreloadConfig(TIM2,ENABLE);

TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);

TIM_Cmd(TIM2,ENABLE);

}

void TIM2_IRQHandler(void)

{

TIM_ClearITPendingBit(TIM2,TIM_IT_CC1);

if(n==1)

{

n=0;

TIM_SetCompare1(TIM2,CCR1_Val2);

}

else

{

n=1;

TIM_SetCompare1(TIM2,CCR1_Val1);

}

}

通过改变比较寄存器(CCR1)中的值,改变PWM的占空比,在每次匹配中断中改变CCR1的值。上面程序实现的是产生一路频率为10K占空比为40%的PWM波。

有了上面的思想我就想产生四路不同频率不同占空比的PWM波,经过反复思考光配函数似乎不能实现,在网上去查了的,很多网友也说不能实现,有一个网友给了一个提示:软件模拟。刚开始没明白什么意思,于是还是自己继续配置库函数,在这个过程中一直有两个疑问:

每次中断中,CCR寄存器的值都在循环的增加,CCR的寄存器不可能是无限大吧?就算是无限大,计数器也不是无限大呀,他只能记到65535。初步确定使用匹配中断不行,我有想过同时使用溢出中断和匹配中断,但这样四路PWM波只能是固定的,频率和占空比不能调。大概说一下怎样用溢出中断和匹配中断实现四路固定的PWM波,把计数器寄存器(CNT)的值装最大周期的那个PWM波,当一次计数完成算一下三路小点周期数,在匹配中断中对应的设个变量,CCR就改变几次,溢出中断来了就再次给计数器装初值,同时四个比较寄存器从装初值,这样很麻烦,理论上可以实现,但我考虑到最终不能实现我的要求,就没有去验证。所以产生四路频率可调占空比可调,用一个定时器似乎不能实现,就一直卡到这里,我又在想飞哥说能实现,就肯定能实现,我又在网上找资料,还是没找到,只是有人题四路,软模拟,于是我就思考用软模拟实现,最后在一个师兄的指点下,确实用软件模拟一个中间比较寄存器能实现,思路大概是这样子的,首先让比较寄存

器装满,也就是最大值(65535),然后通过改变模拟比较寄存器的值,每次匹配中断只需把模拟比较寄存器的值去比较就行,具体方案看程序。

unsigned char Cnt[4]; //一个数组,这个数组的每个元素对应一个通道,用来判断装PWM 得高电平还是低电平数

unsigned int T[4];//周期数组

unsigned int R[4];//模拟的比较寄存器数组,一样的每个通道对应一个数组元素unsigned int Rh[4];//模拟的PWM高电平比较寄存器

unsigned int Rl[4]; //模拟的PWM低电平比较寄存器

unsigned char F[4];//占空比数组

unsigned int CCR1,CCR2,CCR3,CCR4;

void Init(void)

{

unsigned char i = 0;

for(i = 0; i < 4; i++)

{

Cnt[i]= 0;

T[i] = 0;

R[i] = 0;

Rh[i] = 0;

Rl[i] = 0;

F[i] = 0;

}

//t的范围为(0~65536)

T[0] = 450; //F=40K

T[1] = 600; //F=30K

T[2] = 900; //F=20K

T[3] = 1800; //F=10K

//F(占空比)的范围为(0~100)

F[0] = 40;

F[1] = 30;

F[2] = 20;

F[3] = 10;

for(i = 0; i < 4; i++)

{

Rh[i] = (T[i] * F[i]) / 100;

Rl[i] = T[i] - Rh[i];

}

R[0] = Rl[0];

R[1] = Rl[1];

R[2] = Rl[2];

R[3] = Rl[3];

CCR1 = R[0];

CCR2 = R[1];

CCR3 = R[2];

CCR4 = R[3];

}

对应的数组初始化

void RCC_Configuration(void)

{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,EN ABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,E NABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,EN ABLE);

}

时钟配置

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

//Key1 PA0 Key3 PA8

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

GPIO_Init(GPIOA,&GPIO_InitStructure);

//Key2 PC13

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

GPIO_Init(GPIOC,&GPIO_InitStructure);

//Key PD3

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;

GPIO_Init(GPIOD,&GPIO_InitStructure);

//TIM3 CH1 CH2

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

GPIO_Init(GPIOA,&GPIO_InitStructure);

//TIM3 CH3 CH4

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

GPIO_Init(GPIOB,&GPIO_InitStructure);

}

管脚配置

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM

NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);

#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

中断配置

void TIM_Configuration(void)

{

TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

TIM_InternalClockConfig(TIM3);

TIM_BaseInitStructure.TIM_Prescaler=3;//4分频,18M

TIM_BaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;

TIM_BaseInitStructure.TIM_Period=65535;

TIM_BaseInitStructure.TIM_ClockDivision=0;

TIM_BaseInitStructure.TIM_RepetitionCounter=0;

TIM_TimeBaseInit(TIM3,&TIM_BaseInitStructure);

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse=CCR1;

TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

TIM_OC1Init(TIM3,&TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);

TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_Pulse=CCR2;

TIM_OC2Init(TIM3,&TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);

TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_Pulse=CCR3;

TIM_OC3Init(TIM3,&TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Disable);

TIM_ClearITPendingBit(TIM3,TIM_IT_CC3);

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_Pulse=CCR4;

TIM_OC4Init(TIM3,&TIM_OCInitStructure);

TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Disable);

TIM_ClearITPendingBit(TIM3,TIM_IT_CC4);

TIM_Cmd(TIM3,ENABLE);

TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);

TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABL E);

}

void TIM3_IRQHandler(void)

{

if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)

{

TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);

Cnt[0]=(~Cnt[0])&0x01;

if(Cnt[0]==0x01)

R[0]+=Rl[0];

else

R[0] += Rh[0];

if(R[0]>65535)

R[0]=R[0]-65535;

CCR1=R[0];

TIM_SetCompare1(TIM3,CCR1);

}

if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)

{

TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);

Cnt[1]=(~Cnt[1])&0x01;

if(Cnt[1]==0x01)

R[1]+=Rl[1];

else

R[1] += Rh[1];

if(R[1]>65535)

R[1]=R[1]-65535;

CCR2=R[1];

TIM_SetCompare2(TIM3,CCR2);

}

if(TIM_GetITStatus(TIM3,TIM_IT_CC3)!=RESET) {

TIM_ClearITPendingBit(TIM3,TIM_IT_CC3);

Cnt[2]=(~Cnt[2])&0x01;

if(Cnt[2]==0x01)

R[2]+=Rl[2];

else

R[2] += Rh[2];

if(R[2]>65535)

R[2]=R[2]-65535;

CCR3=R[2];

TIM_SetCompare3(TIM3,CCR3);

}

if(TIM_GetITStatus(TIM3,TIM_IT_CC4)!=RESET) {

TIM_ClearITPendingBit(TIM3,TIM_IT_CC4);

Cnt[3] = (~Cnt[3])&0x01;

if(Cnt[3]==0x01)

R[3]+=Rl[3];

else

R[3] += Rh[3];

if(R[3]>65535)

R[3]=R[3]-65535;

CCR4=R[3];

TIM_SetCompare4(TIM3,CCR4);

}

}

中断函数

其余就是按键扫描函数,通过改变周期数组中的值和占空比寄存器中的值就能改变PWM 波的频率和占空比,当然按键可以设置为4个(一个按键对应一个通道),如果IO够用也可以设置8个,没两个按键对应一个通道分别改变频率和占空比。

推荐-stm32中定时器产生不同PWM的基本思路 精品

在stm32中利用定时器TIM调制PWM的几种方法: 说说我的学习经历:从开始接触到现在有好几个月了,但是学习还是比较的费劲,而且速度也比较的缓慢,当然相比之前还是有很大的进步,记得刚刚学习的时候,建工程都是大四学长手把手教的。废话不多说先来讲讲定时器的配置: STM32F10系列最少3个、做多有8个定时器,都是16位定时器,且相互之间是独立的,计数范围为0x0000-0xffff,最大计数值为65535.可以用于测量输入信号的脉冲长度或者产生输出波形(输出比较和PWM)分为通用定时器,高级定时器,以及看门狗定时器 下面主要讲通用定时器的配置问题: 以定时器TIM1为例:先进行函数的配置 void timer1_config() { TIM_TimeBaseInitTypDef TIM_TimeBaseStructure; //开定时器1外设时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM1,ENABLE); //计时50000次时间为50000/10M=500ms TIM_TimeBaseStructure.TIM_Period=50000 ; TIM_TimeBaseStructure.TIM_Prescaler = 720-1;//720分频 TIM_TimeBaseStructure.TIM_ClockDivision =0;//时钟分割为0; //计数模式向上计数 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure)//初始化TIM1 TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);//开启定时器中断 TIM_Cmd(TIM1,ENABLE); //使能定时器 } 关于时间的计算问题: 外设系统时钟的频率为72M,进行720分频以后,频率f=72M/720=100khz. 如果要定时0.1s 则计数值为10000,计算公式为:时间(t)=计数值(n)/频率(f).注意计数值n介于0到65535之间 有定时器则一定会有中断发生,所以要配置中断优先级,对于中断优先 级函数配置如下: V oid nvic_config() { NVIC_InitTypDef NVIC_InitStructure; //抢占优先级为1位,从优先级为3位 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1) ; NVIC_InitStructure.NVIC_IRQChannel=TIM1_IRQn; //定义定时器1为请求通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; //抢占式优先级为0 NVIC_InitStructure.NVIC_IRQChannelSubPriority=2; //从优先级为2 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能中断优先级 NVIC_Init(&NVIC_InitStructure); //初始化中断 } 对于优先级中的抢占式和从优先级做如下解释: 抢占式优先级:是可以抢占的中断,比如正在执行的优先级为10的中断,突然来了一个优

05_STM32F4通用定时器详细讲解精编版

STM32F4系列共有14个定时器,功能很强大。14个定时器分别为: 2个高级定时器:Timer1和Timer8 10个通用定时器:Timer2~timer5 和 timer9~timer14 2个基本定时器: timer6和timer7 本篇欲以通用定时器timer3为例,详细介绍定时器的各个方面,并对其PWM 功能做彻底的探讨。 Timer3是一个16位的定时器,有四个独立通道,分别对应着PA6 PA7 PB0 PB1 主要功能是:1输入捕获——测量脉冲长度。 2 输出波形——PWM 输出和单脉冲输出。 Timer3有4个时钟源: 1:内部时钟(CK_INT ),来自RCC 的TIMxCLK 2:外部时钟模式1:外部输入TI1FP1与TI2FP2 3:外部时钟模式2:外部触发输入TIMx_ETR ,仅适用于TIM2、TIM3、TIM4,TIM3,对应 着PD2引脚 4:内部触发输入:一个定时器触发另一个定时器。 时钟源可以通过TIMx_SMCR 相关位进行设置。这里我们使用内部时钟。 定时器挂在高速外设时钟APB1或低速外设时钟APB2上,时钟不超过内部高速时钟HCLK ,故当APBx_Prescaler 不为1时,定时器时钟为其2倍,当为1时,为了不超过HCLK ,定时器时钟等于HCLK 。 例如:我们一般配置系统时钟SYSCLK 为168MHz ,内部高速时钟 AHB=168Mhz ,APB1欲分频为4,(因为APB1最高时钟为42Mhz ),那么挂在APB1总线上的timer3时钟为84Mhz 。 《STM32F4xx 中文参考手册》的424~443页列出与通用定时器相关的寄存器一共20个, 以下列出与Timer3相关的寄存器及重要寄存器的简单介绍。 1 TIM3 控制寄存器 1 (TIM3_CR1) SYSCLK(最高 AHB_Prescaler APBx_Prescaler

STM32高级定时器日记之PWM

STM32高级定时器PWM实用程序 文章来源:本站原创作者:佚名 该文章讲述了STM32高级定时器PWM实用程序. 高级定时器与通用定时器比较类似,下面是一个TIM1 的PWM 程序,TIM1是STM32唯一的高级定时器。共有4个通道有死区有互补。 先是配置IO脚: GPIO_InitTypeDef GPIO_InitStructure; /* PA8设置为功能脚(PWM) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*PB13 设置为PWM的反极性输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure); /*开时钟PWM的与GPIO的*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*配置TIM1*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; void Tim1_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_DeInit(TIM1); //重设为缺省值 /*TIM1时钟配置*/ TIM_TimeBaseStructure.TIM_Prescaler = 4000; //预分频(时钟分 频)72M/4000=18K TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数TIM_TimeBaseStructure.TIM_Period = 144; //装载值18k/144=125hz 就是说向上加的144便满了 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置了时钟分割不

stm32高级定时器使用教程

STM32 高级定时器-PWM简单使用 2010-04-14 14:49:29| 分类:STM32 | 标签:|举报|字号大中小订阅高级定时器与通用定时器比较类似,下面是一个TIM1 的PWM 程序,TIM1是STM32唯一的高级定时器。共有4个通道有死区有互补。 先是配置IO脚: GPIO_InitTypeDef GPIO_InitStructure; /* PA8设置为功能脚(PWM) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*PB13 设置为PWM的反极性输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); /*开时钟PWM的与GPIO的*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*配置TIM1*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure;

STM32通用定时器_15-1-6

通用定时器的相关配置 1、预装入(Preload) 预装入实际上是设置TIMx_ARR寄存器有没有缓冲,根据“The auto-reload register is preloaded。Writing to or reading from the auto-reload register accesses the preload register。”可知: 1)如果预装入允许,则对自动重装寄存器的读写是对预装入寄存器的存取,自动重装寄存器的值在更新事件后更新; 2)如果预装入不允许,则对自动重装寄存器的读写是直接修改其本身,自动重装寄存器的值立刻更新; 3)设置方式:TIMx_CR1 →ARPE(1) 2、更新事件(UEV) 1)产生条件:①定时器溢出 ②TIMx_CR1→ UDIS = 0 ③或者:软件产生,TIMx_EGR→ UG = 1 2)更新事件产生后,所有寄存器都被“清零”,注意预分频器计数 器也被清零(但是预分频系数不变)。若在中心对称模式下或DIR=0(向上计数)则计数器被清零;若DIR=1(向下计数)则计数器取TIMx_ARR的值。 3)注意URS(复位为0)位的选择,如下:

如果是软件产生更新,则URS→1,这样就不会产生更新请求 和DMA请求。 4)更新标志位(UIF)根据URS的选择置位。 5)可以通过软件来失能更新事件: 3、计数器(Counter) 计数器由预分频器的输出时钟(CK_CNT)驱动,TIMx_CR1→CEN = 1 使能,注意:真正的计数使能信号(CNT_EN)在 CEN 置位后一个周期开始有效。 4、预分频器(Prescaler) 预分频器用来对时钟进行分频,分频值由TIMx_PSC决定,计数器的时钟频率CK_CNT= fCK_PSC / (PSC[15:0] + 1)。 根据“It can be changed on the fly as this control register

STM32的PWM精讲

STM32的PWM精讲 通过对TM1定时器进行控制,使之各通道输出插入死区的互补PWM输出,各通道输出频率均为17.57KHz。其中,通道1输出的占空比为50%,通道2输出的占空比为25%,通道3输出的占空比为12.5%。各通道互补输出为反相输出。 TM1定时器的通道1到4的输出分别对应PA.08、PA.09、PA.10和PA.11 引脚,而通道1到3的互补输出分别对应PB.13、PB.14和PB.15引脚,中止输入引脚为PB.12。将这些引脚分别接入示波器,在示波器上观查相应通道占空比的方波[12]。 配置好各通道后,编译运行工程;点击MDK的Debug菜单,点击Start/Stop Debug Session;通过示波器察看 PA.08、PA.09、PA.10、PB.13、PB.14、PB.15 的输出波形,其中PA.08和PB.13为第一通道和互补通道,PB.09和PB.14为第二通道和其互补通道,PB.10和PB.15为第三通道和其互补通道;第一通道显示占空比为50%,第二通道占空比为25%,第三通道占空比为12.5%。 第2章STM32处理器概述 STM32F103xx增强型系列产品中内置了多达3个同步的标准定时器。每个定时器都有一个16位的自动加载递加/递减计数器、一个16位的预分频器和4个独立的通道,每个通道都可用于输入捕获、输出比较、PWM和单脉冲模式输出,在最大的封装配置中可提供最多12个输入捕获、输出比较或PWM通道。它们还能通过定时器链接功能与高级控制定时器共同工作,提供同步或事件链接功能。 在调试模式下,计数器可以被冻结。任一个标准定时器都能用于产生PWM 输出。每个定时器都有独立的DMA请求机制。 2.4.2 高级控制定时器[22] 高级控制定时器(TM1)由一个16位的自动装载计数器组成,它由一个可编程预分频器驱动。它适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输出比较,PWM,嵌入死区时间的互补PWM等)。 使用定时器预分频器和RCC时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒至几个毫秒的调节。高级控制(TIM1)和通用(TMx)定时器是完全

stm32定时器的区别

STM32高级定时器、通用定时器(TIMx) 、基本定时器(TIM6和TIM7) 区别? 高级定时器TIM1和TIM8、通用定时器(TIM2,TIM3,TIM4,TIM5) 、基本定时器(TIM6和TIM7) 区别? TIM1和TIM8主要特性TIM1和TIM8定时器的功能包括: ● 16位向上、向下、向上/下自动装载计数器 ● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值 ● 多达4个独立通道:─ 输入捕获─ 输出比较─ PWM生成(边缘或中间对齐模式) ─ 单脉冲模式输出 ● 死区时间可编程的互补输出 ● 使用外部信号控制定时器和定时器互联的同步电路 ● 允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器 ● 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态 ● 如下事件发生时产生中断/DMA:─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) ─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) ─ 输入捕获─ 输出比较─ 刹车信号输入 ● 支持针对定位的增量(正交)编码器和霍尔传感器电路 ● 触发输入作为外部时钟或者按周期的电流管理 TIMx主要功能通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括: ● 16位向上、向下、向上/向下自动装载计数器 ● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值 ● 4个独立通道:─ 输入捕获─ 输出比较─ PWM生成(边缘或中间对齐模式) ─ 单脉冲模式输出 ● 使用外部信号控制定时器和定时器互连的同步电路 ● 如下事件发生时产生中断/DMA:─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) ─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) ─ 输入捕获─ 输出比较 ● 支持针对定位的增量(正交)编码器和霍尔传感器电路 ● 触发输入作为外部时钟或者按周期的电流管理 TIM6和TIM7的主要特性TIM6和TIM7定时器的主要功能包括: ● 16位自动重装载累加计数器 ● 16位可编程(可实时修改)预分频器,用于对输入的时钟按系数为1~65536之间的任意数值分频 ● 触发DAC的同步电路注:此项是TIM6/7独有功能. ● 在更新事件(计数器溢出)时产生中断/DMA请求 强大,高级定时器应该是用于电机控制方面的吧

STM32学习笔记通用定时器PWM输出

STM32学习笔记(5):通用定时器PWM输出 2011年3月30日TIMER输出PWM 1.TIMER输出PWM基本概念 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。一般用来控制步进电机的速度等等。 STM32的定时器除了TIM6和TIM7之外,其他的定时器都可以用来产生PWM输出,其中高级定时器TIM1和TIM8可以同时产生7路的PWM输出,而通用定时器也能同时产生4路的PWM输出。 1.1PWM输出模式 STM32的PWM输出有两种模式,模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。模式1和模式2的区别如下: 110:PWM模式1-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。 111:PWM模式2-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为有效电平,否则为无效电平。 由此看来,模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。 而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式,关于3种模式的具体资料,可以查看《STM32参考手册》的“14.3.9 PWM模式”一节,在此就不详细赘述了。 1.2PWM输出管脚 PWM的输出管脚是确定好的,具体的引脚功能可以查看《STM32参考手册》的“8.3.7 定时器复用功能重映射”一节。在此需要强调的是,不同的TIMx有分配不同的引脚,但是考虑到管脚复用功能,STM32提出了一个重映像的概念,就是说通过设置某一些相关的寄存器,来使得在其他非原始指定的管脚上也能输出PWM。但是这些重映像的管脚也是由参考手册给出的。比如

STM32 高级定时器-PWM简单使用

STM32 高级定时器-PWM简 单使用 高级定时器与通用定时器比较类似,下面是一个TIM1 的PWM 程序,TIM1是STM32唯一的高级定时器。共有4个通道有死区有互补。 先是配置IO脚: GPIO_InitTypeDef GPIO_InitStructure; /* PA8设置为功能脚(PWM) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*PB13 设置为PWM的反极性输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); /*开时钟PWM的与GPIO的*/ RCC_APB2PeriphClockCmd(RCC_A PB2Periph_TIM1,ENABLE); RCC_APB2PeriphClockCmd(RCC_A PB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_A PB2Periph_GPIOB, ENABLE); /*配置TIM1*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; void Tim1_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_DeInit(TIM1); //重设为缺省值 /*TIM1时钟配置*/ TIM_TimeBaseStructure.TIM_Prescaler = 4000; //预分频(时钟分频)72M/4000=18K TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseStructure.TIM_Period = 144; //装载值18k/144=125hz 就是说向上加的144便满了 TIM_TimeBaseStructure.TIM_ClockDivision =

STM32-PWM输出总结讲课讲稿

学习后发现stm32的定时器功能确实很强大,小总结一下方便以后使用的时候做参考。Stm32定时器一共分为三种:tim1和tim8是高级定时器,6和7是基本定时器,2—5是通用定时器。从名字就可以看得出来主要功能上的差异。今天我主要是用定时器做pwm输出,所以总结也主要是针对pwm方面的。 先大致说下通用和高级定时器的区别。通用的可以输出四路pwm信号互不影响。高级定时器可以输出三对互补pwm信号外加ch4通道,也就是一共七路。 所以这样算下来stm32一共可以生成4*5+7*2=30路pwm信号。接下来还有功能上的区别:通用定时器的pwm信号比较简单,就是普通的调节占空比调节频率(别的不常用到的没去深究);高级定时器的还带有互补输出功能,同时互补信号可以插入死区,也可以使能刹车功能,从这些看来高级定时器的pwm天生就是用来控制电机的。 Pwm输出最基本的调节就是频率和占空比。频率当然又和时钟信号扯上了关系。高级定时器是挂接到APB2上,而通用定时器是挂接到APB1上的。APB1和APB2的区别就要在于时钟频率不同。APB2最高频率允许72MH,而APB1最高频率为36MHZ。这样是不是通用定时器只最高36MHZ频率呢,不是的;通用定时器时钟信号完整的路线应该是下面这样的:AHB(72mhz)→APB1分频器(默认2)→APB1时钟信号(36mhz)→倍频器(*2倍)→通用定时器时钟信号(72mhz)。 在APB1和定时器中间的倍频器起到了巨大的作用,假如红色字体的“APB1分频器”假如不为1(默认是2),倍频器会自动将APB1时钟频率扩大2倍后作为定时器信号源,这个它内部自动控制的不用配置。设置这个倍频器的目的很简单就是在APB1是36mhz的情况下通用定时器的频率同样能达到72mhz。我用的库函数直接调用函数SystemInit(); 这个函数之后时钟配置好了:通用定时器和高级定时器的时钟现在都是72mhz(你也可以自己再配置一下RCC让他的频率更低,但是不能再高了)。定时器接下来还有一个分频寄存器:TIMX_PSC 经过他的分频后,才是定时器计数的频率。所以真正的时钟频率应该是72mhz/(TIMX_PSC-1),我们设为tim_frepuency下面还会用到。 stm32的时钟频率弄得确实是很饶人的,所以关键就是先要把思路理清楚。时钟的频率弄好了下面终于可以开说重点PWM了。当然还少不了频率:pwm主要就是控制频率和占空比的:这两个因素分别通过两个寄存器控制:TIMX_ARR和TIMX_CCRX。ARR寄存器就是自动重装寄存器,也就是计数器记到这个数以后清零再开始计,这样pwm的频率就是tim_frequency/(TIMX_ARR-1)。在计数时会不停的和CCRX寄存器中的数据进行比较,如果小于的话是高电平或者低电平,计数值大于CCRX值的话电平极性反相。所以这也就控制了占空比。 下面是定时器1的配置代码: GPIO_InitTypeDef GPIO_InitStructure2; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; //第一步:配置时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB|RCC_APB2Periph_TIM1 ,ENABLE); //第二步,配置goio口 /********TIM1_CH1 引脚配置*********/

stm32f103通用定时器pwm应用例程--蜂鸣器演奏乐曲

stm32f103通用定时器pwm应用例程--蜂鸣器演奏乐曲STM32F103通用定时器PWM应用例程:蜂鸣器演奏乐曲一(说明:本例程是将流明LM3SLib_Timer.pdf文档中的例程9及例程10(PWM应用: 蜂鸣器演奏乐曲),移植到STM32F103上。 二(流明LM3SLib_Timer.pdf例程9及例程10的拷贝: 例程9( Timer PWM应用:蜂鸣器发声 如图1.1所示,为EasyARM1138开发板上的蜂鸣器驱动电路。蜂鸣器类型是交流蜂鸣器,也称无源蜂鸣器,需要输入一列方波才能鸣响,发声频率等于驱动方波的频率。 图1.1 蜂鸣器驱动电路 程序清单1.9是Timer模块16位PWM模式的一个应用,可以驱动交流蜂鸣器发声,运行后蜂鸣器以不同的频率叫两声。其中"buzzer.h"和"buzzer.c"是蜂鸣器的驱动程序,仅有3个驱动函数,用起来很简捷。

程序清单1.9 Timer PWM应用:蜂鸣器发声 文件:main.c #include "systemInit.h" #include "buzzer.h" // 主函数(程序入口) int main(void) { jtagWait(); // 防止JTAG失效,重要~ clockInit(); // 时钟初始化:晶振,6MHz buzzerInit(); // 蜂鸣器初始化 buzzerSound(1500); // 蜂鸣器发出1500Hz声音 SysCtlDelay(400* (TheSysClock / 3000)); // 延时约400ms buzzerSound(2000); // 蜂鸣器发出2000Hz声音 SysCtlDelay(800* (TheSysClock / 3000)); // 延时约800ms buzzerQuiet( ); // 蜂鸣器静音 for (;;) { } } 文件:buzzer.h #ifndef __BUZZER_H__ #define __BUZZER_H__ // 蜂鸣器初始化 extern void buzzerInit(void); // 蜂鸣器发出指定频率的声音 extern void buzzerSound(unsigned short usFreq); // 蜂鸣器停止发声

STM32入门篇之通用定时器彻底研究

STM32入门篇之通用定时器彻底研究 STM32的定时器功能很强大,学习起来也很费劲儿,本人在这卡了5天才算看明白。写下下面的文字送给后来者,希望能带给你点启发。在此声明,本人也是刚入门,接触STM32不足10天,所以有失误的地方请以手册为准,欢迎大家拍砖。 其实手册讲的还是挺全面的,只是无奈TIMER的功能太复杂,所以显得手册很难懂,我就是通过这样看手册:while(!SUCCESS){看手册…}才搞明白的!所以接下来我以手册的顺序为主线,增加一些自己的理解,并通过11个例程对TIMER 做个剖析。实验环境是STM103V100的实验板,MDK3.2 +Library2.东西都不怎么新,凑合用…… TIMER主要是由三部分组成: 1、时基单元。 2、输入捕获。 3、输出比较。 还有两种模式控制功能:从模式控制和主模式控制。 一、框图 让我们看下手册,一开始是定时器的框图,这里面几乎包含了所有定时器的信息,您要是能看明白,那么接下来就不用再看别的了… 为了方便的看图,我对里面出现的名词和符号做个注解: TIMx_ETR:TIMER外部触发引脚ETR:外部触发输入 ETRP:分频后的外部触发输入ETRF:滤波后的外部触发输入 ITRx:内部触发x(由另外的定时器触发) TI1F_ED:TI1的边沿检测器。 TI1FP1/2:滤波后定时器1/2的输入 TRGI:触发输入TRGO:触发输出 CK_PSC:应该叫分频器时钟输入 CK_CNT:定时器时钟。(定时周期的计算就靠它) TIMx_CHx:TIMER的输入脚TIx:应该叫做定时器输入信号x

ICx:输入比较x ICxPS:分频后的ICx OCx:输出捕获x OCxREF:输出参考信号 关于框图还有以下几点要注意: 1、影子寄存器。 有阴影的寄存器,表示在物理上这个寄存器对应2个寄存器,一个是程序员可以写入或读出的寄存器,称为preload register(预装 载寄存器),另一个是程序员看不见的、但在操作中真正起作用的寄存 器,称为shadow register(影子寄存器);(详细请参考版主博客 https://www.360docs.net/doc/4218141631.html,/STM32/401461/message.aspx) 2、输入滤波机制 在ETR何TIx输入端有个输入滤波器,它的作用是以采样频率 Fdts来采样N次进行滤波的。(具体也请参考版主博客 https://www.360docs.net/doc/4218141631.html,/STM32/263170/message.aspx ) 3、输入引脚和输出引脚是相同的。 二、时基单元 时基单元有三个部分:CNT、PSC、ARR。CNT的计数方式分三种:向上、向下、中央对齐。通俗的说就是0—ARR、ARR—0、0—(ARR-1)—ARR—1. 三、时钟源的选择 这个是难点之一。从手册上我们看到共有三种时钟源: 1、内部时钟。 也就是选择CK_INT做时钟,这个简单,但是有一点要注意,定 时器的时钟不是直接来自APB1或APB2,而是来自于输入为

STM32 定时器 PWM

STM32+按键调控PWM输出+串口输出占空比(2010-09-20 21:59) 分类:STM32学习笔记

TIM.c

main.c

#include "stm32f10x.h" TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; uint16_t CCR1_V al = 250; uint16_t CCR2_V al = 500; uint16_t CCR3_V al = 750; uint16_t CCR4_V al = 0; uint16_t PrescalerV alue = 0; void RCC_Configuration(void); //时钟配置 void GPIO_Configuration(void); //管脚配置 void Delay (__IO uint32_t nCount); //延时函数 int main(void) { RCC_Configuration(); GPIO_Configuration(); PrescalerV alue = (uint16_t) (SystemCoreClock / 24000000) - 1; TIM_TimeBaseStructure.TIM_Period = 1000; //周期 TIM_TimeBaseStructure.TIM_Prescaler = PrescalerV alue; //分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始TIM3 /*************************** 通道1 ********************************/ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //PWM功能使能TIM_OCInitStructure.TIM_Pulse = CCR1_V al; //写比较值(占空比TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //置高 TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); /****************************** 通道2 ******************************/ /* PWM1 Mode configuration: Channel2 */ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR2_V al; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); /******************************* 通道3 *********************************/ /* PWM1 Mode configuration: Channel3 */

STM32通用定时器

STM32通用定时器 一、定时器的基础知识 三种STM32定时器区别 通用定时器功能特点描述: STM3 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定时器功能特点包括: 位于低速的APB1总线上(APB1) 16 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值。 4 个独立通道(TIMx_CH1~4),这些通道可以用来作为: ①输入捕获 ②输出比较 ③ PWM 生成(边缘或中间对齐模式) ④单脉冲模式输出 可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。 如下事件发生时产生中断/DMA(6个独立的IRQ/DMA请求生成器): ①更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) ②触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) ③输入捕获 ④输出比较 ⑤支持针对定位的增量(正交)编码器和霍尔传感器电路 ⑥触发输入作为外部时钟或者按周期的电流管理 STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。 STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。 定时器框图:

倍频得到),外部时钟引脚,可以通过查看数据手册。也可以是TIMx_CHn,此时主要是实现捕获功能; 框图中间的时基单元 框图下面左右两部分分别是捕获输入模式和比较输出模式的框图,两者用的是同一引脚,不能同时使用。

基于寄存器操作的STM32高级定时器TIM1的四路PWM输出程序讲解

经过一天的努力,终于把stm32 tim1的四路pwm输出搞了出来,为了使大家快速的用起tim1,打算写这篇文档与大家分享。 stm32 tim1功能丰富。针对pwm输出与tim2只有细小的差别,之前在网上找了一些网友的程序,发现大部分都是基于库文件写的,不能对tim1的pwm输出有深层次的理解,个人认为一个合格的程序员,想要最大程度的用好一个片子的话还是要针对寄存器直接操作,完全了解定时器的运行过程,可以对片子的结构有一定的了解。 高级控制定时器(TIM1 和TIM8) 由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动。它适合多种用途,包含测量输入信号的脉冲宽度( 输入捕获) ,或者产生输出波形( 输出比较、PWM、嵌入死区时间的互补PWM等)。使用定时器预分频器和RCC 时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调节。 高级控制定时器(TIM1 和TIM8) 和通用定时器(TIMx) 是完全独立的,它们不共享任何资源。 请读者仔细阅读一下信息: 脉冲宽度调制模式可以产生一个由TIMx_ARR 寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。在TIMx_CCMRx寄存器中的OCxM 位写入’110’(PWM 模式1) 或’111’(PWM 模式2) ,能够独立地设置每个OCx 输出通道产生一路PWM。必须通过设置TIMx_CCMRx寄存器的OCxPE位使能相应的预装载寄存器,最后还要设置TIMx_CR1 寄存器的ARPE 位,( 在向上计数或中心对称模式中)使能自动重装载的预装载寄存器。仅当发生一个更新事件的时候,预装载寄存器才能被传送到影子寄存器,因此在计数器开始计数之前,必须通过设置TIMx_EGR 寄存器中的UG位来初始化所有的寄存器。OCx 的极性可以通过软件在TIMx_CCER 寄存器中的CCxP位设置,它可以设置为高电平有效或低电平有效。OCx 的输出使能通过(TIMx_CCER 和TIMx_BDTR寄存器中)CCxE 、CCxNE、MOE、OSSI和OSSR 位的组合控制。详见TIMx_CCER寄存器的描述。在PWM模式(模式1或模式2) 下,TIMx_CNT 和TIMx_CCRx始终在进行比较,( 依据计数器的计数方向)以确定是否符合TIMx_CCRx≤TIMx_CNT 或者TIMx_CNT ≤TIMx_CCRx。根据TIMx_CR1 寄存器中CMS位的状态,定时器能够产生边沿对齐的PWM信号或中央对齐的PWM信号。 根据以上信息的提示,我们可以归纳出寄存器操作的步骤: (1)使能相应的定时器时钟线。 (2)配置tim1四路pwm输出引脚为复用功能输出。 (3)配置tim1的分频比和计数装载值。 (4)配置相应通道的pwm输出模式和使能预装载。 (5)打开自动重装载预装载允许位。 (6)根据需要选择向上或者是向下计数模式。 (7)打开相应通道的输出使能。 (8)配置各通道的占空比。 (9)开启开启OC和OCN。 (10)最后使能定时器1. 关于分频比和计数装载值的选择: Tim1的最大时钟频率为72M,假设我们想得到一个频率为4KHZ,占空比0~100%步进为1的pwm。根据计数器的时钟频率(CK_CNT) 等于f CK_PSC/( PSC[15:0]+1)。因为占空比0~100%步进为1,所以我们把计数值设为100.比较值可以设为0~100之间,实现占空比的调节。计数器的时钟频率(CK_CNT)应为4KHZ X 100=400KHZ。所以PSC = 179。ARR=100。有不明白的请看手册。

STM32 定时器与 PWM 快速使用入门

STM32 定时器与 PWM 快速使用入门 要求:在万利的开发板 EK-STM32F 上产生周期为1秒,占空比分别为 50% 10%的 PWM 并且点亮板上的 LD1,LD2 灯闪烁。 做法很简单。 STM32的PWM是由定时器来产生的。 可以看出。定时器3的通道1至4在GPIO端口的映像。如果是完全映射。 各通道的连接引脚如下: CH1=PC6, CH2=PC7, CH3=PC8, CH4=PC9 这样,刚好与板上的LD1,LD2灯符合,因为LD1连接到PC7,LD2连接到PC6引脚。 关于PWM一些知识. STM32的TIMx 是 TIMx_ARR 寄存器确定频率(周期)、由TIMx_CCRx 寄存器确定占空比的信号。 使用定时器3。而TIM2、3、4的时钟源是 APB1 即是 PCLK1 ( APB1 对应 PCLK1 ) PCLK1 = APB1 = HCLK/2 = SYSCLK/2 = 36MHZ (36,000,000 HZ) 但是注意:倍频器会自动倍2,即是【72MHZ】! 代码如下: void STM32_PWM_GPIO_Configuration(void) { // 11:完全映像 STM32_Afio_Regs->mapr.bit.TIM3_REMAP=3; // LD1 =P7 LD2=PC6 /*GPIOA Configuration: ( PC6 PC7 ) TIM3 channel 1 and 2 as alternate function push -pull */ STM32_Gpioc_Regs-&https://www.360docs.net/doc/4218141631.html,F6=Output_Af_push_pull; // PC.06 复用功能推挽输出模式 STM32_Gpioc_Regs->crl.bit.MODE6=Output_Mode_50mhz; // PC.06 输出模式,最大速度50MHz STM32_Gpioc_Regs-&https://www.360docs.net/doc/4218141631.html,F7=Output_Af_push_pull; // PC.07 复用功能推挽输出模式 STM32_Gpioc_Regs->crl.bit.MODE7=Output_Mode_50mhz; // PC.07 输出模式,最大速度50MHz

相关文档
最新文档