基于中断DMA的串口通信

重庆交通大学信息科学与工程学院

《嵌入式系统基础 A》课程

实验报告

班 级: 物联网工程 2101

**姓名-学号 : 江欣朋-632007060322 **

实验项目名称: 基于中断/DMA 的串口通信

**实验项目性质: 设计性 **

**实验所属课程: 《嵌入式系统基础 A》 **

**实验室(中心): 南岸校区语音大楼 **

**指 导 教 师 : 娄路 **

完成时间: 2023 年 10 月 28 日

一、实验内容和任务 

1.了解串口协议和 RS-232 标准,以及 RS232 电平与 TTL 电平的区别;了解"USB/TTL 转 232"模块(以 CH340 芯片模块为例)的工作原理。 使用 HAL 库(或标准库)方式,设置 USART1 波特率为 115200,1 位停止位,无校验位,分别采用中断方式、DMA 方式完成下列任务:

STM32 系统给上位机(win10)连续发送“hello windows!”;当上位机给 stm32 发送字符“stop”后,stm32 暂停发送“hello windows!”;发送一个字符“start”后,stm32 继续发送;

参考网址:STM32 串口通信 USART 学习笔记

STM32串口通信USART学习笔记 - 程序员大本营

基于 MDK 创建 STM32 汇编程序:串口输出 Hello worldSTM32最小核心板F103串口通信USART_f103 usart-CSDN博客
HAL 库中断方式进行串口通信

HAL库中断方式进行串口通信-CSDN博客
基于 HAL 库实现 DMA 串口通信

基于HAL库实现DMA串口通信_hal_dma_start_it-CSDN博客

在没有示波器条件下,可以使用 Keil 的软件仿真逻辑分析仪功能观察串口输出波形,并分析时序状态正确与否,计算波特率实际为多少。
参考:stm32外部中断模式控制灯亮灭_stm32编程后怎么停下来-CSDN博客HAL库中断方式进行串口通信-CSDN博客https://www.cnblogs.com/breezy-ye/articles/12157442.html
【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)_stm32h7 串口dma 发送 第一次成功-CSDN博客

二、实验要求

1. 分组要求:每个学生独立完成,即 1 人 1 组。

2. 程序及报告文档要求:具有较好的可读性,如叙述准确、标注明确、截图清晰等。

3.把项目完整打包为 zip 文件,与实验报告(Markdown 源码及 PDF 文件)、作业博客地址一起提交到学习通。

三. 实验过程介绍 (此处可以填博客内容)

1. 用 stm32F103 核心板的 GPIOA 端一管脚接一个 LED,GPIOB 端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED 亮灯;接低电平时,LED 灭灯。

一丶通过 STMCube 配置项目 RCC 配置:

SYS 配置:

SYS 配置:

CLOCK:

配置 GPIO:

 这里要注意: 把 A4 配置为高电平 把 B9 中断配置为上升沿和下降沿都触发 然后创建项目就 OK

 二、通过 KEil 配置代码 在 main.c 中加入:

注意不是加入到 int main 函数当中; 然后编译生成 hex 文件 然后烧录

实例: 插入 B9 灯灭

2. 采用串口中断方式重做上周的串口通信作业,分别实现:1)当 stm32 接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);2)当 stm32 接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”

1) (1)STM32CubeMX 配置 USART1 设置:

RCC 设置:

sys 配置:

USART1 选上这个

(2)编写代码 在 main.c 里声名全局变量

main.c 全部函数

#include "main.h"

#include "usart.h"

#include "gpio.h"

#include <string.h>

void SystemClock_Config(void);

char c;//指令 0:停止  1:开始

char message[]="hello Windows\n";//输出信息

char tips[]="CommandError\n";//提示1

char tips1[]="Start.....\n";//提示2

char tips2[]="Stop......\n";//提示3

int flag=0;//标志 0:停止发送 1.开始发送

int main(void)

{

HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();

  MX_USART1_UART_Init();

//设置接受中断

HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);

//当flag为1时,每秒发送一次信息

//当flag为0时,停止

  while (1)

  {

if(flag==1){

//发送信息

HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);

//延时

HAL_Delay(1000);

}

  }

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

//当输入的指令为0时,发送提示并改变flag

if(c=='t'){

flag=0;

HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);

}

//当输入的指令为1时,发送提示并改变flag

else if(c=='s'){

flag=1;

HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF);

}

//当输入不存在指令时,发送提示并改变flag

else {

flag=0;

HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF);

}

//重新设置中断

HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);

}

/* USER CODE END 4 */

/**

  * @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_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();

  }

  /** 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_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();

  }

}

/* 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 */

}

重写中断函数

实例:

  1. 在 main.c 和 usart.c 中添加头文件#include "stdio.h"之后,在 usart.c 文件中,添加如下代码,进行重定义

在 main.c 中设置两个字符型数组,用来存放需要判别的字符串(记得添加头文件#include "string.h")。同时设置 FLAG 标志变量,来判断电脑向 stm32 发送了哪一个字符串。

uint8_t aRxBuffer;

uint8_t Uart1_RxBuff[256];

uint8_t str1[20]="go stm32!";

uint8_t str2[20]="stop stm32!";

uint8_t Uart1_Rx_Cnt=0;

uint8_t cAlmStr[]="数据溢出(256)\r\n";

在 main.c 主函数 while(1)中添加一下内容(根据你要发送的字符串来修改)

修改回调函数

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 (strcmp(Uart1_RxBuff, str1) == 0) flag = 0;

if (strcmp(Uart1_RxBuff, str2) == 0) flag = 1;

  //if(Uart1_RxBuff[0]=='g') flag = 1;

//if(Uart1_RxBuff[0]=='s') flag = 0;

if(Uart1_Rx_Cnt >= 255)  //溢出判断

{

Uart1_Rx_Cnt = 0;

memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff));

HAL_UART_Transmit(&huart1, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);

}

else

{

Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存

if((Uart1_RxBuff[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuff[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位

{

HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuff, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去

Uart1_Rx_Cnt = 0;

memset(Uart1_RxBuff,0x00,sizeof(Uart1_RxBuff)); //清空数组

}

}

HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断

}

实例演示:

3. STM32 采用串口 DMA 方式,用 115200bps 或更高速率向上位机连续发送数据。

一、工程设置: 1.sys 设置

2.RCC 设置

设置串口

DMA 设置

点击 DMA Setting 的 Add 添加通道,传输速率设置为中速 Medium

在 main.c 文件添加代码

在 while 函数中加入

实例演示:

总结:此次实验我们学习了如何使用串口 DMA 方式向上位机连续发送数据,如何使用串口中断。这次实验让我收获不少,做实验也越来越有心得,更加熟练,希望以后实验也能做好。

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值