搜索
bottom↓
回复: 10

再问 avr mega16 定时器1 OC1A OC1B在相位修正模式,做DA输出,环境gcc,定时器0 10ms定时

[复制链接]

出0入0汤圆

发表于 2007-11-1 09:45:51 | 显示全部楼层 |阅读模式
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/delay.h>

#define uchar unsigned char
#define uint unsigned int

#define key0 PD0
#define pwm2 PD7
#define pwm1a PD5        //定时器1 OC1A输出
#define pwm1b PD4         //定时器1 OC1B输出  


volatile uchar keyv,tempkeyv;  //键值
volatile uchar t1pwm1a;     //定时器1 pwm1a值
volatile uchar t1pwm1b;      //定时器1 pwm1b值

volatile uchar t2pwm;
//************************************************************************************
void timer2_init(void)
{
OCR2=t2pwm;
TCCR2=(0<<WGM21)|(1<<WGM20)|(1<<COM21)|(0<<COM20)|(0<<CS22)|(0<<CS21)|(1<<CS20);
}


//***********************************************************************************
void timer1_init(void)
{
OCR1A=t1pwm1a;    //设定top值
OCR1B=t1pwm1b;   
TCCR1A=(1<<COM1A1)|(0<<COM1A0)|(1<<COM1B1)|(0<<COM1B0)|(0<<WGM11)|(1<<WGM10);
TCCR1B=(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);
//不分频,WGM1=5,快速pwm模式,OC1A,OC1B正向输出

}

//***********************************************************************************
void timer0_init(void)  //ctc模式,10ms定时
{
OCR0=38; //设定top值  top=8000000/(2*1024*100)-1  10ms 即频率为100hz
TCCR0=(1<<WGM01)|(0<<WGM00)|(0<<COM01)|(0<<COM00)|(1<<CS02)|(0<<CS01)|(1<<CS00);
//1024分频,ctc模式,oc0为普通io

}

//************************************************************************************
void delay_10ms(uchar t)
{
uint i;
for(i=0;i<t;i++)
_delay_loop_2(20000);  //延时10ms
}

//*************************************************************************************
SIGNAL(SIG_OVERFLOW2)     //定时器2溢出中断
{
OCR2=t2pwm;     //改变比较值

}
//*************************************************************************************
SIGNAL(SIG_OVERFLOW1)     //定时器1溢出中断
{
OCR1A=t1pwm1a;           //改变比较值
OCR1B=t1pwm1b;
}

//************************************************************************************
SIGNAL(SIG_OUTPUT_COMPARE0)    //键盘扫描中断

{
if(!(PIND&(1<<key0)))    //是否有键按下
keyv=1;

if(keyv!=0)             //如果有键按下
    {
         delay_10ms(1);     //延时10ms
     if(!(PIND&(1<<key0)))    //再次测试按键
                 tempkeyv=1;         

     if(keyv==tempkeyv)    //两次键值相等,证明有键按下
        {
                           
         if(t1pwm1a<254)
          {
            t1pwm1a+=10;
          }
                  
          if(t1pwm1b<254)
           {
            t1pwm1b+=10;
           }
                 
          t2pwm+=5;

        }

    }
keyv=0;         
tempkeyv=0;

}


