xiao5 发表于 2009-4-6 13:12:58

请教马老师:我按照您的<<一个USART(RS232)低层驱动+中间层软件示例&

这个程序我是按照马老师的<<一个USART(RS232)低层驱动+中间层软件示例>>( http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=147242&bbs_page_no=1&search_mode=1&search_text=USART&bbs_id=9999 )改写的但是不知为什么,每次单片机都是不断的复位,详见以下程序,能否麻烦马老师抽空帮我看看!我想这是由于我的浮躁(记得马老师批过我这类学习态度)和急于求成造成的吧,但目前实在是找不到原因,还请马老师批评指正!以前通过看马老师的帖子和回复跟着马老师学了不少知识,在此感谢马老师!

//tool:ICCAVR   
//crystal:8M (M16)
#include "iom16v.h"
#include "macros.h"

#define TEST_LED_ON   (PORTB|=(1<<PB4))   //=======LED_ON
#define TEST_LED_OF   (PORTB&=~(1<<PB4))//=======LED_OF
#define DATA_REGISTER_EMPTY (1<<UDRE)

// USART Transmitter buffer========================================
#define TX_BUFFER_SIZE   20
unsigned char tx_buffer;//发送缓冲区
#if TX_BUFFER_SIZE<256           //定义发送缓冲区环形对列的控制指针
unsigned char tx_wr_index;// tx_wr_index为写指针,
unsigned char tx_rd_index;// tx_rd_index为读指针
unsigned char tx_cnter   ;// tx_cnter为在队列中要发送的字符个数
#else
unsigned int tx_wr_index,tx_rd_index,tx_cnter;//
#endif
//==================================================================
void Delayms(unsigned int i)
{
    unsigned int j;
    for (;i!=0;i--)
    {for (j=100;j!=0;j--); }      
}
//=================================================================
#pragma interrupt_handler uart0_tx_isr:14
void uart0_tx_isr(void)
{
    if (tx_cnter)
    {
      tx_cnter--;
      UDR = tx_buffer;
      if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index = 0;
    }
}
void TX_char(unsigned char c)
{
    while(tx_cnter == TX_BUFFER_SIZE) ;
    CLI();
    if (tx_cnter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
    {
      tx_buffer = c;
      if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
      ++tx_cnter;
    }
    else UDR = c;
    SEI();
}
//================================================================
void main(void)   //==============main
{
    CLI(); //disable all interrupts
    PORTA = 0x00;
    DDRA= 0x00;
    PORTB = 0x00;//
    DDRB= 0x10;
    PORTC = 0x00; //
    DDRC= 0x00;
    PORTD = 0x00;
    DDRD= 0x02;//

    UCSRB = 0x00; //disable while setting baud rate
    UCSRA = 0x00;
    UCSRC = (1<<URSEL)|(0<<UMSEL)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCPOL);//异步模式,8位数据+1位停止位
    UBRRL = 51; //set baud rate lo 9600:514800:1032400:207(8MHz)
    UBRRH = 0x00; //set baud rate hi
    UCSRB=(0<<RXEN)|(1<<TXEN)|(0<<RXCIE)|(0<<TXCIE);//允许发送
    SEI();
    tx_cnter=0;//
    TEST_LED_ON ;//LED亮
    Delayms(1000);
    UCSRB |= 1<<TXCIE;//开中断
       
    while(1)
    {
      Delayms(1000);//
      TEST_LED_OF ;//LED在此熄灭,只要单片机不复位,就不会亮了,但是它一直在亮!!!!
                     //用示波器看了一下,上电后LED有4次反复短暂熄灭后又亮了的过程,之后就一直亮!
                //上电时用串口调试助手测试TX脚收到数据:82828282,之后就没有数据了!
                //此外单片机的电源很稳定.
      TX_char('8');
      TX_char('2');
      TX_char('3');
      TX_char('4');
      TX_char('5');       
   }
}

xiao5 发表于 2009-4-6 17:57:44

也请大家帮忙看看啊!谢谢了!

ba_wang_mao 发表于 2009-4-7 10:48:44

