stm32使用(无线串口)实现收发、判断数据+DMA(HAL库)

目录

前言:

1.    用CubeMX配置串口+DMA所需要的环境

(1)打开CubeMAX,点击红框

 (2)查找stm32F103C8T6的芯片

(3)配置SYS

 (4)配置RCC时钟

(5)配置主频

(6)配置串口

(7)配置DMA

(8)生成工程

2.串口中断与DMA相关重要函数介绍

(1)串口相关 

接收完成回调函数:

 接收串口的函数:

 发送串口的函数:

空闲中断打开函数:

在每次进入中断后,判断是否为空闲中断:

清除空闲标志位

终止当前的接收(会把RxferCount清零)

终止接收回调函数

发送完成回调函数

(2)DMA相关

串口DMA接收函数:

串口DMA发送函数:

3.编写相关代码

(1)项目要求

(2)相关代码编写

1.全局变量

2.main.c

3.stm32f1xx_it.c

4.ATK-LORA-01无线串口的使用

1.使用该无线串口前,需要通过软件调整该串口的参数配置。

2.步骤如下:

总结:


前言:

      本文章使用stm32f103c8t6进行HAL库串口程序的使用,可以解决串口接收发送数据问题,也使用了DMA转运,但没有实现无线数据传输(脑子笨了点),此外,本章也会初步的介绍关于ATK-LORA-01无线串口模块的使用,当然,这也指的是透明传输这一方面。

      STM32的串口收发信息,标准库的代码b站上江协科技我认为已经讲的非常清楚了,但可惜没有hal库的,其他的博主,还有网络上的一些视频,貌似距离如接收“stop”然后发送“”stop”,接着接收“start”然后发送“start”都有些困难,他们通过只接受一个字节然后进入中断,所以我实际用CUbeMX来带领大家来操作一遍,无脑掌握。

     备注:关于串口无限数据传输的方法我认为下面这一篇博客讲的非常厉害,使用串口的空闲中断,而且也给出了解决方法,给了我很大启发,链接如下:超子物联网HAL库笔记:串口篇

1.    用CubeMX配置串口+DMA所需要的环境

(1)打开CubeMAX,点击红框

 (2)查找stm32F103C8T6的芯片

C8T6和C8T6TR都可以,双击。

 

(3)配置SYS

 (4)配置RCC时钟

注意如果这个没有配置好的话,就不能配置72MHz的主频。

(5)配置主频

直接双击改写为72,之后敲下Enter,自动配置完毕。

(6)配置串口

一定要使能串口中断!!接收不到信号。

(7)配置DMA

由于要使用DMA,我们先在这里吧DAM配置好。

配置中等速度其他的不用改。

(8)生成工程

 以上就是CubeMX所有的准备操作啦,下面是实现的代码。

2.串口中断与DMA相关重要函数介绍

(1)串口相关 

HAL库为串口中断提供了很多回调函数。 比如 错误回调、半完成回调、Rx、Tx完成回调。你需要用什么回调,就声明什么回调~

接收完成回调函数:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

其中“RxCpltCallback” 可以分解为以下部分:

  • “Rx” 通常代表 “Receive”,即接收。
  • “Cplt” 通常代表 “Complete”,即完成。
  • “Callback” 即回调,指的是当某个特定事件发生时被调用的函数。

 接收串口的函数:

HAL_UART_Receive_IT(&Uart1,Buff,Rx_Size,200)

他的参数分别为:串口配置结构体地址、接收缓冲区(我们自己定义的数组)、预计接收的字节个数(我们自己定义)、超时时间(单位为ms)

接收串口的函数会有四个返回值:

HAL_OK、 代表此次在200ms内接受到了 200 字节。 (也就是与预计相等)
HAL_ERROR 、代表传参错误、 比如超时时间为0、或者数据缓冲区地址为空
HAL_TIMEOUT 、代表未能在规定时间内接收到 200 个字节
往往分为两种情况: 1、接收了但没接收完、2、一点没接收
HAL_BUSY、代表已经在接受了。在忙

注意!!!当接受完size(预计接受的字节)后就会触发串口中断,但如果没有接收完size个字节,而是少接受了字节,就不会触发串口中断,但是数组缓冲区中仍然有数据,这也就是为什么很多博主喜欢把size设置为1,因为一接触到数据就进一次中断。

 发送串口的函数:

HAL_UART_Transmit_IT(&huart1,txBuff,200);

 他的参数分别为:串口配置结构体地址、发送缓冲区(我们自己定义的数组)、预计发送的字节个数(我们自己定义)。

空闲中断打开函数:

__HAL_UART_ENABLE_IT(&uart1.uart,UART_IT_IDLE);

在每次进入中断后,判断是否为空闲中断:

if(__HAL_UART_GET_FLAG(&uart1.uart, UART_FLAG_IDLE))

清除空闲标志位

__HAL_UART_CLEAR_FLAG(&uart1.uart, UART_FLAG_IDLE);

终止当前的接收(会把RxferCount清零)

HAL_UART_AbortReceive_IT(&uart1.uart);

终止接收回调函数

void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)

发送完成回调函数

HAL_UART_TxCpltCallback

(2)DMA相关

DMA(Direct Memory Access)是一种直接内存访问技术,

