Hi,欢迎来到中国嵌入式培训高端品牌 - 华清远见嵌入式学院<北京总部官网>,专注嵌入式工程师培养13年!
当前位置: > 嵌入式学院 > 嵌入式学习 > 讲师博文 > 从Cortex-A8平台学习PWM
从Cortex-A8平台学习PWM
时间:2016-07-04作者:华清远见

本篇适合对象:有单片机编程经验、C编程、正在学习芯片PWM波控制的人员。

平台: FS_S5PC100硬件开发板。

PWM波又叫脉冲宽度调制波,宽度其实就是高电平占整个周期的比例,也就是常说的占空比。

当高低电平各占到一半周期时,也就是占空比为50%,那么这就是标准方波了。

先举个例子,笔记本电脑散热风扇/智能车速度是通过什么控制的?

笔记本风扇的额定电机控制,额定电机的电流电压的变化范围很小,甚至要求电压稳定在额定电压在0.2V左右变化,所以不能改变电压电流,那么这个时候PWM就派上用场了。

而在开发板上,典型的PWM控制代表就是蜂鸣器了。

假如项目经理拿来一块陌生的开发板,要求控制蜂鸣器输出频率1000hz占空比40%的波形。顺便还晃了晃项目奖金。。。大概是这样的:

我们当然要拿下这笔巨款。

第一步要拿到电路原理图:

电路原理图上有硬件控制模块的电路原理,我们要找到和芯片引脚的联系:

图1Beep模块电路原理图

Buzzer(蜂鸣器)正极连接JP1(跳帽,相当于短路)然后和vdd相连。再看负极连接了一个NPN型的三极管的集电极c,基极b连接的PWMtout1正是我们要找的信息。只要PWMtout1输出一个高电平,c和e之间就能导通,这样蜂鸣器就有电流了。看来成功了一小步了。

那么蜂鸣器会发声么?初中物理知识:“声音是由振动产生的”。虽然蜂鸣器上有电流通过,但电流不变化,蜂鸣器就不振动,所以接下来我们要想办法使蜂鸣器电流变化。最简单的就是将PWMtout1作为输出脚,不停用delay延时改变输出值,也就是循环输出高低切换的电平。我们又知道软件计时只是一个粗略的计时方法,要达到项目经理要求的精确值就要换一种方案了,利用时钟精确计时,输出精准频率的PWM波。

第二步:查看芯片手册中相应引脚,根据引脚查看对应寄存器。

利用目录找到PWM模块说明:

图2 学会查看目录结构

在PWM定时器时钟树图中找到电路原理图中的PWMTOUT1(这图很重要这图很重要这图很重要)。

图3 时钟输出树形图

Step3:分析上图

图中显示芯片有5个寄存器,具有PWM功能的共3个:PWMTOUT0、PWMTOUT1、PWMTOUT2。 PWMTOUT1正是我们苦苦追寻的目标。

图中E点就是最终的时钟输出端,时钟开始从A点由PCLK输入。

绿色模块:

假设A点时钟为66Mhz,先经过绿色8位预分频器PRESCALER0到达B点,B点时钟是A点和prescaler0经过除法运算获得,具体运算如下:

搜索得到prescaler0的寄存器

图4 预分频器说明

先看第二个标记,表明8位预分频器的可设置值范围为1~255。

再看第一个标记,A、B点关系: B = A / (prescaler value + 1)。为什么要加 1?先假设没有加 1的情况下开发者将prescaler value 设置为0,也就是除数为0,而我们知道除数不能为0,除数为0时,CPU就会运算出错,这是不允许的,,但除数加1 就不会出现除数为0的情况了。

如果要求在B点得到2Mhz的频率,那么prescaler value 的值应该为31:

B = 66M / ( 31 + 1 ) = 2 Mhz

标记3正是下面要说明的内容:

蓝色模块:

这是二级分频器divider,作用和预分频器一样,将时钟作除法运算降低时钟。只不过这货只能作2的次方数的除法,也就是1,2,4,8,16和TCLK。

如果要求C点时钟为1Mhz,divider value 的值应该为2:

C = B / (divider value) = 2Mhz / 2 = 1 Mhz

黑色模块:

TCNTB1:计数计时器,这货也可以看着一个除法器,也就是说要在D地得到一个1000hz的时钟(D和E时钟大小相等),即 D = 1000 hz,那么:

D = C / (TCNTB1) = 1000 hz

==> TCNTB1 = C / D = 1 Mhz / 1000 hz = 1000 //计数寄存器的值为1000.

