AVR中断问题?????。。。

xmmant   2007-1-31 21:27 楼主
我这里有一个小小的程序,调试时,只要已打开全局中断(提示:之前有开串口中断),打印信息就打印不全,而且会重复执行main()函数,由于我是初次接触AVR的,现在实在是找不到是怎么回事,所以我把我这个小程序发到网上,请各位帮忙看看!麻烦大家,在此先谢谢了!

// Filename:    Serial.h
#ifndef        __SERIAL_H
#define        __SERIAL_H

#ifndef TRUE
#define TRUE                1
#endif

#ifndef FALSE
#define FALSE        0       
#endif

void SerialTxChar(int8_t data);
void SerialTxString(int8_t *s);

#define        putch        SerialTxChar
#define        putchar        putch
#define        puts        SerialTxString
void SerialInit(void);
void Dprintf(int8_t *f, ...);

#endif




// Filename:    Serial.c
#include
#include
#include "serial.h"

#define MCLK                        3686400                       
#define BAUDRATE      115200

void set_baudrate(void)
{
        uint16_t scaler = MCLK/16/BAUDRATE - 1;                // default baud = 115200
                UBRR1H = scaler >> 8;
                UBRR1L = scaler;
}
void SerialInit(void)
{
        UCSR1C = 0x06;                                       
        UCSR1A = 0x00;                                                       
        set_baudrate();                                       
        UCSR1B = 0xD8;                                       
}

