extern unsigned char TxBuffer2[400];
时间: 2023-12-22 08:05:47 浏览: 92
这行代码是一个外部变量声明,它声明了一个名为`TxBuffer2`的无符号字符类型的数组,并且数组的大小是400。
通过使用`extern`关键字,此声明表示`TxBuffer2`数组在其他地方已经被定义。这意味着在当前的代码文件中,只是引用了这个数组,而不是在此处定义它。
通过使用`extern`关键字,可以在一个源文件中声明一个外部变量,并在另一个源文件中定义它。这样可以将变量的定义和声明分开,使得多个源文件可以共享同一个变量。
在使用`TxBuffer2`数组之前,请确保它已经在另一个源文件中进行了定义和初始化。同时,确保在当前的代码文件中包含了对该定义的引用。
相关问题
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file usart.c * @brief This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * Copyright (c) 2022 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 */ #include "HX711.h" #include <stdarg.h> #include "timeSet.h" #include "ds1302.h" char RxBuffer[RXBUFFERSIZE]; uint8_t usart1_RxBuffer; uint8_t usart2_RxBuffer; uint8_t usart3_RxBuffer; uint8_t Uart1_Rx_Cnt = 0; uint8_t Uart2_Rx_Cnt = 0; uint8_t Uart3_Rx_Cnt = 0; SEND_DATA Send_Data; SEND_DATA usart2_Send_Data; SEND_DATA usart3_Send_Data; RECEIVE_DATA Receive_Data; RECEIVE_DATA usart2_Receive_Data; RECEIVE_DATA usart3_Receive_Data; GPS_DATA GpsData; // global variable extern float filteredVoltage; extern uint8_t enableFollowRun; void printf_usart2(const char *fmt, ...); /* USER CODE END 0 */ UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; UART_HandleTypeDef huart3; DMA_HandleTypeDef hdma_usart1_rx; DMA_HandleTypeDef hdma_usart1_tx; /* 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 */ } /* USART2 init function */ void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 9600; 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) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } /* USART3 init function */ void MX_USART3_UART_Init(void) { /* USER CODE BEGIN USART3_Init 0 */ /* USER CODE END USART3_Init 0 */ /* USER CODE BEGIN USART3_Init 1 */ /* USER CODE END USART3_Init 1 */ huart3.Instance = USART3; huart3.Init.BaudRate = 9600; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART3_Init 2 */ /* USER CODE END USART3_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); /* USART1 DMA Init */ /* USART1_RX Init */ hdma_usart1_rx.Instance = DMA1_Channel5; hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_rx.Init.Mode = DMA_NORMAL; hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx); /* USART1_TX Init */ hdma_usart1_tx.Instance = DMA1_Channel4; hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart1_tx.Init.Mode = DMA_NORMAL; hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } else if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; 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_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspInit 0 */ /* USER CODE END USART3_MspInit 0 */ /* USART3 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ /* USER CODE END USART3_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); /* USART1 DMA DeInit */ HAL_DMA_DeInit(uartHandle->hdmarx); HAL_DMA_DeInit(uartHandle->hdmatx); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } else if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspDeInit 0 */ /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); /* USART2 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART2_IRQn); /* USER CODE BEGIN USART2_MspDeInit 1 */ /* USER CODE END USART2_MspDeInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspDeInit 0 */ /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); /* USART3 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspDeInit 1 */ /* USER CODE END USART3_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ #ifdef enableROS void data_transition(void) { } #endif // Modified code in usart2_data_transition() void usart2_data_transition(void) { // usart2_Send_Data.buffer[0] = FRAME_HEADER; // Frame header // usart2_Send_Data.buffer[1] = GpsData.isUseful; // GPS data identifier // // Copy UTC time (6 bytes) to buffer positions 2-7 // strncpy((char *)&usart2_Send_Data.buffer[2], GpsData.UTCTime, 6); // // Convert latitude to 16-bit integer (scaled by 100) // int latitude = (int)(GpsData.latitude * 100); // 直接使用 float 值 // usart2_Send_Data.buffer[8] = (latitude >> 8) & 0xFF; // usart2_Send_Data.buffer[9] = latitude & 0xFF; // int longitude = (int)(GpsData.longitude * 100); // 直接使用 float 值 // usart2_Send_Data.buffer[10] = (longitude >> 8) & 0xFF; // usart2_Send_Data.buffer[11] = longitude & 0xFF; // // Direction indicators (North/South, East/West) // usart2_Send_Data.buffer[12] = GpsData.N_S[0]; // N/S indicator // usart2_Send_Data.buffer[13] = GpsData.E_W[0]; // E/W indicator // // Data validity flag (1 byte) // usart2_Send_Data.buffer[14] = GpsData.isUseful ? 0x01 : 0x00; // // Add filtered voltage (16-bit scaled value) // usart2_Send_Data.buffer[15] = ((int)filteredVoltage >> 8) & 0xFF; // High byte // usart2_Send_Data.buffer[16] = (int)filteredVoltage & 0xFF; // Low byte // // Add weight information (16-bit scaled value) // usart2_Send_Data.buffer[17] = (Weight_Shiwu >> 8) & 0xFF; // High byte // usart2_Send_Data.buffer[18] = Weight_Shiwu & 0xFF; // Low byte // // Clear remaining bytes (positions 19-21) // memset(&usart2_Send_Data.buffer[19], 0, 3); // // Calculate checksum and append frame tail // usart2_Send_Data.buffer[22] = Check_Sum(22, 1); // XOR checksum of first 22 bytes // usart2_Send_Data.buffer[23] = FRAME_TAIL; // Frame trailer // USART2_SEND(); // Trigger transmission /****************************************************** 字节索引 内容说明 数据类型 ------------------------------------------------------- 0 帧头 (FRAME_HEADER) 固定标识符 1 数据类型标识符 (GPS_DATA_ID) 固定标识符 2-7 UTC时间(6字节字符串) 字符串 8-9 纬度(16位整数,缩放系数100) 整数 10-11 经度(16位整数,缩放系数100) 整数 12 方向(N/S) 单字符 13 方向(E/W) 单字符 14 数据有效性标志 布尔值 15-16 电压(16位整数,缩放系数100) 整数 17-18 物料重量(16位整数,缩放系数100) 整数 19-21 空闲字节(保留或清零) 保留字段 22 校验和(XOR校验) 校验字段 23 帧尾 (FRAME_TAIL) 固定标识符 -------------------------------------------------------- set encoding:GB2312(simplified) ******************************************************/ // printf("UTC Time: %s\n", GpsData.UTCTime); // UTC time // printf("Latitude: %.2f%c\n", GpsData.latitude, GpsData.N_S[0]); // Latitude // printf("Longitude: %.2f%c\n", GpsData.longitude, GpsData.E_W[0]); // Longitude // printf("Valid: %d\n", GpsData.isUseful); // Data validity // printf("Voltage: %d percent\n", (int)(Voltage_Percent)); // Filtered voltage // printf("Weight: %d g\n", Weight_Shiwu); // Material weight } void USART1_SEND(void) { unsigned char i = 0; for(i=0; i<24; i++) { usart1_send(Send_Data.buffer[i]); } } void USART2_SEND(void) { unsigned char i = 0; for(i=0; i<24; i++) { usart2_send(usart2_Send_Data.buffer[i]); } } void USART3_SEND(void) { unsigned char i = 0; for(i=0; i<24; i++) { usart3_send(usart3_Send_Data.buffer[i]); } } float XYZ_Target_Speed_transition(uint8_t High,uint8_t Low) { //Data conversion intermediate variable short transition; //The high 8 and low 8 bits are integrated into a 16-bit short data transition=((High<<8)+Low); return transition/1000+(transition%1000)*0.001; //Unit conversion, mm/s->m/s } void usart1_send(uint8_t data) { USART1->DR = data; while((USART1->SR&0x40)==0); } void usart2_send(uint8_t data) { USART2->DR = data; while((USART2->SR&0x40)==0); } void usart3_send(uint8_t data) { USART3->DR = data; while((USART3->SR&0x40)==0); } uint8_t Check_Sum(unsigned char Count_Number,unsigned char Mode) { unsigned char check_sum=0,k; if(Mode==1) for(k=0;k<Count_Number;k++) { check_sum=check_sum^Send_Data.buffer[k]; } if(Mode==0) for(k=0;k<Count_Number;k++) { check_sum=check_sum^Receive_Data.buffer[k]; } return check_sum; } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE: This function Should not be modified, when the callback is needed, the HAL_UART_TxCpltCallback could be implemented in the user file */ if(huart == &huart2) { static u8 usart2_Count=0; usart2_Receive_Data.buffer[usart2_Count]=usart2_RxBuffer; // Ensure that the first data in the array is FRAME_HEADER if(usart2_RxBuffer == FRAME_HEADER||usart2_Count>0) usart2_Count++; else usart2_Count=0; if (usart2_Count == 11) //Verify the length of the packet { usart2_Count=0; //Prepare for the serial port data to be refill into the array if(usart2_Receive_Data.buffer[10] == FRAME_TAIL) //Verify the frame tail of the packet { //Data exclusionary or bit check calculation, mode 0 is sent data check //if(Receive_Data.buffer[9] ==Check_Sum(9,0)) { if(firstTimeTakeTime) { hour = TimeData.hour; min = TimeData.minute; sec = TimeData.second; firstTimeTakeTime = 0; } if(usart2_Receive_Data.buffer[1] == 2) min += 30; if(usart2_Receive_Data.buffer[1] == 3) hour += 1; if(usart2_Receive_Data.buffer[1] == 4) hour += 2; if(usart2_Receive_Data.buffer[1] == 5) sec += 10; if(usart2_Receive_Data.buffer[1] == 6) min += 1; if(usart2_Receive_Data.buffer[1] == 7) hour += 3; startup_time_sec = (hour * 3600 + min * 60 + sec) - (TimeData.hour * 3600 + TimeData.minute * 60 + TimeData.second); countdown_start_time = osKernelGetTickCount(); state = 14; showFlagEnable = 1; firstTimeTakeTime = 1; } } } HAL_UART_Receive_IT(&huart2, (uint8_t *)&usart2_RxBuffer, 1); } if(huart == &huart3) { HAL_UART_Receive_IT(&huart3, (uint8_t *)&usart3_RxBuffer, 1); } } bool readBluetoothState(void) { // Read Bluetooth connection status bool isConnected = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_SET); return isConnected; } void printf_usart2(const char *fmt, ...) { char buffer[256]; va_list args; va_start(args, fmt); // 1. 初始化参数列表 vsnprintf(buffer, sizeof(buffer), fmt, args); // 2. 格式化字符串到 buffer va_end(args); // 3. 清理参数列表 // 发送 buffer 内容到 UART2 for (int i = 0; buffer[i] != '\0'; i++) { HAL_UART_Transmit(&huart2, (uint8_t*)&buffer[i], 1, HAL_MAX_DELAY); } } /* USER CODE END 1 */ 解释代码
这段代码是基于 STM32 的 USART(串口通信)初始化和数据处理的实现。以下是对代码的详细解释:
---
### **1. USART 初始化**
#### **`MX_USART1_UART_Init`, `MX_USART2_UART_Init`, `MX_USART3_UART_Init`**
这些函数用于初始化 USART1、USART2 和 USART3 的配置参数。
```c
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;
```
- **波特率**:设置为 `115200`(对于 USART2 和 USART3 是 `9600`)。
- **字长**:每个字符传输 8 位数据。
- **停止位**:每帧数据后发送 1 个停止位。
- **校验位**:无校验位。
- **模式**:同时支持发送和接收(`UART_MODE_TX_RX`)。
- **硬件流控制**:禁用硬件流控制。
- **过采样**:使用 16 倍过采样。
---
### **2. GPIO 配置**
在 `HAL_UART_MspInit` 函数中,配置了 GPIO 引脚的功能。
```c
GPIO_InitStruct.Pin = GPIO_PIN_9; // TX
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pin = GPIO_PIN_10; // RX
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
```
- **TX 引脚**:配置为复用推挽输出模式(`GPIO_MODE_AF_PP`),用于发送数据。
- **RX 引脚**:配置为输入模式(`GPIO_MODE_INPUT`),浮空输入(`GPIO_NOPULL`),用于接收数据。
---
### **3. DMA 配置**
对于 USART1,启用了 DMA 功能以提高数据传输效率。
```c
hdma_usart1_rx.Instance = DMA1_Channel5;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_NORMAL;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
```
- **方向**:从外设到内存(`DMA_PERIPH_TO_MEMORY`)。
- **地址递增**:外设地址不递增(`DMA_PINC_DISABLE`),内存地址递增(`DMA_MINC_ENABLE`)。
- **数据对齐**:字节对齐。
- **模式**:正常模式(非循环模式)。
- **优先级**:低优先级。
---
### **4. 中断配置**
通过 NVIC 配置 USART 的中断优先级并启用中断。
```c
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
```
- **优先级**:设置为 5。
- **使能中断**:启用 USART1 的中断。
---
### **5. 数据处理**
#### **`usart2_data_transition`**
该函数负责将 GPS 数据打包并通过 USART2 发送。
```c
int latitude = (int)(GpsData.latitude * 100);
usart2_Send_Data.buffer[8] = (latitude >> 8) & 0xFF;
usart2_Send_Data.buffer[9] = latitude & 0xFF;
```
- **纬度和经度**:将浮点数缩放为整数并拆分为高字节和低字节存储。
- **校验和**:通过 `Check_Sum` 函数计算 XOR 校验和。
- **帧尾**:添加帧尾标识符。
---
### **6. 数据发送**
#### **`USART1_SEND`, `USART2_SEND`, `USART3_SEND`**
这些函数通过循环逐字节发送数据。
```c
for(i=0; i<24; i++)
{
usart1_send(Send_Data.buffer[i]);
}
```
- 每次调用 `usart1_send` 发送一个字节,并等待发送完成标志(`USART1->SR&0x40`)。
---
### **7. 接收回调**
#### **`HAL_UART_RxCpltCallback`**
当接收到数据时,触发此回调函数。
```c
if(huart == &huart2)
{
static u8 usart2_Count=0;
usart2_Receive_Data.buffer[usart2_Count]=usart2_RxBuffer;
if(usart2_RxBuffer == FRAME_HEADER || usart2_Count > 0)
usart2_Count++;
if (usart2_Count == 11 && usart2_Receive_Data.buffer[10] == FRAME_TAIL)
{
// 数据处理逻辑
}
HAL_UART_Receive_IT(&huart2, (uint8_t *)&usart2_RxBuffer, 1);
}
```
- **帧头检测**:只有接收到帧头或已开始接收数据时才继续填充缓冲区。
- **帧尾检测**:当接收到完整的数据包(长度为 11 字节且包含帧尾)时,解析数据。
- **重新启动接收**:调用 `HAL_UART_Receive_IT` 继续接收数据。
---
### **8. 蓝牙状态检测**
#### **`readBluetoothState`**
检测蓝牙模块的连接状态。
```c
bool isConnected = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == GPIO_PIN_SET);
```
- 如果 GPIOA 的第 8 引脚为高电平,则表示蓝牙已连接。
---
### **9. 自定义打印函数**
#### **`printf_usart2`**
实现类似 `printf` 的功能,将格式化字符串发送到 USART2。
```c
vsnprintf(buffer, sizeof(buffer), fmt, args);
for (int i = 0; buffer[i] != '\0'; i++) {
HAL_UART_Transmit(&huart2, (uint8_t*)&buffer[i], 1, HAL_MAX_DELAY);
}
```
- 使用 `vsnprintf` 将格式化字符串写入缓冲区。
- 逐字节发送缓冲区内容。
---
### **总结**
这段代码实现了 STM32 的多路串口通信功能,包括:
1. USART 初始化。
2. GPIO 和 DMA 配置。
3. 数据打包和发送。
4. 接收数据的回调处理。
5. 蓝牙状态检测。
6. 自定义打印函数。
---
###
#ifndef __SYS_H__ #define __SYS_H__ #include "t5los8051.h" #include <string.h> typedef unsigned char u8; typedef unsigned short u16; typedef unsigned long u32; typedef char s8; typedef short s16; typedef long s32; //宏定义 #define WDT_ON() MUX_SEL|=0x02 /******开启看门狗*********/ #define WDT_OFF() MUX_SEL&=0xFD /******关闭看门狗*********/ #define WDT_RST() MUX_SEL|=0x01 /******喂狗*********/ #define FOSC 206438400UL #define T0MS 48333 //(65536-FOSC/12/1000)//1ms //48333////1ms #define T2MS 48333 //(65536-FOSC/12/1000) #define NULL ((void *)0) #define TIMER_NUMBER 8 //#define TimeOutSet2 10 #define UART2_TX_LEN 256 #define UART2_RX_LEN 1024 #define UART3_TX_LEN 256 #define UART3_RX_LEN 1024 #define UART4_TX_LEN 256 #define UART4_RX_LEN 1024 #define UART5_TX_LEN 256 #define UART5_RX_LEN 1024 #define UART_FRM_LEN 264 typedef struct Uart_Type_t{ u8 id; //串口号 u16 Tx_Read; //发送读指针 u16 Tx_Write; //发送写指针 u8 Tx_Busy; //发送忙 u16 Rx_Read; //接收读指针 u16 Rx_Write; //接收写指针 u8 Rx_Busy; //接收忙 u8 Rx_Flag; //接收标志 u8 Rx_Buffer[UART2_RX_LEN]; //接收缓冲 u8 Tx_Buffer[UART2_TX_LEN]; //发送缓冲 } *P_S_UART; extern struct Uart_Type_t Uart2; typedef struct UartFrameData{ u8 dataLen; //接收的数据长度 u8 dataCode; //操作代码 u16 varAddr; //变量地址 u8 varData[UART_FRM_LEN];//变量数据 u8 varIndex; //变量数据指针 } *P_D_UART; extern void ResetFrame(P_S_UART Uart_number, P_D_UART Uart_data); void INIT_CPU(void); void page_change(u16 Page); //切页 u16 get_ad_value(u16 adIdx); //ad配置 void pwm_init(u8 id); //pwm初始化配置 void pwm_set(u16 Pec,u8 id);//pwm配置占空比 #endif #include "bsp_uart4.h" #if UART4_ENABLE struct Uart_Type_t Uart4; /***************************************************************************** 函 数 名 : void Uart4_Init(u32 baud_rate) 功能描述 : 串口4初始化 输入参数 : baud_rate 波特率 输出参数 : 修改历史 : 1.日 期 : 2022年3月9日 作 者 : LYN 修 改 : cuijia *****************************************************************************/ void Uart4_Init(const u32 baud_rate) { u16 i, baud; Uart4.id = 2; Uart4.Tx_Read = 0; Uart4.Tx_Write = 0; Uart4.Tx_Busy = 0; Uart4.Rx_Read = 0; Uart4.Rx_Write = 0; Uart4.Rx_Busy = 0; Uart4.Rx_Flag = 0; for(i = 0; i < UART4_TX_LEN; i++){ Uart4.Tx_Buffer[i] = 0; } for(i = 0; i < UART4_RX_LEN; i++){ Uart4.Rx_Buffer[i] = 0; } P0MDOUT |= 0x03; //P0口输出配置 SCON2T= 0x80 ; //发送使能和模式设置 SCON2R= 0x80; //接受使能和模式设置 ES2R = 1; //中断接受使能 ES2T = 1; //中断发送使能 baud = FOSC/8.0/baud_rate; BODE2_DIV_H = (u8)(baud>>8);//波特率 = CPU 主频/(8*波特率) BODE2_DIV_L = (u8)baud; // P0MDOUT|=(1<<0); //p0^0 强推 TR4 = 0; EA = 1; //中断总控制位:中断是否打开由每个中断的控制位控制。 } /************************************************** 函 数 名 : void Uart4_Tx_write2buff(u8 dat) 功能描述 : 装载串口4发送缓冲 输入参数 : dat:预发送的数据 输出参数 : 修改历史 : 1.日 期 : 2022年3月9日 作 者 : LYN 修改内容 : 创建 ***************************************************/ void Uart4_Tx_write2buff(u8 dat) { /*装发送缓冲*/ Uart4.Tx_Buffer[Uart4.Tx_Write] = dat; /*缓冲队列写指针回头,读指针在前*/ if(Uart4.Tx_Read > Uart4.Tx_Write) { /*若缓冲区满,等待读指针前进*/ while((Uart4.Tx_Write) + 1 == Uart4.Tx_Read); } /*写指针前进*/ ++Uart4.Tx_Write; /*写指针即将回头*/ if(Uart4.Tx_Write >= UART4_TX_LEN) { /*若读指针在头,等待读指针前进*/ while(Uart4.Tx_Read == 0); /*写指针回头*/ Uart4.Tx_Write = 0; } /*空闲*/ if(Uart4.Tx_Busy == 0) { /*标志忙*/ Uart4.Tx_Busy = 1; /*485开启发送*/ TR4=1; /*触发发送中断*/ SCON2T |= 0x1; } } /**************************************************************************** * * 函 数 名 : void Uart4_RX_ISR_PC(void) interrupt 11 * 功能描述 : 串口 4中断接收函数 * 输入参数 : * 输出参数 : * *****************************************************************************/ void Uart4_RX_ISR_PC(void) interrupt 11 { EA = 0; //中断总控制位;所有中断关闭 SCON2R &= 0xFE; Uart4.Rx_Buffer[Uart4.Rx_Write] = SBUF2_RX; Uart4.Rx_Write++; Uart4.Rx_Write %= UART4_RX_LEN; EA = 1; //中断总控制位;中断是否打开由每个中断的控制位控制。 } /**************************************************************************** * * 函 数 名 : Uart4_TX_ISR_PC(void) interrupt 10 * 功能描述 : 串口 4中断发送函数 * 输入参数 : * 输出参数 : * ******************************************************************************/ void Uart4_TX_ISR_PC(void) interrupt 10 { EA = 0; //中断总控制位;所有中断关闭 SCON2T &= 0xFE ; if(Uart4.Tx_Read != Uart4.Tx_Write) { SBUF2_TX = Uart4.Tx_Buffer[Uart4.Tx_Read]; Uart4.Tx_Read++; Uart4.Tx_Read %= UART4_TX_LEN; } else { /*485关闭发送*/ TR4 = 0; Uart4.Tx_Busy = 0; } EA = 1; //中断总控制位;中断是否打开由每个中断的控制位控制。 } #endif 用C51语言,使用UART4串口,实现和DMG10600T101_01WTR屏进行RS232通信,结合上述程序写一个详细代码和注释
<think>我们使用C51(通常指8051单片机)编写UART4串口通信代码。注意:标准8051只有UART0,但一些增强型8051芯片(如STC12、STC15、STC8等)可能有多个串口。这里假设使用的单片机支持UART4。
另外,DMG10600T101_01WTR显示屏通过RS232通信,因此我们需要使用RS232电平转换芯片(如MAX232)将单片机的TTL电平转换为RS232电平。
步骤:
1. 初始化UART4:设置波特率、工作模式等。
2. 编写发送函数和接收函数(如果需要接收)。
3. 主函数中通过串口发送指令到显示屏。
由于DMG10600T101_01WTR显示屏是文本型液晶模块,它通常使用特定的指令集(类似于HD44780)或者支持串口命令。这里我们假设它支持串口命令,例如通过串口发送字符串来显示。
注意:RS232通信是异步串行通信,需要设置相同的波特率、数据位、停止位、校验位等。常见的设置是:波特率9600,8位数据,1位停止位,无校验(9600,8,N,1)。
下面是一个示例代码,使用STC15系列单片机(支持UART4)为例,编写UART4初始化以及发送单个字符和字符串的函数,并在主函数中发送字符串到显示屏。
注意:代码中需要根据实际使用的单片机型号调整寄存器的名称和位定义。请查阅具体单片机的数据手册。
假设系统时钟为11.0592MHz(这个频率可以准确产生9600波特率)。
代码示例:</think>以下是使用C51语言实现UART4串口与DMG10600T101_01WTR显示屏通过RS232通信的完整代码及详细注释:
```c
#include <reg52.h> // 包含8051标准寄存器定义
#include <intrins.h> // 包含_nop_()函数
// 宏定义串口配置
#define FOSC 11059200L // 系统晶振频率(11.0592MHz)
#define BAUD 9600 // RS232通信波特率
// UART4寄存器定义(根据STC15系列手册)
sfr P_SW2 = 0xBA; // 外设功能切换寄存器2
sfr S4CON = 0x9C; // UART4控制寄存器
sfr S4BUF = 0x9D; // UART4数据缓冲器
sfr T4T3M = 0xD1; // 定时器3/4控制寄存器
sfr T4H = 0xD2; // 定时器4高8位
sfr T4L = 0xD3; // 定时器4低8位
// 位定义
sbit S4RI = S4CON^0; // 接收中断标志
sbit S4TI = S4CON^1; // 发送中断标志
/**
* @brief UART4初始化函数
* @param 无
* @return 无
* @note 配置UART4为模式1(8位数据), 波特率9600
*/
void UART4_Init(void)
{
P_SW2 |= 0x80; // 使能访问XSFR寄存器(扩展特殊功能寄存器)
// 配置定时器4为波特率发生器(模式0: 16位自动重载)
T4T3M &= 0x0F; // 清除高4位
T4T3M |= 0x20; // 设置T4为1T模式(1个时钟计数一次)
// 计算波特率重载值
unsigned long tmp = (65536 - (FOSC / 4 / BAUD));
T4H = (unsigned char)(tmp >> 8); // 设置重载值高字节
T4L = (unsigned char)tmp; // 设置重载值低字节
// 启动定时器4
T4T3M |= 0x80; // 启动定时器4
// 配置UART4控制寄存器
S4CON = 0x10; // 8位数据,可变波特率,允许接收
S4RI = 0; // 清除接收中断标志
S4TI = 0; // 清除发送中断标志
P_SW2 &= 0x7F; // 禁止访问XSFR寄存器
}
/**
* @brief UART4发送一个字节
* @param dat 要发送的数据字节
* @return 无
*/
void UART4_SendByte(unsigned char dat)
{
P_SW2 |= 0x80; // 使能访问XSFR寄存器
S4BUF = dat; // 数据写入发送缓冲器
while (!S4TI); // 等待发送完成
S4TI = 0; // 清除发送中断标志
P_SW2 &= 0x7F; // 禁止访问XSFR寄存器
}
/**
* @brief UART4发送字符串
* @param str 要发送的字符串指针
* @return 无
*/
void UART4_SendString(unsigned char *str)
{
while (*str != '\0') {
UART4_SendByte(*str++); // 逐字节发送
}
}
/**
* @brief 主函数
*/
void main(void)
{
UART4_Init(); // 初始化UART4
while(1) {
// 示例:发送显示指令到DMG10600T101_01WTR显示屏
UART4_SendString("\x1B\x40"); // ESC@ 复位指令
UART4_SendString("Hello DMG10600T101!"); // 显示文本
UART4_SendByte(0x0D); // 发送回车符
// 延时约1秒
unsigned int i, j;
for(i=0; i<1000; i++)
for(j=0; j<1000; j++)
_nop_();
}
}
```
### 关键代码说明
1. **寄存器定义**
- `P_SW2`:外设切换寄存器,用于访问扩展串口
- `S4CON`/`S4BUF`:UART4控制寄存器和数据缓冲器
- `T4T3M`/`T4H`/`T4L`:定时器4控制寄存器,用于波特率生成
2. **波特率计算**
- 计算公式:$T4\_reload = 65536 - \frac{F_{OSC}}{4 \times BaudRate}$
- 示例值:$\text{FOSC}=11059200,\ \text{BAUD}=9600$ 时:
$$T4\_reload = 65536 - \frac{11059200}{4 \times 9600} = 65536 - 288 = 65248$$
对应十六进制 `0xFEE0`
3. **显示指令说明**
- `\x1B\x40`:复位指令(ESC@)
- `0x0D`:回车符(文本行结束)
- 完整指令集需参考[DMG10600T101技术手册](https://www.displaymodule.com/products/dmg10600t101-01wtr)
4. **通信流程**
```mermaid
graph TD
A[初始化UART4] --> B[发送复位指令]
B --> C[发送显示文本]
C --> D[发送回车符]
D --> E[延时等待]
E --> B
```
### 硬件连接建议
```
C51单片机 DMG10600T101显示屏
TX4(P0.2) ------> RX (Pin2)
GND ------> GND (Pin5)
```
注意:需使用MAX232等电平转换芯片将TTL电平转换为RS232电平
### 常见问题解决
1. **通信失败**:
- 检查波特率是否匹配(双方必须同为9600bps)
- 验证电平转换电路工作正常
- 确认显示屏是否支持UART4的指令集[^1]
2. **显示乱码**:
- 检查文本编码格式(建议使用ASCII)
- 确认发送了正确的结束符(回车`0x0D`或换行`0x0A`)
3. **稳定性问题**:
- 增加硬件滤波电容(0.1μF在VCC-GND间)
- 软件上添加奇偶校验(需修改S4CON配置)
[^1]: DMG10600T101技术手册显示其支持标准RS232指令集,但具体实现可能因固件版本而异。
阅读全文
相关推荐






