单片机串口通信C程序及应用实例
51单片机的串口通信程序(C语言)

51单片机的串口通信程序(C语言) 51单片机的串口通信程序(C语言)在嵌入式系统中,串口通信是一种常见的数据传输方式,也是单片机与外部设备进行通信的重要手段之一。
本文将介绍使用C语言编写51单片机的串口通信程序。
1. 硬件准备在开始编写串口通信程序之前,需要准备好相应的硬件设备。
首先,我们需要一块51单片机开发板,内置了串口通信功能。
另外,我们还需要连接一个与单片机通信的外部设备,例如计算机或其他单片机。
2. 引入头文件在C语言中,我们需要引入相应的头文件来使用串口通信相关的函数。
在51单片机中,我们需要引入reg51.h头文件,以便使用单片机的寄存器操作相关函数。
同时,我们还需要引入头文件来定义串口通信的相关寄存器。
3. 配置串口参数在使用串口通信之前,我们需要配置串口的参数,例如波特率、数据位、停止位等。
这些参数的配置需要根据实际需要进行调整。
在51单片机中,我们可以通过写入相应的寄存器来配置串口参数。
4. 初始化串口在配置完串口参数之后,我们需要初始化串口,以便开始进行数据的发送和接收。
初始化串口的过程包括打开串口、设置中断等。
5. 数据发送在串口通信中,数据的发送通常分为两种方式:阻塞发送和非阻塞发送。
阻塞发送是指程序在发送完数据之后才会继续执行下面的代码,而非阻塞发送是指程序在发送数据的同时可以继续执行其他代码。
6. 数据接收数据的接收与数据的发送类似,同样有阻塞接收和非阻塞接收两种方式。
在接收数据时,需要不断地检测是否有数据到达,并及时进行处理。
7. 中断处理在串口通信中,中断是一种常见的处理方式。
通过使用中断,可以及时地响应串口数据的到达或者发送完成等事件,提高程序的处理效率。
8. 串口通信实例下面是一个简单的串口通信实例,用于在51单片机与计算机之间进行数据的传输。
```c#include <reg51.h>#include <stdio.h>#define BAUDRATE 9600#define FOSC 11059200void UART_init(){TMOD = 0x20; // 设置定时器1为模式2SCON = 0x50; // 设置串口为模式1,允许接收TH1 = 256 - FOSC / 12 / 32 / BAUDRATE; // 计算波特率定时器重载值TR1 = 1; // 启动定时器1EA = 1; // 允许中断ES = 1; // 允许串口中断}void UART_send_byte(unsigned char byte){SBUF = byte;while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志位}unsigned char UART_receive_byte(){while (!RI); // 等待接收完成RI = 0; // 清除接收完成标志位return SBUF;}void UART_send_string(char *s){while (*s){UART_send_byte(*s);s++;}}void main(){UART_init();UART_send_string("Hello, World!"); while (1){unsigned char data = UART_receive_byte();// 对接收到的数据进行处理}}```总结:通过以上步骤,我们可以编写出简单的51单片机串口通信程序。
基于C#的串口通信上位机和下位机源程序

