基于中断/DMA的串口通信

了解串口协议和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接口传输到计算机。

对于这个实验任务,可以按照以下步骤进行操作:

  1. 使用HAL库(或标准库)的方式,初始化USART1串口,将波特率设置为115200,数据位设置为8位,停止位设置为1位,校验位设置为无校验位。

  2. 配置中断方式的USART接收功能,当接收到上位机发送的字符时触发中断,并进行相应的处理。在中断处理函数中,判断接收到的字符是否为"stop"或"start",根据不同的字符执行相应的操作。

  3. 配置DMA方式的USART发送功能,使用循环模式,将"hello windows!"按照一定的频率发送到上位机。可以使用定时器来产生触发发送的时钟信号。

  4. 在主程序中,设置一个标志位来控制发送操作的开关。初始状态下,标志位为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)
{
  // 错误处理函数
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值