//****************************************************************************
int main(void)
{

DDRD&=~(1<<key0);    //打开键盘引脚上拉电阻
PORTD|=(1<<key0);

t1pwm1a=25;      //设置TOP初值
t1pwm1b=25;
t2pwm=25;
TCNT1=0;

timer0_init();   //定时器0初始化
//timer1_init();    //定时器1初始化
timer2_init();     //定时器2初始化
PORTD&=~((1<<pwm1a)|(1<<pwm1b)|(1<<pwm2));
DDRD=(1<<pwm1a)|(1<<pwm1b)|(1<<pwm2);   //设置OC1A为输出

TIMSK=(1<<OCIE0)|(1<<TOIC1)|(1<<TOIE2);  //T0输出比较匹配中断使能,T1溢出中断使能,T2溢出中断使能
sei();   //使能全局中断

while(1);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2007-11-1 09:57:48 | 显示全部楼层
我已经看过您的书的第八章,仔细看了里面的例程,虽然编译器不一样,但思路应该是一样的,我把改变OCR的值放在了溢出中断中,可现象还是和原来一样,不知是哪的问题,还有我看您的书中,有些疑问如下:
这是您书中第5页的一部分内容和第26页的例程,我觉得在//  //中间的一句话好象和您的例程有些冲突,DDRB=0x08;是否该放在TCCR0=0x69后面:

///外部引脚OC0的设置必须在设置该端口引脚(PB3)为输出之前。///设置OC0的值最简单的方法是在通常模式下使用FOC0来设置,这是因为在改变工作模式时,OC0寄存器将保持其原来的值。
需要注意的是,COM0[1:0]是无缓冲的,改变COM0[1:0]位的设置,会立即影响T/C0的工作方式。
(4)比较匹配输出单元
标志位COM0[1:0]有两个作用:定义OC0的输出状态,以及控制外部引脚OC0是否输出OC0寄存器的值。图8-6为比较匹配输出单元的逻辑图。


void main(void)
{
        “DDRB=0x08;”                                        // PB3输出方式,作为OC0输出PWM波                     // Timer/Counter 0 initialization
                // Clock source: System Clock
                // Clock value: 4000.000 kHz
                // Mode: Fast PWM top=FFh
                // OC0 output: Non-Inverted PWM
                “TCCR0=0x69;”
                OCR0=128;

                TIMSK=0x01;                                        // 允许T/C0溢出中断
                #asm("sei"

出0入0汤圆

 楼主| 发表于 2007-11-1 10:21:28 | 显示全部楼层
怎么有人看,没有人答,各位帮忙看看哪的问题

出0入0汤圆

 楼主| 发表于 2007-11-1 10:49:19 | 显示全部楼层
各位都不用pwm当作DA输出么

出0入0汤圆

 楼主| 发表于 2007-11-1 11:41:16 | 显示全部楼层
顶上去

出0入0汤圆

发表于 2007-11-1 12:35:06 | 显示全部楼层
等我有时间再回答你。建议你在看看第9章,把按键部分改掉。有时间把前11章都看看,肯定对你有好处。

出0入0汤圆

 楼主| 发表于 2007-11-1 12:41:35 | 显示全部楼层
非常感谢,我仔细看了您的例程,除了编译环境不一样,其他的应该没有区别,但现象还是一样,还有我上面提出的问题?

出0入0汤圆

发表于 2007-11-2 01:46:36 | 显示全部楼层
人按下一次按键的过程,从按下到释放一般是300ms,你的读键程序会如何处理?是加了一次10,还是n次的10?

记得在另外一个帖子中,已经叫你修改按键程序了,在5楼位置又一次让你看第9章,提示你把按键部分改掉,为何总是坚持?

既然发贴到这里询问,就应该.....怎么说呢,难道就是要个现成的代码?

实际上你的基本功并不扎实,还是step by step,把我的前11章仔细看看吧。

出0入0汤圆

 楼主| 发表于 2007-11-2 08:44:18 | 显示全部楼层
我不想要现成的代码,因为我现在刚开始学,只是想弄明白问题在哪,如果是按键的问题,我已经试过把按键部分去掉,改为2s定时中断中改变比较值,结果还是一样,还有您书中我提到的部分明显前后矛盾,我刚开始接触,不知道哪是正确的

出0入0汤圆

发表于 2007-11-2 18:21:24 | 显示全部楼层
关于按键,我不知道你是否真的明白和知道是为什么不对。你把这部分去掉了,我也没看到新的代码。

你强调和固执的认为是初始化的问题,我可以明确告诉你,你的PWM不正确与其无关。

原因是你对下面这两句话不明白:
》外部引脚OC0的设置必须在设置该端口引脚(PB3)为输出之前。
》设置OC0的值最简单的方法是在通常模式下使用FOC0来设置,这是因为在改变工作模式时,OC0寄存器将保持其原来的值。

这里主要是指初始化T/C后,OC0的输出应该怎样设置。

例如,在一些严格的应用中,将T/C初始化后(还没有开始工作!),同时要求OC0的输出为一个确定的值,假定为0吧。

那么应该:
1。先设置(改变)T/C的工作模式。
2。通过FOC0将OC0设置为0。
3。将PB3设置为输出。
此时,PB3输出为0。

这只是对开始的OC0的强制设置,一旦T/C工作了,OC0将按根据T/C的模式和方式输出0和1了。

在我的例子中,没有必要去强制设置第一个OC0的值为0还是1,因为它可能会使刚开始第一次的PWM不正确,但后面的PWM根本不受影响吗。

在这里,有许多的答帖是含糊的,甚至是错误的。如果你相信他们的说法,那么就把你带上了歪路。我还是建议你,如果经济上许可的话,买我的新书学习一下,可以少走很多弯路。

出0入0汤圆

 楼主| 发表于 2007-11-3 09:12:16 | 显示全部楼层
谢谢老师耐心详细的指教,一定仔细阅读您的书,遇到问题会再来请教。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-18 15:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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