基于C#的串口通信上位机和下位机源程序基于单片机串口通信的上位机和下位机实践串口是计算机上一种非常通用设备通信的协议(不要与通用串行总线Universal Serial Bus 或者USB混淆)。
大多数计算机包含两个基于RS232的串口。
串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS-232口。
同时,串口通信协议也可以用于获取远程采集设备的数据。
串口通信的概念非常简单,串口按位(bit)发送和接收字节。
尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。
它很简单并且能够实现远距离通信。
比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。
首先亮出C#的源程序吧。
主要界面:只是作为简单的运用,可以扩展的。
源代码:using System;using System.Collections.Generic;using System.ponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO.Ports;using System.Timers;namespace 单片机功能控制{public partial class Form1 : Form{public Form1(){Initializeponent();}SerialPort sp = new SerialPort();private void button1_Click(object sender, EventArgs e) {String str1 = boBox1.Text;//串口号String str2 = boBox2.Text;//波特率String str3 = boBox3.Text;//校验位String str4 = boBox5.Text;//停止位String str5 = boBox4.Text;//数据位Int32 int2 = Convert.ToInt32(str2);//将字符串转为整型Int32 int5 = Convert.ToInt32(str5);//将字符串转为整型groupBox3.Enabled = true;//LED控制界面变可选try{if (button1.Text == "打开串口"){if (str1 == null){MessageBox.Show("请先选择串口!", "Error"); return;}sp.Close();sp = new SerialPort();sp.PortName = boBox1.Text;//串口编号sp.BaudRate = int2;//波特率switch (str4)//停止位{case "1":sp.StopBits = StopBits.One;break;case "1.5":sp.StopBits = StopBits.OnePointFive;break;case "2":sp.StopBits = StopBits.Two;break;default:MessageBox.Show("Error:参数不正确", "Error"); break;}switch (str3){case "NONE":sp.Parity = Parity.None; break;case "ODD":sp.Parity = Parity.Odd; break;case "EVEN":sp.Parity = Parity.Even; break;default:MessageBox.Show("Error:参数不正确", "Error"); break;}sp.DataBits = int5;//数据位sp.Parity = Parity.Even;//设置串口属性sp.Open();//打开串口button1.Text = "关闭串口";textBox1.Text = Convert.T oString(sp.PortName) + "已开启!"; }else{sp.Close();button1.Text = "打开串口";groupBox3.Enabled = false;//LED控制界面变灰色textBox1.Text = Convert.T oString(sp.PortName) + "已关闭!"; }}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error"); return;}}private void Form1_Load(object sender, EventArgs e){//初始化textBox1.Text = "欢迎使用简易的串口助手!";groupBox3.Enabled = false;//LED控制界面变灰色groupBox6.Enabled = false;groupBox7.Enabled = false;groupBox8.Enabled = false;button3.Enabled = false;button6.Enabled = false;timer1.Start();try{foreach (string in System.IO.Ports.SerialPort.GetPortNames()) //自动获取串行口名称this.boBox1.Items.Add();//默认设置boBox1.SelectedIndex = 0;//选择第一个口boBox2.SelectedIndex = 4;//波特率4800boBox3.SelectedIndex = 0;//校验位NONEboBox4.SelectedIndex = 0;//停止位为1boBox5.SelectedIndex = 0;//数据位为8}catch{MessageBox.Show("找不到通讯端口!", "串口调试助手");}}private void timer1_Tick(object sender, EventArgs e){label6.Text = DateTime.Now.T oString();}private void button2_Click(object sender, EventArgs e){try {if (button2.Text == "开启"){groupBox6.Enabled = true;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;button3.Enabled = true;textBox2.Text = String.Empty;button2.Text = "关闭";}else{groupBox6.Enabled = false;button3.Enabled = false;button2.Text = "开启";textBox2.Text = String.Empty;}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error"); return;}}private void button3_Click(object sender, EventArgs e) {groupBox6.Enabled = true;label7.Text = "已发送";if (textBox2.Text == "")MessageBox.Show("发送失败,请选择发送的数据!");elsesp.WriteLine(textBox2.Text);//往串口写数据}private void checkBox1_CheckedChanged(object sender, EventArgs e){try {if (checkBox1.Checked){checkBox1.Checked = true;checkBox2.Checked = false;checkBox3.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;label7.Text = "准备发送";textBox2.Text = "1";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox2_CheckedChanged(object sender, EventArgs e) {try {if (checkBox2.Checked){checkBox1.Checked = false;checkBox2.Checked = true;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;label7.Text = "准备发送";textBox2.Text = "2";radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox3_CheckedChanged(object sender, EventArgs e) {try{if (checkBox3.Checked){checkBox1.Checked = false;checkBox3.Checked = true;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "3";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox4_CheckedChanged(object sender, EventArgs e) {try{if (checkBox4.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "4";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox5_CheckedChanged(object sender, EventArgs e) {try{if (checkBox5.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = true;checkBox7.Checked = false;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "5";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox6_CheckedChanged(object sender, EventArgs e){try{if (checkBox6.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = true;checkBox8.Checked = false;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "6";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox7_CheckedChanged(object sender, EventArgs e){try{if (checkBox7.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = true;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "7";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void checkBox8_CheckedChanged(object sender, EventArgs e) {try{if (checkBox8.Checked){checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = true;radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;label7.Text = "准备发送";textBox2.Text = "8";}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error"); return;}}private void button5_Click(object sender, EventArgs e) { try{if (button5.Text == "开启"){radioButton1.Checked = false;radioButton2.Checked = false;radioButton3.Checked = false;radioButton4.Checked = false;checkBox1.Checked = false;checkBox2.Checked = false;checkBox3.Checked = false;checkBox4.Checked = false;checkBox5.Checked = false;checkBox6.Checked = false;checkBox7.Checked = false;checkBox8.Checked = false;groupBox7.Enabled = true;button6.Enabled = true;textBox2.Text = String.Empty;button5.Text = "关闭";}else{groupBox7.Enabled = false;button6.Enabled = false;button5.Text = "开启";textBox2.Text = String.Empty;}}catch (Exception er){MessageBox.Show("Error:" + er.Message, "Error");return;}}private void button6_Click(object sender, EventArgs e) {label7.Text = "已发送";if (textBox2.Text == "")MessageBox.Show("发送失败。
51单片机串口通信实例

51单片机串口通信实例一、原理简介51 单片机内部有一个全双工串行接口。
什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。
串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信。
其缺点是传输速度较低。
与之前一样,首先我们来了解单片机串口相关的寄存器。
SBUF 寄存器:它是两个在物理上独立的接收、发送缓冲器,可同时发送、接收数据,可通过指令对SBUF 的读写来区别是对接收缓冲器的操作还是对发送缓冲器的操作。
从而控制外部两条独立的收发信号线RXD(P3.0)、TXD(P3.1),同时发送、接收数据,实现全双工。
串行口控制寄存器SCON(见表1) 。
表1 SCON寄存器表中各位(从左至右为从高位到低位)含义如下。
SM0 和SM1 :串行口工作方式控制位,其定义如表2 所示。
经验分享:学习单片机重要的是实践,所以开发板是很重要,给大家推荐些淘宝上信誉良好并且软硬件及小零件等、售前售后服务良好的皇冠级金钻店铺给大家,在硬件购买上少走弯路。
按住Ctrl键单击即可:慧净电子单片机(一皇冠)【天津商盟】天津锐志(电子)单片机经营部(两皇冠)金沙滩工作室(5钻)深圳育松电子元件,模块,传感器,批发部:淘宝最全最平价(5皇冠)志宏电子(4钻)表2 串行口工作方式控制位其中,fOSC 为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。
SM2 :多机通信控制位。
该仅用于方式2 和方式3 的多机通信。
其中发送机SM2 = 1(需要程序控制设置)。
接收机的串行口工作于方式2 或3,SM2=1 时,只有当接收到第9 位数据(RB8)为1 时,才把接收到的前8 位数据送入SBUF,且置位RI 发出中断申请引发串行接收中断,否则会将接受到的数据放弃。
当SM2=0 时,就不管第位数据是0 还是1,都将数据送入SBUF,并置位RI 发出中断申请。
两个单片机间串口通讯

}
while(temp!=0xf0)
{
temp=P2;
temp=temp&0xf0;
}
send(num);
}
}
}
void main()
{
TMOD=0x20;//设置定时器1为工作方式2
TH1=0xfd;//装初值设置波特率
TL1=0xfd;
TR1=1;//打开定时器1
SM0=0;//8位异步收发
单片机间通讯
作者:冉纯雷
1.程序设计
发送程序:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar num,temp;
void delay(uint z)//延时函数
{
uint x,y;
for(x=z;x>0;x--)
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0xee:num=16;
break;
case 0xde:num=12;
break;
case 0xbe:num=8;
break;
case 0x7e:num=4;
break;
}
{
delay(5);
temp=P2;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0xe7:num=13;
用c语言实现串口读写程序

用c语言实现串口读写程序一、前言串口通信是一种常见的通信方式,它可以实现单片机与计算机之间的数据传输。
在嵌入式系统中,使用串口通信可以方便地进行调试和数据传输。
本文将介绍如何使用C语言实现串口读写程序。
二、硬件准备在进行串口通信之前,需要准备好相应的硬件设备。
一般来说,需要一台计算机和一个串口转USB模块(或者直接使用带有串口接口的计算机)。
同时,在单片机端也需要连接一个串口模块。
三、C语言编程实现1. 打开串口在C语言中,可以通过打开文件的方式来打开串口设备。
下面是一个示例代码:```#include <stdio.h>#include <fcntl.h>#include <termios.h>int open_serial_port(const char *device_path, int baud_rate) {int fd;struct termios options;fd = open(device_path, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) {perror("open_serial_port: Unable to open device");return -1;}fcntl(fd, F_SETFL, 0);tcgetattr(fd, &options);cfsetispeed(&options, baud_rate);cfsetospeed(&options, baud_rate);options.c_cflag |= (CLOCAL | CREAD);options.c_cflag &= ~PARENB;options.c_cflag &= ~CSTOPB;options.c_cflag &= ~CSIZE;options.c_cflag |= CS8;options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);options.c_oflag &= ~OPOST;tcsetattr(fd, TCSANOW, &options);return fd;}```在上述代码中,open_serial_port函数用来打开串口设备,并设置相应的参数。
C语言实现串口通信

C语言实现串口通信在使用系统调用函数进行串口通信之前,需要打开串口设备并设置相关参数。
打开串口设备可以使用open(函数,设置串口参数可以使用termios结构体和tcsetattr(函数。
以下是一个简单的串口通信接收数据的示例代码:```c#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <termios.h>int mainint fd; // 串口设备文件描述符char buff[255]; // 存储接收到的数据int len; // 接收到的数据长度//打开串口设备fd = open("/dev/ttyS0", O_RDONLY);if (fd < 0)perror("Failed to open serial port");return -1;}//设置串口参数struct termios options;tcgetattr(fd, &options);cfsetspeed(&options, B1200); // 设置波特率为1200 tcsetattr(fd, TCSANOW, &options);//接收数据while (1)len = read(fd, buff, sizeof(buff)); // 从串口读取数据if (len > 0)buff[len] = '\0'; // 将接收到的数据转为字符串printf("Received data: %s\n", buff);}}//关闭串口设备close(fd);return 0;```这段代码首先通过open(函数打开串口设备文件"/dev/ttyS0",然后使用tcgetattr(函数获取当前设置的串口参数,接着使用cfsetspeed(函数设置波特率为1200,最后使用tcsetattr(函数将设置好的串口参数写回。
51单片机串口通信(相关例程)

51单片机串口通信(相关例程) 51单片机串口通信(相关例程)一、简介51单片机是一种常用的微控制器,它具有体积小、功耗低、易于编程等特点,被广泛应用于各种电子设备和嵌入式系统中。
串口通信是51单片机的常见应用之一,通过串口通信,可以使单片机与其他外部设备进行数据交互和通信。
本文将介绍51单片机串口通信的相关例程,并提供一些实用的编程代码。
二、串口通信基础知识1. 串口通信原理串口通信是通过串行数据传输的方式,在数据传输过程中,将信息分为一个个字节进行传输。
在51单片机中,常用的串口通信标准包括RS232、RS485等。
其中,RS232是一种常用的串口标准,具有常见的DB-9或DB-25连接器。
2. 串口通信参数在进行串口通信时,需要设置一些参数,如波特率、数据位、停止位和校验位等。
波特率表示在单位时间内传输的比特数,常见的波特率有9600、115200等。
数据位表示每个数据字节中的位数,一般为8位。
停止位表示停止数据传输的时间,常用的停止位有1位和2位。
校验位用于数据传输的错误检测和纠正。
三、串口通信例程介绍下面是几个常见的51单片机串口通信的例程,提供给读者参考和学习:1. 串口发送数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendChar(unsigned char dat){SBUF = dat; // 发送数据while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志}void main(){UART_Init(); // 初始化串口while (1){UART_SendChar('A'); // 发送字母A}}```2. 串口接收数据```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_Recv(){unsigned char dat;if (RI) // 检测是否接收到数据{dat = SBUF; // 读取接收到的数据 RI = 0; // 清除接收中断标志// 处理接收到的数据}}void main(){UART_Init(); // 初始化串口EA = 1; // 允许中断ES = 1; // 允许串口中断while (1)// 主循环处理其他任务}}```3. 串口发送字符串```C#include <reg51.h>void UART_Init(){TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600SCON = 0x50; // 设置串口工作方式1,允许串行接收TR1 = 1; // 启动计数器1}void UART_SendString(unsigned char *str){while (*str != '\0')SBUF = *str; // 逐个发送字符while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志str++; // 指针指向下一个字符}}void main(){UART_Init(); // 初始化串口while (1){UART_SendString("Hello, World!"); // 发送字符串}}```四、总结本文介绍了51单片机串口通信的基础知识和相关编程例程,包括串口发送数据、串口接收数据和串口发送字符串。
51单片机串口通信程序。。含详细例子

{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
} void serial () interrupt 4 using 3 //串口接收中断函数 {
if (RI) { RI = 0 ; ch=SBUF; read_flag= 1 ; //就置位取数标志 }
} main()
{ init_serialcom(); //初始化串口 while ( 1 ) { if (read_flag) //如果取数标志已置位,就将读到的数从串口发出 { read_flag= 0 ; //取数标志清 0 send_char_com(ch); } }
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、程序代码#include<STC12C5A.h>//该头文件可到网站下载#define uint unsigned int#define uchar unsigned charuchar indata[4];uchar outdata[4];uchar flag;static uchar temp1,temp2,temp3,temp;static uchar R_counter,T_counter;void system_initial(void);void initial_comm(void);void delay(uchar x);void uart_send(void);void read_Instatus(void);serial_contral(void);void main(){system_initial();initial_comm();while(1){if(flag==1){ES = 0;serial_contral();ES = 1;flag = 0;}elseread_Instatus();}}void uart_send(void){for(T_counter=0;T_counter<4;T_counter++){SBUF = outdata[T_counter];while(TI == 0);TI = 0;}T_counter = 0;}uart_receive(void) interrupt 4{if(RI){RI = 0;indata[R_counter] = SBUF;R_counter++;if(R_counter>=4){R_counter = 0;flag = 1;}}}void system_initial(void){P1M1 = 0x00;P1M0 = 0xff;P1 = 0xff; //初始化为全部关闭temp3 = 0x3f;//初始化temp3的值与六路输出的初始值保持一致temp = 0xf0;R_counter = 0;T_counter = 0;}void initial_comm(void){SCON = 0x50; //设定串行口工作方式:mode 1 ; 8-bit UART,enable ucvr TMOD = 0x21; //TIMER 1;mode 2 ;8-Bit ReloadPCON = 0x80; //波特率不加倍SMOD = 1TH1 = 0xfa; //baud: 9600;fosc = 11.0596IE = 0x90; // enable serial interruptTR1 = 1; // timer 1RI = 0;TI = 0;ES = 1;EA = 1;}void delay(uchar x){uchar i,j;for(i=0;i<x;i++)for(j=0;j<110;j++);}serial_contral(void){if(indata[3] == ((indata[0]^indata[1])^indata[2])){if(indata[1]== 0x01){P0 = 0xff;temp2 = P0; //读取四路输入// temp2 = temp2&0x0f;outdata[0] = 0xee;outdata[1] = 0x02;outdata[2] = temp2;outdata[3] = ((outdata[0]^outdata[1])^outdata[2]);uart_send();return;}if(indata[1]== 0x03){temp3 = indata[2];P1 = temp3; //控制六路输出return;}if(indata[1]==0x04){outdata[0] = 0xee;outdata[1] = 0x05;outdata[2] = temp3;outdata[3] = ((outdata[0]^outdata[1])^outdata[2]);uart_send();return;}}}void read_Instatus(void){P0 = 0xff;temp1 = P0; //读取四路输入if(temp1!=temp){delay(10);P0 = 0xff;temp1 = P0;if(temp1!=temp){temp = temp1;//P0 = 0xff;//temp = P0;//temp = temp&0x0f;outdata[0] = 0xee;outdata[1] = 0x06;outdata[2] = temp;outdata[3] = ((outdata[0]^outdata[1])^outdata[2]);uart_send();}}}//总结:原因在于串口中断接收一定要使用全局变量,并且这个变量R_counter和T_counter 要在主程序中初始化。
这样,当串口有数据进来时,系统进入中断接收程序,就不会出现数组混乱送出的问题。
二、原理图三、四路开关量输入/六路开关量输出通讯协议通信设置:波特率9600b/s8位数据位无校验位1位停止位命令格式:区别码(1字节)+ Command(1字节)+ Content(1字节)+ Xor(1字节)区别码:上位发送/单片机接收:0xff单片机发送/上位机接收:0xeeCommand = 0x01上位机命令单片机读取四路输入开关量的输入状态如:0xff + 0x01 + 0x00 + XorCommand = 0x02单片机返回四路输入状态给上位机此时,Content 的1字节中的低四位分别表示四路开关量的输入状态1表示输入高电平,0表示输入低电平第一路输入(第0位)第二位输入(第1位)第三路输入(第2位)第四路输入(第3位)如:假设某一时刻四路输入开关量的输入状态为0x03,上位机读取其状态为:0xee + 0x02 + 0x03 + XorCommand = 0x03上位机命令单片机控制六路输出的输出状态此时,Content 的1字节中的低六位分别表示六路开关量的输出状态1表示输出高电平,0表示输出低电平第一路输出(第0位)第二路输出(第1位)第三路输出(第2位)第四路输出(第3位)第五路输出(第4位)第六路输出(第5位)如:上位机欲设置某一时刻六路输出开关量的输出状态为0x01:0xff + 0x03 + 0x01 + XorCommand = 0x04上位机命令单片机读取六路输出开关量的输出状态如:0xff + 0x04 + 0x00 + XorCommand = 0x05 单片机返回六路输出状态给上位机此时,Content 的1字节中的低六位分别表示六路开关量的输出状态1表示输出高电平,0表示输出低电平第一路输出(第0位)第二路输出(第1位)第三路输出(第2位)第四路输出(第3位)第五路输出(第4位)第六路输出(第5位)如:某一时刻六路输出开关量的输出状态为0x01,上位机读取其状态为:0xee + 0x05 + 0x01 + XorCommand = 0x06四路输入状态发生变化时单片机读取其变化的状态并返回给上位机此时,Content 的1字节中的低四位分别表示四路开关量的输入状态1表示输入高电平,0表示输入低电平第一路输入(第0位)第二位输入(第1位)第三路输入(第2位)第四路输入(第3位)如:假设某一时刻四路输入开关量的输入状态为0x03,上位机读取其状态为:0xee + 0x06 + 0x03 + XorContent:表示四路输入开关量的输入状态(数据)或者六路输出开关量的输出状态(数据),在不使用它的命令格式中,它的值无意义,为通信方便,在不使用它的命令格式中,规定其值为0x00;Xor :从第一个字节开始到Xor的前一个字节(总共3个字节),做异或运算四、串口助手测试:读取四路输入开关量ff 01 00 fe控制六路输出的输出状态ff 03 XX Xor00 fc 全开01 fd 关闭右边第一个02 fe 关闭右边第二个04 f8 关闭右边第三个08 f4 关闭右边第四个10 ec 关闭右边第五个20 dc 关闭右边第六个3f c3 全关3e c2 开右边第一个3c c1 开右边第二个3b c7 开右边第三个37 cb 开右边第四个2f d3 开右边第五个1f e3 开右边第六个读取六路输出开关量的输出状态ff 04 00 fb简介:本文论述了一个简单的单片机串口通信作品,通过上位机和单片机通信,控制几路开关量的输入和输出。
只限于学习和参考之用,各部分均通过测试成功!是笔者工作和学习之总结,望大家多学习交流!2010-12-22 晚于上海难为。