单片机串口通信C程序及应用实例
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、程序代码
#include<STC12C5A.h>//该头文件可到网站下载#define uint unsigned int
#define uchar unsigned char
uchar 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;
}
else
read_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 Reload
PCON = 0x80; //波特率不加倍SMOD = 1
TH1 = 0xfa; //baud: 9600;fosc = 11.0596
IE = 0x90; // enable serial interrupt
TR1 = 1; // timer 1
RI = 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/s
8位数据位无校验位1位停止位
命令格式:
区别码(1字节)+ Command(1字节)+ Content(1字节)+ Xor(1字节)
区别码:上位发送/单片机接收:0xff
单片机发送/上位机接收:0xee
Command = 0x01上位机命令单片机读取四路输入开关量的输入状态
如:0xff + 0x01 + 0x00 + Xor
Command = 0x02单片机返回四路输入状态给上位机
此时,Content 的1字节中的低四位分别表示四路开关量的输入状态
1表示输入高电平,0表示输入低电平
第一路输入(第0位)
第二位输入(第1位)
第三路输入(第2位)
第四路输入(第3位)
如:假设某一时刻四路输入开关量的输入状态为0x03,上位机读取其状态为:0xee + 0x02 + 0x03 + Xor
Command = 0x03上位机命令单片机控制六路输出的输出状态
此时,Content 的1字节中的低六位分别表示六路开关量的输出状态
1表示输出高电平,0表示输出低电平
第一路输出(第0位)
第二路输出(第1位)
第三路输出(第2位)
第四路输出(第3位)
第五路输出(第4位)
第六路输出(第5位)
如:上位机欲设置某一时刻六路输出开关量的输出状态为0x01:
0xff + 0x03 + 0x01 + Xor
Command = 0x04上位机命令单片机读取六路输出开关量的输出状态
如:0xff + 0x04 + 0x00 + Xor
Command = 0x05 单片机返回六路输出状态给上位机
此时,Content 的1字节中的低六位分别表示六路开关量的输出状态
1表示输出高电平,0表示输出低电平
第一路输出(第0位)
第二路输出(第1位)
第三路输出(第2位)
第四路输出(第3位)
第五路输出(第4位)
第六路输出(第5位)
如:某一时刻六路输出开关量的输出状态为0x01,上位机读取其状态为:0xee + 0x05 + 0x01 + Xor
Command = 0x06四路输入状态发生变化时单片机读取其变化的状态并返回给上位机此时,Content 的1字节中的低四位分别表示四路开关量的输入状态
1表示输入高电平,0表示输入低电平
第一路输入(第0位)
第二位输入(第1位)
第三路输入(第2位)
第四路输入(第3位)
如:假设某一时刻四路输入开关量的输入状态为0x03,上位机读取其状态为:0xee + 0x06 + 0x03 + Xor
Content:表示四路输入开关量的输入状态(数据)或者六路输出开关量的输出状态(数据),在不使用它的命令格式中,它的值无意义,为通信方便,在不使用它的命令格式中,规定其值为0x00;
Xor :从第一个字节开始到Xor的前一个字节(总共3个字节),做异或运算
四、串口助手测试:
读取四路输入开关量
ff 01 00 fe
控制六路输出的输出状态
ff 03 XX Xor
00 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 晚于上海
难为。