我使用ATEMGA16A做控制,PB0接485的RE/DE控制端,串口調制助手發數據,一個幀的格式是24是幀頭,2C是幀尾,把中間的數據(不定長)加起來,這其中不包括2C前一個字節的數據(校驗和)。最后發送校驗和與數據長給串口。PD0+PD1是RXD和TXD,F在的情況是單片機根本收不到幀頭。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,沒回數
幫頂上!!
歡迎光臨 (http://www.zg4o1577.cn/bbs/) | Powered by Discuz! X3.1 |