熔丝位是否配置了看门狗,而在程序中没有看门狗的初始化代码或者没有喂狗呢?

xiao5 发表于 2009-4-7 14:47:03

http://cache.amobbs.com/bbs_upload782111/files_13/ourdev_433702.jpg
M16熔丝位配置 (原文件名:123.jpg)
我这样配置对吗?

ba_wang_mao 发表于 2009-4-7 16:36:16

http://cache.amobbs.com/bbs_upload782111/files_13/ourdev_433776.JPG
(原文件名:ATMEGA128下载器熔丝配置界面.JPG)

ba_wang_mao 发表于 2009-4-7 16:41:22

单片机为ATMEGA128
(1)、BODLEVEL=打勾 表示:门限电压选择4.3V
(2)、BODEN=打勾   表示上电时低于4.3V单片机将不会工作
(3)、SUT1=不打勾 SUT0=打勾 表示最长启动时间
(4)、CKSEL3=打勾 CKSEL2=打勾 CKSEL1=打勾 CKSEL0=打勾  表示选择外部晶体振荡器
(5)、EESAVE=打勾 表示下载时,不擦除EEPROM中的数据
(6)、WDTON=不打勾 表示禁止单片机的看门狗

xiao5 发表于 2009-4-7 19:08:38

我的芯片是M16,没有你上面提到的"(6)、WDTON=不打勾 表示禁止单片机的看门狗 " 这一选项,现在我又在程序的初始化里加了以下关闭看门狗的程序,但是单片机还是在不停的复位!!
void WDT_off(void)
{
CLI();
WDR();/* WDT 复位*/
WDTCR |= (1<<WDTOE) | (1<<WDE);/* 置位 WDTOE 和 WDE*/
WDTCR = 0x00;/* 关闭WDT */
SEI();
}
    可以肯定的是单片机的不断复位是由于我开了"UCSRB |= 1<<TXCIE;//开中断 "这个引起的--我把这句去掉,单片机就不会出现不断复位的现象了,但是我现在已经关了看门狗,还有什么会使单片机不断复位呢?

    麻烦大家帮我看看是怎么回事,是不是我有个别地方由于没有理解透或没有注意到...谢谢!

ba_wang_mao 发表于 2009-4-8 08:44:09

是不是因为有中断服务程序的初始化代码,而没有在程序中编写中断服务程序。
  这种情况,也可能导致上述现象。

xiao5 发表于 2009-4-8 11:33:27

但是我程序里有中断服务程序的:
UCSRB |= 1<<TXCIE;//开中断
与其对应的是:
#pragma interrupt_handler uart0_tx_isr:14
void uart0_tx_isr(void)
{   
    if (tx_cnter)
    {   
      tx_cnter--;
      UDR = tx_buffer;
      if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index = 0;
    }
}

xiao5 发表于 2009-4-8 15:29:06

本人掌握的AVR知识不够多,也不够精,所以这样一个可能让大家感到很简单的问题就把我卡住了好几天,在这里一个初学者请大家帮帮我,给我指出其中的问题,谢谢大家了!

ba_wang_mao 发表于 2009-4-9 14:44:40

会不会是数组溢出了。



void uart0_tx_isr(void)
{   
    if (tx_cnter)   
    {   
      tx_cnter--;
      UDR = tx_buffer;   
      if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index = 0;   
    }
}


改写成

int num=0;

void uart0_tx_isr(void)
{   
       UDR = num;   
       if (num > 255)
          num =0;
}

xiao5 发表于 2009-4-11 09:53:42

结帖了,感谢大家的支持和帮助!
    经过几天的郁闷,在网友的提示下,终于找到了问题:我之前一直用iccv6.31,前几天又装了v7--考虑到还没有找到注册码,暂时先用v6.31,这就是问题所在了,v7会使v6.31编译错误但是又没有任何错误提示,后来我在电脑上只装一个软件就ok了!
    希望我的教训能使可能会遇到这个问题的朋友以提示!
页: [1]
查看完整版本: 请教马老师:我按照您的&lt;&lt;一个USART(RS232)低层驱动+中间层软件示例&