请高手分析我的程序错在哪?

[复制链接]
1587|5
 楼主 | 2016-8-21 15:12 | 显示全部楼层 |阅读模式
本帖最后由 yxx85 于 2016-8-21 15:23 编辑

为什么程序不能在AVR Studio中模拟仿真?仿真时进入不了主循环?定时器0也没反应?

程序如下:

/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.

Project :  AC源

Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 16.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega16.h>  
#include <delay.h>
#include <mega16_bits.h>
#include <math.h>

bit READ_SHOW_Flag;
unsigned char i,k;
unsigned int Iv,Vadj,voltage,current,power,cosa; // 因在math.h中已占用cos,所以用cosa代替cos
unsigned long int VOL,CUR,POW;
flash unsigned char DIG[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};  // 共阴数码管
unsigned char DISP[4];

#define V_CH 0    // 电压ADC通道
#define I_CH 1    // 电流ADC通道
#define IV_CH 2   // 过流ADC通道
#define VAJ_CH 3  // 电压调节ADC通道
#define BEEP PORTA.7  // 声音报警
#define LED PORTA.6   // 报警指示灯
#define LIE0 PORTA.4  // 第一位数码管
#define LIE1 PORTA.5  // 第二位数码管
#define LIE2 PORTB.0  // 第三位数码管
#define LIE3 PORTB.1  // 第四位数码管
#define LIE4 PORTB.2  // 第五位数码管
#define LIE5 PORTB.3  // 第六位数码管
#define LIE6 PORTB.4  // 第七位数码管
#define LIE7 PORTB.5  // 第八位数码管
#define LIE8 PORTB.6  // 第九位数码管
#define LIE9 PORTB.7  // 第十位数码管
#define LIE10 PORTD.0  // 第11位数码管
#define LIE11 PORTD.1  // 第12位数码管
#define LIE12 PORTD.3  // 第13位数码管
#define LIE13 PORTD.5  // 第14位数码管
#define LIE14 PORTD.6  // 第15位数码管
#define LIE15 PORTD.7  // 第16位数码管
#define PWM PORTD.4   // OCR1B输出PWM
#define V_DB 4352   // 分压系数与ADC转换系数之积。
#define I_DB 14142   // 分流系数、分压系数与ADC转换系数之积。

// Standard Input/Output functions
void io_init(void)
{   
DDRA=0xF0;     // PA0~3 ADC输入 PA6-7 报警输出(高电平有效)
PORTA=0x30;    // 数码管位码输出高电平使其灭
DDRB=0xFF;     // 数码管位码输出   
PORTB=0xFF;    // 高电平使其灭
DDRC=0xFF;     // 输出段码
PORTC=0x00;    // 共阴数码管
DDRD=0xFB;     // PD2中断0保护输入 PD4(OC1B)输出PWM 其余数码管位输出
PORTD=0xFB;    // INT0输入置1 数码管位码输出高电平使其灭
}              

void EXT_init(void)
{
GICR=0x40;      // 外部中断0 使能
MCUCR=0x00;     // 外部中断0 低电平触发
GIFR=0x40;      // 外部中断0 标志位允许
}

void TIMER0_init(void) // 625us定时器 用于测量
{               
TCCR0=0x03;      // 普通模式 64分频 (16M/64=250k)
TCNT0=0x63;      // 初值99=255-0.000625/(1/250k) 延时156*(1/250k)=624us
TIMSK=0x01;      // 允许定时器0 溢出中断
}

void PWM_init(void)
{                 // 快速PWM
TCCR1A=0X63;    // 比较匹配时OC1A取反 匹配时清0 TOP时置位 模式15
TCCR1B=0X19;    // 模式15 预分频系数N=1
OCR1A=799;      // PWM频率设为20kHz 799=(16M/20k)-1  OCR1A定f OCR1B定脉宽
OCR1B=0;       // OC1B(PD4)上得PWM
}

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{                 // 过流 过载保护程序
  PWM=0;     // PWM=0
  LED=1;  // 打开报警
  BEEP=1;  
  delay_ms(1000);// 延时1s
}   

unsigned int ADC(unsigned char CH) // ADC程序
{                 
ADCSRA=0x00;       // 关闭ADC
ADMUX|=CH;        // 选择输入
// Delay needed for the stabilization of the ADC input voltage
delay_us(3);
// ADCSRA|=0x40;       // ADC使能并启动
ADCSRA=0xC7;       // ADC使能并启动,预分频128(16M/128=125k)
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;        // ADCIF清0
// Start the AD conversion agen
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;      // ADCIF清0
return ADCW;
}

