wind 发表于 2005-4-15 22:31:48

老师,MEGA8波特率从4800到9600有什么要特别设置的地方吗?

我的程序在4800和2400都能正常工作,上了9600或更高就收不到发不出了,会是硬件问题还是软件问题呢?

另外,AD换通道好象有点乱

UART,485通信,MEGA8L,MAX1487

#include <iom8v.h>

#include <macros.h>

#define fosc 1843200

#define baud 4800



unsigned char flg=1;

static void io_init(void)

{

        PORTB = 0x01;

        DDRB = 0x01;

        PORTC = 0x00;

        DDRC = 0x08;

        PORTD = 0x0;

        DDRD = 0xfe;

}



void adc_init0(void)

{

unsigned char d1,d2;

ADCSRA = 0x00; //disable adc

ADMUX = 0x00; //select adc input 0

ADMUX = 0xc0;

//if (flg==1) ADMUX = 0xc1;

ADCSR = 0xc1;

d1=ADCL;//扔

d2=ADCH;

}



void adc_init1(void)

{

unsigned char d1,d2;

ADCSRA = 0x00; //disable adc

ADMUX = 0x00; //select adc input 0

ADMUX = 0xc1;

ADCSR = 0xc1;

d1=ADCL;//扔

d2=ADCH;

}



void usart_init(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x21;

UCSRC=0x86;

UBRRL = ((fosc/16/baud-1)%256);

UBRRH = ((fosc/16/baud-1)/256);

UCSRB=0x9c;

}



void usart_t(unsigned char f)

{

unsigned int i;

PORTC&=0xf7;

while (!(UCSRA & (1<<UDRE)) )

;//当udre为1时

UCSRB &= 0Xfe;//~(1<<TXB8);//第九位清零

UDR=f;

//delay(50);

for (i=0;i<=2000;i++);

PORTC|=0x08;

}



#pragma interrupt_handler usart_r:12

void usart_r(void)

{

unsigned char r,r1,r2,name=0x38,d3,d4;

CLI();

r=UDR;

usart_t(r);

PORTD^=0X08;//PD.3为标志位

if (r==name)

{

    PORTD^=0x20;//pd.5

    usart_t(0x5a);

       

        adc_init1();

        ADCSRA|=(1<<ADSC);//启动AD转换

        d3=ADCL;

        d4=ADCH;

        usart_t(0x12);

        usart_t(0x34);

        adc_init0();

        ADCSRA|=(1<<ADSC);//启动AD转换

        d3=ADCL;

        d4=ADCH;

       

        usart_t(0x56);

        usart_t(0x78);

}

PORTC|=0x08;

SEI();

}



void delay_1ms(void)

{

unsigned int i;

for (i=0;i<150;i++)

{

;

}

}



void delay(unsigned j)

{

unsigned k;

for (k=0;k<=j;++k)

{

   delay_1ms();

}

}   



void main(void)

{

CLI();

io_init();

adc_init0();

usart_init();

PORTC|=0x08;

SEI();

while(1)

{   

   delay(1000);

   PORTB^=0x01;//Pb.0为标志位

}

}

machao 发表于 2005-4-17 13:36:41

你先写一个最简单的使用9600输出的测试程序,看看能否运行。



   另外请你讲一下,你使用2400、4800时,它们设置和计算同什么有关?

wind 发表于 2005-4-18 11:07:21

老师,这是我的测试程序,可以正常发送

/*测试 mega8 send*/

#include <iom8v.h>

#include <macros.h>

#define fosc 1843200

#define baud 9600



static void io_init(void)

{

        PORTB = 0x01;

        DDRB = 0x01;

        PORTC = 0x30;

        DDRC = 0x08;

        PORTD = 0x00;

        DDRD = 0x7e;

}



void usart_s(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x21;

UCSRC=0x86;

UBRRL = ((fosc/16/baud-1)%256);//

UBRRH = ((fosc/16/baud-1)/256);//

UCSRB=0x9c;

}



void usart_t(unsigned char f)

{

while (!(UCSRA & (1<<UDRE)) )

;//当udre为1时

UCSRB &= 0Xfe;//~(1<<TXB8);//第九位清零

//if (f&0x0100) UCSRB|=(1<<TXB8);//if NO.9=1,set bit

UDR=f;

}





void delay_1ms(void)

{

unsigned int i;

for (i=0;i<150;i++)

{

}

}



void delay(unsigned j)

{

unsigned k;

for (k=0;k<=j;++k)

{

   delay_1ms();

}

}   



void main(void)

