[资料工具]

单片机串口通讯详解

[复制链接]
1402|44
手机看帖
扫描二维码
随时随地手机跟帖
merry_zsp|  楼主 | 2019-7-30 11:15 | 显示全部楼层 |阅读模式
1.通信方式分类
(1)并行通信
发送方和接收方用多根数据线连接,多位数据同时发送。传输线多,长距离传输时成本大。
1751504-20190728132708291-228408365.jpg
(2)串行通信
单根数据线发送数据,逐位发送。长距离传送成本低,但控制相对复杂。
1751504-20190728132716879-230996626.jpg

串行通信又可分为:异步串行通信同步串行通信
异步串行通信:所谓“异步”,指的是双方设备使用各自的时钟,以字符为单位传输,采用一种特殊的格式称为“帧”(如下图),且各字符之间的间隙不等。
一帧数据由起始位,数据位,校验位和停止位构成。
1751504-20190728132811770-1390878637.jpg
常态下,数据线上为高电平。起始位为低电平,也就是说,起始位出现,表示有一帧数据要传输了。

校验方式有奇偶校验、和校验和循环冗余校验三种方式。
其中“和校验”是指,对数据块求和,产生一个字节的校验数据存到数据块末尾,接收方接受数据时对数据块再求和,和末尾的校验数据比较,不一致就表示传输发生错误。
同步串行通信:双方的时钟严格一致,传送的字符数据间没有间隙,双方实现同步。

使用特权

评论回复

相关帖子

merry_zsp|  楼主 | 2019-7-30 11:16 | 显示全部楼层
2.RS232和TTL电平的转换

RS232是美国电子工业协会于1962年发布的串行通信接口标准,RS即Recomend Standard,推荐标准,232为标示号。RS232用的是负电平逻辑,-3V ~ -15V 为1,+3 ~ +15V为0。

TTL是Transistor-Transistor Logic的简写,晶体管-晶体管逻辑。工作电压5V。规定:

对于输出电路:电压大于等于(≥)2.4V为逻辑1;电压小于等于(≤)0.4V为逻辑0;
对于输入电路:电压大于等于(≥)2.0V为逻辑1;电压小于等于(≤)0.8V为逻辑0;
RS232和TTL接口不仅有工作电压的不同。RS232传输速率低,传输距离不长,采用共地传输产生共模干扰。二者之间需要通过转换芯片转换电平,如MAX232。

MAX232外围电路图:
1751504-20190728132919358-103817862.jpg




上半部分为电源转换电路,下半部分为发送和接收部分。

注意输入输出要一一对应。从T1in输入就要从T1out输出,从R1in输入就要从R1out输出。

使用特权

评论回复
merry_zsp|  楼主 | 2019-7-30 11:18 | 显示全部楼层
3.波特率
波特率是衡量串行数据传输速率的指标,和比特率一个单位,即每秒传输了多少位,bit per second,bps。
波特率的计算公式:
1751504-20190728133015945-1896448152.jpg

计算定时器装入的初值
设初值为X,那么定时器就是每计 256-X 个数溢出一次。
首先根据晶振频率计算计一个数需要的时间。
如11.0592MHz,12个时钟周期等于一个机器周期,所以计一个数需要的时间为频率11.0592MHz的倒数再乘上12,即12/11059200(s)。
那么定时器溢出一次的时间就是 12/11059200*(256-X)。作个倒数就是溢出率。
接着根据采用的波特率和选择的工作方式SMOD,代入上面相应的计算公式,就可以计算出初值X了。此时计算出的X为十进制,然后转成16进制。
常用波特率初值表:

为什么51系列单片机的晶振会用11.0592MHz这个神奇的数?
因为如果采用整数如12MHz或6MHz的话,计算出的初值就不是一个整数,导致定时出现累积误差。试来试去,用11.0592MHz能非常准确地计算出定时器的初值。只要是标准的通信速率,算出来的初值都是整的。
1751504-20190728133057630-650326933.jpg

使用特权

评论回复
merry_zsp|  楼主 | 2019-7-30 11:19 | 显示全部楼层
4.通信例程
串口的初始化
  • 设定定时器的工作方式 TMOD = …
  • 根据设定的波特率和晶振频率(以及SMOD),计算定时器的初值。
  • 启动定时器 TR1 = 1;
  • 设定串行口的工作方式 SCON = …
  • 串行口开中断 ES = 1,打开总中断EA = 1。
串口中断程序
  • 从SBUF里取数据
  • RI清0
  • 发送数据
  • 判断是否发送完成;TI清0
  • (可通过设定标志位来把代码移动到主函数里)

