51单片机快速入门之 串行通信 2024/10/21

51单片机快速入门之 串行通信

并行通信:

  1. 好处:传输快 适合短距离通信
  2. 弊端:占用大量io
  3. 接线形式为8对8

串行通信

异步通信:

数据一帧一帧传送,传输完一帧之后,可继续或者等待(等待时为高电平)

其帧细分为(图片来源)

起始位:数据帧开始,一定为 0 外部设备只有接受到 0 之后才会开始接收数据

数据位:低位到高位传输 可是5-8位

奇偶校验: 验证数据有无错误,

说白了就是通过计算数据中一共有几个 1 然后判断其为 奇数 还是 偶数

举例: 传输 1111 0000 这里有4个1 为偶数 我们用奇数校验 就 应设置为 1

如果传输错误 比方说 1101 0000 1 由于校验位为1 此时构成偶数 奇数验证失败,数据传输异常

帧 0 1111 0000 1 1

奇偶校验只能检测到单比特错误,而且只能确定数据中有错误,但不能定位具体是哪一位出错。

如果数据发生多位错误,奇偶校验可能无法检测到。

因此,奇偶校验的可靠性相对较低,通常用于内存等对可靠性要求不高的场合。

停止位:简单的说就是 必须为高电平,其他不考虑 哪怕 是 占用 2位 也可以 例如 0 1111 0000 1 11

只要停止位后或停止位 等于0 即为下一帧起始位!

有四种传输方式:

  1. 方式0: 只有 数据8位 无起始位 无停止位 通常用于 并行IO 的拓展 一共8位
  2. 方式1:起始位 数据8位 停止位 一共10位
  3. 方式2:起始位 数据8位 可编程位 停止位 一个11位
  4. 方式3:起始位 数据8位 可编程位 停止位 一个11位 (不同点: 波特率设置不同)
缺点:数据传输速度较慢

同步通信:

同步信号 数据 数据 数据 .....

同步信号取代了起始位,后方可以跟很多数据 且取消了停止位

优点:高速设备数据传输时常用

缺点:需要复杂的电路支持,单片机一般不用这种!


串行通信的数据传输方向

第一种:单工方式

一个方向传输 只能过去 回不来

T(发送) >>>> R(接收)


第二种:半双工方式

可以过去 也可以回来 但是得吃完了饭才能回来 不可同时

T(发送)>>>>R(接收) 没吃完不准走

R(接收)<<<<T(发送) 吃完饭你走吧


第三种:全双工方式

T====T 可同时

R====R

打包边走边吃,饭也吃了,家也回了.


测试这四种传输方式51单片机串行通信(异步通信):

方式0:

只有 数据8位 无起始位 无停止位 通常用于 并行IO 的拓展 一共8位

74LS164https://baike.so.com/doc/5430847-5669134.html

发送代码实现 :

#include <STC89C5xRC.H>
void delay(unsigned int t);//延时函数声明


void main()
{
	SCON=0X10;  //设置串行控制器0 0 0 1 0000  方式0 允许接受
		
    SBUF=0xfe;  //发送1111 1110
	while(1);//防止程序重复运行

}

void delay(unsigned int t)      //简单延迟函数
{
    while(t--);

}
方式0发送效果:默认1/12 X 波特率

数据从低位到高位 我们发送的 是1111 1110 先发送的是0 然后是1 1 1 1111 所以Q7是输出值的最低位

接收请参考:

74LS165 http://www.doc88.com/p-810688043108.html


方式1: 波特率与定时器/计数器 SMOD的设置有关

起始位 数据8位 停止位 一共10位

代码实现:

#include <STC89C5xRC.H>
 
void delay(unsigned int t); // 延时函数声明
void init();
 
unsigned char str[] = "abcd"; // 定义一个字符数组来存储字符串
 unsigned char i; 