{

unsigned char j1;//晶振,波特率

int k;

io_init( );

usart_s( );

PORTC=0x30;

PORTC&=0xf7;

for ( ; ; )

{

   while (1)

   {

    delay(1000);

    PORTB^=0x01;//PD.6为标志位

    PORTD^=0x20;

        usart_t(0x5a);

   }

}

}



我用的是define预定义,更改波特率时只须改定义值。

初始化是用的书上的公式:

UBRRL = ((fosc/16/baud-1)%256);//

UBRRH = ((fosc/16/baud-1)/256);//

手动设置我也试过,结果是一样的。

UBRR的值只和晶振,波特率有关吧。

请教老师,谢谢!

wind 发表于 2005-4-18 12:42:17

另外,当内部晶振到4M(外部晶振我只有3.57的)时,从2400到14400的通信都不正确了。为什么?

求助啊!

machao 发表于 2005-4-18 14:01:20

首先你仅编写一个简单通用的9600,8位数据,1位停止位,无校验的发送程序进行测试,USART的初始化请使用ICCAVR中的程序生成向导,下面是它生成的初始化代码:



//UART0 initialize

// desired baud rate: 9600

// actual: baud rate:9615 (0.2%)

// char size: 8 bit

// parity: Disabled

void uart0_init(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x00;

UCSRC = BIT(URSEL) | 0x06;

UBRRL = 0x19; //set baud rate lo

UBRRH = 0x00; //set baud rate hi

UCSRB = 0x08;

}



    更换系统的时钟时不仅仅是在程序中使用DEFINE语句,还要注意你M8的系统时钟类型配置的溶丝位是否正确配置了!

   

    使用M8内部4M的RC作为系统时钟时,2400,4800,9600和19200都可以使用,尽管分频后有误差,但在范围内,14.4误差较大,不易使用。

   

    4M系统时钟用于USART时的分频误差和UBRR值(十进制):

    2400 --> 0.2%    103

    4800 --> 0.2%   51

    9600 --> 0.2%   25

    14.4k --> 2.1%    16

    19.2k --> 0.2%    12



    使用简单的发送程序先验证和掌握如何正确的调整波特率,然后再进入你的多机通信程序的调试,此时就是你的程序问题了。

wind 发表于 2005-4-18 15:00:29

老师,我原来的发送测试程序可以在9600发送,只是加入接收部分后

我配置过熔丝位了,CKOPT:1,CKSEL3..0:1101。目前的晶振是1.8432M的,外部,是为了通信准确。

目前还是没能解决问题。发0x5a,接到的是10。在2400,4800正常。

我的ICCAVR好象有问题,不能用APPLICATION BUILDER。

我把您的那一段拷到我的程序里了,作了点小改,UBRRL = 0x0b。

我用的是485通信,目前程序里只剩端口、UART初始化,发,延时,标志位(我接了LED作指示灯)和1487的控制位了。

老师,我是不是太浮躁了?可是我觉得我碰到的问题很怪啊。请老师训导!



#include <iom8v.h>

#include <macros.h>



static void io_init(void)

{

        PORTB = 0x01;

        DDRB = 0x01;

        PORTC = 0x00;

        DDRC = 0x08;

        PORTD = 0x00;

        DDRD = 0xfe;

}



//UART0 initialize

// desired baud rate: 9600

// actual: baud rate:9615 (0.2%)

// char size: 8 bit

// parity: Disabled

void uart0_init(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x00;

UCSRC = BIT(URSEL) | 0x06;

UBRRL = 0x0b; //set baud rate lo

UBRRH = 0x00; //set baud rate hi

UCSRB = 0x08;

}





void usart_t(unsigned char f)

{

unsigned int i;

PORTC&=0xf7;

while (!(UCSRA & (1<<UDRE)) )

;//当udre为1时

UDR=f;

for (i=0;i<=2000;i++);

PORTC|=0x08;

}



void delay_1ms(void)

{

unsigned int i;

for (i=0;i<150;i++)

{

;

}

}



void delay(unsigned j)

{

unsigned k;

for (k=0;k<=j;++k)

{

   delay_1ms();

}

}   



void main(void)

{

int k;

CLI();

io_init();

uart0_init();

SEI();

while(1)

{   

   delay(1000);

   PORTB^=0x01;//Pb.0为标志位

   usart_t(0x5a);

}

}

wind 发表于 2005-4-18 15:13:06

我改到内部4M,只改了熔丝位,和UBRRL=0x19,计算机可以正确收到5A。

19.2k时,UBRRL=0x0c,收到10,这是不是超出的意思?我是新手,乱猜的,请老师指导,谢谢!

wind 发表于 2005-4-18 16:32:04

