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、运行结果