计数计时器的会把值给一个只读寄存器TCNTO1,C每来一个时钟,里面的值就会自减一。当里面的值为0时,表示一个D的时钟周期结束。

红色模块:

比较寄存器。TCNTO1的值在自减的过程中,会不停地把自己的值和TCMPB1比较,当两者的值相等时,D点电平开始翻转,即D点高变低或低变高。

图5 D点时钟翻转示意图

现在我们假设起始电平是低电平,我们要占空比为40%,也就是高电平占40%,换句话说就是低电平输出整个周期的60%时,电平要翻。而整个 周期TCNTO1自减1000次,那么自减600次,TCMPB1==TCTO1,也就是1000 - 600 = 400,此时电平翻转,然后D点会继续输出剩下的400个高电平:

图6 占空比控制示意图

如果起始电平是高电平,那TCMPB1的值是不一样的,应该是600。

离目标越来越近了,仿佛闻到一股浓烈的铜臭味。。。

以上是整个PWM波输出的原理图,接下来就开始看寄存器:(根据树形图一个一个地配置Step4)

图7 PWM引脚群查找

从文档中搜到GPD引脚群是控制PWM波的复用引脚。所以先要设置

GPD引脚为时钟功能。

引脚功能控制寄存器GPDCON:

图8 GPDCON寄存器

GPDCON寄存器控制着GPD引脚群引脚功能,其中将[7:4]位设置为0010时就是TOUT1功能。

GPDCON = (GPDCON & (~0xf0)) | (0x2<<4); //设置GPD_1为 T_OUT1功能。

PS:寄存器操作时不能影响其他位,因为其他的引脚可能处在某个功能下,直接赋值会改变其他位的功能,所以要用位操作来完成,只修改那些我们要设置的位。

预分频器(TCFG0)(没错还是上面的图):

图9 TCFG0寄存器

TCFG0 = ( TCFG0 & ~0xff ) | 31;

//初始化预分频值是prescal0的预分频值是32

二级分配器控制寄存器TCFG1:

图10 TCFG1寄存器

TCFG1 = (TCFG1 & ~0xf ) | (1<<4);

//初始化二级分配器(多路选通开关)的值是 1/2 与prescal0配合

//总的预分频的值是32 * 2 = 66

计数计时器TCNTB1:

TCNTB1 = 1000; //初始化计数值为1000

比较寄存器TCMPB1:

TCMPB1 = 600; //初始化比较寄存器的值为600;

和树形图相关的寄存器都配置ok啦,马上腰包要鼓了,想想都有点激动。。。

到这里可以说是万事具备,只欠东风了,这东风就是TCON,(用到时钟时,必须配置的家伙,他控制整个时钟的参数)。

时钟控制寄存器TCON:(这里直接看Timer1的控制位)

图11 Timer时钟控制寄存器TCON

[8]:Timer1的时钟开关;

TCON = ( TCON & (~(0xf<<8))) | (1<<11) | (1<<8); //开时钟

TCON = ( TCON & (~(0x1<<8))) ; //关时钟

[9]:TCTB1和TCMPB1在设置好后一定一定一定要手动更新一次,即写为1;

TCON = TCON | (1<<9) ;

// TCON寄存器手动更新 TCNTB1 TCMPB1

[10]:起始电平设置位,TCMPB1相同时,起始电平不一样,占空比不同。

TCON = TCON | (1<<10);

//起始电平为高电平。

[11]: 自动加载位, 但TCNTO1自减为0时,会立即自动将TCNB1中的数据重新加载到TCNTO1中,这样就可以源源不断的波形

图12 任务要求的PWM波

TCON = ( TCON & (~(0xf<<8))) | (1<<11);

总结下:

面对一个全新的开发平台,该如何去配置(电子产品更新飞快,在开发过程中简直是家常便饭),但基本思路差异不大:

Step1:查看相应的电路原理图;

Step2:查看芯片帮助手册;

Step3:分析该芯片时钟配置树形图;

Step4:根据树形图一个一个寄存器的配置;

Step5:时钟配置寄存器;

Step6:编程实现、测试、调试;

最后一步,你懂的。。。。。。经理有本事你别跑!


发表评论

全国咨询电话:400-611-6270,双休日及节假日请致电值班手机:15010390966

在线咨询: 曹老师QQ(3337544669), 徐老师QQ(1462495461), 刘老师 QQ(3108687497)

企业培训洽谈专线:010-82600901,院校合作洽谈专线:010-82600350,在线咨询:QQ(248856300)

Copyright 2004-2017 华清远见教育集团 版权所有 ,京ICP备16055225号,京公海网安备110108001117号