52单片机串口通讯

串口通讯

 

 

基本概念

 

数据帧:就是在线路上传递的一组数据,这组数据可大可小。以电子,无线为介质传输。(对应OSI网络7层模型中的数据链路层)

比特率:在1秒钟所传递的bit数量。(bit/s)

波特率:一秒内的载波数量。(Baud)

比特率和波特率不同的是,比特率重点在传输了多少bit,波特率是指传输了多少承载信息的波。在高低电平信息传输中,两者相同。

晶振频率:指在一秒内晶振的震动频率。(fosc)

时钟频率:时钟频率 = 晶振频率

状态频率:时钟频率X2

机械频率:在1T单片机中,机械频率 = 时钟频率。在12T单片机中,机械频率 = 12乘以时钟频率

 

 

串口与并口

 

并口传输

优点:传输速度快

缺点:传输范围短

串口传输

优点:传输距离长

缺点:传输速度慢

 

 

同步通讯与异步通讯

同步通讯:指通讯双方严格按照相同的时钟频率通讯。但是传输的帧很长。

异步通讯

每帧很短,而且有控制bit起到开始结束效验的作用。传输效率低。且每帧之间都用空闲,空闲时电平为1;

 

效验位

 

硬件与兼容

232协议和TTL协议

232协议为大多数主机使用的,高电平为12v,低电平为-12v。

TTL协议多为单片机所用,高电平为5v,低电平为0v。

为了保障两种协议兼容,使用兼容芯片如CH340芯片。使得232转TTL,TTL转232。

由于许多主机没有串口,CH340会将串口转USB。如果使用340芯片,则要在PC上下载对应的驱动。

TXD为发送引脚,RXD为接收引脚。

 

串口

目前只用管着三个帧就好了,公母区别稍微联想一下就很好记。处了这辆还有个串口,就是USB接口。现在基本都是这种方式,传统的串口很少见了。

目前的技术都是用USB虚拟出串口来使用。这个模块有个MAX3232,负责232协议和TTL兼容的,GND用来使得两边电平相同。要不电平会乱跳。

 

 

 

寄存器

串口有关寄存器有:IE,TCON,SCON,PCON,AUXR,SUBF,移位寄存器

IE寄存器和TCON寄存器是定时器里的。

SCON寄存器

RI :接收中断标志位,数据接收结束后,该位由硬件自动置1。由软件置0

TI:发送中断标志位,数据发送结束后,该位由硬件自动置1,由软件置0

RB8:

当SM = 2时,存放接收数据的第9位,在模式2 3 中,用于存放收到的第九位数据,处理数据特征,特征与TB8对应。

当SM2 = 0,且模式为2 3 时,此位用于接收奇偶效验位

TB8:

当SM2 = 0,且模式为2 3时,此位用于发送奇偶效验位

当SM2 = 1时,存放发送数据的第9位,在模式 2 3 中,如果此位置1,则发送的是地址,如果此位置0,则发送的是数据。主要用于多处理机通讯,在此不深究。

REN:串行接收允许位,1允许,0禁止。

SM2:多机通讯使能位,用于处理多机通讯。与接收到的第九位数据有关,当SM2 = 1时,只有第九位数据为1时,才将数据交由SBUF并将第九位数据交由RB8,如果SM2 = 0时,无论第九位数据为什么,都将数据交由SBUF。此位用于多机通讯,不再深究。

 

SUBF寄存器

一个寄存器两个空间,一个收一个发。地址相同。SBUF = A,为发送,A = SBUF为读取

 

PCON有关串口就一位,最高位SMOD。当此位置1时,波特率翻倍。

 

移位寄存器:从SBUF获得并行数据,然后在移位脉冲下一位一位的输出或接收。

 

IE寄存器和TCON寄存器在这里不再赘述,为定时器内容。需要注意的是当一个定时器作为串口波特率发生器时,需要静止该定时器产生中断

 

AUXR一般无需设置,他决定了使用那个时钟频率作为波特率发生器以及详细参数。

 

 

四种工作方式

工作方式基础

 

1:SM0和SM1的组合决定了串口的四种工作方式。

方式0:串口为同步移位寄存器的输入输出方式(波特率固定为fosc/12)fosc = 晶振频率,且必须满足SM2 = 0

输出:

首先向SBUF向移位寄存器写入要输出的数据。RXD引脚负责发送数据。TXD负责发送移位脉冲。每发送一次脉冲,数据都从移位寄存器中移出来一位,就像C语言中的移位操作符。移位会导致丢弃和填充。在这里丢弃对应发送,也就是从移位寄存器移出的数据,填充就是填充0。发送随着移位脉冲的节拍有序发送。当发送完数据后,TI计时器会发送中断。也就是前面有过的串行中断。

