打印

pwm的周期以及占空比设置 求助...

[复制链接]
16913|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
fangfei036|  楼主 | 2012-5-23 14:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
PWM, os, hz, dc, kHz
各位前辈好,我又来叨扰大伙了,我看了许多利用ad反馈调节pwm的资料,可是当我设定pwm周期和占空比的时候发现又有问题了,麻烦您能不能告知一二
下面这两条公式不知道我理解的对不对,总觉得我理解错了
1、PWM 周期 = [(PR2) + 1] • 4 • TOSC • (TMR2 预分频比),用时间单位表示
2、PWM 占空比 = (DCxB9 CxB0 ) • Tosc • (TMR2 预分频比),用时间单位表示


问题1、如果我设计的频率22kHZ的话(TOSC为4Mhz,预分频为1),那么周期设定PR2的值就应该是1/22khz=(PR2+1)*1 則;PR2=44.4=44;则PR2初值为44;



问题2、設定需要占空比為50%(预分频为1/16),則,0.5=(DCxB9 CxB0 )*4*(1/16) 则:(DCxB9 CxB0 )=2;那么CCPR1H:CCPR1L的值分别是什么,感觉这个2肯定是我算的方法不对了,请前辈们指点指点,占空比的初值是怎么算的,最好能举一列子,谢谢了

相关帖子

沙发
fangfei036|  楼主 | 2012-5-23 14:38 | 只看该作者
PWM周期=[(PR2)+1]*4*TOSC*(TMR2预分频比)
       =(255+1)*4*(1/4000000)*16 s = 4.096 ms
                45ms=(x+1)*(1/4000000)*16=
PWM占空比=(DCxB9:DCxB0)*Tosc*(TMR2预分频比)
  =1024*(1/4000000)*16 s =  4.096 ms
注意:如果PWM占空比值大于PWM周期,CCPx 引脚将
      不会被清零,这时占空比将达到100%;


原来真的很错...

使用特权

评论回复
板凳
Tinnal| | 2012-5-23 15:21 | 只看该作者
什么乱七八糟的的公式。从哪弄回来的?
占空比是一个比值,高电平和低电平脉宽的比值,怎么可能是用时间作单位呢。高中物理量纲没学好。
PWM周期和PWM占空比是两个独立的东西,任何PWM周期下可以设定任意的PWM占空比。

使用特权

评论回复
地板
Tinnal| | 2012-5-23 15:23 | 只看该作者
那些PR2、 TOSC、TMR2什么玩意?你是把PIC的手册抄过来了吧,那是寄存器?

使用特权

评论回复
5
fangfei036|  楼主 | 2012-5-23 17:11 | 只看该作者
tinnal兄,谢谢您,这个是在手册上看到的,还有网上查的资料,发现这个16f877a pwm的占空比计算方法挺奇怪的,比,应该是不大于1才是,这个手册上说pr2是用来设置pwm的周期的,tosc是晶振频率,TMR2是pwm比较的一个预分频比,tinnal兄,请问,这个pwm的占空比到底要怎么计算才行呢??

使用特权

评论回复
6
Tinnal| | 2012-5-23 22:29 | 只看该作者
这个看具体CPU的实现。
从原理上来说,占空比就是一个百分比,最大值为1,
像我现在用的9260来说。
有一个计数设定值用于控制频率,通过分频后的Timer时钟,和这个计数器设定值,结合相应的计数器模式,决定最后的频率。
同时,为了PWM,硬件上面会有比较器,PWM用法也是有很多的,举例来说,如果当前计数值大于这个比较器设定值,就输出1,低于这个值就输出0,这样,就能通过设定合适的比较器的值来设定需要的占空比。
这个比较器的值不是占空比,却影响占空比。一般来说,他的最小设定值为0,最大设定值为当前的计数器设定值(其实硬件没有这个规定,但设大了,就达不到我们的效果而已)。

使用特权

评论回复
7
Tinnal| | 2012-5-24 00:09 | 只看该作者
看了一下PICPWM功能,还挺怪的,把PWM的比较器分离出来,结合原有的TIMER2采能产生PWM的信号,这可能是因为兼容的原因才弄成这样的吧,因这同系列的前一个芯片是没有PWM功能的,为了TIMER本身的兼容而这么去做。

好的,入正题,Timer不说了,对于CCPCapture/Compare/PWM (CCP) module)首先,要用Pwm功能,必须设定的PWM模式。
CCP1CON寄存器定义:


bit 3-0 CCPxM3:CCPxM0: CCPx Mode Selectbits 设定为11xx = PWM mode
这里要注意的是bit 5-4 CCPxX:CCPxY: PWM Least Significant bits,因为PWM10位精度的,而后面的CCPR只有8位(8位单片机麻),所以在这里弄了两个低两位出来,不合理,但合情。
好了,下面弄个PWM的结构图出来。


