51_串口

 

1
2
3
4
5
6
7
8
9
10
11
#ifndef __USART_H_
#define __USART_H_
#include <reg51.h>
 
 
 
void Usart_Init(void);
void uart_send_byte(unsigned char i);
 
 
#endif

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "USART.h"
 
#define Crystal_Frequency  12000000UL        //使用12M晶体
#define BAUD_9600 4800UL        //波特率定义为9600
/***************************************************
*                               串口初始化子函数
*               T1工作在方式2,波特率9600,开串口中断
****************************************************/
void Usart_Init(void)
{
    //  EA=0;                   //暂时关闭中断
    TMOD=0x20;   //定时器1工作在模式2,自动重装模式
    SCON=0x50;    //串口工作在模式1
    TH1=256-Crystal_Frequency /(BAUD_9600*12*16);  //计算定时器重装值
    TL1=256-Crystal_Frequency /(BAUD_9600*12*16);
   // TH1=0XF3;         //计数器初始值设置,注意波特率是4800的
    //TL1=0XF3;
    PCON|=0x80;    //串口波特率加倍
    //ES=1;         //串口中断允许
    TR1=1;          //启动定时器1   
    //REN=1;         //允许接受
    //EA=1;          //允许中断
}
 
/***************************************************
*                               串口发送字节子函数
*          
****************************************************/
void uart_send_byte(unsigned char i)
{
        SBUF = i;   //送入发送缓冲寄存器
        while(TI == 0);     //判断发送是否完成
        TI = 0;                     //清除中断标志
}
 
/***************************************************
*                               串口接受中断函数
*          
****************************************************/
//void uart(void) interrupt 4
//{
//   unsigned char uart_buf;  //接受中断缓冲器
//   if(RI)  //是否到数据
//   {
//      RI=0;    //清中断请求
//  uart_buf=SBUF;
//  }
//
//}

UART通信原理

通讯过程描述

  1. 当没有通信信号时,通信线路保持高电平。
  2. 发送数据之前, 先发送一个0表示起位,表示起始位
  3. 接着发送8位数据位,数据位是先低后高的顺序。
  4. 数据位发送完毕,再发送一个1表示停止位

通讯数据帧图

  • UART完整串行数据帧:

UART模块的使用

51单片机的 UART 串口的结构由串行口控制寄存器 SCON ,发送电路接收电路三部分构成。

串口控制寄存器

  • SCON串行控制寄存器的位分配(地址为0x98, 可位寻址)
7 6 5 4 3 2 1 0
符号 SM0 SM1 SM2 REN TB8 RB8 TI RI
复位值 0 0 0 0 0 0 0 0
符号 描述
7 SM0 这两位共同决定了串口通信的模式0 ~模式 3 共 4 种模式 。 最常用的就是模式 1 ,也就是 SM0=0 SM1=1 ,其它模式从略。
6 SM1
5 SM2 多机通信控制位(极少用),模式 1 直接清零。
4 REN 使能串行接收。由软件置位使能接收,软件清零则禁止接收。
3 TB8 模式2 和 3 中要发送的第 9 位数据(很少用)。
2 RB8 模式2 和 3 中接收到的第 9 位数据(很少用),模式 1 用来接收停止位。
1 TI 发送中断标志位,当发送电路发送到停止位的中间位置时,TI 由硬件置 1必须通过软件清零。
0 RI 接收中断标志位,当接收电路接收到停止位的中间位置时,RI 由硬件置 1必须通过软件清零。。
  • 串口模式1: 1 位起始位, 8 位数据位和 1 位停止位。

    • SM0 = 0; SM1 = 1;

波特率

波特率的概念

  • 波特率就是发送二进制数据位所用的时间,用baud表示。

  • 发送1位二进制数据的持续时间为1/baud

波特率计算公式

  • 对于STC89C52单片机来说, 波特率发生器只能由定时器T1/T2产生,不能由T0产生。

  • 使用T1的模式2[自动重装模式], 定时器的重载值计算公式为:

     

    TH1=TL1=256/12/2/16/TH1=TL1=256−晶振值/12/2/16/波特率

     

    • 256 : 定时器模式2(8位)的溢出值
    • 晶振值: 11059200
    • 12 : 一个机器周期(STC89C52中一个时钟周期等于12个时钟周期, 具体看芯片手册)
    • 16: 串口模块将一位信号采集16次,将其中7,8,9次取出来,如果这三次中两次如果是高电平就认为这位数据是1。
    • 波特率: 要设定的波特率
  • 电源管理寄存器PCON, 设置后它可以将波特率提高一倍

    PCON |= 0x80
    
    • 此时波特率公式为:

       

      TH1=TL1=256/12/16/

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//  程序名称: uart/main.c
//  程序简述: uart实例
 
 
/*
    功能描述: 单片机usb接上计算机并实现通讯, 将其结果+1发送给计算机
     
    实现步骤:
    - 1. 配置串口为模式1
    - 2. 配置定时器T1为模式2
    - 3. 根据波特率计算TH1和TL1的初值, 如果有需要则可以使用PCNF进行波特率加倍
    - 4. 打开定时器控制寄存器, 让定时器跑起来
    - 5. 开启UART中断, 1.接收并解析数据, 2.处理数据, 3.发送数据
     
    程序注释:
    - 波特率计算公式:
        TH1 = TL1 = 256 - 晶振值 / 机器周期 / 2 / 16 / 波特率
        - 机器周期: STC89C52RC的机器周期是'晶振/12'
        - 16: 单片机uart模块会将每一个数据位取16次, 然后判断中间值来确定是'0'还是'1'
     
    - 波特率加倍:
        PCON |= 0x80;那么计算公式为:
            - TH1 = TL1 = 256 - 晶振值/12/16/波特率
*/
 
 
#include<reg52.h>
 
#define Crystal_Frequency 11059200 // 定义当前单片机的晶振频率
#define BAUDRATE 9600                // 定义当前单片机UART所采用的波特率
 
 
void ConfigUART(unsigned int baud); // 串口初始化
 
void main() {
    EA = 1; // 打开使能总中断
    ConfigUART(BAUDRATE);
    while(1);
}
 
 
/* 串口配置函数, baud-通信波特率 */
void ConfigUART(unsigned int baud) {
    SCON = 0x50;  // 配置为串口为模式1
    TMOD &= 0x0F; // 清0 T1的控制位
    TMOD |= 0x20; // 配置T1为模式2
     
    TH1 = 256 - (Crystal_Frequency / 12 / 32) / baud; // 计算T1重载值
    TL1 = TH1;  // 初值等于重载值
    ET1 = 0;    // 禁止T1中断
    ES = 1;     // 使能串口中断
    TR1 = 1;    // 启动T1
}
 
 
/* 串口中断服务函数 */
void Uart_Interrupt() interrupt 4 {
     
    if (RI) {// 接收到字节
        RI = 0; // 手动清零接收中断标志位
        SBUF = SBUF + 1; // 接收的数据 +1 后发回,左边是发送 SBUF ,右边是接收 SBUF
    }
     
    if (TI) {// 字节发送完毕
        TI = 0; // 手动清零 发送中断标志位
    }
}

  

 

posted @   xiaoberber  阅读(191)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示