打印
[AVR单片机]

关于用PWM控制LED渐亮的问题

[复制链接]
8972|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
pttangpt|  楼主 | 2007-12-10 15:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我现在要做一个类似于用PWM控制8路LED渐亮或者渐暗的程序(实际应用中并不是LED),8路输出对应有8路输入,类似于开关,使用ATMEGA16单片机,现在只有一组定时/计数器T2可用。要求每动作一个开关后,其对应的输出I/O引脚会输出一组占空比逐渐下降的方波,频率为1KHz,持续时间为500ms。
刚开始做的时候还觉得挺容易实现的,但现在犯难了,我使用了T/C2的PWM功能,当其中一组正在输出过程中时,另外一组输入又动作,这样如果同用一个定时器就会影响输出总时间(500ms);加多个计数值,分别赋给OCR2,则必然只会有一组输出;按普通的定时方式,使用8个计数值,因为要改变占空比,则定时时间小到了几个微秒,这样单片机没法做其他事了,哎!
实恨自已功力太浅,望各位赐教!

相关帖子

沙发
rodger_br| | 2007-12-10 20:10 | 只看该作者

LZ没有写PWM的精度要求

使用特权

评论回复
板凳
农民讲习所| | 2007-12-10 21:13 | 只看该作者

T2设置为PWM模式,打开溢出中断作为定时器,两者可同时使用

使用特权

评论回复
地板
pttangpt|  楼主 | 2007-12-10 23:09 | 只看该作者

谢谢楼上两位

回二楼:对于输出精度,我们也正在实际电路中试验,看多高的精度适合我们的要求,目前是以2%下降。
请问讲习所:我现在也是用的这种方式,控制一组输入输出是没有问题,关键是想其它7路也是收到输入后输出同样的占空比波,若是其中一组正在输出过程中,另外有一路有输入,能保证输出的占空比延时能到500ms吗?只有一个OCR2,我就不知道该咋弄了,您能说得具体点吗?

使用特权

评论回复
5
农民讲习所| | 2007-12-11 09:41 | 只看该作者

1KHZ/8=125uS,要实现PWM,算32位变化量,你的T2要设置为3.9us。
可能需要外部硬件扩展。

使用特权

评论回复
6
xwj| | 2007-12-11 09:46 | 只看该作者

没问题的

AVR可以跑到16MHz,每个IO平均能分到7.9个指令周期,优化下是足够的

使用特权

评论回复
7
xwj| | 2007-12-11 09:52 | 只看该作者

呵呵,搞错了!不是所长那样算的。

PWM频率为1KHz,周期1000uS,算32变化量的话中断间隔是31.25uS,每次中断比较8个计数值、变换IO肯定是没问题的


再就是:LZ只是调光的话有必要用1KHz的PWM频率吗?

使用特权

评论回复
8
农民讲习所| | 2007-12-11 09:53 | 只看该作者

对,算错了

使用特权

评论回复
9
xwj| | 2007-12-11 09:54 | 只看该作者

说到底,还是LZ没掌握复用资源、使用状态机的方法

使用特权

评论回复
10
pttangpt|  楼主 | 2007-12-11 10:42 | 只看该作者

呵呵。。。

呵呵,我上面只是打了个比方,结果越说越糊涂,反把大侠们都给误导了.抱歉先!

首先:我上面有说过的,是一个类似于调光,但并不是调光,PWM是用来作其它用.
这么问吧:
现在外部晶振是3.6864MHz,我用了T2(现在也只有T2可用了),定时周期为1.5ms(667Hz),采用的是32级分频,TCNT2值为83,OCR2从255开始,每次T2溢出时减1,当OCR2值减到84时结束PWM输出,整个PWM输出时间为256ms,这个做法我们改了一路输出,用示波器也多次、多种工作状况下都观察测试了,效果不错。
因为硬件电路已经定型了,原来的输出方式是:一检测到输入就输出低电平(稳态时为高),但根据实际情况看,这样对后面的硬件电路可靠性有一定的影响,现在老板就是想在不动硬件的基础上,将每一路输出时都加一个256ms的PWM延时,关键是这些输入可能不是同时,也可能是同时,还可能是其中一路输出一定时间后再输入,这样,我想保证每一路输入动作时,对应的输出就是256ms的PWM波。
T0、T1的捕捉、匹配中断都早用作其它的了,又不好动。所以犯难啊!

使用特权

评论回复
11
xwj| | 2007-12-11 11:04 | 只看该作者

呵呵,其实还是你没看懂

我们说的是:做软PWM!

使用特权

评论回复
12
pttangpt|  楼主 | 2007-12-11 11:10 | 只看该作者

呵呵...

其实我的只是输出一组占空比渐低的延时.
那请问,我那个问题有法解决吗?
多谢指教哦!我当加倍学习啊!

