fengcongyun 发表于 2008-3-24 11:47:33

AVR STUDIO4仿真中定时器T1工作在模式9(相位与频率可调模式)的奇怪问题.

马老师:
    我刚刚接触AVR单片机,目前我在做一个程序,使用M8输出频率和占空比均可调节的波形.
    选用相位与频率可调模式,使用OCB1为输出;PORTD为输入端(低5位分别对应5个不同的频率值,高3位对占空比进行调节)
    使用ICCAVR编译C代码,用AVR STUDIO4进行仿真,但在对定时器1初始化后,OCR1AH,OCR1BH和TCNT1H的值均自动清零;而在后面对OCR1A的写入时,都是写入高位和低位后执行下一条指令后,OCR1AH自动清零.难道是访问16位寄存器时出的问题,可我写入时都是先写高八位,再写低八位,不清楚,求教.

    程序代码如下:
    //ICC-AVR application builder : 2008-3-20 15:39:09
// Target : M88
// Crystal: 8.0000Mhz


#include<iom88v.h>
#include<macros.h>

void port_init(void)
{
PORTB = BIT(PB2);
DDRB= BIT(PB2);
PORTC = 0x00; //m103 output only
DDRC= 0x00;
PORTD = 0xfe;
DDRD= 0x00;
PIND= 0xFE;
}

//TIMER1 initialize - prescale:1
// WGM: 9) PWM phz freq correct, TOP=OCRnA
// desired value: 73Hz
// actual value: 73.001Hz (0.0%)
void timer1_init(void)
{
TCCR1B = 0x10; //stop
TCNT1H = 0x29; //setup
TCNT1L = 0xF6;
OCR1AH = 0xD6;
OCR1AL = 0x0A;
OCR1BH = 0x6B;
OCR1BL = 0x05;
TCCR1A = 0x11;
TCCR1B = 0x11; //start Timer

}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer1_init();

MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;

TIMSK0 = 0x00; //timer 0 interrupt sources
TIMSK1 = 0x00; //timer 1 interrupt sources
TIMSK2 = 0x00; //timer 2 interrupt sources

