STM32使用DMA+空闲中断方式实现串口数据接收

news2024/11/20 2:34:08

欢迎入群共同学习交流
时间记录:2024/5/23

一、概念介绍

(1)DMA:直接存储器存取(DMA)(Direct Memory Access)也是一个挂载在AHB总线上的外设,用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。两个DMA控制器有12个通道(DMA1有7个通道,DMA2(只存在于大容量和互联网产品中)有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权
(2)STM32F103C8T6单片机通道介绍
DMA1通道
DMA2通道

二、串口接收数据代码示例

(1)头文件

#ifndef __UART_H__
#define __UART_H__
#include "stm32f10x.h"

/**
 * DMA+空闲中断实现UART接收数据
*/

void vUart1Init(int baudrate);
void vUart1Send(u8 *data,int dataLen);
extern void (*vUart1Callback)(u8 *data,int dataLen);

#endif

(2)源文件

#include "uart.h"
#include "string.h"

#define RX_BUF_SIZE 64
static u8 rx_buf[RX_BUF_SIZE];
void (*vUart1Callback)(u8 *data,int dataLen);

void vUart1Init(int baudrate)
{
    //1.初始化串口1GPIO口
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);

    //2.初始化串口1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    
    USART_InitTypeDef USART_InitStruct;
    USART_InitStruct.USART_BaudRate = baudrate;
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(USART1,&USART_InitStruct);

    //3.初始化接收DMA通道
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
    
    DMA_InitTypeDef DMA_InitStruct;
    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART1->DR); //外设地址
    DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)rx_buf; //接收数据的内存地址
    DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA方向,外设到内存
    DMA_InitStruct.DMA_BufferSize = RX_BUF_SIZE; //缓冲区大小
    DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不自增
    DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址自增
    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 移动数据的大小
    DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; //模式,循环模式
    DMA_InitStruct.DMA_Priority = DMA_Priority_Medium; //DMA优先级
    DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; // 禁用内存到内存
    DMA_Init(DMA1_Channel5,&DMA_InitStruct);

    //4.初始化NVIC
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    //5.使能串口、空闲中断、DMA接收
    USART_Cmd(USART1,ENABLE);
    USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
    DMA_Cmd(DMA1_Channel5,ENABLE);
}

void vUart1Send(u8 *data,int dataLen)
{
    for(int i=0;i<dataLen;i++)
    {
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
        USART_SendData(USART1,data[i]);
        while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
    }
}

//中断服务函数
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET)
    {
        USART_ClearITPendingBit(USART1,USART_IT_IDLE);
        u8 temp = (u8)USART_ReceiveData(USART1);
        
        //处理接收数据
        DMA_Cmd(DMA1_Channel5,DISABLE);
        int recvLen = RX_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);
        vUart1Callback(rx_buf,recvLen);
        memset(rx_buf,0,sizeof(rx_buf));
        DMA_SetCurrDataCounter(DMA1_Channel5,RX_BUF_SIZE);
        DMA_Cmd(DMA1_Channel5,ENABLE);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1683194.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

超详细的前后端实战项目(Spring系列加上vue3)(一步步实现+源码)前端篇(一)

最近想着一步步搭建一个前后端项目&#xff0c;将每一步详细的做出来。&#xff08;如果有不足或者建议&#xff0c;也希望大佬们指出哦&#xff09; 前端初始化 1.根据vue脚手架创建vue项目 这里可以用很多方法创建vue项目&#xff0c;大家看着创建吧&#xff0c;只要能创建…

H4vdo 台湾APT-27视频投放工具

地址:https://github.com/MartinxMax/H4vdo 视频 关于 H4vdo RTMP lock 屏播放视频工具&#xff0c;可以向目标发送有效载荷&#xff0c;播放目标的屏幕内容。目标无法曹作计算机 使用方法 安装依赖 根据你的操作系统选择一个安装程序 RTMP 服务端 ./rtsp-simple-server.…

HiWoo Box边缘计算网关

​在数字化浪潮汹涌的今天&#xff0c;边缘计算网关成为了连接物理世界与数字世界的桥梁&#xff0c;其重要性日益凸显。HiWoo Box&#xff0c;作为一款功能强大的边缘计算网关&#xff0c;不仅具备了传统网关的基本功能&#xff0c;更在数据采集、处理、传输等方面展现出了卓越…

不闭合三维TSP:蛇优化算法SO求解不闭合三维TSP(起点固定,终点不定,可以更改数据集),MATLAB代码

旅行商从城市1出发&#xff0c;终点城市由算法求解而定 部分代码 close all clear clc global data load(data.txt)%导入TSP数据集 Dimsize(data,1)-1;%维度 lb-100;%下界 ub100;%上界 fobjFun;%计算总距离 SearchAgents_no100; % 种群大小&#xff08;可以修改&#xff09; …

【数据库基础】基本认识数据库--入门引导

文章目录 什么是数据库&#xff1f;主流数据库基本使用安装MySQL连接服务器服务器、数据库、表关系使用案例数据逻辑存储 MySQL架构SQL语句分类什么叫存储引擎 什么是数据库&#xff1f; 数据库是指在磁盘和内存中存储特定结构组织的数据。数据库通常用于存储于某个系统、组织或…

Python自带爬虫库urllib

