我使用ATEMGA16A做控制,PB0接485的RE/DE控制端,串口调制助手发数据,一个帧的格式是24是帧头,2C是帧尾,把中间的数据(不定长)加起来,这其中不包括2C前一个字节的数据(校验和)。最后发送校验和与数据长给串口。PD0+PD1是RXD和TXD。现在的情况是单片机根本收不到帧头。WHY?
程序如下:
// Target : M16 // Crystal: 1.0000Mhz
#include <iom16v.h> #include <macros.h>
#define uchar unsigned char #define uint unsigned int
#define BAUD 4800 #define F_CPU 1000000 #define RW PORTB0
void delay(uint ms) { uint l,j; for(j=0;j<ms;j++) for(l=0;l<7373;l++); //延时1ms }
void port_init(void) //端口初始化 { PORTA = 0x00; DDRA = 0x00; PORTB = 0x00; DDRB = 0x01; PORTC = 0x00; //m103 output only DDRC = 0xff; PORTD = 0xfd; DDRD = 0xfe; }
void uart_init(void) //串口初始化 { UCSRB = 0x00; //接收发送中断禁止 // RXCIE 7 接收结束中断使能 // TXCIE 6 发送结束中断使能 // UDRIE 5 数据寄存器空中断使能 // RXEN 4 接收使能 // TXEN 3 发送使能 // UCSZ2 2 与UCSZ1 UCSZ0 结合确定字符长度,011为8位 // RXB8 1 接收数据位8 // TXB8 0 发送数据位8 UCSRA = 0x00;//不倍速 // RXC 7 接收结束标志位 // TXC 6 发送结束标志位 // UDRE 5 数据寄存器空标志位 // FE 4 帧错误标志位,在写UCSRA时必须写0 // DOR 3 数据溢出标志位,在写UCSRA时必须写0 // PE 2 奇偶校验错误标志位 // U2X 1 倍数发送 // MPCM 0 多处理器模式 UCSRC|= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //异步,数据格式8,没有校验,1位停止位 // URSEL 7 写UCSRC时,URSEL应设置为 1。UBRRH时为0 // UMSEL 6 0异步1同步 // UPM1 5 奇偶校验模式,UPM1:UPM0,00禁止;10偶校验;11奇校验 // UPM0 4 // USBS 3 停止位选择,0一位,1二位。 // UCSZ1 2 // UCSZ0 1 // UCPOL 0 用于同步模式,异步清零 UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率设置 UBRRH = (F_CPU / BAUD / 16 - 1) / 256;
UCSRB|= (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //接收中断使能,接收使能,发送使能 }
uint uart_receive (void) // 等待获得一个字节数据 { PORTB&=~(1<<RW); while ( !(UCSRA & (1<<RXC)) ); //UCSRA //Bit 7 – RXC: USART 接收结束,接收缓冲器中有未读出的数据时 RXC 置位,否则清零。 //Bit 6 – TXC: USART 发送结束,发送移位缓冲器中的数据被送出,且当发送缓冲器 (UDR) 为空时TXC 置位。 //Bit 5 – UDRE: USART数据寄存器空UDRE标志指出发送缓冲器(UDR)是否准备好接收新数据。UDRE为1说明缓冲器为空,已准备好进行数据接收。 //Bit 4 – FE: 帧错误 //Bit 3 – DOR: 数据溢出 //Bit 2 – PE: 奇偶校验错误 //Bit 1 – U2X: 倍速发送 //Bit 0 – MPCM: 多处理器通信模式 return UDR; } void init_devices(void) //端口初始化 { //stop errant interrupts until set up CLI(); //disable all interrupts port_init(); uart_init(); MCUCR = 0x00; GICR = 0x00; TIMSK = 0x00; //timer interrupt sources SEI(); //re-enable interrupts } //*************串口发送字节数据,调用前先使485的发送脚置高PB0,使用232串口的话,不必处理*********// void uart_send(uint i) { PORTB|=(1<<RW); //485发送使能 while(!(UCSRA&(1<<UDRE))); //等待发送结束 UDR=i; UCSRA|=0x40; //清除发送结束标志位 delay(50); PORTB&=~(1<<RW); //485接收使能 } //*****************************************主程序*********************************************// void main(void) { uint sum=0,overflag=0; uint data_r1=0,data_r2=0,data0=0; //参数初始化 init_devices(); //接收、发送使能 while(data0!=0x24) //检查是否为帧头 { data0=uart_receive(); } while(data_r2!=0x2c) //检查是否为帧尾 { data_r2=uart_receive(); sum=sum+data_r1; data_r1=data_r2; overflag=overflag+1; } overflag=overflag-1; sum=sum%0xff; uart_send(sum); uart_send(overflag); }
发送数据格式为 24 01 02 03 2C,没回数 |