串行通信——基于STM32F407ZGT6芯片

通信

通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统(扩展STM32系统,与别的模块互联,实现外挂模块和读取外挂模块数据)

通信协议:制定通信的规则,通信双方按照协议规则进行数据收发

相关概念

全双工:通信双方能够同时进行双向通信,发送线路与接收线路互不影响(两根通信线)(打电话)

半双工:通信双方在同一时间只能进行单向通信(发电报)

单工:数据只能从一个设备到另一个设备,而不能反着来(收音机)

同步:有单独的时钟线,接收方可以在时钟信号的指引下进行采样

异步:没有始时钟线,需要双方约定一个采样频率,加入帧头帧尾进行采样位置的对齐

单端:引脚的高低电平都是对GND的电压差,所以必须要接GND

差分:靠两个差分引脚的电压差来传输信号的(使用差分信号可以极大地提高看干扰特性,所以一般差分信号的传输速度和距离都会非常高,性能也不错)

串行通信(Serial communication)

是指在计算机总线或其他数据通道上,每次传输一个位元数据,并连续进行以上单次过程的通信方式。与之对应的是并行通信,它在串行端口上通过一次同时传输若干位元数据的方式进行通信。串行通信被用于长距离通信以及大多数计算机网络,在普通应用场合,电缆和同步化使并行通信面临实际应用问题。

(1)异步串行通信 异步串行通信所传输的数据格式(也称为串行帧)由1个起始位、7~9个数据位、1~2个停止位(含1.5个停止位)和1个校验位组成。起始位约定为0,空闲位约定为1。在异步通信方式中,接收器和发送器有各自的时钟,它们的工作是非同步的。

不使用时钟信号进行数据同步,它们直接在数据信号中穿插一些同步用的信号位,

或者把主体数据进行打包,以数据帧的格式传输数据。

(2)同步串行通信 同步串行通信中,发送器和接收器由同一个时钟源控制。

使用时钟信号进行数据同步,在同步通讯中,数据信号所传输的内容绝大部分就是有效数据,而异步通讯中会包含有帧的各种标识符,所以同步通讯的效率更高,但是同步通讯双方的时钟允许误差较小,而异步通讯双方的时钟允许误差较大。

3)波特率及时钟频率** 波特率BR是单位时间传输的数据位数,即单位:bps(bit per second)1bps = 1bit/s。采用异步串行,互相通信甲乙双方必须具有相同的波特率,否则无法成功地完成数据通信。同步通信中通过主从设备的同步时钟完成数据同步,因此很少有波特率说法,当然也可以看作数据传输的波特率即为同步时钟频率。

4)比特率(Bit Rate)

如果每个符号代表 8 个比特,则每个符号可以传输 8 个比特的数据。

因此,波特率为 9600 波特,每个符号传输 8 个比特,所以比特率为 9600 * 8 = 76800 比特每秒(bps)。 这意味着在每秒钟,设备 A 和设备 B 之间会传输 76800 个比特的数据。

常见串行通信方式

(1) UART

UART串行通信方式称作为异步串行通信,主要通过两个引脚发送(TXD)和接收(RXD)实现数据的发送和接收,由于没有时钟线,所以是一种全双工的异步串行通信接口,通信数据的同步利用设置好的波特率来实现,波特率的最大速率传统上是115200bps但现在对于一些微控制器如STM32芯片其波特率可以达到2Mbps。

UART帧结构

当两个设备需要通过UART协议进行通讯时,它们需要同时约定好以下内容:

  • 每一位信号的时间长度T(波特率 = 1/T)

  • 帧结构中每一项的具体位数

  • 是否有校验位,以及校验位的机制(奇/偶/..)

ODD奇校验EVEN偶校验(以数据位中有奇数/偶数个1来校验)

(2)USART

Universal Synchronous/Asynchronous Receiver/Transmitter

(通用同步/异步收发传输器)

USART 串行通信是在UART的基础上增加了同步通信方式,称为同步/异步串行通信。当设置为异步串行通信时,和前面所述的UART的连接和特性是一模一样的。当设置为同步串行通信时,此时在通信接口增加了一个时钟线,用于同步时钟用从而不再需要设置波特率。

TX(Transmit)引脚:发送数据

RX(Receive)引脚:接收数据

看原理图,确定USART1的发送端TX、接收端RX的引脚,分别是PA9、PA10

我们要用跳线帽,短接左右两边引脚这样才能实现通信

与GPIO使用输入输出模式不同,我们需要使用GPIO的复用模式。

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式

上述代码只是将GPIO口设置成了复用模式,我们还需要对每个引脚的复用模式进行设置。

这里如果要一次复用多个引脚,不能使用或,要调用两次复用函数。

GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);

代码

