找回密码
 立即注册
查看: 435|回复: 2

需要 STC89C52RC的串口收发程序,波特率9600,时钟22.1184MHz

[复制链接]
已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
发表于 2026-7-10 20:12:39 | 显示全部楼层 |阅读模式
需要 STC89C52RC的串口收发程序,波特率9600,时钟22.1184MHz

截图202607102012023684.jpg

截图202607102012348287.jpg
回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
 楼主| 发表于 2026-7-10 20:14:18 | 显示全部楼层

手册中给出了常用波特率表格,但22.1184MHz下9600波特率的配置需要计算。让我查一下STC89C52RC的12T/6T模式相关信息,确认默认工作模式。

根据手册中的公式:

模式1、3波特率 = 2SMOD / 32 × (定时器1的溢出率)

定时器1工作方式2(8位自动重装),12T模式下:
溢出率 = SYSclk / (12 × (256 - TH1))

对于 22.1184MHz,目标波特率 9600:

若 SMOD=1(波特率加倍):
9600 = 2¹ / 32 × (22,118,400 / (12 × (256 - TH1)))
9600 = 2 / 32 × (22,118,400 / (12 × (256 - TH1)))
9600 = 1/16 × (22,118,400 / (12 × (256 - TH1)))
9600 = 22,118,400 / (192 × (256 - TH1))
256 - TH1 = 22,118,400 / (192 × 9600) = 22,118,400 / 1,843,200 = 12
TH1 = 256 - 12 = 244 = 0xF4

若 SMOD=0(不加倍):
9600 = 2⁰ / 32 × (22,118,400 / (12 × (256 - TH1)))
9600 = 1/32 × (22,118,400 / (12 × (256 - TH1)))
9600 = 22,118,400 / (384 × (256 - TH1))
256 - TH1 = 22,118,400 / (384 × 9600) = 22,118,400 / 3,686,400 = 6
TH1 = 256 - 6 = 250 = 0xFA

两种方案都可行。我选择 SMOD=0、TH1=0xFA 的方案(更常见)。下面给出完整的串口收发程序。

/*---------------------------------------------------------------------------*/
/* --- STC89C52RC 串口收发程序 (波特率9600, 时钟22.1184MHz) -------------- */
/* --- 功能: 串口方式1, 定时器1方式2(8位自动重装)产生波特率              --- */
/* ---       接收到的数据原样发送回(回环测试)                             --- */
/* --- 接线: RXD(P3.0) - TXD(P3.1) 接USB转串口模块                       --- */
/* --- 晶振: 22.1184MHz, 12T模式(默认)                                   --- */
/*---------------------------------------------------------------------------*/

#include "reg51.h"

/* 波特率参数: SMOD=0, TH1=0xFA, 9600bps @ 22.1184MHz */
#define RELOAD_VALUE  0xFA

/* 缓冲区定义 */
#define RX_BUF_SIZE  16
unsigned char rx_buffer[RX_BUF_SIZE];   /* 接收缓冲区 */
unsigned char rx_index = 0;             /* 接收缓冲区索引 */
unsigned char rx_flag = 0;              /* 接收到一帧数据的标志 */

/* 函数声明 */
void UART_Init(void);
void UART_SendByte(unsigned char dat);
void UART_SendString(unsigned char *str);

/*---------------------------------------------------------------------------*/
/* 串口初始化: 9600bps, 方式1, 定时器1方式2                                */
/*---------------------------------------------------------------------------*/
void UART_Init(void)
{
    /* 配置定时器1: 8位自动重装模式(方式2), 定时器模式 */
    TMOD &= 0x0F;       /* 清除T1的M1、M0位 */
    TMOD |= 0x20;       /* 设置T1为方式2 (8位自动重装) */

    TH1 = RELOAD_VALUE; /* 设置重装值 */
    TL1 = RELOAD_VALUE; /* 设置初值 */

    /* 配置串口: 方式1 (8位UART), 允许接收 */
    SCON = 0x50;        /* SM0=0, SM1=1, REN=1, 方式1 */

    /* SMOD=0, 波特率不加倍 (PCON.7=0) */
    PCON = 0x00;

    TR1 = 1;            /* 启动定时器1 */

    /* 使能串口中断 */
    ES = 1;             /* 允许串口中断 */
    EA = 1;             /* 开总中断 */
}

/*---------------------------------------------------------------------------*/
/* 串口发送一个字节 (查询方式)                                               */
/*---------------------------------------------------------------------------*/
void UART_SendByte(unsigned char dat)
{
    SBUF = dat;                     /* 将数据写入发送缓冲器 */
    while (TI == 0);                /* 等待发送完成 */
    TI = 0;                         /* 清除发送中断标志 */
}

/*---------------------------------------------------------------------------*/
/* 串口发送字符串                                                           */
/*---------------------------------------------------------------------------*/
void UART_SendString(unsigned char *str)
{
    while (*str != '\0')
    {
        UART_SendByte(*str++);
    }
}

