关于嵌入式学习——嵌入式硬件3

一、概念

  • UARTUniversal Asynchronous Receiver/Transmitter 通用异步收发器,硬件通信的形式
  • 51有两个串口(1个串口被用于ISP下载程序,1个串口被用于和主机之间的通信)
  • 串口通信有两个数据传输线 (TXD)发送信号线/(RXD)接收信号线

二、通信方式

1.单工:

  • 发送方和接收方是固定的,数据只能从发送方发给接收方
  • 通过一根信号线进行数据传输,数据传输的方向呈现单一性

2半双工:(I2C)

  • 通信的双方既可以作为发送方也可以作为接收方
  • 数据传输通过一根信号线实现,数据的传输方向可以是双向的
  • 同一时刻,数据传输方向呈现单一性(A给B发的时候,B不能给A发,B只能接收数据)

3全双工(UART)

  • 通信双方既可以作为发送方也可以作为接收方
  • 数据传输是通过两根信号线实现,数据传输在任意时刻都是双向的(收发可以同时进行)

三、数据传输的顺序:

Uart在传输数据时,遵循LSB优先原则**(低位先行**),先发低位数据,一个bit一个bit发

四、数据传输的形式:

串行:通过一根信号线传输数据,按照先后次序逐个bit逐个bit去发送数据

并行:同时多根信号线同时去传输数据

五、串行传输和并行传输的区别:
串行:

  • 传输速率慢(只能通过一根线逐个bit去传输)
  • 硬件成本低,实现简单
  • 传输距离远,抗干扰性好(RS485 差分)

并行:

  • 传输速率快(可以通过多根线同时传输多个bit)
  • 硬件成本高,实现复杂
  • 传输距离近,抗干扰性差(30米以内 距离增加后多根信号新存在信号偏移,会电磁波干扰,会造成误差和干扰)

六、串口通信时序:

1.串口通信时,空闲状态为高电平

2.当由高电平变为低电平(发送一个低电平信号),代表发送了一个起始位 ,准备开始通信

3.发送数据(通常是8bit,遵循先发数据低位LSB原则)

4.再发送一个bit的校验位

tip:

校验:
奇偶校验(串口)
累加和校验
CRC校验(Modbus协议)

七、奇偶校验:

问题:无法检测偶数个bit出错

  • 奇校验:校验位为1,若数据位中1的个数加上校验位中的1,保持1的个数为奇数个,则代表校验通过
  • 偶校验:校验位为0,若数据位中1的个数加上校验位中的0,保持1的个数为偶数个,则代表校验通过

八、串口通信参数(波特率、数据位、停止位、校验位):

波特率:bps(bit per second),每秒钟传输bit的数量,常见的波特率:2400,4800,9600,115200

数据位:8位串口传输通常8bit数据位传输

停止位:1,1bit停止位

校验位:

  • None,N,无校验
  • Even,E,偶校验
  • Odd,O,奇校验

ex:

9600, 8, N, 1

2400,8,E,1

115200, 8, 0, 1

九、同步通信和异步通信

UART、I2C、SPI?同步?异步?

I2C(SCL:时钟线,SDA:数据线)

SPI(SCLK时钟线)

UART(无时钟线)

同步: 通信的双方有一根共享的时钟线 来约定通信的频率(同步发送数据/接收数据)
**异步:**通信双方没有时钟线进行同步,如Uart:可以通过设置波特率来实现同步(发:2400bps收:2400bps)

十、串口相关寄存器:

(1)SCON/PCON串口控制寄存器:

  • PCON寄存器 中的bit6置0代表通过SCON寄存器中SMO和SM1两位指定串口工作方式:
  • 将SCON寄存器中的bit6和bit7清0
  • 将SCON寄存器中的SM1 bit6置1,SM0bit7清0,代表串口工作8位UART模式
  • 将SCON寄存器中REN bit4置1,代表允许串口接收数据
  • SCON寄存器中bit1 T1位,代表串口8位数据发送完毕硬件自动置1,但需要软件清0**(查询)**
  • SCON寄存器bit0 R1位,代表串口8位数据接收完毕硬件自动置1,但需要软件清0**(查询)**
  • PCON寄存器bit7位置1,代表波特率加倍

(2)串口数据缓冲寄存器SBUF:无需配置,数据传入即可:

有2个互相独立的接收、发送缓冲器,可以同时发送和接收数据。发送缓冲器只能写入而不能读出,接收缓冲器只能读出而不能写入,因而两个缓冲器可以共用一个地址码(99H)。两个缓冲器统称串行通信特殊功能寄存器SBUF。

(3)定时器相关配置:

  1. 串口为什么需要定时器?

UART 是异步通信,没有单独的时钟线,收发双方必须事先约定一个比特时间(波特率)。

  • 单片机内部通常没有"波特率发生器"专用模块,于是把定时器借过来当波特率发生器用。

  • 定时器以固定频率溢出(或翻转),每溢出一次就产生一个"tick"给 UART,告诉它:"该发/收 1 位数据了"。