如手册所说,CCPR1L是用于占空比的计算的比较值CCPR1H不用我们去设。
PR2用于控制PWM输出信号的周期。
TMR2从图上看不出来,要从公式上看。
逻辑从那个RS触发器看到出来很简单,就是当前计数值>CCPR时复位,当前计数值>PR2时,复位计数器,重装CCPR1H,置位输出。CCPR1H1L的关系,手册提到如下:
CCPR1L and CCP1CON<5:4> can bewritten to at any time, but the duty cycle value is not latched into CCPR1Huntil after a match between PR2 and TMR2 occurs (i.e., the period is complete).In PWM mode, CCPR1H is a read-only register
好事情,也就是说我们不用管CCPR1H
来看看输出的图片如下:


OK,和我们分析的一样。

好了,来看看周期的公式吧。
PWM period = [(PR2) + 1] • 4 • TOSC •(TMR2prescale value)
哦,从这可以看出来,TMR2其实也是用来分频的。不难理解。TOSCTimer2的输出,怎么会有个4?看PWM结构图吧,10位的PWM,但PR2只有8位喔,相当于左移了2位,也就是乘了个4.
如果TOSC4M,我们想PWM输出的频率为22KHz,为了增加精度,我们把TMR2设为1,则RP2 = 4000KHz / 22KHz/4 - 1 =44.5 = 44;

好,再来看PWM占空比吧,
先看公式:
PWM duty cycle =(CCPR1L:CCP1CON<5:4>)•TOSC • (TMR2 prescale value)
如果要让占空比为50%因为PWM period= 1/22KHz = 45us, PWM duty cycle =45us * 50% = 23us
好吧,同样,TMR2=1(CCPR1L:CCP1CON<5:4>) = 23us / TOSC = 23us / (1/4Mhz) = 23us /0.25us = 92。二进制为1011100,则CCPR1L为:10111(0x17)CCP1CON<5:4>为:000x0)。
OK,任务结束。





使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
fangfei036 + 1 详细到极致
8
Tinnal| | 2012-5-24 00:12 | 只看该作者
本帖最后由 Tinnal 于 2012-5-24 00:16 编辑

好注意,TOSC是Timer2的输出,而不是指晶振的频率,这一点手册TABLE 8-1: CCP MODE - TIMER
RESOURCES REQUIRED已经说明。

通过这个案例,想大家重视手册,手册其实就已经说得很清楚了。
我在fangfei036这个问题上这么关注,但不可能全部的新人我都能给你们去看手册。fangfei036这个案例教的不仅仅是fangfei036,而是和fangfei036类似的所有初学者。重视手册!重视官网!另什么都去先问别人,自己先研究一下,百度一下,google一下。

上面的计算有可能算错,fangfei036你复算一下。

使用特权

评论回复
9
Tinnal| | 2012-5-24 00:25 | 只看该作者
说实在PIC单片机我也没有用过。也是因为fangfei036的问题,去看手册的。
顺便问一下,因为PIC只有8级的硬件堆栈,函数调用地址是直接压入硬件堆栈而不是压到内存的。
想问fangfei036,你有试过函数调用深度超过8级的吗?可以吗。
也就是函数1->函数2->函数...->函数7->函数8->函数9?
函数9能调用吗,麻烦给我做个实验。

因为我本来是想做一个DIY CPU的教程的,PIC16是一个候选的CPU,指令集简单。同时为候选的还有MSP430。想做个教程,把大学的数字电路知识用起来,用一般的通用的逻辑IC来实现。帮大家学以致用。

使用特权

评论回复
10
fangfei036|  楼主 | 2012-5-24 14:24 | 只看该作者
tinnal大哥,对你的详细分析佩服的五体投地,而且是深夜劳累,感激的无以言表,谢谢谢谢  
今天上班太忙了,现在才忙里偷空来看看,你的独到分析也更加深刻的让我们知道官网手册的重要性,让我们清楚分析思路,太感谢了  硬件堆栈实验今天完成  老大又叫了...

使用特权

评论回复
11
fangfei036|  楼主 | 2012-5-24 15:41 | 只看该作者
本帖最后由 fangfei036 于 2012-5-24 15:49 编辑

9# Tinnal tinnal 大哥,你的分析值得我重复再重复的看,刚我上传的这个没有意思的程序,看看是不是八级堆栈调用的?我都调用到十级了,还是可以编译通过而且运行的结果也是对的,不知道是不是我理解的硬件堆栈的八级函数调用,理解错误了呢???
应该是几级就是支持几个的函数嵌套调用 这样的话,是不是我的写法错了?

硬件堆棧.rar

3.52 KB

使用特权

