天嵌 ARM开发社区

 找回密码
 注册
查看: 3956|回复: 7

WinCE 下PWM编程

[复制链接]
billsmate333 发表于 2013-1-6 17:16:50 | 显示全部楼层 |阅读模式
本帖最后由 billsmate333 于 2013-1-6 17:19 编辑

开发平台:TQ2440,WinCE5.0
测试工具:泰克示波器TDS3012B
测试程序为TQ2440光盘提供的PWMTest工程;
问题描述:系统内核是光盘提供的内核,程序是光盘提供的程序。运行PWMTest程序以后从TOUT0口用示波器看到的方波频率与程序设定的不符;程序设定频率为800,示波器测的的频率为1067左右。为什么计算的频率会和实际输出不一致?
以下为我探究的过程:
PWM工作原理:
1S3C2440芯片的PWM是通过引脚TOUT0~TOUT3输出的,从原理图上看出PWMTest输出为TOUT0因为连接蜂鸣器的引脚是TOUT0
2)再设置定时器的输出时钟频率,它是以PCLK为基准,再除以用寄存器TCFG0配置的prescaler参数,和用寄存器TCFG1配置的divider参数。 有如下公式:
定时器输出时钟频率=PCLK ÷ (prescaler+1) ÷ divider
其中prescaler值由TCFG0决定,divider值由TCFG1决定,而prescaler只能取0~255之间的整数,divider只能取2、4、8和16。比如已知PCLK为50MHz,而我们想得到某一定时器的输出时钟频率为25kHz,则依据公式可以使prescaler等于249,divider等于8。有了这个输出时钟频率,理论上我们通过设置寄存器TCNTBn就可以得到任意与0.04毫秒(1÷25000×1000)成整数倍关系的时间间隔了。例如我们想要得到1秒钟的延时,则使TCNTBn为25000(1000÷0.04)即可。
3)然后设置脉冲的具体宽度,它的基本原理是通过寄存器TCNTBn来对寄存器TCNTn(内部寄存器)进行配置计数,TCNTn是递减的,如果减到零,则它又会重新装载TCNTBn里的数,重新开始计数,而寄存器TCMPBn作为比较寄存器与计数值进行比较,当TCNTn等于TCMPBn时,TOUTn输出的电平会翻转,而当TCNTn减为零时,电平会又翻转过来,就这样周而复始。因此这一步的关键是设置寄存器TCNTBnTCMPBn,前者可以确定一个计数周期的时间长度,而后者可以确定方波的占空比。由于s3c2440的定时器具有双缓存,因此可以在定时器运行的状态下,改变这两个寄存器的值,它会在下个周期开始有效。
以上内容来自与CSDN博客,
转化成例程中的代码即以下几句:
intfreq = 800;                           // 工作频率初值
#defineS3C2440_PCLK   50000000           // PCLK是MHz
#definePrescaler0 15                 // 预分频
#defineMUX0       8                  // 定时器分频值
#defineTCNTB0         (S3C2440_PCLK/128/freq)     // 工作频率
#defineTCMPB0         (TCNTB0>>1)            // 占空比,默认是%50

TCNTB0 = 50M/128/800
最终的频率经过一系列的消去就变成了F=freq,这样,freq的值其实就是最后的输出频率,理论上是这么计算;实际上运行就出现了上述问题;

修改Prescaler0和MUX0 的值为24与4这样MUX0×(Prescaler0+1)正好等于100,设定freq=1000,这样TCNTB0 = 50000000/100/freq = 500能整除。

这样得出的结果还是不行,设定1000得到的结果是1333

用驱动的控制字IOCTL_PWM_GET_FREQUENCY获取频率,得到的值也是1333.


细看驱动代码,发现在PWMDriver.c文件中的第29
#defineDEFAULT_S3C2440X_PCLK (405000000 / 8)
这个定义的时钟不是50M,大喜,以为问题就出现在这里,遂将PWMTest程序的时钟定义改为
#defineS3C2440_PCLK   (405000000 / 8)
结果还是有偏差,这时候得到的频率是1317Hz,不论是从驱动GetFrequency还是用示波器测量,结果都是1317.

