PC和單片機通信(二)---使用SerialPort控件
單個單片機與PC串口通信:
1)測試通信狀態
先在文本框中輸入字符串“Hello”,單擊“測試”按鈕,將字符串“Hello”發送到單片機,若PC與單片機通信正常,在PC程序的文本框中顯示字符串“OK!”,否則顯示字符串“ERROR!”。
2)循環計數
單擊“開始”按鈕,文本框中數字從0開始累加,0、1、2、3…,並將此數發送到單片機的顯示器上顯示;當累加到10時,回到0重新開始累加,依次循環;任何時候,單擊“停止”按鈕,PC程序中和單片機顯示器都停止累加,再單擊“開始”按鈕,接着停下的數繼續累加。
3)控制指示燈
在單片機繼電器接線端子的2個通道上分別接上2個指示燈,在PC程序畫面上選擇指示燈號,如1號燈,單擊畫面“打開”按鈕,單片機上1號燈亮,同時蜂鳴器響;單擊畫面“關閉”按鈕,1號燈滅,蜂鳴器停止響;同樣控制2號燈的亮滅(蜂鳴器同時動作)。
1、C#界面和程序設計
(1)界面
(2)代碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace PC控制單片機
{
public partial class Form1 : Form
{
//定義變量
string f;
string data;
int x;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) //窗體加載時進行串口初始化
{
serialPort1.PortName = "COM7"; //端口名稱
serialPort1.BaudRate = 9600; //波特率
serialPort1.Open(); //打開串口
groupBox2.Enabled = false; //GroupBox2中控件不可用
}
private void button2_Click(object sender, EventArgs e)//開始計數
{
timer1.Enabled = true;
timer1.Interval = 400;
serialPort1.Write("R");
}
private void button3_Click(object sender, EventArgs e)//停止計數
{
timer1.Enabled = false;
serialPort1.Write("S");
}
private void radioButton1_CheckedChanged(object sender, EventArgs e) //選擇1號燈
{
f = "1";
}
private void radioButton2_CheckedChanged(object sender, EventArgs e) //選擇2號燈
{
f = "2";
}
private void button4_Click(object sender, EventArgs e) //打開指示燈
{
if (f=="1")
{
serialPort1.Write("A");
}
else
{
serialPort1.Write("C");
}
}
private void button5_Click(object sender, EventArgs e) //關閉指示燈
{
if (f == "1")
{
serialPort1.Write("B");
}
else
{
serialPort1.Write("D");
}
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
data = serialPort1.ReadExisting();
this.Invoke(new EventHandler(DisplayText));
}
private void DisplayText(object sender, EventArgs e)
{
}
private void button6_Click(object sender, EventArgs e) //關閉串口,退出程序
{
serialPort1.Close();
Close();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen)
serialPort1.Close();
}
private void timer1_Tick(object sender, EventArgs e) //循環計數
{
x++;
if (x>20)
x = 1;
textBox2.Text = x.ToString();
}
private void button1_Click(object sender, EventArgs e)//測試按鈕
{
//把字符"H"通過串口發送出去,如果正常,單片機返回字符串"OK"
serialPort1.Write(textBox1.Text);
System.Threading.Thread.Sleep(1000);//延時
if (data == "OK")
{
textBox1.Text = "OK";
groupBox2.Enabled = true;
groupBox3.Enabled = true;
button1.Enabled = false;
}
else
{
textBox1.Text = "ERROR!";
button1.Enabled = false;
}
}
}
}
2、單片機程序
/****************************************************************** ** 單個單片機與PC串口通信 ** 晶 振 頻 率:11.0592M ** 線 路:單片機實驗開發板B ******************************************************************/ /* PC MCU H OK R 開始記數 S 停止記數 A 1號燈亮,同時蜂鳴器響 B 1號燈滅,蜂鳴器停止響 C 2號燈亮,同時蜂鳴器響 D 2號燈滅,蜂鳴器停止響 */ #include <reg51.h> /****************************數碼顯示 鍵盤接口定義****************************************/ sbit PS0=P2^4; //數碼管個位 sbit PS1=P2^5; //數碼管十位 sbit PS2=P2^6; //數碼管百位 sbit PS3=P2^7; //數碼管千位 sfr P_data=0x80; //P0口爲顯示數據輸出口 sbit P_K_L=P2^2; //鍵盤列 unsigned char tab[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e};//字段轉換表 sbit P_1=P1^1; sbit P_3=P1^3; sbit P_7=P1^7; sbit LIGHT1=P2^1; sbit LIGHT2=P2^0; sbit BUZZER=P3^7; unsigned char COUNTER;//循環計數器 bit count;//循環計數器 啓停標誌位 1啓動記數 0停止記數 /*******************************延時函數*********************************/ /*函數原型:delay(unsigned int delay_time) /*函數功能:延時函數 /*輸入參數:delay_time (輸入要延時的時間) /*輸出參數:無 /*調用模塊:無 /**********************************************************************/ void delay(unsigned int delay_time) //短延時子程序 {for(;delay_time>0;delay_time--) {} } unsigned char htd(unsigned char a) { unsigned char b,c; b=a%10; c=b; a=a/10; b=a%10; c=c|b<<4; return c; } void uart(void) interrupt 4 //把接收到的數據寫入ucReceiveData() { TI=0; RI=0; if(SBUF=='H') //接收到'H'字符 發送'OK' { SBUF='O'; while(TI==0) ; TI=0; SBUF='K'; while(TI==0) ; TI=0; } else if(SBUF=='R') //接收到0 { count=1; } else if(SBUF=='S') { count=0; } else if(SBUF=='A') { LIGHT1=1; BUZZER=1; } else if(SBUF=='B') { LIGHT1=0; BUZZER=0; } else if(SBUF=='C') { LIGHT2=1; BUZZER=1; } else if(SBUF=='D') { LIGHT2=0; BUZZER=0; } } /**************************數碼管顯示函數**************************/ /*函數原型:void display(void) /*函數功能:數碼管顯示 /*輸入參數:無 /*輸出參數:無 /*調用模塊:delay() /******************************************************************/ void display(unsigned int temp) { bit b=P_K_L; P_K_L=1; //防止按鍵干擾顯示 P_data=tab[temp&0x0f]; //顯示個位 PS0=0; PS1=1; PS2=1; PS3=1; delay(200); P_data=tab[(temp>>4)&0x0f]; //顯示十位 PS0=1; PS1=0; PS2=1; PS3=1; delay(200); P_data=tab[(temp>>8)&0x0f]; //顯示百位 PS0=1; PS1=1; PS2=0; PS3=1; delay(200); P_data=tab[(temp>>12)&0x0f]; //顯示千位 PS0=1; PS1=1; PS2=1; PS3=0; delay(200); PS3=1; P_K_L=b; //恢復按鍵 P_data=0xff; //恢復數據口 } void main(void) { TMOD=0x20; //定時器1--方式2 /* GATE C/T M1 M0 GATE C/T M1 M0 0 0 1 0 0 0 0 0 | | | | | | | +----方式選擇 | | | | | | +-------方式選擇 | | | | | +-----------定時器0或計數器0選擇位 清零時用作定時器功能 置位時用作計數器功能 | | | | +---------------置位時爲門控位 | | | +-------------------方式選擇 | | +----------------------方式選擇 | +--------------------------定時器1或計數器1選擇位 清零時用作定時器功能 置位時用作計數器功能 +------------------------------置位時爲門控位*/ IE=0x12; //中斷控制設置,串口、T2開中斷 /* EA - ET2 ES ET1 EX1 ET0 EX0 0 0 0 1 0 0 1 0 | | | | | | | +-------外部中斷0 使能。 | | | | | | +-----------定時器0 溢出中斷使能。 | | | | | +---------------外部中斷1 使能。 | | | | +-------------------定時器1 溢出中斷使能。 | | | +----------------------串口中斷使能。 | | +--------------------------定時器2 中斷使能。 | +----------------------------- +-------------------------------中斷使能位:EA=1,允許中斷服務;EA=0,禁能中斷服務。*/ PCON=0x80; //電源控制 /* SMOD SMODO - POF GF1 GF0 PD IDL 1 0 0 0 0 0 0 0 | | | | | | | +--- | | | | | | +------ | | | | | +---------- | | | | +-------------- | | | +------------------ | | +--------------------- | +------------------------- +------------------------------*/ SCON=0x50; //方式1 /* SM0/FE SM1 SM2 REN TB8 RB8 TI RI 0 1 0 1 0 0 0 0 | | | | | | | +-接收中斷標誌 | | | | | | +----發送中斷標誌 | | | | | +--------模式2 和3 中接收的第9 位數據,在模式1 中(SM2 必須爲0),RB8 是接收到的停止位。在模式0 中,RB8 未定義。 | | | | +------------模式2 和3 中將要發送的第9 位數據,可以根據需要由軟件置位或清零。 | | | +----------------使能串行接收 | | +--------------------使能模式2 和3 中的多機通信功能。 | +------------------------和SM0 定義串行口操作模式 +-----------------------------該位的用途由PCON 寄存器中的SMOD0 決定。*/ TL1=0xFa;//0xF4; //12MHZ晶振,波特率爲4800 0xf3 4800 TH1=0xFa;//0xF4; //11.0592MHZ晶振,波特率爲4800 0xf4 9600 0xfa 19200 0xfd TR1=1; //啓動定時 ES=1; EA=1; LIGHT1=1; LIGHT2=1; COUNTER=0; while(1) { unsigned char i; for(i=0;i<50;i++) display(htd(COUNTER)); if(count) COUNTER++; if(COUNTER>10) COUNTER=0; } }
3、運行結果