评论回复
12
Tinnal| | 2012-5-24 16:01 | 只看该作者
void lamp0();
void lamp1();
void lamp2();
void lamp3();
void lamp4();
void lamp5();
void lamp6();
void lamp7();
void lamp8();
void lamp9();

void lamp0()
{
    lamp1();
}

void lamp1()
{
    lamp2();
}

void lamp2()
{
    lamp3();
}

void lamp3()
{
    lamp4();
}

void lamp4()
{
    lamp5();
}

void lamp5()
{
    lamp6();
}

void lamp6()
{
    lamp7();
}

void lamp7()
{
    lamp8();
}

void lamp8()
{
    lamp9();
}

void lamp9()
{
    LED0=1;
}

void main()
{
    lamp0();
}

这样写,麻烦fangfei036给我试试。

使用特权

评论回复
13
Tinnal| | 2012-5-24 16:04 | 只看该作者
注意关掉优化,我怕编译器看到这么多空函数,帮我整合了。或者,在每个函数里都写个LED的操作函数。目的是不让编译器对我的代码结构进行优化。

使用特权

评论回复
14
fangfei036|  楼主 | 2012-5-24 16:14 | 只看该作者
本帖最后由 fangfei036 于 2012-5-24 16:23 编辑

13# Tinnal
tinnal 兄,还是可以编译通过的,我在每一个函数中加了led的操作,不知道哪里取消优化.
在pic16f676 跟pic16f877a都是可以編譯通過
#include <pic.h>     
__CONFIG(XT&WDTDIS&LVPDIS);   
#define LED0 RB0   
//定义U5A为RB0端口
#define LED1 RB1   
//定义U5B为RB1端口
#define LED2 RB2   
//定义U5C为RB2端口
#define LED3 RB3   
//定义U5A为RB0端口
#define LED4 RB4   
//定义U5B为RB1端口
#define LED5 RB5   
//定义U5C为RB2端口
#define LED6 RB6   
//定义U5A为RB0端口
#define LED7 RB7   
//定义U5B为RB1端口
#define LED8 RC7   
//定义U5B为RB1端口
#define LED9 RC6   
//定义U5B为RB1端口
char a,b,c,d,e,f,g,k,x,y;
void lamp0();
void lamp1();
void lamp2();
void lamp3();
void lamp4();
void lamp5();
void lamp6();
void lamp7();
void lamp8();
void lamp9();

void lamp0()
{
    lamp1();

LED0=1;
}

void lamp1()
{
    lamp2();

LED1=1;
}

void lamp2()
{
    lamp3();

LED2=1;
}

void lamp3()
{
    lamp4();

LED3=1;
}

void lamp4()
{
    lamp5();

LED4=1;
}

void lamp5()
{
    lamp6();

LED5=1;
}

void lamp6()
{
    lamp7();

LED6=1;
}

void lamp7()
{
    lamp8();

LED7=1;
}

void lamp8()
{
    lamp9();

LED8=1;
}

void lamp9()
{
    LED9=1;

}

void main()
{
    lamp0();

LED0=1;
}

使用特权

评论回复
15
Tinnal| | 2012-5-24 16:22 | 只看该作者
OK,谢谢,啵一个。哈哈,好了,决定拿PIC16开刀了。接入去就是考虑我恒心的考验了。
对呀,你用的是什么编译器?

使用特权

评论回复
16
fangfei036|  楼主 | 2012-5-24 16:30 | 只看该作者
MPLAB IDE V8.10 的,tinnal大哥,你能不能加我扣扣啊,915471080 現在我在這個公司不是搞單片機的,一個人自學很多都不懂 一师难求啊

使用特权

评论回复
17
fangfei036|  楼主 | 2012-5-24 16:31 | 只看该作者
15# Tinnal
tinnal大哥幽默的很,怎一个谢字了得啊 !!

使用特权

评论回复
18
Tinnal| | 2012-5-24 17:06 | 只看该作者
yewuyi叶大侠那边给我做实验好像出了点问题了,说编译时出了个警告,我不知道程序能不能正确运行。你可以给我看看吗?
贴的地址为:https://bbs.21ic.com/icview-339181-1-1.html

有什么问题可以发在论坛里头,我不在,还有其它人答你麻。如果我长期不回,你可以发站内消息给我,如果还是长时间不回,给我发邮件:tinnal.feng@miartech.com,如果还是长时间不回,那也就是跳槽了,呵呵。

使用特权

评论回复
19
fangfei036|  楼主 | 2012-5-25 08:20 | 只看该作者
9# Tinnal
tinnal 大哥,如果你的這個DIY教程做好了,記得告訴下小弟,讓我好好學習學習啊

使用特权

评论回复
20
hj007| | 2017-3-6 13:13 | 只看该作者
学习学习

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:技术力量,决定上层建筑

2

主题

345

帖子

3

粉丝