51單片機(jī)與計(jì)算機(jī)通信
首先我們先來了解一下51單片機(jī)與計(jì)算機(jī)進(jìn)行通信的實(shí)現(xiàn)方法。先來看一個(gè)實(shí)現(xiàn)這個(gè)功能的基本電路。
圖中的P1就是仿真用的一個(gè)串口接口,這個(gè)仿真電路要實(shí)現(xiàn)與計(jì)算機(jī)通信功能需要用到其他兩個(gè)軟件,一個(gè)是虛擬串口驅(qū)動(dòng)軟件,另外一個(gè)是串口助手軟件,這兩個(gè)軟件在網(wǎng)上都很容易找到。我使用的是Virtual Serial Port Driver和丁丁串口助手,你也可以使用自己熟悉的軟件,如果找不到或使用,安裝這兩個(gè)軟件有問題可以私信。
(資料圖)
虛擬串口驅(qū)動(dòng)軟件安裝后配置兩個(gè)成對(duì)的虛擬串口一個(gè)對(duì)應(yīng)仿真電路中的串口接口,一個(gè)對(duì)應(yīng)在串口助手軟件上,這樣就相當(dāng)于將兩個(gè)軟件通過虛擬串口連接在一起了,將他們配置成相同的串口參數(shù)之后,這時(shí)就可以實(shí)現(xiàn)相互發(fā)送信息了。
這里需要注意的一個(gè)問題,上一篇文章中最后部分列舉了一個(gè)關(guān)于使用12MHz和11.0592MHz兩種晶振配置特定波特率對(duì)應(yīng)定時(shí)器數(shù)據(jù)寄存器的數(shù)據(jù)對(duì)應(yīng)的表格,里面還包含各配置值對(duì)應(yīng)的波特率精度,從圖中可以看出使用12MHz晶振時(shí)誤差率普遍比較大,而使用11.0592MHz時(shí)幾乎沒有誤差,所以現(xiàn)在知道為啥你手上的單片機(jī)使用的晶振都是11.0592MHz的了吧!雖然使用12MHz的晶振進(jìn)行通信計(jì)算機(jī)也能捕獲到數(shù)據(jù),但為了保險(xiǎn)起見,若日后你使用51單片機(jī)開發(fā)項(xiàng)目需要使用到串口時(shí)要注意晶振的選擇,當(dāng)然如果使用其他單片機(jī)就要另說了,最簡單的比如STC生產(chǎn)的1T型的51單片機(jī)(即一個(gè)機(jī)器周期等于一個(gè)時(shí)鐘周期,它的執(zhí)行效率理論上是傳統(tǒng)單片機(jī)的12倍,實(shí)際因程序復(fù)雜程度不一會(huì)低一點(diǎn)),就需要參考對(duì)應(yīng)說明了。
接下來我們要怎么驗(yàn)證單片機(jī)與計(jì)算機(jī)進(jìn)行通信了呢?我們現(xiàn)在就編程實(shí)現(xiàn)計(jì)算機(jī)串口助手發(fā)送數(shù)據(jù),單片機(jī)收到數(shù)據(jù)就做出回應(yīng)將數(shù)據(jù)回傳給計(jì)算機(jī)。
現(xiàn)在我們先來看看程序的具體實(shí)現(xiàn)過程。
/*
*這是一個(gè)串口通信應(yīng)用程序
*目的是將串口助手發(fā)送過來的數(shù)據(jù)回傳
*/
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
u8 data_L,data_H;
u8 T0_cnt = 0;
u8 T0_s = 0;
u8 T1_cnt = 0;
u8 crol = 0xfe;
u8 temp = 0;
u8 code num_codelist[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u8 ms);
void data_init(void);
//void Timer_init(void);
void display(void);
void uart_init(void);
void main(void)
{
//Timer_init();
uart_init();while(1){data_init();display();}
}
void delay(u8 ms)
{
u8 i,j;for(i=0; i
}
void data_init(void)
{
data_L = T0_s%10;data_H = T0_s/10;
}
void display(void)
{
P2 = 0xfe;P0 = num_codelist[data_H];delay(1);P2 = 0xfd;P0 = num_codelist[data_L];delay(1);
}
void uart_init(void) //串口初始化
{
TMOD = 0x20;SCON = 0x50;TH1 = 0xFD;//9600TL1 = TH1;PCON = 0x00;EA = 1;ES = 1;TR1 = 1;
}
void uart() interrupt 4 //串口中斷
{
if(RI){ RI = 0; temp=SBUF; SBUF=temp; while(TI==0); TI=0;}
}
現(xiàn)在來看一下程序的仿真效果:
可以看到串口助手發(fā)送的數(shù)據(jù)馬上又被單片機(jī)傳回來了。這個(gè)程序沒有多少新的代碼,主要就是void uart_init(void)和void uart() interrupt 4這兩個(gè)函數(shù),其中一個(gè)串口初始化函數(shù),另一個(gè)是串口中斷函數(shù)。void uart_init(void)這個(gè)函數(shù)里面設(shè)置串口模式,定時(shí)器計(jì)數(shù)值以及串口中斷設(shè)置。void uart() interrupt 4串口中斷函數(shù)里面非常簡單,就是獲取收到的數(shù)據(jù)然后將數(shù)據(jù)發(fā)送出去。
程序?qū)崿F(xiàn)過程是非常簡單吧,看到這里趕緊去試試看吧。
接下來
51單片機(jī)雙機(jī)通信
在項(xiàng)目開發(fā)時(shí)我們用到串口更多是和其他芯片進(jìn)行通信,所以這里我們再來實(shí)現(xiàn)一個(gè)單片機(jī)雙機(jī)通信的例子,先來看看這個(gè)電路圖。
現(xiàn)在來看看我們要實(shí)現(xiàn)雙機(jī)通信的代碼:
/*
*這是一個(gè)串口通信應(yīng)用程序
*目的是實(shí)現(xiàn)單片機(jī)的雙機(jī)通信
*/
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
sbit key1 = P3^0;
sbit key2 = P3^1;
sbit key3 = P3^2;
sbit key4 = P3^3;
u8 data_L,data_H;
u8 T0_cnt = 0;
u8 T0_s = 0;
u8 T1_cnt = 0;
u8 crol = 0xfe;
u8 temp = 0;
u8 temp_key = 0; //定義一個(gè)變量用來存放臨時(shí)按鍵值
u8 key_num = 0;//定義一個(gè)數(shù)字,用來顯示
u8 code num_codelist[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(u8 ms);
void data_init(void);
//void Timer_init(void);
void display(void);
void key_init(void);
void uart_init(void);
void main(void)
{
//Timer_init();
key_init();uart_init();while(1){data_init();display();}
}
void delay(u8 ms)
{
u8 i,j;for(i=0; i
}
void data_init(void)
{
data_L = key_num%10;data_H = key_num/10;
}
void display(void)
{
P2 = 0xfe;P0 = num_codelist[data_H];delay(1);P2 = 0xfd;P0 = num_codelist[data_L];delay(1); P1 = key_num; //P1端口LED顯示
}
void key_init(void) //按鍵初始化
{
IT0=1; //外部中斷0為下降沿觸發(fā)IT1=1; //外部中斷1為下降沿觸發(fā)EX0=1; //開EX0中斷EX1=1; //開EX1中斷EA=1; //開總中斷
}
void uart_init(void) //串口初始化
{
TMOD = 0x20;SCON = 0x50;TH1 = 0xFD;//9600TL1 = TH1;PCON = 0x00;EA = 1;ES = 1;TR1 = 1;
}
//外部中斷0服務(wù)例程
void P3_2_key_func(void) interrupt 0
{
//將外部中斷0對(duì)應(yīng)的按鍵K3設(shè)置為按鍵加功能if(0 == key3){ delay(15); if(0 == key3) { if(key_num < 100) { key_num++; } else { key_num = 0; } } SBUF = key_num; //串口發(fā)送 while(TI==0); TI=0;}
}
//外部中斷1服務(wù)例程
void P3_3_key_func(void) interrupt 2
{
//將外部中斷0對(duì)應(yīng)的按鍵K4設(shè)置為按鍵減功能if(0 == key4){ delay(15); if(0 == key4) { if(key_num > 0) { key_num--; } else { key_num = 100; } } SBUF=key_num; //串口發(fā)送 while(TI==0); TI=0;}
}
void uart() interrupt 4
{
if(RI){ RI = 0; key_num = SBUF; //串口接收}
}
將這段代碼同時(shí)下載到兩個(gè)單片機(jī)中就實(shí)現(xiàn)兩個(gè)單片機(jī)同步了,現(xiàn)在看看仿真結(jié)果:
這個(gè)程序中的大多數(shù)代碼都是前面的文章中類似的,只做簡單修改就可以,接下來的時(shí)間自己看這代碼理一理邏輯,如果有理解不了的地方再留言或私信吧。
標(biāo)簽: