×
单片机 > 单片机程序设计 > 详情

PIC单片机实例9:PC机与单片机串行全双工通信

发布时间:2020-06-06 发布时间:
|
1.  实例目的:

本实例完全建立在计算机软件的基础上,利用PROTEUS软件构建一个单片机系统,利用VB编写一个计算机控制软件和单片机系统串行通信,计算机上的控制软件可以发送一个值在0——999之间的数,在单片机系统上显示出来,单片机系统上也可输入一个相同值域的数并在计算机控制软件上显示出来。本实例主要是为了展示虚拟串行通信的仿真。

2.  系统配置

本实例虽然简单,但是要想看到想要的仿真结果,建立虚拟的串口连接是必不可少的。要想仿真串行通信,必须要把单片机系统上的串行口与计算机上的串行口连接,这样他们之间才能传输数据,但由于是仿真,实际没有相连接,所以需要创建一对虚拟串行口并使他们相连,这里我使用的是这个软件Virtual Serial Ports Driver XP 5.1(VSPD XP),打开后的界面如图1所示。在右面“ADD PAIR”按钮的旁边的下拉选项中一个选择“COM3”,一个选择

“COM4”,然后点击“ADD PAIR”按钮,这样就完成了虚拟串口“COM3”和“COM4”的连接,完成后如图1所示。简单吧?!

       另外,你还要选择一个串口调试软件作为你的调试软件,因为当你单片机系统弄完以后而计算机上的控制软件还没有编时,没有串口调试软件的话,你就没法知道你单片机系统正确与否。这种软件网上多如牛毛,随便找一个。我的软件为SSCOM32,界面如图2所示。

功能与用法这里就不一一介绍了,反正既能接收又能发送,实例需要的功能他都可以调试。

3.单片机系统

单片机硬件:

电路如图3所示。

本实例采用的单片机依然是PIC16F877,他含有UASRT模块,有了它才能进行串行通信。显示部分采用3位数码管共阳输出。键盘采用矩阵键盘。这里需要特别说明的是,由于是仿真,没有采用电平转换芯片MAX232将TTL电平转换成RS232的电平,实际这一步是必需的。串行口的设置需要特别注意,由于本实例单片机程序中设置的波特率是9600,8位数据,无奇偶校验,所以串行口也要一样设置,这里由于建立的是“COM3”“COM4”之间的虚拟连接,端口号一定要设置成“COM3”或“COM4”,这是关键!如图4所示。

单片机软件:

单片机软件主要由以下几个部分组成:初始化程序,显示程序,键盘输入程序,串行接收程序,串行发送程序。

程序采用C语言,简单明了,经过PICC编译通过。

全部程序如下:

/************************************************************

* 标题:PCtoPIC                                             *

* 用途:用于上位机与单片机之间的通讯(本例为下位机软件)    *

* 时间:2009年1月4日                                      *

* 作者:WUJIEFLASH                                        *

************************************************************/                      

#include

//预定义

#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;//初始化键盘按键标志位,用于锁定按键

      

       //USART部件初始化

       SPBRG=0x19;//设置波特率为9600bps

       TXSTA=0x04;//选择异步高速8位数据传输模式

       RCSTA=0x80;//允许串行端口工作

       TRISC=0x80;//设置为高阻态,防止干扰

       TXEN=1;//发送允许

       CREN=1;//接收允许

       PEIE=1; //开放外设中断

       RCIE=1; //开放串行口中断

       ei();    //开放总中断

}

//显示需要的延时

void delay()

{

       int i;

       for(i=0;i<1000;i++);     

}

 

//发送子程序

void send_usart()

{

       uch i;

       for(i=0;i<3;i++)//每次发3个数据

       {

              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;//等待发送完成

              }

       }

}

 

//中断接收子程序

void interrupt receive(void)

{

       if(point<3)//是否已经接收到3个数据

       buffer[point++]=RCREG-48;//没有,继续接收

       else point=0;//是,指针复位

       data=buffer[0]*100+buffer[1]*10+buffer[2];//组合成三位数

}

 

//数码管显示

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)//若数据为0,只显示1位

       {

              dis_data_ge=0;

              dis_data_shi=10;

              dis_data_bai=10;

       }

       if(dis_data<10)//若数据小于10,则十位与百位关闭显示

       {

              dis_data_shi=10;

              dis_data_bai=10;

       }

       if(dis_data<100)//若数据小于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();  

}

 

//键盘(线反转法)

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;//发送

                     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编写的,功能很简单,主要有发送和接收两个功能。软件的界面如图5所示。

软件主要有2个“TextBox”,3个按钮,和一些文本控件组成。

现把所有程序都贴出来:

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位再发送

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"    '设置数据传输率和发送字符格式

MSComm1.CommPort = 4               '设置通讯串口为4

MSComm1.InputLen = 0               '设置或返回一次从接受缓冲器中读取所有字节数

MSComm1.InBufferSize = 512         '设置接收缓冲区512BYTE

MSComm1.InBufferCount = 0

MSComm1.OutBufferSize = 512        '设置发送缓冲区512BYTE

MSComm1.OutBufferCount = 0

MSComm1.RThreshold = 3             '每3个字符到接收缓冲区都触发接收事件

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 ("请输入数字字符!")

End If

End Sub

软件是简单了点,但功能却齐全的。

5.  总结

这次搞得这个实例仿真的确有点麻烦,不过的确能了解很多关于这串行通信方面的知识,经过自己亲自动手实现,感觉也是蛮不错的。我想大多和我一样的菜鸟或正在找寻这方面资料的朋友一定会获益非浅的。




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向