STM32F407之串口通讯

本文针对串口通讯进行学习  

基础知识补充

串行通信: 定义:串行通信是指利用一条传输线将数据一位位地顺序传送。 传输方式:传输一个字节(8个位)的数据时,串口是将8个位排好队,逐个地在1条连接线上传输。 特点:传输速度较慢,抗干扰能力较强,适用于远距离通信,成本较低。

并行通信: 定义:并行通信是指利用多条传输线将一个数据的各位同时传送。 传输方式:传输一个字节(8个位)的数据时,并口是将8个位一字排开,分别在8条连接线上同时传输。 特点:传输速度较高,抗干扰能力较弱,适用于短距离通信,成本较高。

异步 不使用时钟信号进行数据同步,它们直接在数据信号中穿插一些同步用的号位,或者把主体数据进行打包,以数据帧的格式传输数据。

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

单工方式 只允许数据按照一个固定的方向传送,在任何时刻都只能进行一个方向的通信,一个设备固定为发送设备,一个设备固定为接收设备。

优点:可以利用通信信道的整个带宽,所以一次性可以传输更多的数据。 缺点:通信是单向的,设备之间没有相互通信,效率低。例如:广播电台

半双工方式 两个设备之间可以收发数据,但是不能在同一时刻进行,每次只能有一个设备发送,另一个站接收

优点:半双工在同一时刻也是占用整条带宽,所以每次也能传输很多数据。 缺点:半双工由于在通信的时候,通信一方传输数据,另一方只能等待接收数据,存在一点时延。例如:对讲机

全双工 允许同时在两个方向上进行通信,它将可用通道分为两部分,一部分用于发送数据,另一部分用于接收数据。由于发送和接收数据有单独的路径,因此设备可以在给定时间同时执行这两项任务。 例如:打电话,双方可以同时说话,互不影响

优点:通信双方同时发送和接收数据效率很高缺点:假如设备之间不存在专用路径,那么信道容量就会减少一半

通讯速率衡量通讯性能的一个非常重要的参数就是通讯速率,通常以比特率来表示。

比特率表示实际传输的数据速率,即数据每秒钟可以传输的二进制位数。一个比特表示每秒传输一个二进制位

波特率是指每秒传输的信号变化的次数,通常用波特表示。一个波特表示每秒传输一个信号变化(通常是电平变化,注意和比特率的区分)。

串口通讯—USART

串口通讯是一种设备间非常常用的串行通讯方式,因为它简单便捷,大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。串口通讯的物理层有很多标准及变种,根据通讯使用的 电平标准不同 ,串口通讯可分为多个标准。
简单的板内通讯,或者常见的设备调试场景,使用简单的 LVTTL/TTL 电平即可在两个设备间进行 UART协议通讯。
RS232(逻辑1和0颠倒,如图所示) ,可以增加传输距离,并且抵抗一定程度的信号干扰。付出的成本则是在物理层需要对应的电平转换芯片来实现,发送端需要将内部的高低电平信号转换成电压更高的+/- 电压信号,接收端需要将+/- 电压信号转换成内部的高低电平信号。
在工业通讯的场景下,为了进一步提高传输距离,增强信号的可靠性,一般会采用 RS485 的电平标准。在发送端将普通的高低电平信号转换成一对差分信号,在接收端将差分信号再转换成普通的高低电平信号。另外 RS485允许总线上连接多达128收发器 ,而 TTL 或者 RS232 则是点对点的连接。

 基于TTL的UART通讯

介绍

在目前工业控制,流行使用的串口通讯中,一般只使用RXD、TXD 以及GND 三条信号线,直接传输数据信号,这种方式就是UART,裁剪掉了同步信号线,只能进行异步通讯。我们平时用的串口通信基本都是UART。

TXD发送数据线,RXD接收数据线,GND地线

即直接把数字 I/O 输出的高低电平 作为实际的物理信号进行传输。在物理连接上,只需要 设备共地 ,通过一根信号线即可完成单向的设备通讯。如果需要双向全双工,使用两根信号线即可。
补充知识:
在USART通信中,接地(GND)是一个非常重要的部分,它确保了信号传输的稳定性和准确性。当两个USART设备接同一个地时,主要起到了以下几个作用:
参考电平一致:在电子电路中,接地提供了一个共同的参考电平。当两个USART设备共享同一个接地时,它们的信号电平将相对于这个共同的参考点进行衡量,从而确保信号能够正确地被解释和传输。
消除地电位差:如果两个USART设备没有接在同一个地上,它们之间可能存在地电位差(也称为地回路噪声或地噪声)。这种电位差可能导致信号失真或干扰,影响通信质量。通过接同一个地,可以消除或减小这种电位差,提高通信的可靠性。
减少电磁干扰:在串行通信中,信号线可能受到外部电磁干扰的影响。接地有助于将这些干扰电流引入大地,减少对信号线的干扰。
保护设备安全:接地还可以提供一定程度的设备保护,特别是在遇到雷击或其他电气故障时,有助于防止设备损坏或电击事故的发生。 总之,USART接同一个地主要是为了确保信号传输的稳定性、准确性和安全性。在实际应用中,正确接地是串行通信系统设计的重要部分,需要仔细考虑和实施。