下面是例程的注释,程序实现在上位机上输入字符,下位机(单片机)返回“I get ”+输入的字符。


<p style="margin: 10px auto; padding: 0px; text-align: left; color: rgb(0, 0, 0); text-transform: none; text-indent: 0px; letter-spacing: normal; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-weight: 400; word-spacing: 0px; white-space: normal; orphans: 2; widows: 2; background-color: rgb(255, 255, 255); font-variant-ligatures: normal; font-variant-caps: normal; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> </p>
#include "reg51.h"

typedef unsigned char u8;
typedef unsigned int u16;

u8 flag,r,i;    //定义标志位,取数据的变量r和发送字符的变量i

u8 code table[] = "I get ";

void UsartInit()
{
    TMOD = 0x20;    //设定定时器1为工作方式2,8位自动重装
    TH1 = 0xF3;       //装入初值(波特率4800,晶振12M,加倍)
    TL1 = 0xF3;
    PCON = 0x80;     //SMOD是TCON的最高位,此处设SMOD为1,1000 0000
    TR1 = 1;        //启动定时器1
    SCON = 0x50;     //设置串口为工作方式1,允许接收位REN置1,0101 0000
    ES = 1;         //串口中断允许
    EA = 1;          //打开总中断
}

void main()
{
    UsartInit();       //串口初始化
    while(1)          //持续等待中断的出现
    {
        if(flag == 1)     //中断发生且中断程序跑完
        {
            ES = 0;       //把中断允许先关掉,防止下面发送数据时又申请中断
            for (i=0;i<6;i++)
            {
                SBUF = table[i];   //一位一位地发送数据
                while(!TI);        //判断是否发送完成
                TI = 0;            //TI在发送数据完成后自动置1,把TI清0
            }
            SBUF = r;   //发送最初接收的数据
            while(!TI);
            TI = 0;      //同上清0
            ES = 1;       //中断允许重新打开
            flag = 0;     //标志位清0,等待下次数据的输入
        }
     
    }   
}

void Usart() interrupt 4
{
    r = SBUF;      //从SBUF里取接受到的数据
    RI = 0;          //RI在接收数据完成后自动置1,把RI清0
    flag = 1;        //标志位置为1
}

使用特权

评论回复
zlmin| | 2019-10-3 20:12 | 显示全部楼层
感谢分享!感谢分享!

使用特权

评论回复
gygp| | 2019-10-6 17:19 | 显示全部楼层
用来传送二进制数据的接口形式

使用特权

评论回复
chenci2013| | 2019-10-6 17:19 | 显示全部楼层
测试涉及到底层串口代码的修改

使用特权

评论回复
biechedan| | 2019-10-6 17:19 | 显示全部楼层
串口用作串行通信,通信包括IIC,RS485,RS232等

使用特权

评论回复
wangdezhi| | 2019-10-6 17:19 | 显示全部楼层
单片机的串口本身就已是一个功能完备的外设部件了

使用特权

评论回复
isseed| | 2019-10-6 17:19 | 显示全部楼层
串口自己会执行,不需要干预。  

使用特权

评论回复
xietingfeng| | 2019-10-6 17:19 | 显示全部楼层
串行接口 (Serial Interface) 是指数据一位一位地顺序传送  

使用特权

评论回复
suzhanhua| | 2019-10-6 17:20 | 显示全部楼层
通信线路简单,只要一对传输线就可以实现双向通信  

使用特权

评论回复
mituzu| | 2019-10-6 17:20 | 显示全部楼层
适用于远距离通信,但传送速度较慢  

使用特权

评论回复
uiint| | 2019-10-6 17:20 | 显示全部楼层
单片机内部有一个全双工串行接口  

使用特权

评论回复
uiint| | 2019-10-6 17:20 | 显示全部楼层
单片机与电脑串口通信的C程序,最好是中断方式的.  

使用特权

评论回复
gygp| | 2019-10-6 17:20 | 显示全部楼层
采用了查询式发送?        

使用特权

评论回复
uiint| | 2019-10-6 17:21 | 显示全部楼层
不要忘了把两个单片机的地也连上  

使用特权

评论回复
uiint| | 2019-10-6 17:21 | 显示全部楼层
单片机中全双工串行口是什么意思?  

使用特权

评论回复
mituzu| | 2019-10-6 17:21 | 显示全部楼层
建议你将程序写入开发板运行后和电脑用串口助手联调  

使用特权

评论回复
suzhanhua| | 2019-10-6 17:21 | 显示全部楼层
单片机串口初始化配置的一般步骤  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

75

主题

695

帖子

2

粉丝