基于stm32HAL库的串口通讯介绍及项目案例(一)

八、串口

1. 通信基础

1.1 串行通信与并行通信

1.2 全双工、半双工及单工通信

 单工通信:数据只能沿一个方向传输

半双工通信:数据可以沿两个方向传输但需要分时进行

全双工通信:数据可以同时进行双向传输

1.3 同步通信与异步通信

同步通信

同步通信:发送和接收双方按照预定的时钟节拍进行数据的发送和接收,双方的操作严格同步。
异步通信:双方不需要严格的时钟同步,每个数据块之间通过特定的起始位和停止位进行分隔,接收方可以 独立地识别每个数据块。 

1.4 通信速率

通信速率是指在通信系统中单位时间内传输的信息量,是评估通信系统性能的重要指标之一。

 1. 比特率(Bit rate)

每秒能传输的二进制 位数 bit/s或 bps

2. 波特率(Baud rate)

波特率表示每秒传送的码元的个数 波特(Baud)

3计算公式

比特率 = 波特率 * log2 M ,M表示每个码元承载的信息量

二进制系统中,波特率数值上等于比特率

2. 串口通信简介

串口,也称为串行接口或串行通信接口(通常指COM接口),是一种采用串行通信方式的扩展接口。它实现 了数据一位一位地顺序送,具有通信线路简单、成本低但传送速度慢的特点。只要一对传输线,串口就可 以实现双向通信

串口通信的接口类型包括TTL、CMOS、RS-232和RS-485等,它们分别代表了不同的电平标准。

 

 

1. 起始位(Start Bit)

起始位为低电平时,告诉接收方数据传输即将开始,准备接收。在通信开始时, 发送端首先会发送一个起始位,它是一个逻辑0(低电平)的信号,用于同步发送和接收设备之间的时 钟。接收端在检测到起始位后,会开始准备接收后续的数据位。

2. 有效数据位(Data Bits)

数据位是由一系列二进制值组成,用于传输或接收实际的数据。数据位的数 量决定了可以传输的不同二进制值的数量,常见的有5位、6位、7位、8位,LSB在前,MSB在后。数据 位紧随起始位之后,包含了要传输的实际信息。

3. 校验位(Parity Bit)

校验位用于验证数据的完整性,以确保传输过程中没有出现错误。常见的校验位 选项有None(无校验位)、Odd(奇校验位)和Even(偶校验位)。在发送数据时,校验位会根据数 据位中1的个数进行计算,并加入到数据中一起传输。接收端则会根据校验位的值进行校验,以判断数 据是否存在错误。

4. 停止位(Stop Bit)

停止位是一个逻辑高电平(1),用于指示数据传输的结束。当停止位出现时,接 收端知道数据传输已经完成,并且可以开始处理接收到的数据。停止位位于数据位和校验位之后,它的 作用是确保接收端有足够的时间来识别数据帧的结束,并为下一个数据帧的到来做好准备。  

3. STM32的USART简介

通用同步异步收发器

通用异步收发器

1. 全双工通信

USART支持全双工通信,即数据可以在两个方向上同时传输(A→B且B→A)。这使得 USART能够满足许多需要双向通信的应用场景。

2. 同步与异步传输

尽管USART的“S”代表同步,但在实际应用中,USART更常用于异步通信。然而,它 也支持同步通信模式,只是这种模式通常用于兼容其他协议或特殊模式,并且两个USART设备不能通过 同步模式进行直接通信。

3. 波特率发生器

USART自带波特率发生器,最高可达4.5Mbits/s,可以根据需要配置不同的波特率。

4. 硬件流控制

USART支持硬件流控制,通过特定的信号线(如RTS/CTS)实现数据的可靠传输。当接收 端没有准备好接收数据时,可以通过RTS信号通知发送端暂停发送;当接收端准备好接收数据时,再通 过CTS信号通知发送端恢复发送。

4. USART框图

 

 5. UART寄存器及函数介绍

25.6.1 状态寄存器(USART_SR)

位5RXNE:读数据寄存器非空 (Read data register not empty) 当RDR移位寄存器中的数据被转移到USART_DR寄存器中,该位被硬件置位。如果 USART_CR1寄存器中的RXNEIE为1,则产生中断。对USART_DR的读操作可以将该位清 零。RXNE位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。 0:数据没有收到; 1:收到数据,可以读出。
位4IDLE:监测到总线空闲 (IDLE line detected) 当检测到总线空闲时,该位被硬件置位。如果USART_CR1中的IDLEIE为’1’,则产生中断。由 软件序列清除该位(先读USART_SR,然后读USART_DR)。 0:没有检测到空闲总线1:检测到空闲总线。 注意:IDLE位不会再次被置高直到RXNE位被置起(即又检测到一次空闲总线)

25.6.2 数据寄存器(USART_DR)

位8:0

DR[8:0]:数据值 (Data value) 包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给发送用(TDR),一个给接收 用(RDR),该寄存器兼具读和写的功能。TDR寄存器提供了内部总线和输出移位寄存器之间的 并行接口(参见图248)。RDR寄存器提供了输入移位寄存器和内部总线之间的并行接口。 当使能校验位(USART_CR1中PCE位被置位)进行发送时,写到MSB的值(根据数据的长度不 同,MSB是第7位或者第8位)会被后来的校验位该取代。 当使能校验位进行接收时,读到的MSB位是接收到的校验位。

25.6.3 波特比率寄存器(USART_BRR)

25.6.4 控制寄存器 1(USART_CR1)

通用同步异步收发器(USART)543/754

25.6.5 控制寄存器 2(USART_CR2)

25.6.6 控制寄存器 3(USART_CR3)

25.6.7 保护时间和预分频寄存器(USART_GTPR)

当然可以!这里是个使用STM32HAL进行串口通信的简单实例: 首先,需要在CubeMX中配置串口。打开CubeMX并选择你的微控制器型号,然后点击"Peripherals"选项卡,在左侧的"USART"菜单下选择个可用的串口。根据你的需求,配置串口的参数,例如波特率、数据位、停止位等。最后点击"Pinout & Configuration"选项卡,将串口的引脚分配给正确的GPIO引脚。 生成代码后,在你的工程中打开`main.c`文件,并添加以下代码: ```c #include "stm32fxxx_hal.h" UART_HandleTypeDef huart2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART2_UART_Init(); uint8_t txData[] = "Hello, world!\r\n"; uint8_t rxData[20]; while (1) { HAL_UART_Transmit(&huart2, txData, sizeof(txData), HAL_MAX_DELAY); HAL_UART_Receive(&huart2, rxData, sizeof(rxData), HAL_MAX_DELAY); } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { while(1); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { while(1); } HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); } static void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { while(1); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 这段代码初始化了系统时钟、GPIO和USART2串口。在主循环中,我们通过串口发送"Hello, world!\r\n",然后通过串口接收数据。 请注意,在上述代码中,我们使用了USART2串口和GPIOA的引脚2和3。如果你选择了不同的串口和引脚,请相应地修改代码。 希望这个例子能帮助到你!如有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值