手册中给出了常用波特率表格,但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"
📌 相关论坛讨论
- 【天王归来】STC89C52RC使用专用定时器2做波特率发生器,定时器0做串口接收超时检测!
- STC89C52RC, T2做波特率发生器,波特率 = 系统时钟/32/(65536 - [RCAP2H,RCAP2L
- 图形化配置 STC89C52RC系列各功能模块, 程序框架自动生成, AiCube-ISP-V6.96V
⏱️ 查找用时 3.8s | 总回答用时 20.6s