现在处于崩溃之中,PWM驱动的代码看的迷迷糊糊的,驱动的流程基本上也了解了,计算方法也没有问题。为什么就是不一样。总是多出一些频率。800变成1067.1000变成1333,貌似每次都增加了33%似的。
等等!既然这个关系都知道了,那我设定频率的时候少设置33%,输出的频率不就正好是我要的频率了么?!!!

终极解决办法:将freq乘以0.75,然后再运行,得到的结果就是1001了,虽然还是有点误差,但是至少比1333强。

可是我还是不明白为什么,我哪里计算的有问题?这可是天嵌提供的例程啊!!例程输出的频率还有问题?驱动蜂鸣器的时候不可能听出差别来,蜂鸣器乌里哇啦的,忽悠忽悠小女生还有点用,但是我对频率的要求比较精确啊~,
大神们,救救我吧~

 楼主| billsmate333 发表于 2013-1-6 17:17:36 | 显示全部楼层
不知道我说的有什么不清楚的地方,请大婶不吝赐教~
亚瑟王 发表于 2013-1-7 11:16:59 | 显示全部楼层

回帖奖励 +1

1、频率的问题请以BSP包中实际使用的频率为准,(查看MPLL相关寄存器中的值计算出来的频率)
2、例程中的值是举例用的,没有实际按照频率来计算,所以有误差。
 楼主| billsmate333 发表于 2013-1-7 11:30:55 | 显示全部楼层
亚瑟王 发表于 2013-1-7 11:16
1、频率的问题请以BSP包中实际使用的频率为准,(查看MPLL相关寄存器中的值计算出来的频率)
2、例程中的值 ...

1. 你说的BSP包中实际使用的频率是不是就是指TQ2440配套光盘201006\TQ2440_CD\WinCE资源\WinCE源码\WinCE 5.0\BSP\TQ2440\Src\Drivers\PWMDriver\PWMDriver.c文件中定义的
#define DEFAULT_S3C2440X_PCLK (405000000 / 8)
如果是,我的应用程序里面的时钟也应该定义为这个值对吗?
2. 我怎么计算才能够得到正确的频率呢?难道说例程中的计算方式也有问题吗?正确的计算方法是什么呢?

谢谢大神!
亚瑟王 发表于 2013-1-7 19:05:30 | 显示全部楼层
billsmate333 发表于 2013-1-7 11:30
1. 你说的BSP包中实际使用的频率是不是就是指TQ2440配套光盘201006\TQ2440_CD\WinCE资源\WinCE源码\WinCE ...

实际看一下MPLLCOM、CLKDIVN的值,然后再根据这个值计算出来就准确了。
 楼主| billsmate333 发表于 2013-1-16 21:28:37 | 显示全部楼层
亚瑟王 发表于 2013-1-7 19:05
实际看一下MPLLCOM、CLKDIVN的值,然后再根据这个值计算出来就准确了。

大婶莫怪我,我实在是找不到MPLLCOM、CLKDIVN,求教了~
亚瑟王 发表于 2013-1-17 10:48:29 | 显示全部楼层
billsmate333 发表于 2013-1-16 21:28
大婶莫怪我,我实在是找不到MPLLCOM、CLKDIVN,求教了~

亲,你可以叫我大叔,但是不能叫我大婶。
这两个寄存器你可以在BSP包中搜索到的。然后读取值根据芯片手册讲的公式计算即可。
 楼主| billsmate333 发表于 2013-3-28 01:06:04 | 显示全部楼层
亚瑟王 发表于 2013-1-17 10:48
亲,你可以叫我大叔,但是不能叫我大婶。
这两个寄存器你可以在BSP包中搜索到的。然后读取值根据芯片手册 ...

谢谢啦,虽然我还是没有搜到~:lol,我已经不在乎这个频率了,我直接用暴力的方式校准输出频率。自己加一个比例系数。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-4-28 07:39 , Processed in 1.046875 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表