4M接发,2400正常,4800有误码,9600误码高,只改动UBRRL

machao 发表于 2005-4-18 20:41:23

首先你应该验证在“最简单的、最基本的发送”时(不用485、不接受),在4M下2400、4800、9600都没问题(应该没问题的)。



   然后再考虑发和收的结合以及使用RS485。另外,RS485一般是半双工方式工作,485发送和接受转换中间要加一定的延时时间,否则会丢“位”。

wind 发表于 2005-4-19 23:45:19

接了MAX232,试了最简单的、最基本的发送时(不用485、不接受),在4M下2400、4800、9600都没问题

收有点问题

wind 发表于 2005-5-1 09:32:44

/*单字节地址点名,发送ID,两路AD,SUM,收发正常,*/

/*点名由PC4,5,PD3--7读出*/





#include <iom8v.h>

#include <macros.h>

#define fosc 3686400

#define baud 14400

//#define name 0x41   



unsigned char am,flg=1,sbuf1,sbuf0,sbuf2,intflg=0,sbuf;

unsigned int rbuf;

static void io_init(void)

{

        PORTB = 0x00;

        DDRB = 0x00;

        PORTC = 0x00;

        DDRC = 0x08;

        PORTD = 0x0;

        DDRD = 0x00;

}



//ADC initialize

// Conversion time: 26uS

void adc_init0(void)

{

unsigned char d1,d2;

ADCSRA = 0x00; //disable adc

ADMUX = 0x00; //select adc input 0

ADMUX = 0xc0;

ADCSRA = 0xc1;

d1=ADCL;

d2=ADCH;

}



void adc_init1(void)

{

unsigned char d1,d2;

ADCSRA = 0x00; //disable adc

ADMUX = 0x00; //select adc input 0

ADMUX = 0xc1;

ADCSRA = 0xc1;

d1=ADCL;

d2=ADCH;

}



void usart_init(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x01;

UCSRC=0x86;

UBRRL = ((fosc/16/baud-1)%256);

UBRRH = ((fosc/16/baud-1)/256);

UCSRB=0x9c;

}



void usart_t(unsigned char f)

{



while (!(UCSRA & (1<<UDRE)) );

UCSRB &= ~(1<<TXB8);//第九位清零

UDR=f;

while (!(UCSRA & (1<<TXC)) );

}



#pragma interrupt_handler usart_r:12

void usart_r(void)

{

unsigned char r;

CLI();

r=UDR;

if (r==am)

   {

    intflg=1;       

   }

SEI();

}

       

void cmp(void)

{

unsigned char m,n;

unsigned int temp,s;

for (m=0;m<32;m++)

{

   for (n=0;n<32;n++)

   {

    if (rbuf<rbuf)

    {

    temp=rbuf;

        rbuf=rbuf;

        rbuf=temp;

    }

   }

}

s=rbuf;

for(n=9;n<24;n++)

{

s=(s+rbuf);

}

s=(s/16);

sbuf2=(unsigned char)(s>>8);

sbuf2=(unsigned char)s;

for (m=0;m<32;m++)

{

   sbuf=(unsigned char) rbuf;

   sbuf=(unsigned char)(rbuf>>8);

}

}



void adc_send(void)

{

    unsigned int j;

    unsigned char k,m;

        CLI();

        PORTC&=0xf7;//485

        sbuf1=am;

        sbuf0=am;

       

        if (flg==0)

        {       

       for(k=0;k<6;k++)

                usart_t(sbuf1);

        }

        else

        {

       for(k=0;k<6;k++)

                usart_t(sbuf0);

        }

        //for (m=0;m<66;m++)

   //{

      //usart_t(sbuf);

   //}

        for (j=0;j<5000;j++);

    PORTC|=0x08;//485

        intflg=0;

   SEI();

}





       

void adc_save(void)

{   

    unsigned char vl,vh,tl,th,sum;

        unsigned int n,i,v,t;

        flg=1;

        while (1)

   {

    if (intflg) adc_send();

        adc_init1();

        for (i=0;i<32;i++)

        {

       ADCSRA|=(1<<ADSC);//启动AD转换

       while (ADCSRA & (1<<ADSC));

       tl=ADCL;

       th=ADCH;

       th&=0x03;

       t=th*256+tl;

       rbuf=t;

       if (intflg) adc_send();

       //for (n=0;n<600;n++);

        }

        cmp();

        th=sbuf2;

        tl=sbuf2;

   

        adc_init0();

        for (i=0;i<32;i++)

        {

       ADCSRA|=(1<<ADSC);//启动AD转换

       while ((ADCSRA & (1<<ADSC)));

       vl=ADCL;

       vh=ADCH;

       vh&=0x03;

       v=vh*256+vl;

       rbuf=v;

       if (intflg) adc_send();

       //for (n=0;n<600;n++);

        }

        cmp();

        if (intflg) adc_send();

        vh=sbuf2;

        vl=sbuf2;

       

        if (flg==1)

        {

          flg=0;

           sbuf1=vh;

           sbuf1=vl;

           sbuf1=th;

           sbuf1=tl;

           sum=sbuf1;

           for (i=1;i<5;i++)

          {

             sum^=sbuf1;

          }

           sbuf1=sum;          

    }

        else

        {

           flg=1;

           sbuf0=vh;

           sbuf0=vl;

           sbuf0=th;

           sbuf0=tl;

           sum=sbuf0;

           for (i=1;i<5;i++)

          {

             sum^=sbuf0;

          }

           sbuf0=sum;

    }



}

}









void main(void)

{

unsigned char an;

CLI();

io_init();

usart_init();

PORTC|=0x08;

am=PIND;

am&=0xfc;

an=(PINC&0x30);

am=((an<<2)|am);

SEI();

adc_save();

}

wind 发表于 2005-5-1 09:34:09

/*多字节点名测试程序,收4字节:41,01,02,03,

发6字节:38,12,13,14,15,16,正常*/





#include <iom8v.h>

#include <macros.h>

#define fosc 3686400

#define baud 14400

#define name 0x41



unsigned char intflg=0,c=0,resb,res={name,0x01,0x02,0x03};

//c:

static void io_init(void)

{

        PORTB = 0x01;

        DDRB = 0x01;

        PORTC = 0x00;

        DDRC = 0x08;

        PORTD = 0x0;

        DDRD = 0x00;

}



void usart_init(void)

{

UCSRB = 0x00; //disable while setting baud rate

UCSRA = 0x01;

UCSRC=0x86;

UBRRL = ((fosc/16/baud-1)%256);

UBRRH = ((fosc/16/baud-1)/256);

UCSRB=0x9c;

}



void usart_t(unsigned char f)

{

while (!(UCSRA & (1<<UDRE)) );

UCSRB &= ~(1<<TXB8);//第九位清零

UDR=f;

while (!(UCSRA & (1<<TXC)) );

}



void putchar(unsigned char ch)

    {

       unsigned int i;

       PORTC&=0xf7;

   while (!(UCSRA&(1<<UDRE)));

   UDR=ch;

       for (i=0;i<5000;i++);

   PORTC|=0x08;   

    }



#pragma interrupt_handler usart_r:12

void usart_r(void)

{

unsigned char r;

CLI();

r=UDR;

resb=r;

c++;

putchar(r);

SEI();

}



void jur(void)

{

unsigned char m=0,n,j;



for (n=0;n<10;n++)

{

   if(m<4)

   {

   if (resb==res)

   {

          m++;

       }

        }

}

switch (m)

{

   case 0:

          c=0;

                  break;

   case 1:

         

   case 2:

            

   case 3:

         for (n=0;n<m;n++)

               {

                  resb=res;

               }               

               c=m;

         break;   

   

   case 4:

         c=0;

               intflg=1;

               break;

   default: break;

   }

   

   //putchar(c);

}

       

void adc_send(void)

{   

    unsigned char buf;

        unsigned int i;

        CLI();

    PORTC&=0xf7;

       

        buf=0x38;

        buf=0x12;

        buf=0x13;

        buf=0x14;

        buf=0x15;

        buf=0x16;

        for(i=0;i<6;i++)

                usart_t(buf);

        for (i=0;i<5000;i++);

    PORTC|=0x08;

        intflg=0;

    SEI();

}



void main(void)

{

CLI();

io_init();

usart_init();

PORTC|=0x08;

SEI();

while(1)

{

   if(c>=4)

   jur();

   if(c>=20) c=0;

   while(intflg)

   {

    adc_send();       

   }

}

}

wind 发表于 2005-5-1 09:38:17

谢谢老师和各位前辈的帮助,小子我小有进步,沾沾自喜,将程序贴出来,敬请各位批评斧正,望各位不吝赐教!再次感谢!!!!

PS:五一祝各位辛苦工作的朋友们快乐!

wind 发表于 2005-5-1 09:41:50

忘了注释,程序中的putchar()为监视用,可以不予考虑。

UART,多机,485通信,MEGA8L,MAX1487,ICCAVR
页: [1]
查看完整版本: 老师,MEGA8波特率从4800到9600有什么要特别设置的地方吗?