TMOD定时器模式选择寄存器:

  • 将TMOD寄存器中的高四位清0(定时器1)
  • 将TMOD寄存器中的bit5置1,bit4清0,代表定时器1工作在8位自动重装载模式
  • 将TCON寄存器中的bit6置1,代表允许定时器1开始计数

定时器初值的计算公式:

公式:2^8-2^smod * focs / 32 / bps / 12

其中smod表示PCON的B7,根据实际情况带入,不是0就是1(波特率是否加倍);

focs晶振频率,我是12Mhz = 12000000hz;

bps目标波特率 我是2400bps

2^8这里的8来自定时器的工作方式,因为我使用的是8位自动重装方式,所以是8

按要求2400bps,smod=1时,该公式计算结果为:230

(4)中断寄存器相关配置:

为什么需要中断寄存器?如果没有,定时器溢出之后也不会有中断产生呀
IE中断控制寄存器:

  • 将IE寄存器中的bit7 EA位 置1,代表CPU能够响应所有中断
  • 将IE寄存器中的bit4 ES位 置1,代表允许串口产生中断
cpp 复制代码
//串口初始化
void Uart_Init(void)
{
//串口控制寄存器配置
	PCON &= ~(1 << 6);//CON寄存器中的bit6置0 代表通过SCON寄存器中SMO和SM1两位指定串口工作方式
	
	SCON &= ~(3 << 6);//将SCON寄存器中的bit6和bit7清0
	SCON |= (1 << 6);//将SCON寄存器中的SM1bit6置1,M0bit7清0(前一步已清),表串口工作8位UART模式
	SCON |= (1 << 4);//将SCON寄存器中RENbit4置1,代表允许串口接收数据

	PCON |= (1 << 7);//CON寄存器bit7位置1,代表波特率加倍


//定时器和中断寄存器相关配置初始化  (定时器1 8位自动重装载模式)

	//定时器1
	TMOD &= ~(0xF0 << 0);//将TMOD寄存器中的高四位清0(定时器1)
	TMOD |= (1 << 5);//TMOD寄存器中的bit5置1,bit4清0(前一步已清),代表定时器1工作在8位自动重装载模式
	//计算起始点: 2^8-2^smod *focs / 32 / bps / 12
	Tl1 = 230;
	TH1 = 230;

	TCON |= (1 << 6);//将TCON寄存器中的bit6置1,代表允许定时器1开始计数

	//定时器中断
	IE |= (1 << 7);//总开关	  将IE寄存器中的bit7EA位置1,代表CPU能够响应所有中断
	IE |= (1 << 4);//允许定时器1产生中断  将IE寄存器中的bit4 ES位置1,代表允许串口产生中断
	return;
}

十一 、串口中断服务函数------传递字符、传递字符串、传递数组

cpp 复制代码
	while (1)
	{
//		 Uart_SendChar('y');
//	     Uart_SendStr("Hello world!");

		 Uart_SendBuffer(buffer, strlen(buffer));//向串口发送数组里的内容
		 delay(0x3FFF);
	
		 }
		
	}

#include <reg51.h>

xdata char recv_buffer[32];
unsigned int pos = 0;
//串口接收服务函数
void Uart_RecvHandler(void) interrupt 4
{
	if((SCON & (1 << 0)) == 1)//成功接收到8位数据 根据SCON bit0判断是否接收到
	{
		if (pos < 32)
		{
			recv_buffer[pos++] = SBUF;//一次串口中断 接收到一个字节 存入数组 并把数组下标后移一位 
		  	recv_buffer[pos] = 0;//下一个数组下标的元素值清零
		}
	  	SCON &= ~(1 << 0);//SCON bit0 软件置0;
	}

	return ;
}