一、什么是urllib 它是一个http请求的Python自带的标准库&#xff0c;无需安装&#xff0c;直接可以用。并且提供了如下功能&#xff1a;网页请求、响应获取、代理和cookie设置、异常处理、URL解析&#xff0c;可以说是一个比较强大的模块。 二、urllib模块 可分为以下模块&am…

2024中青杯数学建模C题:“X 疾病”在人群中的传播代码论文思路分析

2024中青杯数学建模C题论文和代码已完成&#xff0c;代码为C题全部问题的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1模型的建立和求解、问题2模型的建立和求解、问题3模型的建立和求解&#xff09;、模型的评价…

Docker Compose使用

Docker-Compose是什么 docker建议我们每一个容器中只运行一个服务,因为doker容器本身占用资源极少&#xff0c;所以最好是将每个服务单独分割开来&#xff0c;但是这样我们又面临了一个问题&#xff1a; 如果我需要同时部署好多个服务&#xff0c;难道要每个服务单独写Docker…

如何彻底搞懂迭代器(Iterator)设计模式?

说起迭代器&#xff08;Iterator&#xff09;&#xff0c;相信你并不会陌生&#xff0c;因为我们几乎每天都在使用JDK中自带的各种迭代器。那么&#xff0c;这些迭代器是如何构建出来的呢&#xff1f;就需要用到了今天内容要介绍的迭代器设计模式。在日常开发过程中&#xff0c…

刷题之将有序数组转换成二叉搜索树(leetcode)

将有序数组转换成二叉搜索树 正常递归&#xff0c;中序遍历 递归经常会把自己绕晕&#xff0c;还是得画图分析 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(null…

【LeetCode 随笔】面试经典 150 题【中等+困难】持续更新中。。。

文章目录 380.【中等】O(1) 时间插入、删除和获取随机元素238.【中等】除自身以外数组的乘积134.【中等】 加油站135.【困难】分发糖果42.【困难】接雨水 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面…

【Docker实操】启动redis服务

一、步骤 1、获取redis镜像 执行获取redis镜像命令&#xff1a;docker pull redis。打印镜像清单&#xff0c;可以看到新拉到的redis镜像。 2、创建redis.conf配置文件 linux主机 mkdir -p /root/www/redis/conf touch /root/www/redis/conf/redis.conf cat << EOF &…

vue中数据已经改变了,但是table里面内容没更新渲染!

解决方案&#xff1a; 给table或者el-table标签上添加一个动态key值&#xff0c;只要数据发生改变&#xff0c;key值变动一下即可 标签上&#xff1a; :key“timeStamp” 初始data&#xff1a;timeStamp:0, 更新数据&#xff1a;this.timeStamp 这样每次更新数据&#xff…

网络的基础理解

文章目录 网络的基础认识 网络协议协议分层OSI七层模型TCP/IP 五层/四层 模型 网络的基础认识 先来看下面几个问题 什么是网络&#xff1f; 网络就是有许多台设备包括计算机单不仅限于计算机&#xff0c;这些设备通过相互通信所组成起来系统&#xff0c;我们称之为网络所以如…

通过 Spring 操作 Redis

要想通过 Java 操作 redis&#xff0c;首先要连接上 redis 服务器&#xff0c;推荐看通过 Java 操作 redis -- 连接 redis 创建项⽬ 勾选 NoSQL 中的 Spring Data Redis 当然, 把 Web 中的 Spring Web 也勾选⼀下.⽅便写接进⾏后续测试. 配置 redis 服务地址 在 application.…

CF451E: Devu and Flowers(容斥原理 + 考虑反面 + golang组合模版)

题目截图 题目翻译 题目分析 正难则反&#xff0c;考虑所有不符合的例子 由于n很小&#xff0c;所以可以状态压缩二进制遍历完全部不符合例子的组合 对于不符合的例子&#xff0c;假设其中第i个不符合&#xff0c;那么就消耗掉fi 1个球 以此类推&#xff0c;减剩下s2个球 这时…

盘点28个免费域名申请大全

盘点28个免费域名申请大全 免费域名推荐学习使用&#xff0c;免费就意味着没任何保障。 名称稳定时间支持解析模式后缀格式说明地址EU.org28 年NS.eu.org/. 国家简写.eu.org需要审核&#xff0c;稳定性高&#xff0c;限制少&#xff0c;国内访问有问题&#xff0c;可 CFeu.orgp…

关于「公 告」根据中华人民共和国法律,Bing 在中国内地暂停 “搜索自动建议” 功能 30 天

当我看见我们大家都这样我可放心了&#xff0c;我打开电脑搜索图片就发生了。 当我看见我们大家都这样我可放心了&#xff0c;坐等攻城狮修复。

前端vue用el-table如何实现表头内容过长换行处理,实现换行效果

前端vue用el-table如何实现表头内容过长换行处理&#xff0c;实现换行效果 这是效果图 有两种方法&#xff0c;一种简易版本&#xff0c;一种万能方法,都是el-table&#xff0c;先看文档 表头标题是可以自定义的 方法一 label的解释写在代码里面了&#xff0c;这里会自动形成换…

六零导航页 file.php 任意文件上传漏洞复现(CVE-2024-34982)

0x01 产品简介 LyLme Spage(六零导航页)是中国六零(LyLme)开源的一个导航页面。致力于简洁高效无广告的上网导航和搜索入口,支持后台添加链接、自定义搜索引擎,沉淀最具价值链接,全站无商业推广,简约而不简单。 0x02 漏洞概述 六零导航页 file.php接口处任意文件上传…