1. 51-microcontroler

51-microcontroler-第八话-串口

一.写在前面

随着计算机系统的应用和微机网络的发展,通信功能越来越显得重要.这里所说的通信是指计算机与外界的信息交换.因此,通信既包括计算机与外部设备之间,也包括计算机和计算机之间的信息交换.由于串行通信是在一根传输线上一位一位的传送信息,所用的传输线少,并且可以借助现成的电话网进行信息传送,因此,特别适合于远距离传输.对于那些与计算机相距不远的人-机交换设备和串行存储的外部设备如终端、打印机、逻辑分析仪、磁盘等,采用串行方式交换数据也很普遍.在实时控制和管理方面,采用多台微机处理机组成分级分布控制系统中,各 CPU 之间的通信一般都是串行方式.所以串行接口是微机应用系统常用的接口。许多外设和计算机按串行方式进行通信,这里所说的串行方式,是指外设与接口电路之间的信息传送方式,实际上,CPU 与接口之间仍按并行方式工作.

所以本次测试主要是围绕着两个C51单片机之间的串口通讯。

C51有一个可编程全双工异步串行通信接口(UART),管脚TXD(P3.1)RXD(P3.0);可以同时发送和接受数据,有四种工作方式,帧格式有8,10,11位。

1、89c51串行口特点

※全双工串口,能同时发送和接收数据

※可编程:其帧格式可以是8位,10位,11位,并能设置各种波特率

※发送完一个数据TI标志置1,接受完一个数据RI标志置1,可以工作在中断或查询方式

※波特率可以是固定的,也可以是由定时器1的溢出率来决定

※有一个地址相同的接受(发送)缓冲器SBUF(地址99H)

2.SCON—-串行通信控制寄存器

它是一个可寻址的专用寄存器,用于串行数据的通信控制,单元地址是98H,其结构格式如下:

SCON 串行通信控制寄存器
D7 D6 D5 D4 D3 D2 D1 D0
SM0 SM1 SM2 REN TB8 RB8 TI RI

(1)SM0、SM1:串行口工作方式控制位。
SM0,SM1    工作方式
00      方式0-波特率由振荡器频率所定:振荡器频率/12
01      方式1-波特率由定时器T1或T2的溢出率和SMOD所定:2SMOD ×(T1溢出率)/32
10      方式2-波特率由振荡器频率和SMOD所定:2SMOD ×振荡器频率/64
11      方式3-波特率由定时器T1或T2的溢出率和SMOD所定:2SMOD ×(T1溢出率)/32
(2)SM2:多机通信控制位。< br>    多机通信是工作于方式2和方式3,SM2位主要用于方式2和方式3。接收状态,当串行口工作于方式2或3,以及SM2=1时,只有当接收到第9位数据(RB8)为1时,才把接收到的前8位数据送入SBUF,且置位RI发出中断申请,否则会将接受到的数据放弃。当SM2=0时,就不管第位数据是0还是1,都难得数据送入SBUF,并发出中断申请。
工作于方式0时,SM2必须为0。
(3)REN:允许接收位。< br>    REN用于控制数据接收的允许和禁止,REN=1时,允许接收,REN=0时,禁止接收。
(4)TB8:发送接收数据位8。< br>    在方式2和方式3中,TB8是要发送的——即第9位数据位。在多机通信中同样亦要传输这一位,并且它代表传输的地址还是数据,TB8=0为数据,TB8=1时为地址。
(5)RB8:接收数据位8。
在方式2和方式3中,RB8存放接收到的第9位数据,用以识别接收到的数据特征。
(6)TI:发送中断标志位。
可寻址标志位。方式0时,发送完第8位数据后,由硬件置位,其它方式下,在发送或停止位之前由硬件置位,因此,TI=1表示帧发送结束,TI可由软件清“0”。
(7)RI:接收中断标志位。
可寻址标志位。接收完第8位数据后,该位由硬件置位,在其他工作方式下,该位由硬件置位,RI=1表示帧接收完成。

3.PCON—–电源管理寄存器

PCON主要是为CHMOS型单片机的电源控制而设置的专用寄存器,单元地址是87H,其结构格式如下:

PCON电源管理寄存器结构
D7 D6 D5 D4 D3 D2 D1 D0
SMOD GF1 GF0 PD IDL

在CHMOS型单片机中,除SMOD位外,其他位均为虚设的,SMOD是串行口波特率倍增位,当SMOD=1时,串行口波特率加倍。系统复位默认为SMOD=0。

二.代码

/* Main.c file generated by New Project wizard
 *
 * Created:   周日 6月 9 2019
 * Processor: 80C31
 * Compiler:  Keil for 8051
 */

#include <reg51.h>
#include <stdio.h>

#define SEG P1
typedef unsigned char uint8_t;

// 0~F 数字字模
const uint8_t n[4][4] = {
    {0x40, 0x79, 0x24, 0x30}, 
    {0x19, 0x12, 0x02, 0x78},
    {0x00, 0x10, 0x08, 0x03},
    {0x46, 0x21, 0x06, 0x0E}
};
uint8_t col;
uint8_t row;

//把数据从串行口推出
void tx(uint8_t dat){
   SBUF=dat;
   while(TI==0);       //若发送中断标志位没有置"1",就等待
   TI=0;
}

//从串口读取数据
void rx() interrupt 4{
    if(RI==1){
        RI = 0;
        SEG = SBUF;//把收到的数据通过SEG显示出来
    }
}


void main(){

    TMOD = 0x20;  //定时器工作在方式2
    SCON = 0x50;  //串口工作方式1,允许接受数据
    PCON = 0x00;  //设置波特率不倍增
    TH1 = 0xfd;   //设置波特率为9600b/s
    TL1 = 0xfd;
    TR1 = 1;
    EA = 1;     //打开中断总开关
    ES = 1;     //串行口中断打开

    while(1){

        //行选,列选归位
        row = 0xFF;
        col = 0xFF;

        //置P0低四位高电平读行数
        P0 = 0x0F;
        switch(P0){
            case 0x0E:row = 0;break;
            case 0x0D:row = 1;break;
            case 0x0B:row = 2;break;
            case 0x07:row = 3;break;
        }

        //置P0高四位高电平读列数
        P0 = 0xF0;
        switch(P0){
            case 0xE0:col = 0;break;
            case 0xD0:col = 1;break;
            case 0xB0:col = 2;break;
            case 0x70:col = 3;break;
        }
        
        //判断读到的数字并由SEG显示
        if(col != 0xFF && row != 0xFF){
            tx(n[row][col]);//发送按下的数字
        }     
    }
}

 

通讯双方共用一份代码,在A机键盘输入0-A数据,然后通过串行口发送到B,B机接受到后将收的数据显示到SEG上。以此类推B机也可以发送数据,由A机接收并显示、

效果图如下: