找回密码
 立即注册

QQ登录

只需一步,快速开始

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

请教单片机串口通信方面的问题,希望做过这一方面的大佬能解答一下

[复制链接]
跳转到指定楼层
楼主
最近正在用51单片机做串口通信,已经完成了基本的发送接收。想做更深入一点:1.对接收到的数据能进行解析,比如串口助手发送了一组电压电流数据:V1012A0022,要把它还原成电压1.012伏,电路0.022A,用两数码管显示出来。
2.发送数据能不用中断吗?现在用的是interrupt 0(外部中断0),能不能不用中断,用单片机上任意的一个口控制发送。

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

使用道具 举报

沙发
ID:303383 发表于 2018-4-23 17:28 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

板凳
ID:213173 发表于 2018-4-23 19:37 | 只看该作者
你可以自定义通讯协议,比如:数据头0xff,电压整数0x01,电压小数0x0c,电流整数0x00,电流小数0x16,数据尾为有效数据和0x23,0xff 0x01 0x0c 0x00 0x16 0x23,由6组8位数据组成一个数据串,下位机收到数据串后保存在缓存中,根据数据头尾判断数据传输正确后对有效数据解析,提供给显示模块。
回复

使用道具 举报

地板
ID:308816 发表于 2018-4-23 19:58 | 只看该作者
发数据不需要中断接收需要
回复

使用道具 举报

5#
ID:304431 发表于 2018-4-24 12:11 | 只看该作者
wulin 发表于 2018-4-23 19:37
你可以自定义通讯协议,比如:数据头0xff,电压整数0x01,电压小数0x0c,电流整数0x00,电流小数0x16,数据 ...

通过状态机实现么?能否给一个大概的代码框架么,因为刚接触这方面,个人编程也不熟练,没法直接根据您提供的思路搭建出来。
回复

使用道具 举报

6#
ID:213173 发表于 2018-4-24 14:41 | 只看该作者
mdzzlsf 发表于 2018-4-24 12:11
通过状态机实现么?能否给一个大概的代码框架么,因为刚接触这方面,个人编程也不熟练,没法直接根据您提 ...

没有你想的那么复杂,给你写一个示例程序参考,经TX-1C实验板与串口助手验证无误。
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;                        //段选
sbit wela=P2^7;                        //位选
uchar code table[]={                //共阴数码管0~F、U数组
        0x3f,0x06,0x5b,0x4f,
        0x66,0x6d,0x7d,0x07,
        0x7f,0x6f,0x77,0x7c,
        0x39,0x5e,0x79,0x71,0x3e};
