最终打开效果,(单片机的程序简单写了一个,上位机的程序编写完用作测试)附带C#源码和单片机源码和代码解释,请大家多多批评指正。
所使用的单片机为STC89C52
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace _15汉字串口助手
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
serialPort1.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); //串口数据接收事件
serialPort1.Encoding = Encoding.GetEncoding("GB2312"); //串口接收编码
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; //
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) //串口接收事件
{
if (!radioButton3.Checked)
{
textBox1.AppendText(serialPort1.ReadExisting()); //串口类会自动处理汉字,所以不需要特别转换
}
else
{
byte[] data = new byte[serialPort1.BytesToRead]; //定义缓冲区,因为串口事件触发时有可能收到不止一个字节
serialPort1.Read(data, 0, data.Length);
foreach (byte Member in data) //遍历用法
{
string str = Convert.ToString(Member, 16).ToUpper();
textBox1.AppendText("0x" + (str.Length == 1 ? "0" + str : str) + " ");
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i < 20; i++)
{
comboBox1.Items.Add("COM" + i.ToString()); //添加串口
}
comboBox1.Text = "COM1"; //默认选项
comboBox2.Text = "9600";
}
private void button1_Click(object sender, EventArgs e)
{
try
{
serialPort1.PortName = comboBox1.Text; //端口号
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text); //波特率
serialPort1.Open(); //打开串口
button1.Enabled = false;
button2.Enabled = true;
}
catch
{
MessageBox.Show("端口错误", "错误");
}
}
private void button2_Click(object sender, EventArgs e)
{
try
{
serialPort1.Close(); //关闭串口
button1.Enabled = true;
button2.Enabled = false;
}
catch
{
}
}
private void button3_Click(object sender, EventArgs e)
{
byte[] Data = new byte[1]; //单字节发数据
if (serialPort1.IsOpen)
{
if (textBox2.Text != "")
{
if (!radioButton1.Checked)
{
try
{
serialPort1.Write(textBox2.Text);
//serialPort1.WriteLine(); //字符串写入
}
catch
{
MessageBox.Show("串口数据写入错误", "错误");
}
}
else //数据模式
{
try //如果此时用户输入字符串中含有非法字符(字母,汉字,符号等等,try,catch块可以捕捉并提示)
{
for (int i = 0; i < (textBox2.Text.Length - textBox2.Text.Length % 2) / 2; i++)//转换偶数个
{
Data[0] = Convert.ToByte(textBox2.Text.Substring(i * 2, 2), 16); //转换
serialPort1.Write(Data, 0, 1);
}
if (textBox2.Text.Length % 2 != 0)
{
Data[0] = Convert.ToByte(textBox2.Text.Substring(textBox2.Text.Length - 1, 1), 16);//单独处理最后一个字符
serialPort1.Write(Data, 0, 1); //写入
}
//Data = Convert.ToByte(textBox2.Text.Substring(textBox2.Text.Length - 1, 1), 16);
// }
}
catch
{
MessageBox.Show("数据转换错误,请输入数字。", "错误");
}
}
}
}
}
}
}
#include <REGX52.H>
#include <stdio.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit DU =P2^6;//段选
sbit WE =P2^7;//位选
uchar num;//数码管显示的值
//共阴极数码管0-9
uchar code duanxuan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
//位选前三个数码管
uchar code weixuan[] ={0xfe,0xfd,0xfb,0xf7};
//void delay(uint x) //@12.000MHz 延迟函数1毫秒 和上述的函数一样
//{
// unsigned char i, j;
// while(x--)
// {
// i = 2;
// j = 239;
// do
// {
// while (--j);
// } while (--i);
// }
//}
void display(uchar i) //数码管显示函数
{
static uchar wei;
uchar qian,bai, shi, ge;
qian =i/1000;
bai = i / 100%10;
shi = i /10%10;
ge = i % 10;
P0 = 0XFF;//清除断码
WE = 1; //位选打开
P0 = weixuan[wei];
WE = 0; //关闭位选寄存器
switch(wei)
{
case 0:DU = 1;P0 = duanxuan[qian];DU = 0;break;
case 1:DU = 1;P0 = duanxuan[bai];DU = 0;break;
case 2:DU = 1;P0 = duanxuan[shi];DU = 0;break;
case 3:DU = 1;P0 = duanxuan[ge];DU = 0;break;
}
wei++;
if(wei ==4)
wei =0;
}
void timer0Init() //定时器0初始化
{
EA =1;
ET0 =1;
TR0 =1;
REN =1;//允许串口接收
//TCON中的打开定时器
TMOD |=0x01; //TMOD不能位寻址 0000 0001中 0 01表示定时器模式 16位定时
TH0 =0xed; //(65535-46082)/256; //定时器 50ms 65536-50000/1.085/256 高8位
TL0 =0xff; //(65535-46082)%256; //低8位
}
//串口初始化
void UARTInit()
{
EA =1;//打开总中断
ES =1;//打开串口中断
SM0 =0;//工作方式为1 8位UART波特率可变
SM1 =1;
REN =1;//串口允许接收
TR1 =1;//定时器1产生波特率
TMOD |=0x20;//0010 0000 8位自动重装载定时器,当溢出时将TH1存放的值自动重装入TL1
//通过比特率的计算公式 9600 计算出TH1 TL1
TH1 =0XFD;
TL1 =0XFD;
}
//写串口中断程序
void UART() interrupt 4
{
//uchar temp;
if(RI==1)//表示串口接收
{
num =SBUF;//读SBUF缓存其中的数据送给num
RI =0; //软件置零接收标志位
//temp =num;
//SBUF =++temp;//写SBUF,把要发送的数据送给缓存器
//SBUF =temp;
TI =1;
puts("已收到");//自动换行
while(!TI);
TI =0;
}
if(TI==1)//判断是否发送完成
TI =0; //清零发送完成标志位
}
void timer0() interrupt 1 //定时器0中断
{
TH0 =0xed;
TL0 =0xff;
display(num);
}
void main()
{
UARTInit();
timer0Init();
while(1)
{
}
}