可以在不经过CPU的情况下实现外设与内存之间的数据传输,提高数据传输效率

同时,DMA同样可以触发串口中断,进入串口中断函数处理任务。

串口DMA接收函数:

HAL_UART_Receive_DMA(&huart1, (uint8_t *)&ReBuff,5);

他的参数分别为:串口配置结构体地址、接收缓冲区(我们自己定义的数组)、预计接收的字节个数(我们自己定义)。

其效果和串口接收函数是一样的,注意的要点也一样,这里就不多描述。

串口DMA发送函数:

HAL_UART_Transmit_DMA(&huart1,(uint8_t *)"stop",5);

他的参数分别为:串口配置结构体地址、发送缓冲区(我们自己定义的数组或字符串)、预计发送的字节个数(我们自己定义)。

3.编写相关代码

(1)项目要求

stm32使用(无线串口)实现收发、判断数据+DMA(HAL库),现象如下:

项目开始:单片机通过串口发送: Hello windows! ,后PC端通过串口助手发送stop,单片机接收到后停止Hello windows!发送,PC端再通过串口助手发送start,单片机接收到后同样发送start,并且开始Hello windows!发送。如下图

(2)相关代码编写

1.全局变量

char ReBuff[5];//接收缓冲区
int flag=1;//对于stop和start的判断标志
uint8_t SendBuff[]="Hello windows! ";//字符串"Hello windows! "封装
const char *str1="start";//字符串"start! "封装
const char *str2="stop";//字符串"stop "封装
char *result1 ;//strstr比较结果
char *result2 ;

2.main.c

在while函数上加上HAL_UART_Receive_DMA(&huart1, (uint8_t *)&ReBuff,5);

接收串口信息,当达到5个数组时触发中断。

下面是while里面的函数

/* USER CODE BEGIN 3 */
        result1 = strstr(ReBuff, str1);
    result2 = strstr(ReBuff, str2);
        if(result1)
        {
            flag=1;
        HAL_UART_Transmit_DMA(&huart1,(uint8_t *)"start",5);
            memset(ReBuff, 0, sizeof(ReBuff));   
            result1 =0;
            
        }
        else if(result2)
        {
          flag=0;
            HAL_UART_Transmit_DMA(&huart1,(uint8_t *)"stop",5);
            memset(ReBuff, 0, sizeof(ReBuff));
      result2 =0;            
        }
        if(flag==1)
     {
          HAL_UART_Transmit_DMA(&huart1,(uint8_t *)SendBuff,17);
            HAL_Delay(1000);
     }
  }
  /* USER CODE END 3 */

这里使用的strstr函数,用于查找子字符串在另一个字符串中的第一次出现,使用此函数时要添加下面的头文件才可以使用。

#include "string.h"
#include "stdio.h"

 这里使用的memset函数,用于清零数组。同样要加上述头文件。

下面是,HAL_UART_RxCpltCallback里触发中断后的操作

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//判断是串口1中断被触发
	{
		HAL_UART_Receive_DMA(&huart1, (uint8_t *)&ReBuff,5); //用于再次开启串口中断等待
	}
}

3.stm32f1xx_it.c

主要修改void USART1_IRQHandler(void),其他不需要修改。

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  /* 在每次进入中断后,判断是否为空闲中断 */
    if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)){
        /* 清除空闲标志位 */
        //__HAL_UART_CLEAR_FLAG(&uart1.uart, UART_FLAG_IDLE);
        __HAL_UART_CLEAR_IDLEFLAG(&huart1);
        /* 终止当前的接收(会把RxferCount清零) */
        HAL_UART_AbortReceive_IT(&huart1);//放弃串口1中断
        HAL_UART_Receive_DMA(&huart1, (uint8_t *)&ReBuff,5);//开启串口1中断
    }
  /* USER CODE END USART1_IRQn 1 */
}

      这里最后放弃串口1中断,是因为不放弃的话,比如串口1接收到长度为4的信号stop,这时候主函数中判断已经发生,且已经将接收缓冲数组中的值清零,但由于没有放弃串口1中断,导致继续接收的数据没有从缓冲数组的首位开始写,使得数据紊乱。所以需要重新关闭再开启接收中断。

      至此,软件部分编写完毕。

4.ATK-LORA-01无线串口的使用

1.使用该无线串口前,需要通过软件调整该串口的参数配置。

2.步骤如下:

(1)用UBS-TTL串口连接无线串口进行参数配置

连接MD0引脚后,在上位机按下

等待出现框中回复时,可进行配置,再按下“保存配置”时,配置成功!

注意!!!通讯中的两个ATK-LORA-01模块都要配置相同信道、波特率、地址、功率。

上位机软件如下:

通过网盘分享的文件:上位机软件.rar
链接: https://pan.baidu.com/s/1qQxlQT5BfZvN-iksfvM45g 提取码: ua25

总结:

       我们学习知识,要理解运用,将所用到的知识化为自己的知识才是重点。此外,串口通常只是单对单的通信,这一点上我认为不如IIC,希望这篇文章能够帮助到大家,谢谢!

       文章程序源码我发在下面了,需要自取。

通过网盘分享的文件:DMA-test1
链接: https://pan.baidu.com/s/1HVK7Me02YbYHvHsmysKrFA 提取码: ike8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值