UART桢结构
  • 每一位信号的时间长度T(波特率 = 1/T)
    如一个波特率为115200的UART波形表示1秒可容纳115200个bit位,也就是说每一位bit数据占大 约8.68us的时长。
  • 帧结构中每一项的具体位数
  • 是否有校验位,以及校验位的机制(奇//..

 有了这些约定,接收设备只需要等待起始位的到来,再对之后的波形进行固定间隔的采样即可获得传输的具体信息。

空闲位 设备之间不传输数据时以持续的高电平表示空闲。
起始位 UART接收端会一直检测信号线上的电平变化,开始传输数据时,发送端将信号线从高电平拉到低电平结束空闲状态,并保持一个bit 位的时长。接收器检测到高低电平转换时,开始接收信号。
数据位 数据位包含传输的实际数据,可选8 位或 9 位,如果没有使能奇偶校验控制,一般使用 8 数据位;如果使能了奇偶校验则一般设置为 9 数据位。数据首先从最低有效位开始发送,高位在后。(表示每一位电平信号都可高可低)
校验位 校验位可以用来提高传输的可靠性。如果信号在传输过程中因为干扰而导致某些位置的电平产生错误,通过计算接收的数据和校验位是否匹配即可判断数据是否有传输错误,从而给应用层提供有效信息来决定接受/ 丢弃对应的数据。
奇校验 (ODD) :每个字节传送整个过程中 bit 1 的个数是奇数个(数据加校验是否是奇数)。
偶校验 (EVEN) :每个字节传送整个过程中 bit 1的个数是偶数个(数据加校验是否是偶数)。
停止位 表示一帧数据的结束,实际信号是一段时间的高电平。停止位的时间长短可以设置为1 1.5 或者2bits 的停止位。大部分情况使用 1bit 的停止位。(停止位的选择间隔前后帧)

编译

  1. 使能RX TX 引脚GPIO 时钟和USART 时钟;
  2. 初始化GPIO,并将GPIO 复用到USART 上;
  3. 配置USART 参数;
  4. 配置中断控制器并使能USART 接收中断;
  5. 使能USART
  6. USART 接收中断服务函数实现数据接收和发送。

由于开发板上跳帽线连接PA9--RXD,PA10--TXD,开发板通过串口Type-C链接电脑,双方建立协议可传输数据。

1 typedef struct {
2 uint32_t USART_BaudRate; // 波特率
3 uint16_t USART_WordLength; // 字长
4 uint16_t USART_StopBits; // 停止位
5 uint16_t USART_Parity; // 校验位
6 uint16_t USART_Mode; // USART 模式
7 uint16_t USART_HardwareFlowControl; // 硬件流控制
8 } USART_InitTypeDef;

1) USART_BaudRate:波特率设置。一般设置为2400、9600、19200、115200。标准库函数会根据设定值计算得到USARTDIV 值,并设置USART_BRR 寄存器值。 2) USART_WordLength:数据帧字长,可选8 位或9 位。它设定USART_CR1 寄存器的M 位的值。 如果没有使能奇偶校验控制,一般使用8 数据位;如果使能了奇偶校验则一般设置为9 数据位。 3) USART_StopBits:停止位设置,可选0.5 个、1 个、1.5 个和2 个停止位,它设定USART_CR2 寄存器的STOP[1:0] 位的值,一般我们选择1 个停止位。 4) USART_Parity:奇偶校验控制选择,可选USART_Parity_No(无校验)、USART_Parity_Even(偶校验) 以及USART_Parity_Odd(奇校验),它设定USART_CR1 寄存器的PCE 位和PS 位的值。 5) USART_Mode:USART 模式选择,有USART_Mode_Rx 和USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定USART_CR1 寄存器的RE 位和TE 位。 6) USART_HardwareFlowControl:硬件流控制选择,只有在硬件流控制模式才有效,可选有 使 能RTS、 使能CTS、同时使能RTS 和CTS、不使能硬件流。当使用同步模式时需要配置SCLK 引脚输出脉冲的属性,标准库使用一个时钟初始化结构体USART_ClockInitTypeDef 来设置,因此该结构体内容也只有在同步模式才需要设置

 usart.c