void main()
{
    init(); 
			SBUF=0;  //发送起始位
	 while(!TI);
        TI = 0; // 清除发送中断标志位 
	
    for(i = 0; str[i] != '\0'; i++) {
        SBUF = str[i]; // 逐个字符发送 
			
						 while(!TI);
        TI = 0; // 清除发送中断标志位 
        delay(200); // 添加一点延迟,以便接收端有时间处理 
    } 
		
			SBUF=1;  //发送停止位
	 while(!TI);
        TI = 0; // 清除发送中断标志位 
		
				
    P22 = 0; // 假设 P22 是你想要控制的某个输出引脚 
 
    while(1); // 防止程序重复运行 
}
 
void init() 
{
    SCON = 0x50; // 设置串口工作在模式1,8位UART,允许接收 
    TMOD |= 0x20; // 设置定时器1为模式2,8位自动重装载 
    TH1 = 253; // 设置波特率为9600(假设晶振频率为11.0592MHz)
    TR1 = 1; // 启动定时器1
    PCON = 0x00; // SMOD = 0,波特率不加倍 
    EA = 1; // 开启全局中断 
    ES = 1; // 允许串口中断
}
 
void delay(unsigned int t) // 简单延迟函数 
{ 
    while(t--); 
} 

方式一效果展示:

单片机必须是11.0592mhz 程序也得是,不然会出错

方式2:与SMOD 有关=0时 1/64 x 波特率 =1时 1/32 x 波特率

起始位 数据8位 可编程位 停止位 一个11位

代码实现:

#include <reg51.h> // 包含51单片机的寄存器定义头文件 
 
// 初始化串口模式2和定时器1
void init_serial() {
    SCON = 0x80; // 设置串口模式2,REN = 0(不允许接收),TB8 = 0(第9位数据为0) 
	  PCON=0X80;  //设置smod=1 模式2工作在 加倍环境 12mhz 的 32分之一 也就是 375kbit/s
} 


void delay(unsigned char t){while(t--);}
  unsigned char dat[]= "modd"; // 要发送的字符串 
    unsigned char i;
// 主函数 
void main() {
   
   
						 init_serial(); 
	
    for (i = 0; dat[i] != '\0'; i++) {
        SBUF = dat[i]; // 将字符发送到串口缓冲区
        while (!TI); // 等待发送完成
        TI = 0; // 清除发送中断标志
			delay(1000);
    } 
 
    while (1) {} // 主循环,保持程序运行
}

程序效果:

方式3:起始位 数据8位 可编程位 停止位 一个11位 (不同点: 波特率设置不同)

1和3 波特率求法 2^smod/32 x T1溢出率(溢出脉冲频率)

相关推荐
安科瑞刘鸿鹏6 小时前
校园建筑用电安全监测装置 电气火灾监测预防设备功能介绍
运维·服务器·网络·嵌入式硬件·安全·能源
Wx120不知道取啥名6 小时前
C语言之长整型有符号数与短整型有符号数转换
c语言·开发语言·单片机·mcu·算法·1024程序员节
Cici_ovo9 小时前
摄像头点击器常见问题——摄像头视窗打开慢
人工智能·单片机·嵌入式硬件·物联网·计算机视觉·硬件工程
无际单片机项目实战9 小时前
为什么STM32的HAL库那么难用,ST还是要硬推HAL库?
c语言·stm32·单片机·嵌入式硬件·物联网
正在努力的小立12 小时前
STM32 HAL 点灯
stm32·单片机·嵌入式硬件
TeYiToKu13 小时前
笔记整理—linux驱动开发部分(1)驱动梗概
linux·c语言·arm开发·驱动开发·嵌入式硬件
Whappy00114 小时前
3. STM32之TIM实验--输出比较(PWM输出,电机,四轴飞行器,智能车,机器人)--(实验1:PWM驱动LED呼吸灯)
stm32·嵌入式硬件·机器人
Java Fans16 小时前
嵌入式软件在电子烟开发中的应用
嵌入式硬件
环能jvav大师18 小时前
使用Ubuntu系统+VS Code开发STC51单片机
linux·c语言·开发语言·单片机·嵌入式硬件·ubuntu
q47259945119 小时前
UART通过DMA接收和发送,使用环形缓冲区,状态机的使用
stm32·单片机·嵌入式硬件