uchar table0[] ="OK\n";        //用于串口助手返回验证
uchar table1[]="ERROR\n";//用于串口助手返回验证
uchar rec_buf[6];                        //缓存
uint swan,wan,qian,bai,shi,ge;//数码管显示位
bit flag=0;                                        //接收完成标
/*************初始化串口**************/
void InitUART()                //9600bps@11.0592MHz
{
        PCON &= 0x7F;                //波特率不倍速
        SCON = 0x50;                //8位数据,可变波特率
        TMOD= 0x20;                        //设定定时器1为8位自动重装方式
        TL1 = 0xFD;                        //设定定时初值
        TH1 = 0xFD;                        //设定定时器重装值
        ET1 = 0;                                //禁止定时器1中断
        TR1 = 1;                                //启动定时器1
        EA = 1;                                //开总中断
        ES = 1;                                //开串口中断
}
/**********串口发送函数*************/
void SendOneByte(uchar c)
{
    SBUF = c;                //发送数据
    while(!TI);        //等待发送完成
    TI = 0;                        //发送中断请求标志位清0
}
/************数据解析函数*************/
void analysis()
{
        uchar i;                        //临时变量
        if(flag==1)                //一帧数据串接收完成
        {
                ES=0;                        //关串口中断
                flag=0;                //接收完成标志清0
                if(rec_buf[5]==rec_buf[1]+rec_buf[2]+rec_buf[3]+rec_buf[4])//验证数据和,超出8位溢出舍弃
                {
                        for(i=0;i<3;i++)
                        SendOneByte(table0);//返回OK
                }
                else
                {
                        for(i=0;i<6;i++)
                                SendOneByte(table1);//返回ERROR
                        rec_buf[0]=rec_buf[1]=rec_buf[2]=rec_buf[3]=rec_buf[4]=rec_buf[5]=0;//清除缓存数据
                }
                ES=1;                //开串口中断
        }
}
/*************数据分解***************/
void Transformation()
{
        static uint i=0;
        static bit j=0;
        i++;
        if(i==7500)                //计数延时切换显示内容
        {
                i=0;
                j=~j;
        }
        if(j==0)                        //换算电压
        {
                swan = rec_buf[1]%100/10;                        // 十万位
                wan  = rec_buf[1]%10;                                // 万位
                qian = rec_buf[2]%1000/100;                // 千位
                bai  = rec_buf[2]%100/10;                        // 百位
                shi  = rec_buf[2]%10;                                // 十位
                ge   = 16;                                                                // 个位"V"
        }
        else                        //换算电流
        {
                swan = rec_buf[3]%100/10;                        // 十万位
                wan  = rec_buf[3]%10;                                // 万位
                qian = rec_buf[4]%1000/100;                // 千位
                bai  = rec_buf[4]%100/10;                        // 百位
                shi  = rec_buf[4]%10;                                // 十位
                ge   = 10;                                                                // 个位"A"
        }
}
/**********6位数码管显示程序************/
void display()
{
        static uchar k=0;                        //分时显示变量
        switch(k)
        {
                case 0:
                   dula=0;
                   P0=table[swan];                //显示十万位段码
                   dula=1;
                   dula=0;
               
                   wela=0;
                   P0=0x7e;                                                //显示十万位码
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 1:
                   dula=0;
                   P0=table[wan]|0x80;                //显示万位段码+小数点
                   dula=1;
                   dula=0;
               
                   wela=0;
                   P0=0x7d;                                                //显示万位位码
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 2:
                   P0=table[qian];                        //显示千位段码
                   dula=1;
                   dula=0;
               
                   P0=0x7b;                                                //显示千位位码
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 3:
                   P0=table[bai];                        //显示百位段码
                   dula=1;
                   dula=0;
               
                   P0=0x77;                                                //显示百位位码
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 4:
                   P0=table[shi];                        //显示十位段码
                   dula=1;
                   dula=0;
               
                   P0=0xef;                                                //显示十位位码
                   wela=1;
                   wela=0;
                        k++;
                 break;       

                case 5:
                   P0=table[ge];                        //显示个位段码
                   dula=1;
                   dula=0;
               
                   P0=0xdf;                                                //显示个位位码
                   wela=1;
                   wela=0;
                        k=0;
                 break;       
        }
}
/**************主程序**************/
void main()
{
        InitUART();                //初始化串口
        while(1)
        {
                analysis();        //数据解析
                Transformation();//数据分解
                display();        //数码管显示
        }
}
/*********串口中断服务程序**********/
void UARTInterrupt() interrupt 4
{
        static uchar num=0;        //静态计数变量
        RI=0;                                                //接收中断请求标志位清0
        rec_buf[num]=SBUF;        //接收到的数据串保存在缓存数组
        if(rec_buf[0]==0xff)        //验证数据头(起始位)
        {
                num++;
                if(num>=6)
                {
                        flag=1;                        //接收完成标志置1
                        num=0;                        //计数变量清0
                }
        }
}
//0xff 0x01 0x0c 0x00 0x16 0x23


评分

参与人数 1黑币 +5 收起 理由
mdzzlsf + 5 很给力!

查看全部评分

回复

使用道具 举报

7#
ID:266627 发表于 2018-4-24 16:16 | 只看该作者
接收要用中断,因为接收缓冲区只有一个字节,不停下手头的事去接收,SBUF会被下一个字节改变。
发送不用中断。

将发送的数据包装成一个个的数据帧,加上帧头和校验,一般还是很可靠的。
回复

使用道具 举报

8#
ID:304431 发表于 2018-4-25 11:40 | 只看该作者
wulin 发表于 2018-4-24 14:41
没有你想的那么复杂,给你写一个示例程序参考,经TX-1C实验板与串口助手验证无误。
#include
#define  ...

谢谢您的解答!
回复

使用道具 举报

9#
ID:451441 发表于 2019-9-5 10:36 | 只看该作者
谢谢LZ分享,借鉴下
回复

使用道具 举报

10#
ID:438771 发表于 2019-9-7 20:17 来自手机 | 只看该作者
绪爷 发表于 2018-4-23 19:58
发数据不需要中断接收需要

请教一下怎么发送?我每次发送数据都上位机都乱码了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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