隨著嵌入式系統(tǒng)在電子領(lǐng)域應(yīng)用的不斷深入,可視化的單片機(jī)控制與檢測系統(tǒng)越來越成為單片機(jī)技術(shù)的應(yīng)用熱點(diǎn)。廣泛應(yīng)用到工業(yè)自動化生產(chǎn)、交通、醫(yī)療、教育和各種自動控制等領(lǐng)域,如心電監(jiān)護(hù)、全方位視頻跟蹤監(jiān)視。在這些復(fù)雜的數(shù)字系統(tǒng)中,計算機(jī)被稱為上位機(jī),通過上位機(jī)和相關(guān)的軟件實(shí)現(xiàn)傳感信號的檢測和對外部設(shè)備的控制。利用計算機(jī)實(shí)現(xiàn)可視化的控制系統(tǒng)包括上位機(jī)程序設(shè)計、接口設(shè)計和單片機(jī)系統(tǒng)設(shè)計。 單片機(jī)相比較計算機(jī)而言又叫下位機(jī),是直接對檢測對象測量和控制的系統(tǒng),有時也把接口與下位機(jī)設(shè)計在在一個系統(tǒng)中統(tǒng)稱接口電路;谟嬎銠C(jī)基礎(chǔ)的上位機(jī)程序可以提高復(fù)雜的單片機(jī)控制系統(tǒng)的人機(jī)交互功能。 本項目設(shè)計的內(nèi)容是一個簡單的溫度檢測系統(tǒng),上位機(jī)程序用來檢測和顯示單片機(jī)系統(tǒng)發(fā)送的數(shù)據(jù),下位機(jī)是一個簡單的溫度檢測系統(tǒng),通過USB接口虛擬一個串口傳輸數(shù)據(jù),上位機(jī)程序?qū)崟r顯示溫度,并通過曲線的形式描繪出溫度的變化過程。上位機(jī)程序VB6.0設(shè)計,程序執(zhí)行后,上位機(jī)程序要定時向下位機(jī)即單片機(jī)系統(tǒng)發(fā)送指令,下位機(jī)在接到命令后就開始發(fā)送溫度信息。上位機(jī)顯示的溫度曲線要能準(zhǔn)確的表示當(dāng)時的溫度,誤差不能超過5%,能過顯示的溫度范圍在20攝氏度到80攝氏度之間。上位機(jī)程序兩次接收的溫度數(shù)據(jù)間隔控制在在1秒鐘左右,能夠顯示的溫度曲線的總時間在2分鐘左右。 3.1 VB簡單認(rèn)識 VB是Visual Basic的簡稱,是由美國微軟公司于1991年開發(fā)的一種可視化的、面向?qū)ο蠛筒捎檬录?qū)動方式的結(jié)構(gòu)化高級程序設(shè)計語言,可用于開發(fā) Windows 環(huán)境下的各類應(yīng)用程序。今天我們以VB6.0為基礎(chǔ),簡單的認(rèn)識VB,然后我們就可以利用VB這個強(qiáng)大的開發(fā)工具去開發(fā)我們需要的各類程序。 3.1.1 VB6.0基本操作 在Visual Basic安裝成功之后,安裝程序自動在【開始】菜單中建立Visual Basic 6.0的程序組和程序項。單擊【開始】按扭,指向【所有程序】選項,再指向【Microsoft Visual Basic 6.0中文版】程序組,單擊【Microsoft Visual Basic 6.0中文版】選項即可啟動Visual Basic6.0中文版。 在VB6.0啟動后,屏幕上將出現(xiàn)如圖3-1所示的啟動界面,在啟動界面中會出現(xiàn)一個【新建工程】對話框。 圖3-1 VB6.0啟動界面 一、創(chuàng)建工程 在VB6.0啟動界面中的【新建工程】對話框中選擇一個合適的工程類型,然后單擊【打開】按鈕,就可以新建一個工程,新工程打開后的用戶界面如圖3-2所示。 圖3-2 VB6.0的用戶界面 二、放置控件和設(shè)置控件屬性 在用戶界面的左側(cè)是VB6.0的【工具箱】,在【工具箱】中有我們常用的各類控件,在設(shè)計窗體時我們可以直接從工具箱中選擇控件,然后在中間的【對象窗口】中按住鼠標(biāo)左鍵拖出一個矩形后,相應(yīng)的控件就放置到了用戶的編輯窗口中,對于控件的各個屬性,我們可以通過VB界面右面的【屬性窗口】設(shè)置各個控件的各種屬性,放置并調(diào)整好控件的各個屬性的【對象窗口】如圖3-3所示。 圖3-3 添加控件后的對象窗口 三、添加代碼 雙擊【對象窗口】的空白處或者某個控件,就會出現(xiàn)【代碼窗口】,代碼窗口如圖3-4所示。 圖3-4 代碼窗口 在代碼窗口中為各個事件添加相應(yīng)的代碼,在程序運(yùn)行的時候一旦某個事件發(fā)生,就會執(zhí)行相應(yīng)的代碼段,這里以Form_Load()事件為例,簡單的設(shè)計一個實(shí)例程序。Form_Load()事件是在程序啟動時調(diào)用的,這里我們添加如下代碼: Private Sub Form_Load() Form1.Caption = "示例程序" '設(shè)置窗體的標(biāo)題為“示例程序” Text1.Text = "文本框" '設(shè)置文本框的文本為“文本框” Command1.Caption = "按鈕" '設(shè)置按鈕的標(biāo)題為“按鈕” Combo1.Text = "下拉列表框" '設(shè)置下拉列表框的文本為“下拉列表框” End Sub 五、程序運(yùn)行 添加好代碼后,我們可以通過單擊工具欄上的【啟動】按鈕,或者單擊菜單欄的【運(yùn)行啟動】菜單項,也可以直接按F5鍵運(yùn)行程序,程序運(yùn)行時的界面如圖3-5所示。 圖3-5 程序運(yùn)行界面 3.2 上位機(jī)程序設(shè)計 上位機(jī)程序設(shè)計不但要求界面簡單,而且操作人性化,本項目上位機(jī)程序運(yùn)行后的界面如圖6-1-6所示。界面包括串口設(shè)置選擇窗口,串口控制按鍵、溫度顯示窗口等。 圖3-6 上位機(jī)程序運(yùn)行界面 3.2.1新建工程并添加控件 根據(jù)前面介紹,先建立一個【標(biāo)準(zhǔn)EXE】工程。然后添加MSComm控件。過程如下: (1)單擊【工程→部件】菜單項,打開部件對話框,如圖3-7所示,選中【控件】選項卡里面的【Microsoft Comm Control 6.0】控件列表項,單擊【確定】按鈕。 圖3-7 添加MSComm控件 3-8 添加控件后的工具箱 添加過MSComm控件后,就可以看到在工具箱中增加了一個像電話的圖標(biāo),如圖3-8右下角的電話圖標(biāo)就是VB串口通信所用的標(biāo)準(zhǔn)控件(MSComm控件)。 (2)單擊【MSComm】控件,并在窗體Form1上拖出一個矩形,如圖3-9所示,這時MSComm控件就被添加到了該工程中。 圖3-9 添加MSComm控件 3.2.2 添加其他控件并設(shè)置屬性 在VB的編輯窗口中依次添加下列控件:一個下拉列表框,一個按鈕,一個定時器,一個圖片框和30個靜態(tài)文本框,所有的屬性設(shè)置如表3-1所示。添加完控件后的VB編輯界面如圖3-9所示。 表3-1 控件屬性表 3.2.3 添加代碼 為各個事件處理函數(shù)添加代碼如下: Dim flag_com_open As Boolean '定義COM端口的打開標(biāo)識 Dim time_temp As Integer '定義記錄時間的變量 Dim temp_bufx, temp_bufy As Integer '定義兩個存放坐標(biāo)的變量
Private Sub Combo_Com_Click() On Error Resume Next x = Combo_Com.Text '獲取選擇的列表項的文本 m = Len(x) '獲取列表項的長度 n = Val(Right$(x, m - 3)) '獲取列表項里的端口號 MSComm_Temp.CommPort = n '設(shè)置MScomm控件的端口號為選擇的端口號 End Sub
Private Sub Comm_open_Click() If (flag_com_open = False) Then Comm_open.Caption = "關(guān)閉端口" '根據(jù)flag_com_open的值設(shè)置按鈕Comm_open的Caption的值 flag_com_open = True If MSComm_Temp.PortOpen = False Then MSComm_Temp.PortOpen = True End If Timer1.Enabled = True '打開端口后使Timer1有效并開始計時 Else Comm_open.Caption = "打開端口" MSComm_Temp.PortOpen = False flag_com_open = False Timer1.Enabled = False '關(guān)閉端口后使Timer1無效 End If End Sub
Private Sub Form_Load() Dim i As Integer Timer1.Enabled = False '設(shè)置定時器Timer1無效 Timer1.Interval = 1000 '設(shè)定定時器的觸發(fā)時間是1000ms temp_bufx = 0 temp_bufy = 5500 Templine.AutoRedraw = True Templine.DrawStyle = 2 '將劃線的格式改為虛線格式 For i = 250 To 6250 Step 500 '依次畫出溫度的各條基準(zhǔn)線 Templine.Line (0, i)-(9250, i) Next i Templine.DrawStyle = 0 '將劃線的格式改為實(shí)線格式 For i = 1 To 16 '依次為下拉列表框添加列表項 Combo_Com.AddItem "COM" & i Next i MSComm_Temp.Settings = "9600,N,8,1" '波特率是9600,無校驗(yàn),8為數(shù)據(jù)位, 1位停止位 MSComm_Temp.OutBufferSize = 0 '設(shè)置發(fā)送緩沖區(qū)的大小,以字符為單位 MSComm_Temp.InBufferSize = 0 '設(shè)置接收緩沖區(qū)的大小,以字符為單位 MSComm_Temp.InputMode = comInputModeText '以文本方式接收 MSComm_Temp.RThreshold = 4 '設(shè)置產(chǎn)生oncomm事件的字符數(shù),以字符為單位 MSComm_Temp.SThreshold = 1 MSComm_Temp.InputLen = 0 '設(shè)置從接收緩沖區(qū)讀取的字符數(shù),為0表示全部讀取 MSComm_Temp.InBufferCount = 0 '清空接收緩沖區(qū) End Sub
Private Sub MSComm_Temp_OnComm() Dim a As String Dim temp As Integer If MSComm_Temp.CommEvent = comEvReceive Then a = MSComm_Temp.Input '讀取緩沖區(qū)內(nèi)的數(shù)據(jù) For i = 1 To 4 temp = temp * 10 + Val(Mid(a, i, 1)) '分析數(shù)據(jù),得到傳輸?shù)臄?shù)據(jù)值 Next i Templine.Line (temp_bufx, temp_bufy)-(time_temp * 50, 8250 - temp), vbRed '根據(jù)得到的數(shù)據(jù)值和當(dāng)前的時間以及原有的數(shù)據(jù)畫出一條直線 temp_bufx = time_temp * 50 '存儲當(dāng)前數(shù)據(jù),以方便下次使用 temp_bufy = 8250 - temp time_temp = time_temp + 1 '時間值增加1 End If End Sub
Private Sub Timer1_Timer() 'Timer1中斷處理函數(shù) MSComm_Temp.Output = Chr(&H30) '向下位機(jī)發(fā)送一個數(shù)據(jù),用于和下位機(jī)通信 End Sub 3.3 單片機(jī)電路 下位機(jī)電路中數(shù)碼管和DS18B20與單片機(jī)的連接圖,如圖3-10所示。 圖3-10 實(shí)驗(yàn)板上數(shù)碼管和DS18B20與單片機(jī)的連接圖 3.4 單片機(jī)程序設(shè)計 - /********該程序主要是利用DS18B20采集溫度,然后通過數(shù)碼管顯示溫度*************/
- /*當(dāng)程序收到上位機(jī)發(fā)送的命令之后,該程序會將當(dāng)時的溫度值通過串口發(fā)送給上位機(jī)*/
- #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit DQ = P1^0; //定義DS18B20的信號線端口
- uchar i,j;
- uchar dis_buffer[4];//定義數(shù)據(jù)緩沖數(shù)組
- uchar bit_ser[]={0xfe,0xfd,0xfb,0xf7}; //定義數(shù)碼管片選數(shù)組
- uchar seven_seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- //定義數(shù)碼管段選數(shù)組
- /****************************延時函數(shù)*********************************/
- void delay(uint x)
- {
- while(x)
- x--;
- }
- /*************************DS18B20初始化函數(shù)***************************/
- void Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ復(fù)位
- delay(8); //稍做延時
- DQ = 0; //單片機(jī)將DQ拉低
- delay(80); //精確延時 大于 480us
- DQ = 1; //拉高總線
- delay(14);
- x=DQ; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
- delay(20);
- }
- /***************************從18B20中讀一個字節(jié)************************/
- uchar ReadOneChar(void)
- {
- uchar i=0;
- uchar dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 給脈沖信號
- dat>>=1;
- DQ = 1; // 給脈沖信號
- if(DQ)
- dat|=0x80;
- delay(8);
- }
- return(dat);
- }
- /***************************向18B20中寫一個字節(jié)************************/
- Write_OneChar(uchar dat)
- {
- uchar i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0; //給脈沖信號
- DQ = dat & 0x01;
- delay(5);
- DQ = 1; //給脈沖信號
- dat >>= 1;
- }
- delay(4);
- }
- /**************************從18B20中讀取一個字節(jié)***********************/
- int Read_Temperature(void)
- {
- uchar i = 0,t = 0,a,b;
- int temp;
- Init_DS18B20();
- Write_OneChar(0xcc); // 跳過讀序號列號的操作
- Write_OneChar(0x44); // 啟動溫度轉(zhuǎn)換
- Init_DS18B20();
- Write_OneChar(0xcc); //跳過讀序號列號的操作
- Write_OneChar(0xbe); //讀取溫度寄存器等(共可讀9個寄存器)前兩個就是溫度
- i = ReadOneChar(); //讀取溫度值低位
- t = ReadOneChar(); //讀取溫度值高位
- a = i & 0x0f;
- b = t;
- i = i >> 4; //低位右移4位,舍棄小數(shù)部分
- t = t << 4; //高位左移4位,舍棄符號位
- t = t | i;
- temp = (t + a * 0.0625) * 100; //得到一個比實(shí)際溫度擴(kuò)到100倍的值,主要是為了更好的顯示和傳輸
- return(temp); //返回溫度值
- }
-
- /***************************初始化定時器0******************************/
- void timer0_init(void) //
- {
- TMOD = 0x21; //由于串口通信需要使用定時器1,因此TMOD的值是0x21
- TL0 = (65536-5000) % 256;
- TH0 = (65536-5000) / 256;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- /*************************發(fā)送數(shù)據(jù)的函數(shù)********************************/
- void txd_data(char send_data)
- {
- SBUF = send_data; //將需要發(fā)送的數(shù)據(jù)放入發(fā)送緩沖區(qū)
- while(!TI); //等待發(fā)送數(shù)據(jù)
- TI = 0;
- }
- /********************T0中斷處理函數(shù),主要用于顯示當(dāng)前溫度***************/
- void timer0_isr(void) interrupt 1
- {
- int temp;
- TR0 = 0;
- TL0 = (65536-5000) % 256;
- TH0 = (65536-5000) / 256;
- TR0 = 1;
- switch(i)
- {
- case 0:
- P2 = bit_ser[0];
- P0 = seven_seg[dis_buffer[0]];
- break;
- case 1:
- P2 = bit_ser[1];
- P0 =seven_seg[dis_buffer[1]] & 0x7f;
- break;
- case 2:
- P2 = bit_ser[2];
- P0 =seven_seg[dis_buffer[2]];
- break;
- case 3:
- P2 = bit_ser[3];
- P0 =seven_seg[dis_buffer[3]];
- break;
- }
- i++;
- if(i >= 4)
- {
- i = 0;
- j++;
- if(j >= 10) //如果到200ms就會讀取一次溫度,并將溫度值放入顯示緩沖區(qū)
- {
- j = 0;
- temp = Read_Temperature();
- dis_buffer[0] = temp / 1000;
- dis_buffer[1] = temp % 1000 / 100;
- dis_buffer[2] = temp % 100 / 10;
- dis_buffer[3] = temp % 10;
- }
- }
- }
-
- /***************************串口通信初始化函數(shù)***************************/
- void uart_init(void)
- {
- SCON = 0x50; //方式1,充許接收
- TMOD = 0x21; //T1方式2定時,T0方式是1
- TH1 = 0xFd; //波特率9600,Fosc=11.0592MHz
- TL1 = 0xFd;
- TR1 = 1;
- ES = 1; // 打開串口中斷
- }
- /**************************串口中斷處理函數(shù)*****************************/
- void uart() interrupt 4
- {
- char y,i;
- while(!RI);
- y = SBUF; //讀取接收的信息,然后判斷是否為發(fā)送溫度命令
- if(y == '0') //如果為發(fā)送命令,就將當(dāng)前數(shù)據(jù)緩沖數(shù)組內(nèi)的數(shù)據(jù)發(fā)送給上位機(jī)
- {
- for(i = 0;i <= 3;i++)
- {
- txd_data(dis_buffer[i] + 48);
- }
- }
- RI = 0;
- }
- /*******************************主函數(shù)*********************************/
- void main()
- {
- timer0_init(); //調(diào)用T0初始化函數(shù)
- uart_init(); //調(diào)用串口初始化函數(shù)
- while(1)
- {}
- }
復(fù)制代碼
3.5 聯(lián)機(jī)調(diào)試 第一步,首先用USB線連接實(shí)驗(yàn)板和計算機(jī),通過軟件向?qū)嶒?yàn)板中燒錄編寫的程序,并且讓實(shí)驗(yàn)板加電啟動,然后通過系統(tǒng)的設(shè)備管理器查看實(shí)驗(yàn)板與計算機(jī)通信的端口號,如圖3-11所示。 圖3-11 設(shè)備管理器 第二步,啟動上位機(jī)程序,根據(jù)實(shí)驗(yàn)板和計算機(jī)之間的通信端口,選擇合適的端口號,如圖3-12所示。 圖3-11 選擇端口號 然后單擊【打開端口】按鈕,即可實(shí)現(xiàn)實(shí)驗(yàn)板和計算機(jī)之間的串口通信,計算機(jī)程序會根據(jù)實(shí)驗(yàn)板傳輸?shù)臏囟葦?shù)據(jù)畫出各個時刻的溫度曲線,如圖3-13所示,其中開始的一段為室溫下的溫度曲線,中間凸起的部分曲線是加熱后產(chǎn)生的曲線。 圖3-13 溫度曲線圖 思考題: 1.修改上位機(jī)和單片機(jī)程序,使之能通過上位機(jī)進(jìn)行溫度上下限的設(shè)置。 2.修改上下位機(jī)的程序,使之能夠顯示零攝氏度下的圖形。
51hei.png (3.46 KB, 下載次數(shù): 114)
下載附件
2020-6-10 03:35 上傳
全部資料51hei下載地址:
|