51单片机串口通信补充

warning: 这篇文章距离上次修改已过1384天,其中的内容可能已经有所变动。

串口相应寄存器

SCON串口控制寄存器(主要用方式1)

D7D6D5D4D3D2D1D0
SM0SM1SM2RENTB8RB8TIRI

SM1,SM0:

SM0SM1工作方式功能波特率
00方式08位同步移位寄存器晶振频率 / 12
01方式110位UART可变
10方式211位UART晶振频率/32或晶振频率/64
11方式311位UART可变

SM2:----多机通信控制位(可以先不理)
多机通信是工作在方式2和方式3的,所以SM2主要用于方式2和方式3,多级通信时,SM2=1,当SM2=1时,只有当接收到的数据帧第9位(RB8)为1时,
单片机才把前八位数据放入自己的SBUF中,否则,将丢弃数据帧。当SM2=0时,不论RB8的值是什么,都会把串口收到的数据放到SBUF中。

REN:-----允许接收位
REN用于控制是否允许接收数据,REN=1时,允许接收数据,REN=0时,拒绝接收数据

TB8:-------是要发送的第9位数据位
在方式2和方式3中,TB8是要作为数据帧第9位被发送出去的,在多机通信中,可用于判断当前数据帧的数据是地址还是数据,TB8=0为数据,TB8=1为地址

RB8:-------接收到的第9位数据位
当单片机已经接收一帧数据帧时,会把数据帧中的第9位放到 RB8中。方式0不使用RB8,在方式2和方式3中,RB8为接收到的数据帧的第9位数据位。

TI:-----发送中断标志位
方式0中,不用管他。其他方式下,当发送数据完毕,硬件会将其置1,当 TI 被置1,会向CPU发送中断请求。我们记得要在中断服务程序中把 IT 置回0.

RI:-----接收中断标志位
当接受完一帧数据时,RI 由硬件置1,当RI 被置1,会向CPU请求中断。同样要在中断服务程序中把 RI 置回0。

PCON功率控制寄存器

76543210
SOM///////PCON

这个寄存器只有一个位SMOD,在方式1,2.,3时,波特率都与SMOD有关,当SMOD=1时,波特率会增加一倍。复位时,SMOD变回0

C51发送数据到电脑:

/*
效果:串口助手连接后会不停显示 hello world。(串口助手波特率要设成和单片机发送波特率一样,COM口也是)
*/
#include <reg51.h>
 
typedef   unsigned char  uint8;
typedef   unsigned int   uint16;
 
uint8 Buf[]="hello world!\n";
 
void delay(uint16 n)
{
    while (n--);
}
 
/*波特率为9600*/
void UART_init(void)
{
    SCON = 0x50;        //串口方式1
 
    TMOD = 0x20;        // 定时器使用方式2自动重载
    TH1 = 0xFD;    //9600波特率对应的预设数,定时器方式2下,TH1=TL1
    TL1 = 0xFD;
 
    TR1 = 1;//开启定时器,开始产生波特率
}
 
/*发送一个字符*/
void UART_send_byte(uint8 dat)
{
    SBUF = dat;       //把数据放到SBUF中
    while (TI == 0);//未发送完毕就等待
    TI = 0;    //发送完毕后,要把TI重新置0
}
 
/*发送一个字符串*/
void UART_send_string(uint8 *buf)
{
    while (*buf != '\0')
    {
        UART_send_byte(*buf++);
    }
}
 
main()
{
    UART_init();
    
    while (1)
    {
        UART_send_string(Buf);
        delay(20000);
    }
 
}

电脑发送数据到单片机:

/*
效果:当用电脑的串口助手向单片机发送数字1的时候,单片机会亮起LED0,以此类推。
*/
#include<reg52.h>
#define uchar unsigned char
#define uint  unsigned int
uchar buf;
void main(void){
    SCON=0x50;//设定串口工作方式0101 0000
    PCON=0x00;
    TMOD=0x20;
    EA=1;
    ES=1;
    TL1=0xfd;//波特率9600
    TH1=0xfd;
    TR1=1;
    while(1);
}
 
//串行中断服务函数
void serial() interrupt 4{
    ES=0;        //暂时关闭串口中断
    RI=0;
    buf=SBUF;    //把收到的信息从SBUF放到buf中。
    switch(buf){
        case 0x31: P2=0xfe;break;   //二进制 0011 0001  十进制 49 控制字符 1  16进制 0X31
        case 0x32: P2=0xfd;break;    //1111 1101
        case 0x33: P2=0xfb;break;
        case 0x34: P2=0xf7;break;
        case 0x35: P2=0xef;break;   
        case 0x36: P2=0xdf;break;    
        case 0x37: P2=0xbf;break;
        case 0x38: P2=0x7f;break;
    }
    ES=1;        //重新开启串口中断
 
}

单片机与电脑交互:

/*
将收到的数据返回给电脑
*/
#include "reg52.h"             //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16;      //对数据类型进行声明定义
typedef unsigned char u8;


void UsartInit(){
    TMOD=0x20; // 0010 0000 定时器使用方式2自动重载
    TH1=0xFD;    //波特率9600
    TL1=0xFD;    
    // PCON=0x80;  // 1000 0000 SMOD=1时频率倍增
    PCON=0x00;
    TR1=1;    //打开计数器
    SCON=0x50;    //设置为工作方式1 ,既然是方式一,自然要确定波特率,设置定时器1
    ES=1;    //打开通信中断
    EA=1;    //打开总中断

}
void main()
{    
    UsartInit();
    while(1);        
}
void Usart() interrupt 4{
    u8 recData;
    recData=SBUF;    //存储接收到的数据
    RI=0;    //清除接收中断标志位
    SBUF=recData;    //将接收到的数据放入到发送寄存器
    while(!TI);    //等待发送数据完成
    TI=0;    //清除发送完成标志位
}
最后修改于:2021年02月14日 13:50

添加新评论