PC機與PIC單片機串行全雙工通信
本實例完全建立在計算機軟件的基礎(chǔ)上,利用PROTEUS軟件構(gòu)建一個單片機系統(tǒng),利用VB編寫一個計算機控制軟件和單片機系統(tǒng)串行通信,計算機上的控制軟件可以發(fā)送一個值在0——999之間的數(shù),在單片機系統(tǒng)上顯示出來,單片機系統(tǒng)上也可輸入一個相同值域的數(shù)并在計算機控制軟件上顯示出來。本實例主要是為了展示虛擬串行通信的仿真。
本文引用地址:http://www.ex-cimer.com/article/201611/316210.htm2. 系統(tǒng)配置
本實例雖然簡單,但是要想看到想要的仿真結(jié)果,建立虛擬的串口連接是必不可少的。要想仿真串行通信,必須要把單片機系統(tǒng)上的串行口與計算機上的串行口連接,這樣他們之間才能傳輸數(shù)據(jù),但由于是仿真,實際沒有相連接,所以需要創(chuàng)建一對虛擬串行口并使他們相連,這里我使用的是這個軟件Virtual Serial Ports Driver XP 5.1(VSPD XP),打開后的界面如圖1所示。在右面“ADD PAIR”按鈕的旁邊的下拉選項中一個選擇“COM3”,一個選擇
“COM4”,然后點擊“ADD PAIR”按鈕,這樣就完成了虛擬串口“COM3”和“COM4”的連接,完成后如圖1所示。簡單吧?!
另外,你還要選擇一個串口調(diào)試軟件作為你的調(diào)試軟件,因為當(dāng)你單片機系統(tǒng)弄完以后而計算機上的控制軟件還沒有編時,沒有串口調(diào)試軟件的話,你就沒法知道你單片機系統(tǒng)正確與否。這種軟件網(wǎng)上多如牛毛,隨便找一個。我的軟件為SSCOM32,界面如圖2所示。
功能與用法這里就不一一介紹了,反正既能接收又能發(fā)送,實例需要的功能他都可以調(diào)試。
3.單片機系統(tǒng)
單片機硬件:
電路如圖3所示。
本實例采用的單片機依然是PIC16F877,他含有UASRT模塊,有了它才能進(jìn)行串行通信。顯示部分采用3位數(shù)碼管共陽輸出。鍵盤采用矩陣鍵盤。這里需要特別說明的是,由于是仿真,沒有采用電平轉(zhuǎn)換芯片MAX232將TTL電平轉(zhuǎn)換成RS232的電平,實際這一步是必需的。串行口的設(shè)置需要特別注意,由于本實例單片機程序中設(shè)置的波特率是9600,8位數(shù)據(jù),無奇偶校驗,所以串行口也要一樣設(shè)置,這里由于建立的是“COM3”“COM4”之間的虛擬連接,端口號一定要設(shè)置成“COM3”或“COM4”,這是關(guān)鍵!如圖4所示。
單片機軟件:
單片機軟件主要由以下幾個部分組成:初始化程序,顯示程序,鍵盤輸入程序,串行接收程序,串行發(fā)送程序。
程序采用C語言,簡單明了,經(jīng)過PICC編譯通過。
全部程序如下:
/************************************************************
* 標(biāo)題:PCtoPIC *
* 用途:用于上位機與單片機之間的通訊(本例為下位機軟件) *
* 時間:2009年1月4日 *
* 作者:WUJIEFLASH *
************************************************************/
#include
//預(yù)定義
#define uch unsigned char
//顯示用碼表
const uch shu[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98,0xff};
//變量
int data,temp1,temp2,temp3,temp;
uch flag,keylock;
uch point,buffer[3];
//初始化
void init()
{
TRISB=0;
PORTB=0;
TRISC=0;
PORTC=0;
keylock=1;//初始化鍵盤按鍵標(biāo)志位,用于鎖定按鍵
//USART部件初始化
SPBRG=0x19;//設(shè)置波特率為9600bps
TXSTA=0x04;//選擇異步高速8位數(shù)據(jù)傳輸模式
RCSTA=0x80;//允許串行端口工作
TRISC=0x80;//設(shè)置為高阻態(tài),防止干擾
TXEN=1;//發(fā)送允許
CREN=1;//接收允許
PEIE=1; //開放外設(shè)中斷
RCIE=1; //開放串行口中斷
ei(); //開放總中斷
}
//顯示需要的延時
void delay()
{
int i;
for(i=0;i<1000;i++);
}
//發(fā)送子程序
void send_usart()
{
uch i;
for(i=0;i<3;i++)//每次發(fā)3個數(shù)據(jù)
{
if(i==0)TXREG=data/100+0x30;//求得百位
if(i==1)TXREG=data%100/10+0x30; //求得十位
if(i==2)TXREG=data%10+0x30; //求得個位
while(1)
{
if(TXIF==1)break;//等待發(fā)送完成
}
}
}
//中斷接收子程序
void interrupt receive(void)
{
if(point<3)//是否已經(jīng)接收到3個數(shù)據(jù)
buffer[point++]=RCREG-48;//沒有,繼續(xù)接收
else point=0;//是,指針復(fù)位
data=buffer[0]*100+buffer[1]*10+buffer[2];//組合成三位數(shù)
}
//數(shù)碼管顯示
void display(int dis_data)
{
int dis_data_ge,dis_data_shi,dis_data_bai;
dis_data_ge =dis_data%10;//個位
dis_data_shi=dis_data%100/10;//十位
dis_data_bai=dis_data/100; //百位
if(dis_data==0)//若數(shù)據(jù)為0,只顯示1位
{
dis_data_ge=0;
dis_data_shi=10;
dis_data_bai=10;
}
if(dis_data<10)//若數(shù)據(jù)小于10,則十位與百位關(guān)閉顯示
{
dis_data_shi=10;
dis_data_bai=10;
}
if(dis_data<100)//若數(shù)據(jù)小于100,則只顯示兩位
{
dis_data_bai=10;
}
RC0=0;
RC1=0;
RC2=1;
PORTB=shu[dis_data_ge];//個位送顯
delay();
RC0=0;
RC2=0;
RC1=1;
PORTB=shu[dis_data_shi];//十位送顯
delay();
RC1=0;
RC2=0;
RC0=1;
PORTB=shu[dis_data_bai];//百位送顯
delay();
}
//鍵盤(線反轉(zhuǎn)法)
void presskey()
{
uch line,column,key;
TRISD=0x07;
PORTD=0xf0;
column=PORTD & 0x07;//取列碼
TRISD=0xf0;
PORTD=0x0f;
line=PORTD&0xf0;//取行碼
key=line|column;//合成鍵值
if(key==0)keylock=0;//保證每次只按一次鍵
if(keylock==0)
{
if(key!=0)keylock=1;
switch(key)//查找鍵值
{
case 0x11:temp=3;flag++;break;
case 0x12:temp=2;flag++;break;
case 0x14:temp=1;flag++;break;
case 0x21:temp=4;flag++;break;
case 0x22:temp=5;flag++;break;
case 0x24:temp=6;flag++;break;
case 0x41:temp=9;flag++;break;
case 0x42:temp=8;flag++;break;
case 0x44:temp=7;flag++;break;
case 0x82:temp=0;flag++;break;
case 0x81:flag=4;send_usart();break;//發(fā)送
case 0x84:flag=0;data=0;break;//清零鍵
}
}
if(flag==1)//第一次按鍵
{
if(temp==0)flag=0;//若按0,則忽略
temp1=temp;
data=temp1;
}
if(flag==2)//第二次按鍵
{
temp2=temp;
data=temp1*10+temp2;//原來的個位變成十位
}
if(flag==3)//第三次按鍵
{
temp3=temp;
data=temp1*100+temp2*10+temp3;//原來的十位變成百位
flag=4;//屏蔽按鍵
}
}
//主程序
main()
{
init();
while(1)
{
presskey();
display(data);
}
}
4. 計算機控制軟件
上位機軟件是用VB編寫的,功能很簡單,主要有發(fā)送和接收兩個功能。軟件的界面如圖5所示。
軟件主要有2個“TextBox”,3個按鈕,和一些文本控件組成。
現(xiàn)把所有程序都貼出來:
Private Sub Cmdquit_Click()
i = MsgBox("您要離開嗎?", vbQuestion Or vbYesNo, "溫馨提示")
If i = 6 Then
Shell "explorer.exe http://blog.163.com/wujieflash"
End
End If
End Sub
Private Sub Cmdsend_Click()
If Len(Text1.Text) = 1 Then MSComm1.Output = "0" + "0" + Text1.Text 不滿3位補足3位再發(fā)送
If Len(Text1.Text) = 2 Then MSComm1.Output = "0" + Text1.Text
If Len(Text1.Text) = 3 Then MSComm1.Output = Text1.Text
End Sub
Private Sub cmdzero_Click()
Text2.Text = ""
Text1.Text = ""
End Sub
Private Sub Form_Load()
MSComm1.Settings = "9600,n,8,1" 設(shè)置數(shù)據(jù)傳輸率和發(fā)送字符格式
MSComm1.CommPort = 4 設(shè)置通訊串口為4
MSComm1.InputLen = 0 設(shè)置或返回一次從接受緩沖器中讀取所有字節(jié)數(shù)
MSComm1.InBufferSize = 512 設(shè)置接收緩沖區(qū)512BYTE
MSComm1.InBufferCount = 0
MSComm1.OutBufferSize = 512 設(shè)置發(fā)送緩沖區(qū)512BYTE
MSComm1.OutBufferCount = 0
MSComm1.RThreshold = 3 每3個字符到接收緩沖區(qū)都觸發(fā)接收事件
MSComm1.SThreshold = 1
MSComm1.PortOpen = True
End Sub
Private Sub Label6_Click()
Shell "explorer.exe http://blog.163.com/wujieflash" 我博客的超連接,多多捧場
End Sub
Private Sub MSComm1_OnComm()
Text2.Text = MSComm1.Input
End Sub
Private Sub Text1_KeyPress(KeyAscii As Integer)
If KeyAscii < Asc("0") Or KeyAscii > Asc("9") Then
KeyAscii = 0
MsgBox ("請輸入數(shù)字字符!")
End If
End Sub
軟件是簡單了點,但功能卻齊全的。
5. 總結(jié)
這次搞得這個實例仿真的確有點麻煩,不過的確能了解很多關(guān)于這串行通信方面的知識,經(jīng)過自己親自動手實現(xiàn),感覺也是蠻不錯的。我想大多和我一樣的菜鳥或正在找尋這方面資料的朋友一定會獲益非淺的。
評論