//串口初始化
void Uart_Init(void)
{
//串口控制寄存器配置
	PCON &= ~(1 << 6);//CON寄存器中的bit6置0 代表通过SCON寄存器中SMO和SM1两位指定串口工作方式
	SCON &= ~(3 << 6);//将SCON寄存器中的bit6和bit7清0
	SCON |= (1 << 6);//将SCON寄存器中的SM1bit6置1,M0bit7清0(前一步已清),表串口工作8位UART模式
	SCON |= (1 << 4);//将SCON寄存器中RENbit4置1,代表允许串口接收数据

	PCON |= (1 << 7);//CON寄存器bit7位置1,代表波特率加倍


//定时器和串口中断寄存器相关配置初始化  (定时器1 8位自动重装载模式)

	//定时器1
	TMOD &= ~(0xF0 << 0);//将TMOD寄存器中的高四位清0(定时器1)
	TMOD |= (1 << 5);//TMOD寄存器中的bit5置1,bit4清0(前一步已清),代表定时器1工作在8位自动重装载模式
	//计算起始点: 2^8-2^smod *focs / 32 / bps / 12
	TL1 = 230;
	TH1 = 230;

	TCON |= (1 << 6);//将TCON寄存器中的bit6置1,代表允许定时器1开始计数

	IE |= (1 << 7);//总开关	  将IE寄存器中的bit7EA位置1,代表CPU能够响应所有中断
	IE |= (1 << 4);//允许串口产生中断  将IE寄存器中的bit4 ES位置1,代表允许串口产生中断
	return;
}
//向串口发送字符
void Uart_SendChar(unsigned char buff)
{
	///tip:SCON寄存器初始上电后 所有位置清零
	SBUF = buff;
	//SCON寄存器中bit1 T1位,代表串口8位数据发送完毕硬件自动置1,但需要软件清0(查询)
	while((SCON & (1 << 1)) == 0);//发送数据完毕后,硬件置1,查询是否发送
	SCON &= ~(1 << 1); //软件给此位清零
	return;
}
//向串口发送字符串
void Uart_SendStr(const char *p)
{
	while(*p)
	{
		 Uart_SendChar(*p++); //等价于*(p++)
		 //1取出当前 p 指向的值(*p)
		//2把指针 p 向后挪一个元素(p++)
	}
	return;
}
//向串口发送数组中的数据
void Uart_SendBuffer(const char *p, int lenth)
{
//	int i = 0;
//	for(i = 0; i < lenth; i++)
//	{
//		Uart_SendChar(*p);
//		p+=i;
//	}
	while(lenth--)
	{
		Uart_SendChar(*p++);
	}
	return;
}

十二、主从应答:

主机:拥有对通信绝对控制权,通信都是由主机发起

从机:无法直接发起通信,只能根据主机下发的指令完成对应操作

cpp 复制代码
#include <reg51.h>
#include <string.h>
#include "uart.h"
#include "delay.h"

int main(void)
{
	xdata char buffer[32] = {0};
	
	Uart_Init();	

	while (1)
	{
//		 Uart_SendChar('y');
//	     Uart_SendStr("Hello world!");
//		 Uart_SendBuffer(buffer, strlen(buffer));
		 if(pos != 0)
		 {	 
//			 Uart_SendBuffer(recv_buffer, strlen(recv_buffer));//向串口发送数组里的内容
			 delay(0x3FFF);
			
			 if(strcmp(recv_buffer,"hello") == 0)
			 {
			  	Uart_SendStr("Hello world!");
			 }
			 if(strcmp(recv_buffer,"hi") == 0)
			 {
			 	Uart_SendStr("Hi world!");
			 }
			  pos = 0;
		 }
		
	}

	return 0;
}

十二、Modbus协议:

Modbus协议

(主机 - >从机)
起始位 地址码 功能码 数据位1 数据位2 校验码 停止位

0xAA 0x01 0x01 00 42 EE(累加和校验) 0xBB

(从机->主机)

起始位 地址码 功能码 数据位1 数据位2 校验码 停止位

0xAA 0x01 0x81 00 42 6E 0xBB

**累加和校验:**前五个之和等于校验码

功能码:bit7:数据流向位 0"表示从主机流向从机 / 1表示从从机流向主机

bit0: 1:控制LED灯

2:控制数码管(动态显示)

3:控制 蜂鸣器(频率)

4::温度采集

总结重点:

一、主机发送指令,从机解析主机发送的指令并获得功能码,根据功能码完成对外设的控制,并回复应答给主机

(01 --- LED控制 02 --- 数码管控制 03 --- 蜂鸣器控制)

二、

1.UART的概念

2、单工、半双工、全双工概念

3、串行、并行概念

4、串行、并行区别

5、 串口通信时序

6、奇偶校验的概念/缺点

7、串口通信参数(波特率 数据位 停止位 校验位 2400 8 N 1)

8、同步、异步概念

9、主从应答的概念

10、主机、从机

相关推荐
豆浩宇5 小时前
学习PaddlePaddle--环境配置-PyCharm + Conda
人工智能·深度学习·学习·目标检测·计算机视觉·pycharm·paddlepaddle
励志不掉头发的内向程序员6 小时前
从零开始的python学习——列表
开发语言·python·学习
不会留有遗憾6 小时前
【FPGA】单总线——DS18B20
stm32·单片机·嵌入式硬件
JQLvopkk6 小时前
CSS学习及心得之二
css·学习·tensorflow
非凡ghost6 小时前
PDF24 Creator:免费的多功能PDF工具
学习·pdf·生活·软件需求
hexiaoyan8277 小时前
光纤加速的板卡设计原理图:基于6U VPX XCVU9P+XCZU7EV的双FMC信号处理板卡
嵌入式硬件·fpga开发·光纤加速板卡·国产化板卡·xcvu9p板卡·xcvu9p
悠哉悠哉愿意7 小时前
【数学建模学习笔记】机器学习回归:XGBoost回归
学习·机器学习·数学建模
无法无天霸王龙7 小时前
云计算培训为什么这么贵?
linux·运维·学习·云计算
addaduvyhup7 小时前
【RNN-LSTM-GRU】第五篇 序列模型实战指南:从选型到优化与前沿探索
学习