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