void SerialTxChar(int8_t data)
{
        if(data=='\n') {               
                while(!(UCSR1A & (1<                 UDR1='\r';
        }
        while(!(UCSR1A & (1<         UDR1=data;
}

void SerialTxString(int8_t *s)
{
         while(*s)
                SerialTxChar(*s++);
}

int16_t strlen(const int8_t *s)
{
        int16_t i = 0;

        for(; *s; s++)
                i++;
       
        return i;
}

/*---------------------printf and support routines ---------------------*/
/* print c count times */
void PutRepChar(int8_t c, int16_t count)
{
        while (count--) putch(c);
}

/* put string reverse */
void PutStringReverse(int8_t *s, int16_t index)
{
  while ((index--) > 0) putch(s[index]);
}

/*-------------------------------------------------------------------------*/
/*
   prints value in radix, in a field width width, with fill
   character fill
   if radix is negative, print as signed quantity
   if width is negative, left justify
   if width is 0, use whatever is needed
   if fill is 0, use ' '
*/

static void PutNumber(int16_t value, int16_t radix, int16_t width, int8_t fill)
{
  int8_t buffer[40];
  int16_t bi = 0;
  uint16_t         uvalue;
  int16_t digit;
  int16_t left = FALSE;
  int16_t negative = FALSE;

  if (fill == 0) fill = ' ';

  if (width < 0) {
    width = -width;
    left = TRUE;
  }
  if (width < 0 || width > 80) width = 0;
  
  if (radix < 0) {
    radix = -radix;
    if (value < 0) {
      negative = TRUE;
      value = -value;
    }
  }
  uvalue = value;
  do {
    if (radix != 16) {
      digit = uvalue % radix ;
      uvalue = uvalue / radix ;
    }
    else {
      digit = uvalue & 0xf;
      uvalue = uvalue >> 4;
    }
    buffer[bi] = digit + ((digit <= 9) ? '0' : ('A' - 10));
    bi++;

    if (uvalue != 0) {
      if ((radix==10)&&((bi==3)||(bi==7)||(bi==11)|(bi==15))) {
        buffer[bi++]=',';
      }
    }
  } while (uvalue != 0);

  if (negative) {
    buffer[bi] = '-';
    bi += 1;
  }
  if (width <= bi) PutStringReverse(buffer, bi);
  else {
    width -= bi;
    if (!left) PutRepChar(fill, width);
    PutStringReverse(buffer, bi);
    if (left) PutRepChar(fill, width);
  }
}

/*-------------------------------------------------------------------------*/
static int8_t *FormatItem(int8_t *f, int16_t a)
{
  int8_t c;
  int16_t fieldwidth = 0;
  int16_t leftjust = FALSE;
  int16_t radix = 0;
  int8_t fill = ' ';

  if (*f == '0') fill = '0';
  while ((c = *f++)!=0) {
    if (c >= '0' && c <= '9') {
      fieldwidth = (fieldwidth * 10) + (c - '0');
    }
    else switch (c) {
    case '\000': return(--f);
    case '%': putch('%');
      return(f);
    case '-': leftjust = TRUE;
      break;
    case 'c': {
      if (leftjust) putch(a & 0x7f);
      if (fieldwidth > 0) PutRepChar(fill, fieldwidth - 1);
      if (!leftjust) putch(a & 0x7f);
      return(f);
    }
    case 's': {
      if (leftjust) puts((int8_t *) a);
      if (fieldwidth > strlen((int8_t *) a))
        PutRepChar(fill, fieldwidth - strlen((int8_t *)a));
      if (!leftjust) puts((int8_t *) a);
      return(f);
    }
    case 'd':
    case 'i': radix = -10;break;
    case 'u': radix = 10;break;
    case 'x': radix = 16;break;
    case 'X': radix = 16;break;
    case 'o': radix = 8;break;
    default : radix = 3;break;    // unknown switch!
    }
    if (radix) break;
  }
  if (leftjust) fieldwidth = -fieldwidth;
  PutNumber(a, radix, fieldwidth, fill);
  return(f);
}

#define vaStart(list, param) list = (int8_t*)((int16_t)¶m + sizeof(param))
#define vaArg(list, type) ((type *)(list += sizeof(type)))[-1]
#define vaEnd(list)

void Dprintf(int8_t *f, ...)       // variable arguments
{
        int8_t *argP;
       
        vaStart(argP,f);                // point at the end of the format string
        while (*f) {                        // this works because args are all ints
                if (*f == '%')
                        f = FormatItem(f + 1, vaArg(argP, int16_t));
                else
                        putch(*f++);
        }
        vaEnd(argP);
}


int16_t main()
{
        int16_t temp1,temp2,sum,product,divide,minus,i;
        int8_t  *string1;
        temp1=1024;
        temp2=4;
        string1="Hello,I'll come to here!";

        asm("CLI");
        asm("wdr");
        SerialInit();
        asm("wdr");
        //asm("SEI");

        Dprintf("%s\n",string1);
        Dprintf("%d\n",temp1);
        Dprintf("%x\n",temp1);

        sum=temp1+temp2;        //result as dec=1028,hex=0x404
        Dprintf("sum(decimal)%d",sum);
        Dprintf("sum(hex)=0x%x\n\n",sum);

        product=temp1*temp2;        //result as dec=4096,hex=0x1000
        Dprintf("\nproduct(decimal)=%d\n",product);
        Dprintf("product(hex)=0x%x\n\n",product);

        divide=temp1/temp2;        //result as dec=256,hex=0x100
        Dprintf("\ndivide(decimal)=%d\n",divide);
        Dprintf("divide(hex)=0x%x\n\n",divide);

        minus=temp1-temp2;        //result as dec=1020,hex=0x3FC
        Dprintf("\nminus(decimal)=%d\n",minus);
        Dprintf("minus(hex)=0x%x\n\n",minus);
       
        while(1)
        {
                asm("wdr");
        }

            return (0);
}

回复评论 (8)

//asm("SEI");
也就是打开了这个后!
asm("SEI");
就出现上面所述情形了!
点赞  2007-1-31 21:29
先看看芯片里有没有看门狗?

好像你的没做看门狗处理,如果看门狗是默认起动的就对了,把它关掉就完

如果可能的话看看复位电路有没有问题...
点赞  2007-1-31 21:43
看门狗有清除的呀
asm("wdr");
我去检查一下复位看看!
点赞  2007-1-31 22:03

5楼 hwh 

不是知道是不是所谓的术语用错

清看门狗是不够的,应该禁用!!

呵呵
点赞  2007-2-1 08:44
而且会重复执行main()函数

>>这句是什么意思,是指不停的复位吗?
点赞  2007-2-1 13:30
和复位的效果差不多吧,就是重复的从main()函数的开始执行!
从上面程序看,只要执行就应该是在While(1)的循环当中不会出来的!
但我在调试使,它总会从头再执行!
点赞  2007-2-1 20:26
精通施奈德PLC,要有实际经验,有一定的自主支配时间。待遇面谈。联系方式:027-87792427;E@mail:bb0912@163.com
点赞  2007-2-2 08:30
你的中断向量初使化了吗,指向的中断函数定义了吗,如果没有,有的单片机可能跳转的是随机地址,对AVR来说,它可能是跳到0000地址去了,也就是中断产生后就复位了,与关看门狗没有关系
点赞  2007-2-2 12:14
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复