STM32-(串口通信)

什么是通信?
  1. 数据交互
  2. 信息传递
  3. 条件:两个端  发送端  

一、通信基础知识

1、时钟信号划分

同步通信:通信双方根据同步信号通信,比如双方有一个共同的时钟信号(SPI全双工 I2C半双工)

异步通信:通信双方有自己独立的系统时钟,大家约定好通信的速度。异步通信不需要同步信号,但是并不是说通信的过程不同步(UART)

2、通信方式划分

串行通信:指的是同一时刻只能收或发一个bit位信息。因此只用1根信号线即可。

     串行传输:数据一位一位串起来,逐个传输,数据按位顺序传输。

      优点:占用引脚资源少

      缺点:速度相对较慢

     并行通信:指的是同一时刻可以收或发多个bit位的信息,因此需要多根信号线才行

    并行传输:使用多根线同时传输一个字的多个位,如 8 根线一次传输 8 个位。

     优点:速度快

     缺点:占用引脚资源多

3、通信方向划分

单工:要么收,要么发,只能做接收设备或者发送设备。比如收音机

一根信号线只能单向发送或单向接收

半双工:可以收,可以发,但是不能同时收发, 比如对讲机

一根信号线可以接收数据也可以发送数据,但是两者不能同时进行

全双工:可以在同一时刻既接收,又发送。 手机 

两根信号线,一根发送数据,另一根接收数据,真正实现同时收发数据,速度快

Tips:总线协议(电气协议)补充

TTL电平:数字电路中,由TTL电子元器件组成电路使用的电平。电平是个电压范围,规定输出高电平>2.4V,输出低电平<0.4V。在室温下,一般输出高电平是3.5V,输出低电平是0.2V。最小输入高电平和低电平:输入高电平>=2.0V,输入低电平<=0.8V,噪声容限是0.4V。

 RS-232:RS232电平    

    1:-15~-3V      0:+3~+15V RS232采用负逻辑电平      非法状态:-3 ~ +3V

RS-485 :半双工、是电气协议(逻辑1:+2V–+6V 逻辑0: -6V— -2V)是二线制差分信号,也就是实际传输的数据是通过判断这两条信号线上的电压差来实现的,RS-485总线弥补了RS-232通信距离短,速率低的缺点,RS-485的速率可高达10Mbit/s,理论通讯距离可达1200米;RS-485和RS-232的单端传输不一样,是差分传输,使用一对双绞线

二、USART 

中文参考手册564页

    Universal Synchonous Asynchronous receiver transmitter  

USART:支持同步/异步通信   、全双工 、串行

UART:支持异步通信(没有时钟线)、全双工 、串行      

三、串口通信协议

数据帧格式:

空闲状态:信号线保持高电平

起始位:1位,低电平表示数据包的起始

数据位:8位/9位

校验位(可选):奇偶校验

奇校验:

数据位上的1的个数 + 校验位上1的个数 = 奇数

偶校验:

数据位上的1的个数 + 校验位上1的个数 = 偶数

停止位:1位 将信号线电平拉高,代表一个数据包发送结束,回到空闲状态。

注:除了配置协议还需要配置波特率

波特率:每秒传输的数据位数 bps  bit/s          1Byte = 8bit 

常用的:9600bit/s 115200bit/s

四、USART功能框图 

Tx:数据发送端

Rx:数据接收端

流控概念p

在两个设备正常通信时,由于处理速度不同,就存在这样一个问题,有的快,有的慢,在某些情况下,就可能导致丢失数据的情况。如台式机与单片机之间的通讯,接收端数据缓冲区已满,则此时继续发送来的数据就会丢失。流控制能解决这个问题

nRTS:请求以发送(Request To Send),n表示低电平有效。当本设备准备好接收新数据时就会将nRTS变成低电平;当接收寄存器已满时,nRTS将被设置为高电平。

nCTS:清除以发送(Clear To Send) 为输入信号,低电平有效。用于判断是否可以向对方发送数据,低电平说明本设备可以向对方发送数据。

该引脚只适用于硬件流控制

SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。(UART是异步通信)

发送过程:由CPU或DMA向数据发送寄存器(TDR)中写入要发送的数据,由发送移位寄存器将数据按位移到发送端口输出。

接收过程:由CPU和DMA读取接收数据寄存器(RDR)中的数据。

五、相关寄存器 

串口控制寄存器 

USART_CR 决定帧格式:起始位+数据位+校验位+停止位

   (设备功能初始化、通信帧格式配置)

USART_CR1

USART_CR2

USART_CR3

 波特率寄存器

USART_BRR 决定通信速度:bit/s

   中断和状态寄存器 

USART_ISR

数据接收寄存器 

         USART_RDR               决定接收的数据:将要接收数据的读取

   数据发送寄存器  

USART_TDR 决定发送的数据:将要发送的数据写入

