当前位置: 首页 > article >正文

C51串口初始化及波特率设置

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
	SCON=0x40;
	PCON |= 0x80;
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xF3;		//设定定时初值
	TH1 = 0xF3;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
#include <REGX52.H>
#include <intrins.h> // 引入延时函数所需的头文件

// 延时函数,用于控制字母发送的间隔
void DelayMs(unsigned int ms)
{
    unsigned int i, j;
    for (i = ms; i > 0; i--)
        for (j = 110; j > 0; j--)
            ;
}

// 串口初始化函数,设置波特率为 9600bps@11.0592MHz
void UartInit()
{
    PCON &= 0x80; // 波特率不加倍
    SCON = 0x50;  // 8 位数据,可变波特率
    TMOD |= 0x20; // 定时器 1 工作在 8 位自动重装模式
    TL1 = 0xFD;   // 波特率初值
    TH1 = 0xFD;   // 波特率重载值
    IE |= 0x90;   // 使能串口中断
    TR1 = 1;      // 启动定时器 1
    ET1 = 0;      // 禁止定时器 1 中断
}

// 串口发送一个字节数据的函数
void Uartsend(unsigned char byte)
{
    SBUF = byte; // 将数据写入发送缓冲区
    // 等待发送完成,发送完成后 TI 会被置 1
    while (TI == 0)
        ;
    TI = 0; // 清除发送完成标志
}

// 定义一个全局变量用于存储接收到的 8 位数据
unsigned char receivedData = 0;
// 定义一个计数器,用于记录接收到的字符数量
unsigned char count = 0;
// 串口中断服务函数
void UART_ISR() interrupt 4
{
    if (RI)
    {                                      // 判断是否接收到数据
        unsigned char receivedChar = SBUF; // 读取接收到的数据
        RI = 0;                            // 清除接收中断标志
        /*
        if (receivedChar == '0' || receivedChar == '1')
        {
            // 将接收到的字符转换为对应的二进制位
            receivedData <<= 1; // 左移一位
            if (receivedChar == '1')
            {
                receivedData |= 0x01; // 若为 '1',则该位置 1
            }
            count++;

            if (count == 8)
            {                       // 接收到 8 位数据
                P2 = ~receivedData; // 取反是因为 LED 是低电平点亮
                count = 0;          // 重置计数器
                receivedData = 0;   // 重置数据
            }
        }
        */
       Uartsend(SBUF); 
    }
}
int main()
{
    unsigned char ch;
    UartInit(); // 初始化串口

    // 循环发送 a - z 这 26 个字母
    /*
    for (ch = 'a'; ch <= 'z'; ch++) {
        Uartsend(ch);  // 发送当前字母
        DelayMs(100);  // 延时 100 毫秒,控制发送间隔
    }
    */

    // LED接收亮灭
    P2 = 0xFF;
    while (1)
    {
        // 主循环可以留空,也可以添加其他任务
    }
}

1. 波特率设置

  • 第一个函数 UART_Init
    • PCON |= 0x80; 这行代码将 PCON 寄存器的最高位 SMOD 置为 1,使波特率加倍。
    • 定时器 1 工作在 8 位自动重装模式(TMOD |= 0x20),初值 TL1 = 0xF3 和重装值 TH1 = 0xF3 是针对 4800bps@12.000MHz 晶振计算得出的。在波特率加倍(SMOD = 1)的情况下,定时器 1 溢出率用于产生 4800bps 的波特率。
  • 第二个函数 UartInit
    • PCON &= 0x80; 这行代码将 PCON 寄存器的最高位 SMOD 清 0,波特率不加倍。
    • 定时器 1 同样工作在 8 位自动重装模式(TMOD |= 0x20),初值 TL1 = 0xFD 和重装值 TH1 = 0xFD 是针对 9600bps@11.0592MHz 晶振计算得出的。在波特率不加倍(SMOD = 0)的情况下,定时器 1 溢出率用于产生 9600bps 的波特率。

2. 串口模式设置

  • 第一个函数 UART_Init
    • SCON = 0x40; 将 SCON 寄存器设置为模式 1,即 8 位数据,固定波特率。这种模式下,波特率由定时器 1 的溢出率决定。
  • 第二个函数 UartInit
    • SCON = 0x50; 将 SCON 寄存器设置为模式 1,不过这里强调是 8 位数据,可变波特率(其实模式 1 就是由定时器 1 溢出率控制波特率,可看作可变)。

3. 中断使能设置

  • 第一个函数 UART_Init:没有使能串口中断,这意味着在串口接收到数据或者发送完成时不会触发中断服务函数。如果需要处理串口通信的事件,需要额外手动编写轮询代码来检查相关标志位。
  • 第二个函数 UartInitIE |= 0x90; 使能了串口中断(ES = 1)和全局中断(EA = 1),当串口接收到数据或者发送完成时,会触发相应的中断服务函数来处理。

4. 可能存在的问题

  • 第一个函数 UART_Init
    • 晶振不匹配问题:如果实际使用的晶振频率不是 12.000MHz,那么设置的波特率 4800bps 可能不准确,会导致通信出现乱码。
    • 无中断处理:由于没有使能串口中断,在处理串口数据时可能需要编写复杂的轮询代码,并且在多任务场景下,可能会影响系统的实时性。
  • 第二个函数 UartInit
    • 晶振不匹配问题:如果实际使用的晶振频率不是 11.0592MHz,设置的 9600bps 波特率也会不准确,同样会造成通信乱码。
    • 中断处理负担:使能串口中断后,如果中断服务函数编写不当,可能会导致系统资源消耗过大,影响系统的稳定性。

http://www.kler.cn/a/580391.html

相关文章:

  • SOAP与NETCONF:协议特性、场景与应用全景解析
  • Apache XTable:在数据湖仓一体中推进数据互作性
  • 面试题之webpack file-loader和url-loader
  • 1688店铺所有商品数据接口详解
  • python文本处理pdfminer库安装与使用
  • LeetCode热题100中的背包问题
  • 基于大数据的商品数据可视化及推荐系统
  • 鸿蒙应用开发—数据持久化之SQLite
  • RangeError: Maximum call stack size exceeded
  • 【人工智能】随机森林的智慧:集成学习的理论与实践
  • 元脑服务器的创新应用:浪潮信息引领AI计算新时代
  • 物联网-电路局“一杆一档”管理
  • 【开源宝藏】Spring Trace 一种轻量级的日志追踪新方式
  • Flutter 学习之旅 之 flutter 使用flutter_native_splash 简单实现设备启动短暂白屏黑屏(闪屏)的问题
  • 如何实现wordpress搜索自字义字段内容
  • 《 YOLOv5、YOLOv8、YOLO11训练的关键文件:data.yaml文件编写全解》
  • JVM常用概念之本地内存跟踪
  • 如何下载一些网上只提供了预览的pdf
  • 【C#学习笔记02】基本元素与数据类型
  • 从0开始的操作系统手搓教程33:挂载我们的文件系统