色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > PC機(jī)與PIC單片機(jī)串行全雙工通信

          PC機(jī)與PIC單片機(jī)串行全雙工通信

          作者: 時(shí)間:2016-11-13 來(lái)源:網(wǎng)絡(luò) 收藏
          1. 實(shí)例目的:

          本實(shí)例完全建立在計(jì)算機(jī)軟件的基礎(chǔ)上,利用PROTEUS軟件構(gòu)建一個(gè)單片機(jī)系統(tǒng),利用VB編寫(xiě)一個(gè)計(jì)算機(jī)控制軟件和單片機(jī)系統(tǒng)串行通信,計(jì)算機(jī)上的控制軟件可以發(fā)送一個(gè)值在0——999之間的數(shù),在單片機(jī)系統(tǒng)上顯示出來(lái),單片機(jī)系統(tǒng)上也可輸入一個(gè)相同值域的數(shù)并在計(jì)算機(jī)控制軟件上顯示出來(lái)。本實(shí)例主要是為了展示虛擬串行通信的仿真。

          本文引用地址:http://cafeforensic.com/article/201611/316210.htm

          2. 系統(tǒng)配置

          本實(shí)例雖然簡(jiǎn)單,但是要想看到想要的仿真結(jié)果,建立虛擬的串口連接是必不可少的。要想仿真串行通信,必須要把單片機(jī)系統(tǒng)上的串行口與計(jì)算機(jī)上的串行口連接,這樣他們之間才能傳輸數(shù)據(jù),但由于是仿真,實(shí)際沒(méi)有相連接,所以需要?jiǎng)?chuàng)建一對(duì)虛擬串行口并使他們相連,這里我使用的是這個(gè)軟件Virtual Serial Ports Driver XP 5.1(VSPD XP),打開(kāi)后的界面如圖1所示。在右面“ADD PAIR”按鈕的旁邊的下拉選項(xiàng)中一個(gè)選擇“COM3”,一個(gè)選擇

          “COM4”,然后點(diǎn)擊“ADD PAIR”按鈕,這樣就完成了虛擬串口“COM3”和“COM4”的連接,完成后如圖1所示。簡(jiǎn)單吧?!

          另外,你還要選擇一個(gè)串口調(diào)試軟件作為你的調(diào)試軟件,因?yàn)楫?dāng)你單片機(jī)系統(tǒng)弄完以后而計(jì)算機(jī)上的控制軟件還沒(méi)有編時(shí),沒(méi)有串口調(diào)試軟件的話,你就沒(méi)法知道你單片機(jī)系統(tǒng)正確與否。這種軟件網(wǎng)上多如牛毛,隨便找一個(gè)。我的軟件為SSCOM32,界面如圖2所示。

          功能與用法這里就不一一介紹了,反正既能接收又能發(fā)送,實(shí)例需要的功能他都可以調(diào)試。

          3.單片機(jī)系統(tǒng)

          單片機(jī)硬件:

          電路如圖3所示。

          本實(shí)例采用的單片機(jī)依然是PIC16F877,他含有UASRT模塊,有了它才能進(jìn)行串行通信。顯示部分采用3位數(shù)碼管共陽(yáng)輸出。鍵盤(pán)采用矩陣鍵盤(pán)。這里需要特別說(shuō)明的是,由于是仿真,沒(méi)有采用電平轉(zhuǎn)換芯片MAX232將TTL電平轉(zhuǎn)換成RS232的電平,實(shí)際這一步是必需的。串行口的設(shè)置需要特別注意,由于本實(shí)例單片機(jī)程序中設(shè)置的波特率是9600,8位數(shù)據(jù),無(wú)奇偶校驗(yàn),所以串行口也要一樣設(shè)置,這里由于建立的是“COM3”“COM4”之間的虛擬連接,端口號(hào)一定要設(shè)置成“COM3”或“COM4”,這是關(guān)鍵!如圖4所示。

          單片機(jī)軟件:

          單片機(jī)軟件主要由以下幾個(gè)部分組成:初始化程序,顯示程序,鍵盤(pán)輸入程序,串行接收程序,串行發(fā)送程序。

          程序采用C語(yǔ)言,簡(jiǎn)單明了,經(jīng)過(guò)PICC編譯通過(guò)。

          全部程序如下:

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

          * 標(biāo)題:PCtoPIC *

          * 用途:用于上位機(jī)與單片機(jī)之間的通訊(本例為下位機(jī)軟件) *

          * 時(shí)間: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;//初始化鍵盤(pán)按鍵標(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; //開(kāi)放外設(shè)中斷

          RCIE=1; //開(kāi)放串行口中斷

          ei(); //開(kāi)放總中斷

          }

          //顯示需要的延時(shí)

          void delay()

          {

          int i;

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

          }

          //發(fā)送子程序

          void send_usart()

          {

          uch i;

          for(i=0;i<3;i++)//每次發(fā)3個(gè)數(shù)據(jù)

          {

          if(i==0)TXREG=data/100+0x30;//求得百位

          if(i==1)TXREG=data%100/10+0x30; //求得十位

          if(i==2)TXREG=data%10+0x30; //求得個(gè)位

          while(1)

          {

          if(TXIF==1)break;//等待發(fā)送完成

          }

          }

          }

          //中斷接收子程序

          void interrupt receive(void)

          {

          if(point<3)//是否已經(jīng)接收到3個(gè)數(shù)據(jù)

          buffer[point++]=RCREG-48;//沒(méi)有,繼續(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;//個(gè)位

          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];//個(gè)位送顯

          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();

          }

          //鍵盤(pán)(線反轉(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;//原來(lái)的個(gè)位變成十位

          }

          if(flag==3)//第三次按鍵

          {

          temp3=temp;

          data=temp1*100+temp2*10+temp3;//原來(lái)的十位變成百位

          flag=4;//屏蔽按鍵

          }

          }

          //主程序

          main()

          {

          init();

          while(1)

          {

          presskey();

          display(data);

          }

          }

          4. 計(jì)算機(jī)控制軟件

          上位機(jī)軟件是用VB編寫(xiě)的,功能很簡(jiǎn)單,主要有發(fā)送和接收兩個(gè)功能。軟件的界面如圖5所示。

          軟件主要有2個(gè)“TextBox”,3個(gè)按鈕,和一些文本控件組成。

          現(xiàn)把所有程序都貼出來(lái):

          Private Sub Cmdquit_Click()

          i = MsgBox("您要離開(kāi)嗎?", 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位補(bǔ)足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個(gè)字符到接收緩沖區(qū)都觸發(fā)接收事件

          MSComm1.SThreshold = 1

          MSComm1.PortOpen = True

          End Sub

          Private Sub Label6_Click()

          Shell "explorer.exe http://blog.163.com/wujieflash" 我博客的超連接,多多捧場(chǎng)

          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 ("請(qǐng)輸入數(shù)字字符!")

          End If

          End Sub

          軟件是簡(jiǎn)單了點(diǎn),但功能卻齊全的。

          5. 總結(jié)

          這次搞得這個(gè)實(shí)例仿真的確有點(diǎn)麻煩,不過(guò)的確能了解很多關(guān)于這串行通信方面的知識(shí),經(jīng)過(guò)自己親自動(dòng)手實(shí)現(xiàn),感覺(jué)也是蠻不錯(cuò)的。我想大多和我一樣的菜鳥(niǎo)或正在找尋這方面資料的朋友一定會(huì)獲益非淺的。



          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