输入:

首先REN 由1变为0,表示允许接收。然后RXD随着TXD移位脉冲输入到移位寄存器中。RI在输入过程中为0,输入结束后为1,表示输入结束。发送接收中断。并将数据交给SBUF寄存器

 

方式1:10位异步通信(波特率可变)

从起始位开始到停止位结束,中间1字节的数据。

REN置1时,不断采样RXD的脉冲,当检测到RXD中有脉冲变化,则REN置0开始接收数据。使其移位到移位寄存器中去。REN为1时对RXD的检测称为位采样脉冲。采样频率为波特率的16倍。

将数据八位不断移入移位寄存器,数据从移位寄存器右边移入,当起始位位于移位 。

 

方式2和3 方式2的波特率为fosc/64或fosc/32,方式3可变

输出

先将起始位输出到TXD引脚,随后移位寄存器开始输出。第一次右移位将D0输出,并在移位寄存器第9位补停止位1,随后依次输出,并补0。当停止位移动到输出位时,检测到这一行为会控制最后一次移位并使得T1置1,引发中断。

输出

接收数据时,移位寄存器从右向左存入数据。当起始位移动到最左边时,检测这一行为并控制最后一次移位。此时诺RI = 0且 SM2 = 0或第九位为1,则RI置1触发中断。并将移位寄存器的数据前八位装入SBUF,第九位装入RB8中。

 

 

 

代码1:实现数码管显示主机用串口发来的数据

#include<reg52.h>
sbit la = P0^0;
sbit lb = P0^1;
#define dataport P1//定义数码管数据端口
unsigned int lbarr[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//段码
unsigned int laarr[] = {0x7f};//位码
void delay(unsigned int time)//延迟函数
{
    while(time--){}
}
void dispaly(unsigned char a)//显示函数
{
    int i = 0;
    while(i<8)
    {
    dataport = laarr[0];
    la = 1;
    la = 0;
    
    dataport = lbarr[a];
    lb = 1;
    lb = 0;
    delay(1000);
    i++;
    }
}
void init_serial()
{
    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率
    TMOD &= 0x0F;        //清除定时器1模式位
    TMOD |= 0x20;        //设定定时器1为8位自动重装方式
    TL1 = 0xFD;        //设定定时初值
    TH1 = 0xFD;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
    EA = 1;
    ES = 1;
}//串口初始化,在工具中得到正确的值复制并打开IE寄存器各项开关,当定时器作为波特率发生器时必须关闭对应的计时器中断
int main()
{
    while(1)
    {
        init_serial();
    }
}
void interrupt_serial() interrupt 4
{
    unsigned char serial_data;//SBUF缓冲变量
    if(RI)//如果中断是由接收引起的
    {
        serial_data = SBUF;//读取SBUF数据
        P1 = serial_data;//显示在P1针脚上方便观察
        dispaly(serial_data);//带入显示函数
        RI = 0;//置0
    }
    if(TI)//如果是发送引起的
    {
        TI = 0;//置0
    }
}

代码2

实现单片机返还从主机的通讯

#include<reg52.h>
sbit la = P0^0;
sbit lb = P0^1;
#define dataport P1//定义数码管数据端口
unsigned int lbarr[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//段码
unsigned int laarr[] = {0x7f};//位码
void delay(unsigned int time)//延迟函数
{
    while(time--){}
}
void dispaly(unsigned char a)//显示函数
{
    int i = 0;
    while(i<8)
    {
    dataport = laarr[0];
    la = 1;
    la = 0;
    
    dataport = lbarr[a];
    lb = 1;
    lb = 0;
    delay(1000);
    i++;
    }
}
void init_serial()
{
    PCON &= 0x7F;        //波特率不倍速
    SCON = 0x50;        //8位数据,可变波特率
    TMOD &= 0x0F;        //清除定时器1模式位
    TMOD |= 0x20;        //设定定时器1为8位自动重装方式
    TL1 = 0xFD;        //设定定时初值
    TH1 = 0xFD;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
    EA = 1;
    ES = 1;
}//串口初始化,在工具中得到正确的值复制并打开IE寄存器各项开关,当定时器作为波特率发生器时必须关闭对应的计时器中断
int main()
{
    while(1)
    {
        init_serial();
    }
}
void interrupt_serial() interrupt 4
{
    unsigned char serial_data;
    if(RI)
    {
        serial_data = SBUF;
        P1 = serial_data;
        dispaly(serial_data);
        RI = 0;
    }
    if(TI)
    {
        TI = 0;
    }
}

 

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值