/*---------------------------------------------------------------------------*/
/* 串口中断服务函数                                                         */
/*---------------------------------------------------------------------------*/
void UART_ISR(void) interrupt 4
{
    unsigned char ch;

    if (RI == 1)                    /* 接收中断 */
    {
        RI = 0;                     /* 清除接收中断标志 */
        ch = SBUF;                  /* 读取接收到的数据 */

        /* 将接收到的数据存入缓冲区 (防止溢出) */
        if (rx_index < RX_BUF_SIZE)
        {
            rx_buffer[rx_index++] = ch;
        }

        /* 如果收到换行符(0x0A)或回车符(0x0D), 置位接收完成标志 */
        if ((ch == '\n') || (ch == '\r'))
        {
            rx_buffer[rx_index - 1] = '\0';  /* 字符串结束符替换换行符 */
            rx_flag = 1;                     /* 置位接收完成标志 */
        }
    }

    if (TI == 1)                    /* 发送中断 (本程序未使用) */
    {
        TI = 0;                     /* 清除发送中断标志 */
    }
}

/*---------------------------------------------------------------------------*/
/* 主函数                                                                   */
/*---------------------------------------------------------------------------*/
void main(void)
{
    unsigned char i;

    UART_Init();                    /* 初始化串口 */

    UART_SendString("STC89C52RC UART Test @ 9600bps, 22.1184MHz\r\n");

    while (1)
    {
        /* 检查是否接收到一帧数据 */
        if (rx_flag == 1)
        {
            rx_flag = 0;            /* 清除标志 */

            /* 将接收到的数据回显 */
            UART_SendString("Received: ");
            UART_SendString(rx_buffer);
            UART_SendString("\r\n");

            /* 清空接收缓冲区 */
            for (i = 0; i < RX_BUF_SIZE; i++)
            {
                rx_buffer[i] = 0;
            }
            rx_index = 0;
        }
    }
}

程序说明

1. 波特率计算(22.1184MHz,12T模式)

STC89C52RC 默认工作在 12T模式(烧录时可在 ISP 软件中设置,此处按默认12T处理)。

公式:波特率 = 2^SMOD / 32 × (SYSclk / (12 × (256 - TH1)))

取 SMOD=0(不加倍),代入:

9600 = 1/32 × (22,118,400 / (12 × (256 - TH1)))
9600 = 22,118,400 / (384 × (256 - TH1))
256 - TH1 = 22,118,400 / (384 × 9600) = 6
TH1 = 256 - 6 = 250 = 0xFA

2. 寄存器配置

寄存器 值 说明
TMOD 0x20 定时器1方式2(8位自动重装)
TH1/TL1 0xFA 波特率重装值
SCON 0x50 方式1(8位UART),允许接收
PCON 0x00 SMOD=0,波特率不加倍

3. 程序功能

  • 上电后串口发送欢迎信息
  • 串口接收数据存入缓冲区,遇到 \n 或 \r 认为一帧结束
  • 将接收到的数据原样回显(回环测试)

4. 使用说明

  • 晶振使用 22.1184MHz(注意不是11.0592MHz)
  • 串口连接:P3.0(RXD) 接 USB转串口模块的 TXD,P3.1(TXD) 接 RXD,GND 共地
  • 串口助手设置为:9600bps,8数据位,1停止位,无校验

🔍 搜索 "STC89C52RC 串口收发 波特率9600 22.1184MHz"

📌 相关论坛讨论

  1. 【天王归来】STC89C52RC使用专用定时器2做波特率发生器,定时器0做串口接收超时检测!
  2. STC89C52RC, T2做波特率发生器,波特率 = 系统时钟/32/(65536 - [RCAP2H,RCAP2L
  3. 图形化配置 STC89C52RC系列各功能模块, 程序框架自动生成, AiCube-ISP-V6.96V

⏱️ 查找用时 3.8s | 总回答用时 20.6s

回复

使用道具 举报 送花

已绑定手机

872

主题

1万

回帖

2万

积分

管理员

积分
25428
 楼主| 发表于 2026-7-10 20:15:41 | 显示全部楼层
让 STC 【AI 助手】自动帮您写你需要的通用MCU程序

STC-ISP最新版软件,AiCube-ISP V6.96Z版内置:
STC 【AiCube】:图形化配置各功能模块外设,自动生成程序;
STC 【AI 助手】:按输入的要求,自动生成程序,
或排查您程序的错误。

STC 【AI 助手】,已加载 STC全系列MCU专业技术手册。
help.stcaimcu.com
可以帮您:
- 回答STC技术手册中的技术问题
- 自动生成您需要的通用MCU程序
- 自动高效排查您程序中的错误

所以只要有 C语言的基础,STC的MCU,你其实已经算能用了,
再用到哪,研究到哪,
让 STC 【AI 助手】帮你研究总结

让 STC 【AI 助手】自动帮您写你需要的通用MCU程序

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-11-7 14:42 , Processed in 0.073315 second(s), 50 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表