?? main.c
字號:
/* 通訊規(guī)則:
01:時鐘7.3728 MHz/波特率9600/9個數據位/奇校驗/1個停止位/硬件多機通訊功能/
02:通訊連接采用硬件MAX485,雙向單工
03:MAX485的RE/DE并聯接到單片機的PD2腳(高電平發(fā)送/低電平接收)
04:所有MAX485的A腳并聯/B腳并聯/D腳接TXD/R腳接RXD
05:每個上行/下行的數據包的字節(jié)個數都是一樣的(通訊數據量)
06:數據包格式: 地址_數據1_數據2_數據3_數據n_CRC8校驗碼
07:所有單元的數據接收都是采用中斷+查詢的方式
08:總是由主機向從機下發(fā)一個數據包,從機收到數據包并校驗正確后向主機回復一個數據包
09:不管是主機還是從機,如果收到的數據包有任何錯誤,都將丟棄該數據包,等效于沒有接收
10:通訊采用主機輪詢方式,從機之間不能相互通訊,必須通過主機才能交換數據
11:無效地址是0,主機地址是1,從機地址是11.12.13...廣播地址是255
*/
#include<iom16v.h>
#include <macros.h>
#include "1602.h"
#include "delay.h"
#define amount 10
#define address 1
unsigned char send[amount];
unsigned char inbox[amount];
unsigned char n=0;//記憶叫斷接收的次數
//end
//波特率9600/9個數據位/1個停止位/奇校驗/收發(fā)開啟/接收中斷/地址過濾
void usart_init(void)
{
UCSRA=0x01;
UCSRB=0x9C;
UCSRC=0xB6;
UBRRH=0x00;
UBRRL=47;
}
unsigned char crc8(unsigned char *ptr, unsigned char len)
{
unsigned char i;
unsigned char crc=0;
while(len--!=0)
{
for(i=1; i!=0; i*=2)
{
if((crc&1)!=0) {crc/=2; crc^=0x8C;}
else crc/=2;
if((*ptr&i)!=0) crc^=0x8C;
}
ptr++;
}
return(crc);
}
#pragma interrupt_handler RXC_Int: 12
void RXC_Int(void)
{
if( UCSRA&28 ){ n=UDR; n=0; UCSRA|=0x01; } else //接收出錯就重新打開地址幀篩選功能
{
if( UCSRB&2 ) n=0; //檢測到地址信息時計數清零
inbox[n]=UDR; n++; //把接收到的數據保存到收件箱
if( inbox[0]==address ) UCSRA&=254; else UCSRA|=0x01; //地址篩選
}
}
void usart_out(unsigned char *datas,unsigned char n)
{
unsigned char i=0;
PORTD |=(1<<PD4); //使MAX485處于發(fā)送狀態(tài)
while(i<n) //一共發(fā)送n個數據
{
if(i==0) UCSRB|=1; else UCSRB&=254;
UDR=*(datas+i); //裝載數據開始發(fā)送
while((UCSRA&64)==0); //等待發(fā)送結束
UCSRA|=64; //清除發(fā)送結束標志
i++; //發(fā)送次數統計
}
PORTD&=~(1<<PD4); //使MAX485處于接收狀態(tài)
}
void main()
{
usart_init();
LCD_init(); //液晶初始化
DDRD |=(1<<PD4);
DDRA |=0x07;
SEI(); //打開全局中斷,需要macros.h支持
LCD_write_string(0,0,"Send:");
LCD_write_string(0,1,"Rev:");
while(1){
send[3]=9; //更新發(fā)件箱的數據(測試代碼)
send[0]=11; //指向從機地址
send[amount-1]=crc8(send,amount-1); //計算發(fā)件箱數據的crc8校驗碼
usart_out(send,amount); //將發(fā)件箱的數據send[]發(fā)送出去;
LCD_write_string(5,0,send);
n=0; //計數復位,準備接收新數據
delay_nms(15); //等待從機回復數據,這個時間要計算好
if(n==amount && inbox[amount-1]==crc8(inbox,amount-1)) //接收正確處理與測試
{
PORTA|=(1<<PA1); delay_nms(10); PORTA&=~(1<<PA1);
}
else //接收錯誤處理與測試
{
PORTA|=(1<<PA2); delay_nms(10); PORTA&=~(1<<PA2);
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -