**************************************************************************************
工程名稱:雙機通信 說明:此程序可以實現(xiàn)兩個單片機之間的相互通信;串口采用方式1 工作,10位異步接受和發(fā)送,波特率可變,由定時器1控制;且含有校驗 程序說明:SCON:串口通信控制寄存器 SBUF:串行口的收發(fā)緩沖寄存器 PCON:電源管理寄存器。當(dāng)SMOD=1時串行口的波特率加倍。 IE:中斷允許寄存器。ES=1表示允許串行口中斷 TI:發(fā)送中斷標(biāo)志位,TI由硬件置位,置位表示一幀信息發(fā)送結(jié)束,TI在發(fā)送數(shù)據(jù)前必須由軟件清0 RI:接收中斷標(biāo)志位,RI由硬件置位,置位表示一幀信息接收結(jié)束,RI在接收數(shù)據(jù)前必須由軟件清0 完成日期:2009年8月18日 修改日期:2009年8月23日 *******************************************************************************************/
#include<reg51.h> //將51中定義常用特殊功能寄存器的變量定義文件包含進(jìn)來
#include "lcd12864.h" unsigned long vo_num1=0;//接收到的頻率值
unsigned long vo_num3=0;// 接收到的失真度 unsigned int vo_num4=0;//緩存校驗值 unsigned char vo_num2[8];//緩存我們串口接收到的數(shù)據(jù) unsigned char m=0; unsigned int buf; unsigned int pf=0;//校驗和 #define seg_c P2 //將數(shù)碼管的段顯示定義到P2口 #define bit_c P0 //將數(shù)碼管的位選擇定義到P0口 #define fosc 22118400 //定義晶體振蕩頻率 #define bps 9600 //定義我們要通訊的波特率 #define th1 256-(fosc/12/16/bps) //利用宏計算出我們要給定時器中賦什么樣的值才能滿足我們需要的波特率 //將0-F 查表 成我們鍵盤對應(yīng)的字符 unsigned char code seg[11]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x09,0xff};//定義從0-9 所對應(yīng)的段碼 unsigned char num[8]={9,8,7,6,5,4,3,2}; //聲明8個顯示緩存 對應(yīng)我們數(shù)碼管的8個位 /********************************************************************************** 函數(shù)名稱:串口初始化函數(shù) **********************************************************************************/ void serial_init (void) //在使用串口模式1 前要初始 化串口寄存器等... { SCON=0x50; //串口工作于方式1,10位異步接收/發(fā)送,波特率可變 TMOD=0X20; //因為模式1用到了定時器1的自動重裝模式,所以要這樣設(shè)置定時器 PCON=0X00; //為了讓通訊速率更快,設(shè)置SMOD=1 那么它所在的寄存器PC0N=0X80 ,串行口的波特率加倍。 TH1=th1; //將宏計算的定時器初值放到TH1中 TL1=th1; TR1=1;//啟動定時器來產(chǎn)生串口工作所需要的波特率 ES =1;//允許出串口中斷 EA=1; //打開總中斷允許位 } /**********************************************************************************
函數(shù)名稱:串口發(fā)送數(shù)據(jù)函數(shù) **********************************************************************************/ void putbyte(unsigned char byte)// 利用硬件串口方式1 發(fā)送一個字節(jié)數(shù)據(jù)
{ SBUF=byte;//將要發(fā)送的數(shù)據(jù)送到發(fā)送緩沖區(qū)域,系統(tǒng)自動發(fā)送 while(!TI);//查詢是否發(fā)送結(jié)束 當(dāng)TI=1 代表發(fā)送結(jié)束 TI=0;//清發(fā)送結(jié)束位方便下一次發(fā)送 } /********************************************************************************** 函數(shù)名稱:串口接收數(shù)據(jù)函數(shù) 說明:采用中斷方式接收數(shù)據(jù),串口中斷的服務(wù)號是4 **********************************************************************************/ //串口中斷服務(wù)函數(shù) 無論接收中斷或者發(fā)送中斷都能進(jìn)來 serial () interrupt 4 { if(RI) //RI=1,表示一楨數(shù)據(jù)接收完 { vo_num2[m]=SBUF; m++; // if(m>8) // m=0; } RI=0; //RI清0之后才能接收到下一幀數(shù)據(jù)。 } /**********************************************************************************
函數(shù)名稱:軟件延時函數(shù) **********************************************************************************/
void delay(unsigned char ms) //軟件延遲函數(shù) { unsigned int a=0; while(ms--)
{ for(a=0;a<10;a++); } } /**********************************************************************************
函數(shù)名稱:顯示函數(shù) 說明:數(shù)碼管段選是P2口,位選是P0口。 **********************************************************************************/
void display(unsigned int dis)
{ unsigned char loop=0; num[0]=10; num[1]=10; num[2]=10; num[3]=dis/10000; //得到要顯示數(shù)據(jù)的萬位 num[4]=(dis%10000)/1000; //得到要顯示數(shù)據(jù)的千位 num[5]=(dis%1000)/100; //得到要顯示數(shù)據(jù)的百位 num[6]=(dis%100)/10; //得到要顯示數(shù)據(jù)的十位 num[7]=(dis%10); //得到要顯示數(shù)據(jù)的個位 for(loop=0;loop<8;loop++) { bit_c=~(0x01<<loop); seg_c=seg[num[loop]]; delay(6); seg_c=0xff; //在這里加了這句話,消除鬼影 } } /********************************************************************************** 函數(shù)名稱發(fā)送校驗函數(shù) 說明: **********************************************************************************/
void check_transport( unsigned int buf)
{ do { pf=0x00; //校驗和清零 putbyte(buf); //發(fā)送數(shù)據(jù)并求解校驗和 pf=(pf+buf&0x01+buf&0x02+buf&0x04+buf&0x08+buf&0x10+buf&0x20+buf&0x40+buf&0x80); //求解校驗和 putbyte(pf); //發(fā)送校驗和 } while(SBUF!=0);
} /********************************************************************************** 函數(shù)名稱:接收校驗函數(shù) 說明: **********************************************************************************/
void check_receive() { while(1) { pf=0x00; //校驗和清零 // vo_num4=SBUF; // pf=pf+(vo_num4&0x01+vo_num4&0x02+vo_num4&0x04+vo_num4&0x08+vo_num4&0x10+vo_num4&0x20+vo_num4&0x40+vo_num4&0x80); vo_num2[m]=SBUF;
pf=pf+( vo_num2[m]&0x01+vo_num2[m]&0x02+ vo_num2[m]&0x04+ vo_num2[m]&0x08+ vo_num2[m]&0x10+ vo_num2[m]&0x20+ vo_num2[m]&0x40+vo_num2[m]&0x80); //求解校驗和 if((SBUF^pf)==0x00) //判斷求出的校驗和與接收到的校驗和是否相等 { putbyte(0x00); m++; break;
} else { putbyte(0xff); //如果不相等。則發(fā)送ff } }//while(1) } /**********************************************************************************
函數(shù)名稱:主函數(shù) 說明: **********************************************************************************/
void disp(void)
{ lcd_init(0); refrash_charactor(); lcd_clear(); str_1="頻率: Hz"; str_2="失真度:0. "; lcd_display(1,1,str_1);
lcd_display(1,2,str_2); } main()
{ unsigned char temp; serial_init (); //在使用串口模式1 前要初始 disp(); while(1)
{ // putbyte(0xeb) ; // putbyte(0x90) ; // putbyte(0xaa) ; // m=0; // check_receive(); if(vo_num2[0]==0xeb&&vo_num2[1]==0x90&&vo_num2[2]==0xaa) { vo_num1=vo_num2[3]*256+vo_num2[4];//頻率 vo_num3=(vo_num2[5]*256+vo_num2[6])*10; //失真度 refrash_charactor(vo_num1,vo_num3); lcd_display(4,1,freq); lcd_display(6,2,dist); m=0; } }//while(1) } |
|