老师,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为标志位
}
} 你先写一个最简单的使用9600输出的测试程序,看看能否运行。
另外请你讲一下,你使用2400、4800时,它们设置和计算同什么有关? 老师,这是我的测试程序,可以正常发送
/*测试 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的值只和晶振,波特率有关吧。
请教老师,谢谢! 另外,当内部晶振到4M(外部晶振我只有3.57的)时,从2400到14400的通信都不正确了。为什么?
求助啊! 首先你仅编写一个简单通用的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
使用简单的发送程序先验证和掌握如何正确的调整波特率,然后再进入你的多机通信程序的调试,此时就是你的程序问题了。 老师,我原来的发送测试程序可以在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);
}
} 我改到内部4M,只改了熔丝位,和UBRRL=0x19,计算机可以正确收到5A。
19.2k时,UBRRL=0x0c,收到10,这是不是超出的意思?我是新手,乱猜的,请老师指导,谢谢! 4M接发,2400正常,4800有误码,9600误码高,只改动UBRRL 首先你应该验证在“最简单的、最基本的发送”时(不用485、不接受),在4M下2400、4800、9600都没问题(应该没问题的)。
然后再考虑发和收的结合以及使用RS485。另外,RS485一般是半双工方式工作,485发送和接受转换中间要加一定的延时时间,否则会丢“位”。 接了MAX232,试了最简单的、最基本的发送时(不用485、不接受),在4M下2400、4800、9600都没问题
收有点问题 /*单字节地址点名,发送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();
} /*多字节点名测试程序,收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();
}
}
} 谢谢老师和各位前辈的帮助,小子我小有进步,沾沾自喜,将程序贴出来,敬请各位批评斧正,望各位不吝赐教!再次感谢!!!!
PS:五一祝各位辛苦工作的朋友们快乐! 忘了注释,程序中的putchar()为监视用,可以不予考虑。
UART,多机,485通信,MEGA8L,MAX1487,ICCAVR
页:
[1]