您的位置:首页 > 其它

rip动态路由以及三层交换实现DHCP服务实验【笔记|实验】

2014-04-19 00:21 736 查看
14.1 PWM 简介
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。

STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4 路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!

14.2 硬件设计
本实验用到的硬件资源有:
1) 指示灯 DS0
2) 定时器 TIM3
这两个前面都有介绍,但是我们这里用到了TIM3的部分重映射功能,把TIM3_CH2直接映射到了 PB5 上,而通过前面的学习,我们知道 PB5 和 DS0 是直接连接的,所以电路上并没有任何变化。

我们要利用TIM3的CH2输出PWM来控制 DS0 的亮度,但是TIM3_CH2 默认是接在PA7上面的,而我们的 DS0 接在 PB5 上面,如果普通 MCU,可能就只能用飞线把 PA7 飞到 PB5 上来实现了,不过,我们用的是 STM32,它比较高级,可以通过重映射功能,把 TIM3_CH2 映射到PB5 上。
(也就是说,TIM3的CH2通道是与PA7引脚连通的,而灯DS0是与PB5引脚连通的。现在希望通过PA7引脚的输出脉宽 带动 PB5引脚的灯DSO的亮度,所以应当把PA7和PB5这两个引脚连接在一起,而在stm32中,可采用重映射的方法,从而使PB5也能够输出PWM(PA7的PWM转给PB5))

//tim.h
void TIM3_PWM_Configuration(u16 arr,u16 psc);
//tim.c
//TIM3 PWM 部分初始化
//PWM 输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Configuration(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |

RCC_APB2Periph_AFIO,ENABLE);	//①使能 GPIO 和 AFIO 复用功能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  //①使能定时器 3 时

钟

//改变指定管脚的映射
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3 ,ENABLE); //②重映射

TIM3_CH2->PB5

//设置该引脚为复用输出功能,输出 TIM3 CH2 的 PWM 脉冲波形       GPIOB.5
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);

//初始化 TIM3
TIM_DeInit (TIM3);
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:
//TDTS = Tck_tim ,TIM_CKD_DIV1 == 0
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = arr;//设置在自动重装载周期值,计数器记到 arr 归零(计数的数值范围是0~65535)
TIM_TimeBaseInitStruct.TIM_Prescaler = psc;	 //设置预分频值,定时器时钟APB1除以psc(也就是分频psc)计数脉冲的频率是72M/psc HZ(psc = 0则不分频,则PWM 频率=72MHz)
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct); //③初始化 TIMx

//初始化 TIM3 Channel2 PWM 模式
TIM_OCInitStruct.TIM_OCMode = 	TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
//输出比较极性的指的是你在比较匹配之后输出口输出的极性。也就是设置比较输出的有效电平。你可以设置为高电平有效或者低电平有效。
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高,即高电平所占占空比为有效电平
TIM_OC2Init(TIM3,&TIM_OCInitStruct);  //④初始化外设 TIM3 OC2

TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能预装载寄存器

TIM_Cmd(TIM3,ENABLE); //⑤使能 TIM3

}
//main.c
int main(void)
{
u16 led0pwmval=0;
u8 dir = 1;
MySysTick_Init();
TIM3_PWM_Configuration(899,0); //不分频,所以频率为72M,则PWM 频率=72000/900=8Khz

while(1)
{
MyDelay_ms(10);
if(dir)
++led0pwmval;
else
--led0pwmval;

if(led0pwmval>300)
dir = 0;
if(led0pwmval == 0)
dir = 1;
//设置 TIMx 捕获比较2寄存器值
TIM_SetCompare2(TIM3,led0pwmval);
}

}

/*
这里,我们从死循环函数可以看出,我们将led0pwmval这个值设置为PWM比较值,也就
是通过 led0pwmval 来控制 PWM 的占空比,然后控制 led0pwmval 的值从 0 变到 300,然后又
从 300变到0,如此循环,因此DS0 的亮度也会跟着从暗变到亮,然后又从亮变到暗。至于这
里的值,我们为什么取300,是因为PWM的输出占空比达到这个值的时候,我们的 LED 亮度
变化就不大了(虽然最大值可以设置到899),因此设计过大的值在这里是没必要的。
*/
注:PWM占空比 = ccr / arr;
注:PWM模式的选择决定OC1REF的极性,例如当选择PWM1模式时,OC1REF信号是"正极性";而选择PWM2模式时,OC1REF信号是"负极性"。输出极性控制位决定OC1与OC1REF的关系,TIM1_OCInitStructure.TIM_OCPolarity就是配置这个控制位,选择TIM_OCPolarity_Low时表示把OC1REF反相后作为OC1输出,选择TIM_OCPolarity_High时表示不反相OC1REF,直接输出到OC1。
所以如果此程序极性选择High,则由刚开始的很多高电平就变成了很多低电平了。(就是两者的图像相反)
理解:

本程序中,设置了PWM2的模式,并且输出极性为高电平有效,并且ccr = 0-300,arr = 899.
程序刚开始时,ccr=led0pwmval=1,而计数器int=0,此时,由于设置了PWM2模式,int>ccr时输出有效电平,所以此时为无效电平。接下来,int递增一直到899,所以程序刚进来时会有一个低电平到高电平的跳变。然后会有一个比较大的高电平占空比。由于我们的DS0是低电平亮,此时的低电平占空比很小,几乎为0,所以此时的灯几乎不亮。随着ccr=led0pwmval的递增(0-300),高电平的占空比会减小(最小的占空比约为300/900 = 30%),所以灯会变亮・・・・
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: