51单片机上位机编写与串口通信-深入了解串口
Posted CHENxiaomingming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51单片机上位机编写与串口通信-深入了解串口相关的知识,希望对你有一定的参考价值。
采用环境
VS,keil:
简单介绍
简单的利用VS写上位机 ,和51单片机进行一个通信
单片机通信原理这里不多说直接放链接CSDN有很多很详细的博客
C#网上很多教程这里推荐一篇更加详细的博客
对于串口不理解的可以看这一篇
此项目下载地址
https://download.csdn.net/download/chen_taifu/19827747
代码
C51
/*
开发者邮箱
@m.t-chen@foxmail.com
串口发送数据和接收
*/
#include <reg52.h>
#include <stdio.h>
#include "ccom.h"
//串口寄存器配置
void init()
{
TMOD=0x20; //定时器工作方式,选择了定时器1,工作方式2 八位初值自动重装的8位定时器。
TH1=0xfd; //定时器1初值 ,设置波特率为9600 晶振11.0529MHZ?
TL1=0xfd;
TR1=1; //打开计数器 TCON
SCON=0X50; //设置为工作方式1 (10位/8位数据)允许串口接收位
EA=1; //允许中断(总闸)
ES=1; //允许串口中断
}
void main()
{
init(); //初始化
while(1)
{
if(bzf_cz==1) //接收到数据运行
{
if(bzf_hh!=0) //是否需要换行检测
{
bzf_hh=0; //重置
TI=1;
printf("\\n"); //换行
while(!TI);
TI=0;
}
for(i=0;i<50;i++)
{
SBUF=s[i];
while(!TI);
TI=0;
}
bzf_cz=0;
}
}
}
void ser() interrupt 4
{
if(RI) //接收数据,手动将RI清0
{
RI=0;
if(bzf_cz==0&&j!=0) //第二次输入后将数组a还原
{
for(j=0;j<50;j++) //最大50个字符
s[j]='\\0';
j=0;
bzf_hh=1; //换行标识符
}
s[j]=SBUF; //读取数据到s
bzf_cz=1; //接收标识符
j++;
}
}
上位机项目建立流程
新建项目/Visual C# 选择窗体应用
控件有label1 ,comboBox,textBox,button,
容器panel
组件serialPort
代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;
namespace _51串口机
{
public partial class Form1 : Form
{
private StringBuilder sb = new StringBuilder(); //为了避免在接收处理函数中反复调用,依然声明为一个全局变量
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
int i;
for (i = 300; i <= 38400; i = i * 2)
{
comboBox2.Items.Add(i.ToString()); //添加波特率列表
}
//获取电脑当前可用串口并添加到选项列表中
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
//批量添加波特率列表
string[] comboxD = { "43000", "56000", "57600", "115200", "128000", "230400", "256000", "460800" };
comboBox2.Items.AddRange(comboxD);
//添加数据位列表
string[] comboxA = { "6", "7", "8" };
comboBox3.Items.AddRange(comboxA);
//添加校验位列表
string[] comboxC = { "0", "1" };
comboBox4.Items.AddRange(comboxC);
//添加停止位位列表
string[] comboxB = { "1.5", "2" };
comboBox5.Items.AddRange(comboxB);
//设置默认值
comboBox1.Text = "COM1";
comboBox2.Text = "9600";
comboBox3.Text = "8";
comboBox4.Text = "None";
comboBox5.Text = "1";
}
private void button1_Click(object sender, EventArgs e)
{
try
{
//将可能产生异常的代码放置在try块中
//根据当前串口属性来判断是否打开
if (serialPort1.IsOpen)
{
//串口已经处于打开状态
serialPort1.Close(); //关闭串口
button1.Text = "打开串口";
button1.BackColor = Color.ForestGreen;
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
textBox1.Text = ""; //清空接收区
textBox2.Text = ""; //清空发送区
}
else
{
//串口已经处于关闭状态,则设置好串口属性后打开
comboBox1.Enabled = false;
comboBox2.Enabled = false;
comboBox3.Enabled = false;
comboBox4.Enabled = false;
comboBox5.Enabled = false;
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.DataBits = Convert.ToInt16(comboBox3.Text);
if (comboBox4.Text.Equals("None"))
serialPort1.Parity = System.IO.Ports.Parity.None;
else if (comboBox4.Text.Equals("Odd"))
serialPort1.Parity = System.IO.Ports.Parity.Odd;
else if (comboBox4.Text.Equals("Even"))
serialPort1.Parity = System.IO.Ports.Parity.Even;
else if (comboBox4.Text.Equals("Mark"))
serialPort1.Parity = System.IO.Ports.Parity.Mark;
else if (comboBox4.Text.Equals("Space"))
serialPort1.Parity = System.IO.Ports.Parity.Space;
if (comboBox5.Text.Equals("1"))
serialPort1.StopBits = System.IO.Ports.StopBits.One;
else if (comboBox5.Text.Equals("1.5"))
serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
else if (comboBox5.Text.Equals("2"))
serialPort1.StopBits = System.IO.Ports.StopBits.Two;
serialPort1.Open(); //打开串口
button1.Text = "关闭串口";
button1.BackColor = Color.Firebrick;
}
}
catch (Exception ex)
{
//捕获可能发生的异常并进行处理
//捕获到异常,创建一个新的对象,之前的不可以再用
serialPort1 = new System.IO.Ports.SerialPort();
//刷新COM口选项
comboBox1.Items.Clear();
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
//响铃并显示异常给用户
System.Media.SystemSounds.Beep.Play();
button1.Text = "打开串口";
button1.BackColor = Color.ForestGreen;
MessageBox.Show(ex.Message);
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
}
}
private void SerialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
sb.Clear(); //防止出错,首先清空字符串构造器
int num = serialPort1.BytesToRead; //获取接收缓冲区中的字节数
byte[] received_buf = new byte[num]; //声明一个大小为num的字节数据用于存放读出的byte型数据
serialPort1.Read(received_buf, 0, num); //读取接收缓冲区中num个字节到byte8位类型 received数组中
sb.Append(Encoding.ASCII.GetString(received_buf)); //将整个数组解码为ASCII数组
foreach (byte b in received_buf) //遍历数组进行字符串转化及拼接
{
sb.Append(b.ToString());
}
try
{
//因为要访问UI资源,所以需要使用invoke方式同步ui
Invoke((EventHandler)(delegate
{
textBox1.AppendText(sb.ToString());
}
));
}
catch (Exception ex)
{
//响铃并显示异常给用户
System.Media.SystemSounds.Beep.Play();
MessageBox.Show(ex.Message);
}
}
private void label6_Click(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
try
{
//首先判断串口是否开启
if (serialPort1.IsOpen)
{
serialPort1.Write(textBox2.Text);
}
}
catch (Exception ex)
{
serialPort1.Close();
//捕获到异常,创建一个新的对象,之前的不可以再用
serialPort1 = new System.IO.Ports.SerialPort();
//刷新COM口选项
comboBox1.Items.Clear();
comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
//响铃并显示异常给用户
System.Media.SystemSounds.Beep.Play();
button1.Text = "打开串口";
button1.BackColor = Color.ForestGreen;
MessageBox.Show(ex.Message);
comboBox1.Enabled = true;
comboBox2.Enabled = true;
comboBox3.Enabled = true;
comboBox4.Enabled = true;
comboBox5.Enabled = true;
}
}
private void button3_Click(object sender, EventArgs e)
{
textBox2.Text = ""; //清空接收文本框
textBox1.Text = ""; //清空发送文本框
}
}
}
以上是关于51单片机上位机编写与串口通信-深入了解串口的主要内容,如果未能解决你的问题,请参考以下文章