标题:
大家新年好,请教一个单片机串口通信问题
[打印本页]
作者:
as252585425
时间:
2018-2-19 18:20
标题:
大家新年好,请教一个单片机串口通信问题
我现在写出来一个,单片机接收1个字符,用串口调试助手软件通过串口向单片机发送数据。当发送的数据为1到8时,P1口分别对应点亮相应的发光二极管。发送其他数据,蜂鸣器会响。 注意:波特率9600 。
1,现在我是想,如果我要一次接收3个字符,分别对应控制P0-P2口的LED灯。如何写呢?10位通信,只能有8个位是数据。是串口通信,只能一个10位接一个10位的发。怎么区分第二个是对应P1口,第三个是对应P2口呢?
2,这个一次只能点亮1个LED灯,如果我想同时点亮多个LED灯,那该怎么写呢?
最后祝大家,新年快乐,恭喜发财,万事如意。
这个是我写的代码
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar buf;
sbit beep=P2^3;
void main(void)
{
SCON=0x50; //设定串口工作方式
PCON=0x00; //波特率不倍增
TMOD=0x20; //定时器1工作于8位自动重载模式, 用于产生波特率
EA=1;
ES = 1; //允许串口中断
TL1=0xfd;
TH1=0xfd; //波特率9600
TR1=1;
while(1);
}
/*********************************************************
串行中断服务函数
*********************************************************/
void serial() interrupt 4
{
ES = 0; //关闭串行中断
RI = 0; //清除串行接受标志位
buf = SBUF; //从串口缓冲区取得数据
switch(buf)
{
case 0x31: P1=0xfe;beep=1;break; //接受到1,第一个LED亮
case 0x32: P1=0xfd;beep=1;break; //接受到2,第二个LED亮
case 0x33: P1=0xfb;beep=1;break; //接受到3,第三个LED亮
case 0x34: P1=0xf7;beep=1;break; //接受到4,第四个LED亮
case 0x35: P1=0xef;beep=1;break; //接受到5,第五个LED亮
case 0x36: P1=0xdf;beep=1;break; //接受到5,第六个LED亮
case 0x37: P1=0xbf;beep=1;break; //接受到5,第七个LED亮
case 0x38: P1=0x7f;beep=1;break; //接受到5,第八个LED亮
default: beep=0;P1=0xff;break; //接受到其它数据,蜂鸣器响
}
ES = 1; //允许串口中断
}
作者:
wulin
时间:
2018-2-20 14:56
//利用串口传输控制信号不是简单的发送一帧数据,而是需要多功能的数据串,也不要把控制程序放在中断里。
//以下是依你的程序和要求改为串口信号多功能控制,供参考。自定义协议:以此为例 "AA 55 AA 5A 59"共五位数据
//AA是数据头,55 AA 5A 是三位有效数据,59是数据尾,是三位有效数据和的余数,依此验证数据传输是否正确
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar table0[] ="OK "; //用于串口助手返回验证
uchar table1[]="ERROR ";//用于串口助手返回验证
uchar rec_buf[5]; //数据缓存
bit flag=0; //接收完成标志
bit sign=0; //数据验证标志
sbit beep=P2^3;
/**********串口发送函数*************/
void SendOneByte(uchar k)
{
SBUF = k; //发送数据
while(!TI); //等待发送完成
TI = 0; //发送中断请求标志位清0
}
void main(void)
{
uchar i,j; //临时变量
SCON=0x50; //设定串口工作方式
PCON=0x00; //波特率不倍增
TMOD=0x20; //定时器1工作于8位自动重载模式, 用于产生波特率
TL1=0xfd;
TH1=0xfd; //波特率9600
TR1=1;
EA=1;
ES = 1; //允许串口中断
while(1)
{/************数据解析*************/
if(flag==1) //5位数据串接收完成
{
ES=0; //关串口中断
flag=0; //接收完成标志清0
j=rec_buf[1]+rec_buf[2]+rec_buf[3];//三位有效数据的和,溢出部分舍弃
if(rec_buf[4]==j)//验证数据和
{
for(i=0;i<3;i++)
SendOneByte(table0[i]);//返回串口助手字符"OK"
sign=1; //数据传输正确
}
else
{
for(i=0;i<6;i++)
SendOneByte(table1[i]);//返回串口助手字符"ERROR"
sign=0; //数据传输错误
}
ES=1; //开串口中断
/******控制任务*******/
if(sign==1)
{
P0=rec_buf[1];
P1=rec_buf[2];
P2=rec_buf[3];
beep=1;
}
else
{
P0=0xff;
P1=0xff;
P2=0xff;
beep=0;
}
}
}
}
/*********************************************************
串口中断服务函数
*********************************************************/
void serial() interrupt 4
{
static uchar num=0; //静态计数变量
RI=0; //接收中断请求标志位清0
rec_buf[num]=SBUF; //接收到的数据串保存在缓存数组
if(rec_buf[0]==0xAA) //验证数据头(起始位)
{
num++;
if(num>=5)
{
flag=1; //接收完成标志置1
num=0; //计数变量清0
}
}
}
作者:
999333
时间:
2018-2-20 15:12
一次接收3个是吗,也就是说把这个分门别类就行,比如说接收到的数据是1,就写p0=???;如果是2就写p2=???;用case语句就足够了
作者:
0x00,0xff
时间:
2018-2-21 17:31
如果只是控制两个端口的16个等的话,而且是可以一次点亮多个,如果是三帧数据,可以对着三帧数据进行编码,将解码函数放在外部,不必放在串口中断内,设置一个标志位,接收到数据后,标志位置1,主函数检测到标志位时,关闭串口中断以防下一帧数据影响到这一帧数据的处理,并进行数据的解码以及置位标志位,解码并执行开关完毕后打开串口中断,准备接收下一帧数据。
举个例子
收到三帧数据,00 fe 01
串口接收并存入数据缓冲区后,解码函数对第一针数据解码,00代表开灯操作,进入开灯的函数,在开灯函数内将收到的数据按位与进入P1端口,将第三帧数据按位或进入P2口,这时,第二第三针数据中对应的0位会使对应位输出位零,
当收到第一帧数据为ff时,进入关灯程序,第二与第三帧要按位与进入对应的端口,否则会使某些灯关不掉。
当第一帧数据为其他时,蜂鸣器响。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1