C51 - 串口UART_发送

UART

  • 0> 引言
  • 1> 通讯协议
    • 1.1> 示波器测试
  • 2> 硬件组成
    • 2.1> 串口工作模式1 (8N1)
    • 2.2> 并转串-移位寄存器(74HC165)
  • 3> 波特率发生器
    • 3.1> 定时器1 配置
    • 3.2> 8位自动重装载
    • 3.3> 初始值计算
  • 4> 程序设计
    • 4.1> 发送1字节数据
    • 4.2> 发送字符串
    • 4.3> printf重定向

±-------------------------+

B站:视频链接

单片机-通信基础

±-------------------------+

0> 引言


C51 - 串口UART_发送_第1张图片


C51 - 串口UART_发送_第2张图片


1> 通讯协议

UART 概述

一帧数据:
C51 - 串口UART_发送_第3张图片

位段 内容
空闲位 TX保持高电平
起始位 TX由高变低,保持=1bit位宽
数据为 5~8位ASCII的编码数据
校验位 校验方式:奇校验 / 偶校验
停止位 TX由低变高,保持>=0.5bit位宽

1.1> 示波器测试

C51 - 串口UART_发送_第4张图片

波特率9600;


2> 硬件组成

2.1> 串口工作模式1 (8N1)

8N1: 8位数据位, 无校验位,1位停止位;

C51 - 串口UART_发送_第5张图片

发送框图:
C51 - 串口UART_发送_第6张图片

发送时序:

C51 - 串口UART_发送_第7张图片

1> 定时器1作,脉冲发生器;
2> 并转串 移位寄存器,作数据通路;
3> TX/RX ConTROL单元,作控制单元;

注意: UART模块内部通过SMOD 和 [/16分频] 对定时器的溢出率进行分频


2.2> 并转串-移位寄存器(74HC165)

通过74HC165芯片,了解 移位寄存器,工作本质

C51 - 串口UART_发送_第8张图片
C51 - 串口UART_发送_第9张图片

一个CLK移动移位;


3> 波特率发生器

通过定时器1的溢出,产生CLK方波;
STC89C516RD+ 有3个定时器, 通常,Tim1 用作串口波特率发生器, Tim2用于整个系统定时, Timer0用于其他;

3.1> 定时器1 配置

/**
 * @brief UART initialization
 * @note 8N1, 115200
 */ 
void UART_Init(void)
{
	ES = 0;					// 禁止串口中断;
	ET1 = 0;				// 禁止定时器1中断 
	RI = 0;					// 清零接收中断请求标志
	
	/* UART Config */
	SCON = 0x50;    		// 串口工作模式:8位数据位, 0101  0000
	PCON |=  0x80;			// 串口波特率加倍;1000 0000

	/* Tim1 Config */
    TMOD &= 0x0F;
    TMOD |= 0x20;			// 定时器1工作模式2:8位自动重装载
    TH1 = 0x100 - (SYS_CLK / 12 * 2 / 32 / 115200);   
    TL1 = TH1;				// 定时器1初始值
	
    TR1 = 1;				// 启动定时器1
}

3.2> 8位自动重装载

C51 - 串口UART_发送_第10张图片

对SYSclk 分频后, 进行+1 计数器;
当加满溢出时, 硬件自动将TH1值装入TL1;

定时器溢出率 = SYSclk / 12 / (2 ^ 8 - N);


3.3> 初始值计算

相关概念:

定时器的溢出率 : 1S内定时器加满次数,
波特率: 1S内传输二进制bit位数;

C51 - 串口UART_发送_第11张图片

C51 - 串口UART_发送_第12张图片

公式总结:
串口方式1, 定时器模式8位自动重装载:

波特率 = 定时器溢出率 * ( 2 ^ SMOD / 32 ) ;

定时器溢出率 = SYSclk / 12 / (2 ^ 8 - N);
波特率 = SYSclk / 12 / (256 - N) * ( 2 ^ SMOD / 32 )

256 - N = SYSclk / 12 * (2 ^ SMOD / 32) / 波特率
N = 256 - SYSclk / 12 * (2 ^ SMOD / 32) / 波特率

以外部晶振22.1184MHz, 12T模式, 加倍计算, 产生115200波特率的N值;

N = 256 - (22118400 / 12 * 2 / 32 / 115200);  
  = 256 - 1
  = 255  //0xFF
  

C51 - 串口UART_发送_第13张图片

与串口波特率计算工具的结果一样;


4> 程序设计


4.1> 发送1字节数据

轮询方式,注意先发送数据,再判断TI;

/**
 * @brief UART put one Byte
 * @c put data
 */ 
void UART_Putchar(uchar8_t c)
{
    
	
    SBUF = c;
    while(!TI) {
		/* Nothing */ ;
	}
	
    TI = 0;
	
}

4.2> 发送字符串

void bsp_uart_putstring(unsigned char *str)
{
	while (*str) {
		if (*str == '\n') {
			bsp_uart_putbyte('\r');	
		}

		bsp_uart_putbyte(*str++);
	}
}

Windows系统对于文本都是以‘\r’回车结束,再’\n’换行,所以要插入一个‘\r’;


4.3> printf重定向

用字节写的发送一个字符函数,编写库函数的putchar, 因为库函数printf调用putchar输出;

#include 

char putchar(char c)
{
	ES = 0;

	if (c == '\n') {
		SBUF = '\r';
		while ( !TI ) { /*  waiting */;	} 
		TI = 0;	
	}

	SBUF = c;
	while ( !TI ) { /*  waiting */;	} 
	TI = 0;
	ES = 1;	

	return 1; 
}

查看库函数
C51 - 串口UART_发送_第14张图片

格式化输出方式,注意char 用 %bd;

C51 - 串口UART_发送_第15张图片

使用printf测试数据类型,所占内存大小

C51 - 串口UART_发送_第16张图片

好嘛,有了printf, 51上就可以练习C语言了;

你可能感兴趣的:(51单片机开发-DAYi,51单片机)