使用特权

评论回复
13
pttangpt|  楼主 | 2007-12-11 11:14 | 只看该作者

还有:

一路当然是没有问题的,但是多路输入输出呢?怎样才能保证它们共一个定时器而不相冲突呢?

使用特权

评论回复
14
pttangpt|  楼主 | 2007-12-11 11:18 | 只看该作者

如果

我做个8uS的定时,以计个数的方式来调占空比,恐怕单片机没时间来做其它的事了吧

使用特权

评论回复
15
xwj| | 2007-12-11 11:26 | 只看该作者

再去看7楼和9楼的贴

肯定可以的,但前提是你要有正确的编程理念,而且会很复杂,频繁中断也会带来其他的影响...


建议你去看看所长的教材或者学习下OS:-)

使用特权

评论回复
16
pttangpt|  楼主 | 2007-12-11 11:55 | 只看该作者

呵呵,好的

谢谢哟!
就是因为怕频繁中断所以才不敢用普通中断方式做PWM,现在看来也只有一试了!

使用特权

评论回复
17
酷每秒| | 2007-12-11 12:28 | 只看该作者

弱弱的问一下:所长就是指“农民讲习所”?



    还有就是“所长的教材”指的是什么?_new comer。。。

使用特权

评论回复
18
fzj| | 2007-12-11 12:45 | 只看该作者

根据XWJ的意思是不是这样写,请XWJ指点

#include   "iom16.h"

volatile unsigned char t1,t2,t3,t4,t4,t6,t7,t8;
volatile unsigned char t1_buffer,t2_buffer........; //
volatile unsigned char time_1ms;//PWM周期

  #pragma interrupt_handler INT_time2:5
  void    INT_time2   (void)
{   if   (++time_1ms>=32)   {time_1ms=0; PORTB=0;}
    else
  {
    if   (++t1_buffer>=t1)  {t1_buffer=0;PORTB|=(1<<0);}
    if   (++t2_buffer>=t2)  {t2_buffer=0;PORTB|=(1<<1);}
    if   (++t3_buffer>=t3)  {t3_buffer=0;PORTB|=(1<<2);}
    if   (++t4_buffer>=t4)  {t4_buffer=0;PORTB|=(1<<3);}
    if   (++t5_buffer>=t5)  {t5_buffer=0;PORTB|=(1<<4);}
    if   (++t6_buffer>=t6)  {t6_buffer=0;PORTB|=(1<<5);}
    if   (++t7_buffer>=t7)  {t7_buffer=0;PORTB|=(1<<6);}
    if   (++t8_buffer>=t8)  {t8_buffer=0;PORTB|=(1<<7);}
  }
}
/*软件模拟PWM TIME2每31.25US中断一次,T1~T8作为PWM调节,T1_BUFFER~T8_BUFFER作为比较,限制T1~T8的取值范围(1~31)要注意PWM高电平脉宽和T1~T8的值成反比.*/
请XWJ指点,谢谢

使用特权

评论回复
19
fzj| | 2007-12-11 12:50 | 只看该作者

..../////

#include   "iom16.h"

volatile unsigned char t1,t2,t3,t4,t4,t6,t7,t8;
volatile unsigned char t1_buffer,t2_buffer........; //
volatile unsigned char time_1ms;//PWM周期

  #pragma interrupt_handler INT_time2:5
  void    INT_time2   (void)
{   if   (++time_1ms>=32)   {time_1ms=0; PORTB=0XFF;}
    else
  {
    if   (++t1_buffer>=t1)  {t1_buffer=0;PORTB&=~(1<<PB0);}
    if   (++t2_buffer>=t2)  {t2_buffer=0;PORTB&=~(1<<PB1);}
    if   (++t3_buffer>=t3)  {t3_buffer=0;PORTB&=~(1<<PB2);}
    if   (++t4_buffer>=t4)  {t4_buffer=0;PORTB&=~(1<<PB3);}
    if   (++t5_buffer>=t5)  {t5_buffer=0;PORTB&=~(1<<PB4);}
    if   (++t6_buffer>=t6)  {t6_buffer=0;PORTB&=~(1<<PB5);}
    if   (++t7_buffer>=t7)  {t7_buffer=0;PORTB&=~(1<<PB6);}
    if   (++t8_buffer>=t8)  {t8_buffer=0;PORTB&=~(1<<PB7);}
  }

/*如果PWM高电平脉宽和T1~T8的值成正比应该这样写*/

使用特权

评论回复
20
pttangpt|  楼主 | 2007-12-11 13:33 | 只看该作者

呵呵

其实楼上的写法就跟我最开始的想法一样,只是怕中断过于频繁,所以才问了有没有其它方法呢.

使用特权

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

本版积分规则

11

主题

53

帖子

0

粉丝