了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别;了解"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理。 使用HAL库(或标准库)方式,设置USART1 波特率为115200,1位停止位,无校验位,分别采用中断方式、DMA方式完成下列任务:
STM32系统给上位机(win10)连续发送“hello windows!”;当上位机给stm32发送字符“stop”后,stm32暂停发送“hello windows!”;发送一个字符“start”后,stm32继续发送;
要实现这个任务,首先需要了解串口协议和RS-232标准的基本知识。
串口协议是一种在计算机和外部设备之间进行数据传输的通信协议。RS-232是一种常用的串行通信标准,定义了数据传输的电气特性、数据位数、停止位数、校验方式等。RS-232标准使用负逻辑电平,即+12V表示逻辑0,-12V表示逻辑1。
与RS-232电平相比,TTL电平(Transistor-Transistor Logic)使用的是0V和5V的电压表示逻辑0和逻辑1。TTL电平通常用于微控制器等低功耗设备。
"USB/TTL转232"模块是一种将TTL电平转换为RS-232电平(或将RS-232电平转换为TTL电平)的转换模块。CH340芯片模块是其中一种常用的USB/TTL转232芯片模块。它通过USB接口与计算机连接,提供TTL电平的串口通信接口,可以将数据通过USB接口传输到计算机。
对于这个实验任务,可以按照以下步骤进行操作:
-
使用HAL库(或标准库)的方式,初始化USART1串口,将波特率设置为115200,数据位设置为8位,停止位设置为1位,校验位设置为无校验位。
-
配置中断方式的USART接收功能,当接收到上位机发送的字符时触发中断,并进行相应的处理。在中断处理函数中,判断接收到的字符是否为"stop"或"start",根据不同的字符执行相应的操作。
-
配置DMA方式的USART发送功能,使用循环模式,将"hello windows!"按照一定的频率发送到上位机。可以使用定时器来产生触发发送的时钟信号。
-
在主程序中,设置一个标志位来控制发送操作的开关。初始状态下,标志位为1,允许发送操作。当接收到"stop"字符时,将标志位改为0,禁止发送操作。当接收到"start"字符时,将标志位改为1,允许发送操作。
代码如下,演示了如何使用STM32的HAL库和USART1实现串口通信任务:
使用中断方式:
#include "stm32f4xx_hal.h"
#include <string.h>
UART_HandleTypeDef huart1;
char txBuffer[15] = "hello windows!";
char startBuffer[] = "start";
char stopBuffer[] = "stop";
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
void sendUARTData(char* data, uint16_t size)
{
HAL_UART_Transmit_IT(&huart1, (uint8_t*)data, size);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_IT(&huart1, (uint8_t*)stopBuffer, sizeof(stopBuffer)-1);
while (1)
{
if (strcmp(stopBuffer, "stop") == 0)
{
HAL_UART_Abort_IT(&huart1);
}
else if (strcmp(startBuffer, "start") == 0)
{
HAL_UART_Transmit_IT(&huart1, (uint8_t*)txBuffer, sizeof(txBuffer)-1);
}
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
// Transmission complete callback
if (huart == &huart1)
{
HAL_UART_Receive_IT(&huart1, (uint8_t*)stopBuffer, sizeof(stopBuffer)-1);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
// Reception complete callback
if (huart == &huart1)
{
// Process the received data
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
// UART error callback
}
void SystemClock_Config(void)
{
// System clock configuration
}
static void MX_GPIO_Init(void)
{
// GPIO configuration
}
static void MX_USART1_UART_Init(void)
{
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;
HAL_UART_Init(&huart1);
}
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
使用DMA方式:
#include "stm32fxxx_hal.h"
#define UART_BUFFER_SIZE 20
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_usart1_tx;
char uartBuffer[UART_BUFFER_SIZE] = "hello windows!";
char uartReceiveBuffer[UART_BUFFER_SIZE];
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_DMA_Init(void);
void MX_USART1_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
while (1)
{
if (strcmp(uartReceiveBuffer, "stop") == 0)
{
// 停止发送
HAL_UART_DMAStop(&huart1);
}
else if (strcmp(uartReceiveBuffer, "start") == 0)
{
// 继续发送
HAL_UART_Transmit_DMA(&huart1, (uint8_t*)uartBuffer, UART_BUFFER_SIZE);
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_POWER_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
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)
{
Error_Handler();
}
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)
{
Error_Handler();
}
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void MX_DMA_Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
}
void MX_USART1_UART_Init(void)
{
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_DMA;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
HAL_UART_Receive_IT(&huart1, (uint8_t*)uartReceiveBuffer, UART_BUFFER_SIZE);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
// 发送完成中断回调函数
}
void DMA1_Channel4_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_usart1_tx);
}
void Error_Handler(void)
{
// 错误处理函数
}