TTL232485信号
112.4.2TTL232485信号
/* ==================== Core\Inc\main.h ==================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define LED2_Pin GPIO_PIN_5
#define LED2_GPIO_Port GPIOE
#define LED1_Pin GPIO_PIN_5
#define LED1_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/* ==================== Core\Inc\gpio.h ==================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.h
* @brief This file contains all the function prototypes for
* the gpio.c file
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_GPIO_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */
/* ==================== Core\Inc\usart.h ==================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.h
* @brief This file contains all the function prototypes for
* the usart.c file
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
extern uint8_t u_buf[256];
#define printf(...) HAL_UART_Transmit(&huart1, (uint8_t *)u_buf, sprintf((char*)u_buf, __VA_ARGS__), 0xffff)
/* USER CODE END Private defines */
void MX_USART1_UART_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __USART_H__ */
/* ==================== Core\Src\main.c ==================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t UART_Recv[5];
uint8_t DHT11_Buf[30];
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_UART_Receive(&huart1, UART_Recv, 4, 1000);
if(strcmp("LED1", (char *)UART_Recv)==0)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
memset(UART_Recv, '\0', 4);
}
if(!strcmp("LED2", (char *)UART_Recv))
{
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
memset(UART_Recv, '\0', 4);
}
sprintf((char *)DHT11_Buf,"H2:%f T2:%f\n",30.1,36.5);
HAL_UART_Transmit(&huart1, (char *)DHT11_Buf, strlen(DHT11_Buf), 1000);
printf("Hellow world wfeng %d!\n",123);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/* ==================== Core\Src\gpio.c ==================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file gpio.c
* @brief This file provides code for the configuration
* of all used GPIO pins.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure GPIO */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* ==================== Core\Src\usart.c ==================== */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
uint8_t u_buf[256];
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
一、实验演示
本节继续使用开发板的 USART1 完成串口通信。电脑端串口助手发送 LED1 或 LED2,STM32 接收 4 个字符后比较命令,并翻转相应 LED;程序也可以把收到的 4 个字节回传给电脑,用来验证发送与接收通路。
开发板上 USART1 的逻辑链路如下:
flowchart LR
PC[电脑串口助手] <-->|USB D+ / D-| CH340[CH340C<br/>USB转TTL串口]
CH340 -- TXD --> PA10[PA10 / USART1_RX]
PA9[PA9 / USART1_TX] -- TXD --> CH340
MCU[STM32F103] -->|PB5、PE5| LED[低电平点亮的LED]
注意两组“发送—接收”必须交叉:
CH340 TXD ─────> STM32 PA10 / USART1_RX
CH340 RXD <───── STM32 PA9 / USART1_TX
CH340 GND ────── STM32 GND
板载 CH340C 已经完成 USB 协议与 TTL 电平 UART 之间的转换。USB 的 D+、D−不能直接接 STM32 的 UART RX、TX;外接 USB 转 TTL 模块时,还要确认其 IO 电压与 STM32 兼容,并且两端必须共地。
1.1 控制LED灯
原理图中 LED1、LED2 的阳极接 3.3 V,阴极分别经过 1 kΩ 电阻接 PB5、PE5,因此 GPIO 输出低电平时产生电流,LED 点亮;输出高电平时两端电位接近,LED 熄灭。这叫“低电平有效”。
3.3 V ──>| LED ── 1 kΩ ── GPIO
点亮方向
GPIO = 0 V:3.3 V → LED → 电阻 → GPIO,形成电流,LED亮
GPIO = 3.3 V:两端压差很小,几乎无电流,LED灭
限流电阻不能省略。它限制 LED 和 GPIO 引脚电流,避免器件损坏。HAL_GPIO_TogglePin() 每调用一次,就把当前输出状态翻转一次,所以同一命令连续发送两次会完成“亮→灭”或“灭→亮”。
二、理论部分
2.1 USART
USART 是“通用同步/异步收发器”。STM32 的 USART 外设既能进行常见的异步 UART 通信,也能在特定模式下输出同步时钟。日常所说的“串口”通常指异步 UART:TX 发送、RX 接收,没有单独时钟线。
UART 定义的是字节如何变成串行位流,TTL、RS-232、RS-485则主要描述物理电气层。它们不能混为一谈:相同的 UART 数据帧可以经过不同的收发器变成不同电气信号。
2.1.1 同步异步通信方式
同步通信由发送方提供时钟,接收方按时钟边沿采样;异步通信没有共享时钟线,双方预先约定波特率,再借助起始位重新对齐每一帧。
典型 8N1 UART 帧为:
空闲 起始位 8个数据位(低位先发) 停止位 空闲
1 0 D0 D1 D2 D3 D4 D5 D6 D7 1 1
└──────────── 一个字符帧 ────────────────┘
“115200、8 数据位、无校验、1 停止位”必须在通信两端保持一致。115200 bit/s 的 8N1 帧每个字节占 10 位,理论上最多约为 115200 ÷ 10 = 11520 字节/秒,实际吞吐量还会受软件和协议开销影响。
2.1.2 SPI
SPI 是同步串行总线,常见信号包括 SCK、MOSI、MISO 和片选 CS:
- SCK:主机输出的串行时钟;
- MOSI:主机发送、从机接收;
- MISO:从机发送、主机接收;
- CS:选择某个从设备。
SPI 的时钟线通常写作 SCK,不是 I²C 中常见的 SCL。SPI 可以同时发送和接收,速度通常较高,但占用引脚较多,而且没有统一的数据包格式。
2.1.3 异步通信方式
UART 接收器会在检测到起始位下降沿后,按照设定波特率在数据位中心附近采样。因此双方时钟允许有少量误差,但误差过大时,采样点会逐位漂移,最终造成帧错误。
UART 中的“空闲高电平”是逻辑概念。实际导线上的电压要看采用哪种物理层:
- 3.3 V TTL/CMOS UART:通常低电平接近 0 V,高电平接近 3.3 V;
- RS-232:逻辑 1 通常对应负电压,逻辑 0 对应正电压,且需要专用电平转换芯片;
- RS-485:接收器判断 A、B 两线的差分电压,不用某一根线对地的电压直接代表数据位。
2.1.4 串行和并行的区别
并行通信在同一时刻用多根数据线传送多位;串行通信依次用较少导线传送各位。
并行:D7 D6 D5 D4 D3 D2 D1 D0 ── 同时传8位
串行:TX ── D0─D1─D2─...─D7 ── 依次传8位
并行并不必然永远更快。距离变长、速率提高以后,各根并行线的到达时间可能不一致,还会出现串扰和布线困难;高速串行链路可以通过差分传输、编码和时钟恢复获得很高的有效速率。
2.1.5 并行和串行的比较效率和速度
选择接口时需要综合考虑:
| 对比项 | 串行通信 | 并行通信 |
|---|---|---|
| 引脚和线缆 | 少,布线简单 | 多,布线复杂 |
| 远距离能力 | 通常更好,尤其是差分链路 | 容易受线间偏斜影响 |
| 单个时钟传输量 | 通常较少 | 可同时传多位 |
| 抗干扰能力 | 取决于物理层,差分方式较强 | 多线之间可能串扰 |
| 典型场景 | UART、USB、RS-485、SPI | MCU 外扩存储器、LCD 并口 |
不能只看“串行/并行”就判断速度,还必须看时钟或波特率、编码开销、总线宽度、线缆长度和收发器性能。
2.1.6 方向与时间
2.1.6.1 全双工、半双工、单工
- 全双工:双方能同时收发,例如普通 TX/RX 两线 UART;
- 半双工:双方都能发送,但同一时刻通常只有一方驱动总线,例如常见的两线 RS-485;
- 单工:数据始终只沿一个方向传输,例如只发送的广播链路。
全双工 UART 的两根信号线各自承担一个方向;半双工 RS-485 的收发器共用 A/B 总线,需要用 DE、/RE 控制发送和接收状态。
2.1.6.2 串口相关的硬件信号
1. TTL/CMOS UART
TTL UART 使用单端信号,以 GND 为参考:
设备A TX ─────────> 设备B RX
设备A RX <───────── 设备B TX
设备A GND ───────── 设备B GND
它适合板内或短距离连接。STM32 使用 3.3 V IO,不能仅凭“TTL 串口”几个字就认定可直接连接 5 V 设备;应查双方数据手册的输入阈值和耐压范围。
2. RS-232
RS-232 使用正、负电压并反相表示逻辑,典型有效范围为:
| RS-232 线电压 | 逻辑含义 |
|---|---|
| −3 V~−15 V | 逻辑 1(Mark,空闲态) |
| +3 V~+15 V | 逻辑 0(Space) |
| −3 V~+3 V | 未定义区 |
STM32 引脚不能直接承受这种电压,必须通过 MAX3232 一类收发器:
flowchart LR
MCU[STM32 3.3V UART] <-->|TX/RX| MAX[MAX3232<br/>电平转换与反相]
MAX <-->|RS-232正负电压| DB9[RS-232接口]
RS-232 一般用于点对点、短距离通信。传统接口还可能带 RTS、CTS 等硬件流控信号,但最简通信只需 TXD、RXD、GND。
3. RS-485
RS-485 使用差分信号。接收器关注 VAB = VA − VB 的极性,外界噪声若同时耦合到 A、B 两线,差值变化较小,因此抗共模干扰能力更强。
MCU TX/RX ── RS-485收发器 ── A ================= A ── 收发器 ── 对端
B ================= B
120Ω端接 120Ω端接
两根线应尽量使用双绞线;总线两端各放一个与电缆特性阻抗匹配的端接电阻,常用 120 Ω。端接电阻不是每个节点都装,否则负载会过重。空闲时还常使用偏置电阻维持确定电平。两线制 RS-485 通常为半双工,多节点挂在一条总线上,布线宜采用总线型并缩短支线。
差分传输不是“任何噪声都能抵消”。噪声超过收发器允许的共模范围、线路接错、端接不当或地电位差过大,仍会导致通信失败。