PCMSK0 = 0x00; //pin change mask 0
PCMSK1 = 0x00; //pin change mask 1
PCMSK2 = 0x00; //pin change mask 2
PCICR = 0x00; //pin change enable
PRR = 0x00; //power controller
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void delay_short(int t) // 短延時
{
int i;
for (i=0;i<t;i++);
}
char scan_key1(void)// 按鍵掃瞄
{
char s;
   s = 0;
if ((PIND & 0x1f) != 0x1f)
{

if ((PIND & 0x01) == 0)
{
    s = 1;
    delay_short(1000);   
}
   
if ((PIND & 0x2) == 0)
{
    s = 2;
    delay_short(1000);   
}

if ((PIND & 0x4) == 0)
{
    s = 3;
    delay_short(1000);   
}
    if ((PIND & 0x8) == 0)
{
    s = 4;
    delay_short(1000);   
}
    if ((PIND & 0x10) == 0)
{
    s = 5;
    delay_short(1000);   
}
PIND=0xff;
};
while((PIND & 0x1f) != 0x1f);   // 判斷按鍵是不是放開   
return s;   
}
char scan_key2(void)// 按鍵掃瞄
{
char v;
   v = 0;
if ((PIND & 0xe0) != 0xe0)
{

if ((PIND & 0x20) == 0)
{
    v = 1;
    delay_short(1000);   
}
   
if ((PIND & 0x40) == 0)
{
    v = 2;
    delay_short(1000);   
}
   
if ((PIND & 0x80) == 0)
{
    v = 3;
    delay_short(1000);   
}
};
while((PIND & 0xe0) != 0xe0);   // 判斷按鍵是不是放開   
return v;   
}
void main(void)
{   
char key1,key2,OCR1_VH,OCR1_VL;
init_devices();
OCR1_VL = OCR1AL;
OCR1_VH = OCR1AH;
while(1)
{
   key1 = scan_key1();
   if (key1 > 0)
   {
   if (key1==1) // 设定频率值
    {
      OCR1AH = 0x6B;
      OCR1AL = 0x05;
      OCR1BH = 0x35;
      OCR1BL = 0x82;       
          
    };
   
   if (key1==2) // 设定频率值
    {
      OCR1AH = 0x35;
      OCR1AL = 0x82;
          OCR1BH = 0x1A;
      OCR1BL = 0xC1;
    };   
   
   if (key1==3) //设定频率值
    {
      OCR1AH = 0x1A;
      OCR1AL = 0xC1;
          OCR1BH = 0x0D;
      OCR1BL = 0x60;
    };      
       if (key1==4) // 设定频率值
    {
      OCR1AH = 0x0D;
      OCR1AL = 0x60;
          OCR1AH = 0x06;
      OCR1AL = 0xB0;
    };
       if (key1==5) // 设定频率值
    {
      OCR1AH = 0x06;
      OCR1AL = 0xB0;
          OCR1AH = 0x03;
      OCR1AL = 0x5B;
    };
   }
   key2 = scan_key2();
   if (key2 > 0)
   {
   if (key2==1) // 減少佔空比
    {
          if(OCR1_VL > 100)
      {
          OCR1_VL -= 100;
          }
          else
          {
          if (OCR1_VH > 0)
          {
                  OCR1_VH -= 1;
                  OCR1_VL += 156;
                }
                else
                {
                  OCR1_VH = 0;
                  OCR1_VL= 0;
                }
          }
              OCR1BH = OCR1_VH;
                  OCR1BL = OCR1_VL;
      };
   
   if (key2==2) // 增加佔空比
    {
      if(OCR1_VL < 156)
      {
          OCR1_VL += 100;
          }
          else
          {
          if (OCR1_VH < 255)
          {
                  OCR1_VH += 1;
                  OCR1_VL -= 156 ;
                }
                else
                {
                  OCR1_VH = 0xFF;
                  OCR1_VL = 0xFF;
                }
          }
              OCR1BH = OCR1_VH;
                  OCR1BL = OCR1_VL;
    };   
   
   if (key2==3) // 全黑,佔空比為100%
    {
      OCR1_VH = OCR1AH;
          OCR1_VL = OCR1AL;
      OCR1BH = OCR1_VH;
          OCR1BL = OCR1_VL;
    };      
   }
};
}

machao 发表于 2008-3-24 20:43:31

在C里面最好直接用16位的赋值语句,如:OCRA1 = 0Xxxxx.分成高位和低位写的话,中间被中断打断就出问题了.

fengcongyun 发表于 2008-3-25 19:14:53

老师:
   我使用直接赋值语句:OCRA1 = 0Xxxxx,结果还是不行.
   定时器初始化代码:
void timer1_init(void)
{
TCCR1B = 0x10; //stop
// TCNT1H = 0x29; //setup
// TCNT1L = 0xF6;
   TCNT1=0x29F6;
//OCR1AH = 0xD6;
//OCR1AL = 0x0A;
   OCR1A = 0xD60A;
// OCR1BH = 0x6B;
//OCR1BL = 0x05;
   OCR1B = 0x6B05;
TCCR1A = 0x11;
TCCR1B = 0x11; //start Timer
}
寄存器TCNT1,OCR1A,OCR1B中的内容均能写入,只是在执行 "TCCR1B = 0x11; //start Timer"后自动将三个16位寄存器的高位清零.
还有,我在主程序中将key1设为1,在执行语句:
if (key1==1) // 设定频率值
    {   
   OCR1A = 0x6B05;
   OCR1B = 0x3582;      
         
    };
 发现:低8位能写入,但高8位不能写入,即执行语句后:OCR1A 内容为0005H;OCR1B内容为0082H.
 应该不会是AVR STUDIO本身模拟存在的问题吧?
 

querli_wjh 发表于 2008-3-25 21:55:11

AVR STUDIO4软仿真定时器不准确。

fengcongyun 发表于 2008-3-26 11:33:27

那有没有其它的仿真软件??
    这个程序有没有出错的地方,能不能直接转为HEX文件,烧写入单片机?
    我目前在做毕业设计,时间比较紧,请各位多多帮忙.
页: [1]
查看完整版本: AVR STUDIO4仿真中定时器T1工作在模式9(相位与频率可调模式)的奇怪问题.