六、串口发送实验

实验要求

             通过单片机以1s间隔向电脑发送“helloworld”

6.1 观察实物

找到通信接口    丝印“P4”

6.2 分析原理图

CH340:电平转换芯片,可以转换TTL电平—USB电平。(3.3V------->12V)

需要安装驱动

数据选择/多路复用器

MX配置

初始化代码分析

6.4 代码编写

  1. 实现单个字符发送函数uart_putchar();

2)实现字符串发送函数uart_puts();

void uart_putchar(uint8_t ch)
{
      
	while(!(USART1->ISR & (1<<7))){}	//等待发送寄存器为空
	//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据
	//当发送数据寄存器为空时,while(!1);跳出循环,向下执行
	USART1->TDR = ch;
}
void uart_puts(uint8_t *p)
{
      
	while(*p)
	{
      
		uart_putchar(*p);
		p++;
	}
}

七、串口收发实验

实验要求

通过串口助手向单片机发送数据,单片机接收到数据后原样返回。

  1. 实现字符接收函数 uart_getchar()

  1. 实现字符串接收函数 uart_gets()

void uart_putchar(uint8_t ch)
{
      
	while(!(USART1->ISR & (1<<7))){}	//等待发送寄存器为空
	//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据
	//当发送数据寄存器为空时,while(!1);跳出循环,向下执行
	USART1->TDR = ch;
}
void uart_puts(uint8_t *p)
{
      
	while(*p)
	{
      
		uart_putchar(*p);
		p++;
	}
}

uint8_t uart_getchar()
{
      
	uint8_t c;
	while(!(USART1->ISR & (1<<5))){}
= USART1->RDR;
	return c;
}

void uart_gets(uint8_t *p)
{
      
	uint8_t ch;
	while(1)
	{
      
		ch = uart_getchar();
		if(ch != '\n')		//将回车作为输入结束标志
		{
      
			*= ch;
		}else
		{
      
			*= '\0';			//填充字符串的结束标志
			break;
		}
		p++;
	}
}

八、printf的重定向

int  printf(const char * format,...)

printf函数底层调用的是fputc函数,fputc是将要发送的数据写入到标准输出流stdout

int fputc(int /*c*/, FILE * /*stream*/) 

        因此如果想让printf将数据输出到串口,需要重写fputc  

WEAK弱符号

weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。

加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 修饰的函数,并且编译器不会报错。

int fputc(int ch,FILE *p)
{
      
	while(!(USART1->ISR & (1<<7))){}	//等待发送寄存器为空
	//ISR的第7位为1,说明发送数据寄存器为空,此时再写入要发送的数据
	//当发送数据寄存器为空时,while(!1);跳出循环,向下执行
	USART1->TDR = ch;
	return ch;
}

九、HAL库函数

串口发送函数

HAL_StatusTypeDef HAL_UART_Transmit  (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size,  uint32_t Timeout) 

         功能:以阻塞模式通过串口发送数据

         参数:UART_HandleTypeDef * huart 设备的句柄

                      uint8_t * pData  要输出的缓存区首地址 

                      uint16_t Size  发送的数据量

                      uint32_t Timeout  超时时间

         返回值:发送状态

串口接收函数

HAL_StatusTypeDef HAL_UART_Receive  (UART_HandleTypeDef * huart, uint8_t * pData, uint16_t Size,  uint32_t Timeout) 

          功能:以阻塞模式通过串口接收数据

         参数:UART_HandleTypeDef * huart 设备的句柄

                      uint8_t * pData 输入缓存区首地址 

                      uint16_t Size  接收的数据量

                      uint32_t Timeout  超时时间

         返回值:接收状态

STM32常见通信协议

STM32-通信协议

相关推荐

  1. STM32单片机实现串口通信

    2023-12-06 09:32:08       18 阅读
  2. K210 UART串口通信介绍与 STM32通信

    2023-12-06 09:32:08       31 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-06 09:32:08       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-06 09:32:08       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-06 09:32:08       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-06 09:32:08       18 阅读

热门阅读

  1. gd32和stm32的区别

    2023-12-06 09:32:08       25 阅读
  2. AI全栈大模型工程师(十九)Semantic Kernel

    2023-12-06 09:32:08       26 阅读
  3. 重构第二章:重构的原则

    2023-12-06 09:32:08       26 阅读
  4. 波场TRON将致力于推动各方合作打击恐怖主义融资

    2023-12-06 09:32:08       29 阅读
  5. 怎样用Ajax提交from表单并接收其中的json数据

    2023-12-06 09:32:08       31 阅读
  6. 安卓adb【备忘录】

    2023-12-06 09:32:08       33 阅读
  7. 贪心算法个人见解

    2023-12-06 09:32:08       31 阅读
  8. Nginx实现(负载均衡)

    2023-12-06 09:32:08       36 阅读