找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2036|回复: 5
打印 上一主题 下一主题
收起左侧

大家新年好,请教一个单片机串口通信问题

[复制链接]
跳转到指定楼层
楼主
ID:269508 发表于 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;    //允许串口中断
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 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
                }
        }
}

评分

参与人数 1黑币 +8 收起 理由
arthuryu + 8 赞一个!

查看全部评分

回复

使用道具 举报

板凳
ID:222948 发表于 2018-2-20 15:12 | 只看该作者
一次接收3个是吗,也就是说把这个分门别类就行,比如说接收到的数据是1,就写p0=???;如果是2就写p2=???;用case语句就足够了

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:250496 发表于 2018-2-21 17:31 | 只看该作者
如果只是控制两个端口的16个等的话,而且是可以一次点亮多个,如果是三帧数据,可以对着三帧数据进行编码,将解码函数放在外部,不必放在串口中断内,设置一个标志位,接收到数据后,标志位置1,主函数检测到标志位时,关闭串口中断以防下一帧数据影响到这一帧数据的处理,并进行数据的解码以及置位标志位,解码并执行开关完毕后打开串口中断,准备接收下一帧数据。
举个例子
收到三帧数据,00 fe 01
串口接收并存入数据缓冲区后,解码函数对第一针数据解码,00代表开灯操作,进入开灯的函数,在开灯函数内将收到的数据按位与进入P1端口,将第三帧数据按位或进入P2口,这时,第二第三针数据中对应的0位会使对应位输出位零,
当收到第一帧数据为ff时,进入关灯程序,第二与第三帧要按位与进入对应的端口,否则会使某些灯关不掉。
当第一帧数据为其他时,蜂鸣器响。

评分

参与人数 1黑币 +80 收起 理由
admin + 80 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表