//usart代码
#include "usart.h"
#include "stdio.h"
/*
串口通信
//用串口软件发送hello ,并且在软件上回显
代码思路:
1.查看原理图确定串口引脚 USART1 			USART1_TX PA9					USART1_RX PA10
2.GPIO配置
	...
	选择复用模式
3.USART1配置
	a.结构体申明 	USART_InitTypeDef
	b.时钟使能		使能USART1的时钟
	c.将GPIO引脚复用为串口		GPIO_PinAFConfig
	d.配置结构体
			波特率、模式(收/发)、终止位、校验位、数据位、流控
	c.初始化 			EXTI_Init
	串口中断(可选)
			和前面学习的中断一样,需要使能接收中断
			USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	重写串口中断服务函数
		USART1_IRQHandler
4.使能串口
	USART_Cmd	
5.使用串口
	调用USART_SendData  /	USART_ReceiveData
6.串口重定向
	重写stdio
*/
void usart1_init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef	NVIC_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//通电还是断电
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //串口1时钟使能
	
	//开始配置F端口下的9号跟10号引脚。
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10; 
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF; //复用模式
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉模式,暂时没讲
	GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed; //引脚响应速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//将PA9、PA10复用为串口1
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
	
	USART_InitStructure.USART_BaudRate = 9600; 
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//8位数据位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;		//1位停止位
	USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验
	USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //收和发都使能,必须进行或操作
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无流控
	USART_Init(USART1, &USART_InitStructure);
	
	/*
	中断
	*/
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //外部中断4 EXTI4
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//使能接收中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
	
	USART_Cmd(USART1, ENABLE);

}
char *p = "hello";

//发单个字符
void usart_sendbyte(USART_TypeDef* usrUSARTx, uint16_t ch)
{
	USART_SendData(usrUSARTx,ch);
	
	//等待数据发送寄存器为空
	//USART_FLAG_TXE 表示寄存器可以写入下一个数据了,当为SET的时候可以写入
	while(USART_GetFlagStatus(usrUSARTx, USART_FLAG_TXE) == RESET);
	
}

//发字符串
void usart_string(USART_TypeDef* usrUSARTx, char *str)
{
	int i= 0;
	do
	{
		usart_sendbyte(usrUSARTx, *(str+i));
		i++;
	}	
	while(*(str+i) != '\0' );
}
int fputc(int ch, FILE *stream)
{
	USART_SendData(USART1 ,(uint16_t)ch);
	//等待数据发送寄存器为空
	//USART_FLAG_TXE 表示寄存器可以写入下一个数据了,当为SET的时候可以写入
	while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
	return ch;
}

注意:

  1. 在.c文件里写的函数,一点要在.h文件里面一对一声明

  2. 重写中断服务函数时要一一对照库函数

  3. 在主函数里面调用各函数初始化各部分才能正常工作

  4. 在用printf函数时要重写int fputc(int ch, FILE *stream)函数,加头文件#include "stdio.h",并且要给微库打钩,这样printf才能在串口正常输出。

//重写串口中断服务函数
void USART1_IRQHandler(void)
{
	uint16_t rev;
	
	//判断串口接收中断标志是否被置位
	if(USART_GetITStatus(USART1 ,USART_IT_RXNE) == SET)
	{
		rev = USART_ReceiveData(USART1);
		//判断亮灯
		//清楚中断标志
		USART_ClearITPendingBit(USART1 ,USART_FLAG_RXNE);
	}
	
}
//主函数
		printf("hello world");
		usart_sendbyte(USART1, 'B');

		rev = USART_ReceiveData(USART1);
		if(rev == 'a')
		{
			usart_sendbyte(USART1, rev);
			//点亮led
			GPIO_ToggleBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
			yanshi();
		}

附:

I2C(Inter-Integrated Circuit):I2C是一种双向、串行、同步的通信协议,由Philips公司开发。 它使用两根线进行通信:SCL(时钟线)和SDA(数据线)。 I2C支持多主设备和多从设备,每个设备具有唯一地址,通过地址识别实现数据的发送和接收。 主设备控制时钟线,负责同步数据传输的时序。

SPI(Serial Peripheral Interface):SPI是Motorola公司推出的一种同步串行接口技术。 它以主从方式工作,需要至少四条线:SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。 SPI通信是高速、全双工、同步的,适用于高速数据传输的场景。 当有多个从设备时,可以通过片选信号选择与主设备进行通信的从设备。

相关知识:

串行通信:是一种数据一位一位按顺序传送的通信方式,相比并行通信,它传输速度慢,但传输距离较远且成本较低。

总线:是一种传输数据的通道,它可以在多个设备之间共享,实现设备间的数据通信。

主从设备:在串行通信中,通常有一个主设备负责控制通信的时序和数据流,而从设备则按照主设备的指令进行数据的发送或接收。 在选择USART、UART、I2C或SPI协议时,需要根据应用需求、硬件支持以及通信性能等因素进行综合考虑。例如,如果需要灵活支持同步和异步通信,可以选择USART;如果只需要简单的异步通信,UART可能是更好的选择;如果需要连接多个设备并进行高速数据传输,SPI可能更适合;而如果需要实现设备间的双向通信并控制数据传输的时序,I2C则是一个不错的选择。

原文链接:串行通信大比拼:USART、UART、I2C、SPI有何不同?_spi i2c usart uart cec-CSDN博客

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值