void SHOW(void)
{
  if(i/2==0)
   {
    DISP[0]=voltage/1000;
    DISP[1]=(voltage%1000)/100;
    DISP[2]=(voltage%100)/10;
    DISP[3]=voltage%10;
    k=0;
    if(DISP[0]==0)
     {
       DISP[0]=10;
       if(DISP[1]==0) DISP[1]=10;
     }
   }
  if(i/2==4)
   {
    DISP[0]=current/1000;
    DISP[1]=(current%1000)/100;
    DISP[2]=(current%100)/10;
    DISP[3]=current%10;
    k=4;
    }
  if(i/2==8)
   {
     DISP[0]=power/1000;
     DISP[1]=(power%1000)/100;
     DISP[2]=(power%100)/10;
     DISP[3]=power%10;
     k=8;
     if(DISP[0]==0)
      {
       DISP[0]=10;
       if(DISP[1]==0) DISP[1]=10;
     }
   }   
  if(i/2==12)
   {
     DISP[0]=cosa/1000;
     DISP[1]=(cosa%1000)/100;
     DISP[2]=(cosa%100)/10;
     DISP[3]=cosa%10;
     k=12;
   }   
  switch(i/2)    // 关闭位码
   {
    case 0:
      LIE15=1;
      break;
    case 1:
      LIE0=1;
      break;
    case 2:
      LIE1=1;
      break;
    case 3:
      LIE2=1;
      break;
    case 4:
      LIE3=1;
      break;
    case 5:
      LIE4=1;
      break;
    case 6:
      LIE5=1;
      break;
    case 7:
      LIE6=1;
      break;
    case 8:
      LIE7=1;
      break;
    case 9:
      LIE8=1;
      break;
    case 10:
      LIE9=1;
      break;
    case 11:
      LIE10=1;
      break;
    case 12:
      LIE11=1;
      break;
    case 13:
      LIE12=1;
      break;
    case 14:
      LIE13=1;
      break;
    case 15:
      LIE14=1;
      break;
   }
  PORTC=DIG[DISP[i/2-k]];   // 段码赋值
  switch(i/2)    // 打开位码
   {
    case 0:
      LIE0=0;
      break;
    case 1:
      LIE1=0;
      break;
    case 2:
      LIE2=0;
      break;
    case 3:
      LIE3=0;
      break;
    case 4:
      LIE4=0;
      break;
    case 5:
      LIE5=0;
      break;
    case 6:
      LIE6=0;
      break;
    case 7:
      LIE7=0;
      break;
    case 8:
      LIE8=0;
      break;
    case 9:
      LIE9=0;
      break;
    case 10:
      LIE10=0;
      break;
    case 11:
      LIE11=0;
      break;
    case 12:
      LIE12=0;
      break;
    case 13:
      LIE13=0;
      break;
    case 14:
      LIE14=0;
      break;
    case 15:
      LIE15=0;
      break;
   }
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
unsigned int V1,I1;  // 定义瞬时值
TCNT0=0x63;  // 装入初值
if(i%2)
  {
    SHOW();   
  }
else
  {
   if(!READ_SHOW_Flag)
    {
      V1=ADC(V_CH)*V_DB/1024;
      VOL+=(unsigned long int)V1*V1;
      I1=ADC(I_CH)*I_DB/1024;
      CUR+=(unsigned long int)I1*I1;
      POW+=(unsigned long int)V1*I1;
    }
   else
    {
     switch(i/2)
      {
       case 1:
         voltage=(unsigned int)lsqrt(VOL/16);
         break;
      case 3:
         current=(unsigned int)lsqrt(CUR/16);
         break;
      case 5:
         power=(unsigned int)POW/1000/16;
         break;
      case 7:
         if(voltage*current==0)    cosa=0;
         else cosa=power*1000/(voltage*current);
         break;
      case 15:
         VOL=0;
         CUR=0;
         POW=0;
         break;
      default: break;
    }
  }
if(++i>31)  
   {
    i=0;
    READ_SHOW_Flag=~READ_SHOW_Flag;
   }
}
}

void main(void)
{
io_init();   
EXT_init();
ACSR=0x80;
PWM_init();
TIMER0_init();
delay_us(4);  
// Global enable interrupts
#asm("sei")

while (1)
   {
     if(READ_SHOW_Flag)
       {
         LED=0;  // 关闭报警
         BEEP=0;         
         Iv=ADC(IV_CH);
         if(Iv>1000)
          {
            LED=1;
            if(Iv>1022) PORTD.2=0;
          }
         Vadj=ADC(VAJ_CH);
         OCR1B=25*Vadj/32;  
       }
   }
}
 楼主 | 2016-8-23 19:34 | 显示全部楼层
为什么没高手回复呀

使用特权

评论回复
| 2016-8-24 10:57 | 显示全部楼层
因为都是学徒啊,没有高手啊,就我浅显的目光看,你的定时器0初始化好像就不正常。这个初始化你看满意不?
  1. //ICC-AVR application builder : 2016-8-24 AM 10:53:33
  2. // Target : M16
  3. // Crystal: 8.0000Mhz
  4. #include <iom16v.h>
  5. #include <macros.h>
  6. //TIMER0 initialize - prescale:64
  7. // WGM: Normal
  8. // desired value: 625uSec
  9. // actual value: 624.000uSec (0.2%)
  10. void timer0_init(void)
  11. {
  12. TCCR0 = 0x00; //stop
  13. TCNT0 = 0xB2; //set count
  14. TCCR0 = 0x03; //start timer
  15. }

  16. #pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
  17. void timer0_ovf_isr(void)
  18. {
  19. TCNT0 = 0xB2; //reload counter value
  20. }

  21. //call this routine to initialize all peripherals
  22. void init_devices(void)
  23. {
  24. //stop errant interrupts until set up
  25. CLI(); //disable all interrupts
  26. timer0_init();

  27. MCUCR = 0x00;
  28. GICR  = 0x00;
  29. TIMSK = 0x01; //timer interrupt sources
  30. SEI(); //re-enable interrupts
  31. //all peripherals are now initialized
  32. }
复制代码

使用特权

评论回复
 楼主 | 2016-8-27 16:52 | 显示全部楼层
复仇之矛:  谢谢您的回复!
你的定时器0初始化和我的是一样的,只是您的晶振是8M,我是16M。
所以您的 “TCNT0 = 0xB2”  我的 “TCNT0=0x63”  没有差别。

使用特权

评论回复
| 2016-11-16 19:37 | 显示全部楼层
6.合 采高手交流 裙5 9 2 3 4 0 5 6 0 。开 码 日还有 红包发送 更有稳定ss 彩 计划。」!《

使用特权

评论回复
| 2016-11-17 08:53 | 显示全部楼层
看看熔丝位有没有设置对,晶振的选择

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