#include "stm32f4xx.h"
#include "tim.h"//中断
#include "usart.h"//串口

//PA9/10
void USART_Init_Config(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;                  //声明引脚结构体
	USART_InitTypeDef  USART_InitStructure;                //声明串口结构体
	NVIC_InitTypeDef   NVIC_InitStructure;                 //声明NVIC的结构体

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  //使能RX 和TX 引脚GPIO 时钟和USART 时钟
	
	//初始化GPIO,并将GPIO 复用到USART上;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);    //端口使能
	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_Speed = GPIO_Speed_100MHz;       //不考虑功耗,最大功率
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;             //上拉
	GPIO_Init(GPIOA, &GPIO_InitStructure);                   //初始化结构体
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);  //复用引脚
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //复用引脚
	
	//配置USART 参数;
	USART_InitStructure.USART_BaudRate = 9600;                     //波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;    //八位数据帧
	USART_InitStructure.USART_StopBits = USART_StopBits_1;         //一位停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;            //没有校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式
	USART_Init(USART1,&USART_InitStructure);                       //串口初始化
	
	//配置中断控制器并使 接收中断;
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;          //中断函数
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;            //使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x1;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x1;       //响应优先级
	NVIC_Init(&NVIC_InitStructure);
	
	//使能USART
	USART_Cmd(USART1,ENABLE);
	
	//在USART 接收中断服务函数实现数据接收和发送。
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
}

void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch)
{
	//发送一个字节数据到USARTx
	USART_SendData(USART1,ch);
	//监测串口1发送数据寄存器是否为空,为空将跳出
	//等待发送数据寄存器为空,TXE 位由硬件置 1,
	//它表示:USART_DR (数据寄存器)中可写入下一个数据,而不会覆盖前一个数据。
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}

//这里参数str被系统分配四个字节,char型指针接收未命名字符串地址
void Usart_SendString(USART_TypeDef* pUSARTx, char* str)
{
	uint16_t k = 0;
	
	do
	{
		Usart_SendByte(pUSARTx,*(str+k));
		k++;
	}while(*(str+k)!='\0');

}

//重定向c库函数printf到串口1,这样我们就可以使用printf函数打印输出信息到串口1了
int fputc(int ch, FILE *stream)
{
	//发送一个字节数据到串口1
	USART_SendData(USART1,(uint16_t)ch);
	
	//等待发送数据寄存器为空
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);

	return ch;
}

usart.h

#ifndef __USART_H
#define __USART_H

#include "stm32f4xx.h"
#include <stdio.h>

void USART_Init_Config(void);
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t ch);
void Usart_SendString(USART_TypeDef* pUSARTx, char* str);
int fputc(int ch, FILE *stream);

#endif

调用printf(已被重定向)可实现发送数据到电脑端。但电脑需要软件处理接收到的数据(我用的是下面这款)

 记住,主函数(默认main)中不要只执行一遍就结束了(用while(1)循环保持程序运行)

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //2号分组:2bit给抢占  2bit给响应   0-3  0-3 
	USART_Init_Config();                             //初始化
	
	Usart_SendString(USART1,"5Ta");//方式一
	
	printf("发送的数据为:%d\n",150);//方式二
	
	while(1);	
}

  • 35
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ld3320与stm32f407之间的串口通信可以通过连接ld3320的TX和RX引脚到stm32f407的相应串口引脚来实现。在stm32f407的代码中,可以使用HAL库来配置和控制串口通信。首先,需要在代码中定义一个全局变量来接收ld3320发送的数据,例如`uint8_t cmd = 0;`\[2\]。然后,可以重写串口的回调函数`HAL_UART_RxCpltCallback`来处理接收到的数据。在回调函数中,可以通过判断接收到的数据来执行相应的操作。例如,如果接收到的数据是1,可以执行打开LED的操作,如果接收到的数据是2,可以执行关闭LED的操作。在执行完相应的操作后,可以通过串口发送回复信息给ld3320,例如发送"ON LED!\r\n"或"OFF LED!\r\n"来确认操作已执行\[3\]。同时,需要在回调函数的最后重新启动串口接收功能,以便继续接收ld3320发送的数据。这样就可以实现ld3320与stm32f407之间的串口通信。 #### 引用[.reference_title] - *1* [基于STM32F407的语音控制小音箱](https://blog.csdn.net/weixin_44705079/article/details/119089882)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [stm32单片机与LD3320语音模块交互法二](https://blog.csdn.net/weixin_44236302/article/details/113602958)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值