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溢出率(溢出脉冲频率)

相关推荐
国科安芯10 小时前
航天器多路并联大功率电源系统设计与ASP4644均流特性分析
单片机·嵌入式硬件·fpga开发·安全性测试
茯苓gao12 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
梁朝辉15 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者16 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间17 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious17 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng21 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计1 天前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试一、基本概念
嵌入式硬件·通信与接口协议
wuyk5552 天前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机