STM32F103ZET6串口使用USAR_TFLAG_IDLE空闲中断实现UART_DMA接收和发送不定长数据

2023-05-16

本文是实现STM32F103ZET6串口通过使用STM32的IDLE空闲中断(USAR_TFLAG_IDLE)实现UART_DMA接收和发送(Rx和Tx均通过DMA通道)不定长数据。本文实现了UART1_DMA、UART2_DMA、UART3_DMA、UART4_DMA,文末均有代码下载

本文以UART1_DMA为例。

一、为什么要使用 UART DMA 传输

直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。通俗的讲就是CPU不需要负责具体数据的收发,只要告诉DMA将一块数据从某处搬运到某处,搬完后,CPU再去使用。

二、STM32F103ZET6 DMA控制器

STM32F103ZET6有2个DMA控制器,UART1/2/3在DMA1控制器,UART4在DMA2控制器,UART5不支持DMA功能。

外设的DMA请求,可以通过设置相应外设寄存器中的控制位,被独立地开启或关闭。查询手册,STM32F103ZET6的DMA通道如下表,由表可知,UART1的TX是通道4,RX是通道5。

如图:

 代码:

(1)串口初始化

/**********************************************************************
  * @brief  USART1初始化
  * @param  null
  * @retval null
  **********************************************************************/
void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	//打开串口GPIO时钟
	USART1_GPIO_APBxClkCmd(USART1_GPIO_CLK, ENABLE);
	//打开串口外设时钟
	USART1_APBxClkCmd(USART1_CLK, ENABLE);
	//将USART_Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = USART1_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStructure);
	//将USART_Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = USART1_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStructure);
	//配置串口工作参数
	//配置波特率
	USART_InitStructure.USART_BaudRate = USART1_BAUDRATE;
	//配置针数数据字长
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	//配置停止位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	//配置校验位
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	//配置硬件流控制
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	//配置工作模式,收发一起
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	//完成串口初始化配置
	USART_Init(USART1, &USART_InitStructure);
	//配置串口中断优先级
	NVIC_Configuration(USART1_IRQ);
	//使能串口接收中断,接收一帧数据产生USART_IT_IDLE中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); 
    //使能串口接收中断,发送完一帧数据产生USART_IT_TC中断
	USART_ITConfig(USART1, USART_IT_TC,   ENABLE);
	//使能串口
	USART_Cmd(USART1, ENABLE);	    
}

 

(2)USARTx_TX DMA初始化

/**
  * @brief  USARTx TX DMA 配置,内存到外设(USART1->DR)
  * @param  null
  * @retval null
  */
void USART1_TX_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	DMA_DeInit(USART1_TX_DMA_CHANNEL);		//USART_TX_DMA

	//开启DMA时钟,DMA1
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	//设置DMA源地址,串口数据寄存器地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_ADDRESS;
	//内存地址(要传输的变量的指针)
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_TX_BUF;
	//方向:从内存到外设
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	//传输大小
	DMA_InitStructure.DMA_BufferSize = 0;
	//外设地址不增    
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	//内存地址自增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable ;
	//外设数据单位
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	//内存数据单位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;	 
	//DMA模式,一次或者循环模式
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
	//优先级:中
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 
	//禁止内存到内存传输
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	//配置DMA UART TX通道   
	DMA_Init(USART1_TX_DMA_CHANNEL, &DMA_InitStructure);		
	USART_DMACmd(USART1, USART_DMAReq_Tx , ENABLE);
	//使能DMA TX通道
	DMA_Cmd(USART1_TX_DMA_CHANNEL,DISABLE);
}

(3)USARTx_RX DMA初始化

/**
  * @brief  USARTx RX DMA 配置,外设到内存(USART1->DR)
  * @param  null
  * @retval null
  */
void USART1_RX_DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	DMA_DeInit(USART1_RX_DMA_CHANNEL);  // USART_TX_DMA

	//开启DMA时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	//设置DMA源地址,串口数据寄存器地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_ADDRESS;
	//内存地址(要传输的变量的指针)
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RX_BUF;
	//方向:外设到内存
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC ;
	//传输大小
	DMA_InitStructure.DMA_BufferSize = sizeof(USART1_RX_BUF);
	//外设地址不增   
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//
	//内存地址不增
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable ;//
	//外设数据单位
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//
	//内存数据单位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;	 
	//DMA模式,一次或者循环模式
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
	//优先级:中
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 
	//禁止内存到内存的传输  
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	// 配置DMA通道
	DMA_Init(USART1_RX_DMA_CHANNEL , &DMA_InitStructure);	
	USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
	//使能DMA_Rx通道
	DMA_Cmd(USART1_RX_DMA_CHANNEL,ENABLE);
}

(4)串口中断&DMA接收数据

/***********************************************************************
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  null
  * @retval null
  **********************************************************************/
static void NVIC_Configuration(uint8_t NVIC_IRQChannel)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	/* 嵌套向量中断控制器组选择 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
	/* 配置USART为中断源 */
	NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQChannel;
	/* 抢断优先级 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	/* 子优先级 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	/*使能中断 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	/* 初始化配置NVIC */
	NVIC_Init(&NVIC_InitStructure);
}





 /***********************************************************************
  * @brief  USART1中断
  * @param  null
  * @retval null
  **********************************************************************/
void USART1_IRQHandler(void)
{
	uint8_t clear = clear;
	//串口接收一次数据结束
	if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE) !=RESET )
	{
		clear = USART1->SR;
		clear = USART1->DR;
		//清除USART1空闲中断标志
		USART_ClearITPendingBit(USART1, USART_FLAG_IDLE);  
		USART1_Rx_Len = UART_BUF_SIZE - DMA_GetCurrDataCounter(USART1_RX_DMA_CHANNEL);
		//清除RX_DMA的传输寄存器
		USART1_DMA_RX_CLC(USART1_RX_DMA_CHANNEL);//RX
		
		//Todo
		//...
		//对收到的数据再此进行解析
		//本Demo将接收到的数据复制到发送数据,发送出去。即收发的数据原封不动发送出去
		//...
		
		USART1_Tx_Len = USART1_Rx_Len;
		memcpy(USART1_TX_BUF,USART1_RX_BUF,USART1_Rx_Len); 
		//发送数据
		USART1_DMA_SendBuf(USART1_TX_BUF, USART1_Tx_Len);
	}
	//数据发送完成中断
    if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)   
    {
		//清除数据发送完成中断
        USART_ClearITPendingBit(USART1, USART_IT_TC);  
		//关闭SART1 DMA Tx通道
        DMA_Cmd(USART1_TX_DMA_CHANNEL, DISABLE);    
		//初始化接收发送数组等
		USART1_Rx_Len = 0;
		USART1_Tx_Len = 0;
		memset(USART1_RX_BUF,0,UART_BUF_SIZE);
		memset(USART1_TX_BUF,0,UART_BUF_SIZE);
	}
}

(5)DMA发送数据

//开启一次DMA数据传输
void USART1_DMA_RX_CLC(DMA_Channel_TypeDef *DMA_CHx)
{ 
	DMA_Cmd(DMA_CHx, DISABLE );  //关闭SART1 TX DMA1所指示的通道      
 	DMA_SetCurrDataCounter(DMA_CHx,UART_BUF_SIZE);//设置DMA通道的DMA缓存大小
 	DMA_Cmd(DMA_CHx, ENABLE);  //使能USART1 TX DMA1所指示的通道
}

//USART1 DMA发送数据
void USART1_DMA_SendBuf(uint8_t *arr, uint8_t len)
{
	uint8_t sendLen= 0;
	if(len == 0)
	{		
		return;
	}
	
	sendLen = len > UART_BUF_SIZE ? UART_BUF_SIZE : len;	
    //判断DMA通道里是否还有数据,即上一帧数据是否发送完毕
    while(DMA_GetCurrDataCounter(USART1_TX_DMA_CHANNEL)); 
   
	if(arr) 
	{
		memcpy(USART1_TX_BUF, arr, sendLen);
	}
	//关闭USART1_DMA_Tx通道
    DMA_Cmd(USART1_TX_DMA_CHANNEL, DISABLE);
	//设置DMA_TX要传输的数据长度
    DMA_SetCurrDataCounter(USART1_TX_DMA_CHANNEL, sendLen); 
	//使能USART1 DMA Tx通道,发送数据
    DMA_Cmd(USART1_TX_DMA_CHANNEL, ENABLE);
}

-------------------------------------------------

代码下载:

(1)STM32F103ZET6 UART1_DMA收发不定长数据:

https://download.csdn.net/download/wangzhichunnihao/69328698

(2)STM32F103ZET6 UART2_DMA收发不定长数据:

https://download.csdn.net/download/wangzhichunnihao/69329351

(3)STM32F103ZET6 UART3_DMA收发不定长数据:

https://download.csdn.net/download/wangzhichunnihao/69330092

(4)STM32F103ZET6 UART4_DMA收发不定长数据:

STM32F103ZET6UART4_DMA收发不定长数据-嵌入式文档类资源-CSDN下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F103ZET6串口使用USAR_TFLAG_IDLE空闲中断实现UART_DMA接收和发送不定长数据 的相关文章

  • 匿名上位机使用方法分享--总体介绍

    不知不觉 xff0c 匿名科创已经走过了7个年头 xff0c 这里首先要感谢大家这么久以来对匿名的支持与帮助 xff01 匿名为了提供给大家一个更好的调试工具 xff0c 始终在维护开发我们的匿名上位机软件 xff0c 7年时间 xff0c
  • 匿名上位机使用方法分享--高级收码

    匿名上位机总体介绍移步 xff1a https blog csdn net wangjt1988 article details 83684188 本文视频介绍 xff1a https www bilibili com video av35
  • 匿名上位机使用方法分享--波形显示

    匿名上位机总体介绍移步 xff1a https blog csdn net wangjt1988 article details 83684188 波形显示可以说是上位机的功能重点 xff0c 是各种调试 数据分析的有力助手 xff0c 下
  • 匿名数传使用方法分享

    目录 欢迎使用匿名数传模块匿名数传的特点硬件介绍使用介绍指示灯连接匿名飞控建议 欢迎使用匿名数传模块 大家调试各种设备时 xff0c 一般用什么方式呢 xff1f 相比答案大多是上位机 43 串口的方式 如果您还在使用usb转串口芯片然后连
  • 匿名科创--X2212版到手飞套件介绍

    匿名科创到手飞X2212版 xff0c 使用朗宇X2212系列无刷电机 xff0c 配合特制的6mm正反螺纹螺旋桨安装柱 xff0c 可以同时兼容8寸普通螺旋桨和9寸9450自锁螺旋桨 优点 xff1a 可直接使用普通8寸螺旋桨 xff0c
  • vscode最皮实的C++格式化的配置方法

    1 安装C C 43 43 2 在vscode界面 xff0c 按 34 Ctrl 43 34 进入设置界面 xff0c 搜索Format 3 设置保存文件时 xff0c 按格式对代码排版 4 向下拉 xff0c 找到下图选项 xff0c
  • 通过openmv生成apriltag标签

    Apriltag官网提供的tag图片分辨率很低 xff0c 完全无法使用 xff0c 通过openmv生成apriltag标签 生成方法如下 xff1a openmv IDE的下载与安装 openmv官方提供了各种版本的IDE xff0c
  • 串口传输数据错位 的几种解决办法

    1 代码优化等级 2 使用晶振 晶振自身产生时钟信号 xff0c 为各种微处理芯片作时钟参考 无源晶振需要用CPU内部的振荡器信号差接线麻烦石英 gt 陶瓷有源晶振是一个完整的振荡器信号好接线简单灵活性较差 3 使用降低传输速率 xff1f
  • sip 认证分析

    SIP类似Http协议 其认证模式也一样 Http协议 xff08 RFC 2616 xff09 规定可以采用Basic模式和摘要模式 xff08 Digest schema xff09 RFC 2617 专门对两种认证模式做了规定 RFC
  • MicroPython移植

    MicroPython移植 1 目标板 stm32f407zgt6 2 下载移植准备 micropython源码 arm交叉编译工具 sudo apt get install git sudo apt get install gcc arm
  • 了解ESP32睡眠模式及其功耗

    陈拓翻译 2022 05 30 2022 05 30 原文 https lastminuteengineers com esp32 sleep modes power consumption 毫无疑问 xff0c ESP32是许多WiFi
  • 浅谈布隆过滤器

    什么是布隆过滤器 布隆过滤器是一种数据结构 xff0c 比较巧妙的概率型数据结构 xff08 probabilistic data structure xff09 xff0c 特点是高效地插入和查询 xff0c 可以用来告诉你 某样东西一定
  • 浅谈CGI基本原理和底层基本实现

    历史来由 xff1a 早期的Web服务器 xff0c 只能响应浏览器发来的HTTP静态资源的请求 xff0c 并将存储在服务器中的静态资源返回给浏览器 随着Web技术的发展 xff0c 逐渐出现了动态技术 xff0c 但是Web服务器并不能
  • linux的两种共享内存方式---mmap和shmat区别

    linux中的两种共享内存 一种是我们的IPC通信System V版本的共享内存 xff0c 另外的一种就是我们今天提到的存储映射I O xff08 mmap函数 xff09 在说mmap之前我们先说一下普通的读写文件的原理 xff0c 进
  • tcp发送窗口(滑动窗口)、拥塞窗口

    TCP发送窗口拥塞窗口试题分析 题目一 xff1a 来源2015年408计算机综合 试题链接 xff1a https www nowcoder com questionTerminal 3241441c88f04ab58585a187716
  • mktime函数性能分析

    mktime函数性能分析 1月 02 2019 in Linux环境高级编程 mktime函数性能分析 mktime是一个将break down时间 struct tm 转化为日历时间 time t 的转换函数 它的转换与struct tm
  • iptables原理和防火墙主要命令使用场景

    https www zsythink net archives 1764 朱双印的个人日志 xff0c 写的非常的通俗易懂 xff0c 好文章 https blog csdn net u011277123 article details 8
  • 链路mtu

    常常见到交换机和网卡说明中提到支持Jumbo Frame xff0c 但我一直对以太网的Jumbo Frame xff08 巨帧 xff09 如何使用不太理解 xff0c 今日在网上找到2则现摘录下来 xff0c 相信看了以后大家会有收获
  • eggjs

    https editor csdn net md not checkout 61 1 amp spm 61 1001 2014 3001 4503 https blog csdn net weixin 42304193 article de
  • mini6410上HelloQt4运行出现libQtGui.so.4: cannot open shared的原因

    主要原因是在3 3 3节中 xff0c 编写的环境变量搭建文件setqt4env中设置路径不对 export LD LIBRARY PATH 61 xff08 看看有没有文件中的目录 xff09 应该改成你所在的qt4 7目录中的lib目录

随机推荐

  • VINS技术路线与代码详解

    VINS技术路线 写在前面 xff1a 本文整和自己的思路 xff0c 希望对学习VINS或者VIO的同学有所帮助 xff0c 如果你觉得文章写的对你的理解有一点帮助 xff0c 可以推荐给周围的小伙伴们 xff0c 当然 xff0c 如果
  • 用MicroPython开发ESP32- 用Thonny写程序

    陈拓 2022 06 11 2022 06 12 1 简介 在 用MicroPython开发ESP32 固件烧写与测试 https zhuanlan zhihu com p 527291091 https blog csdn net che
  • 单片机 stm32 接收数据和处理

    背景 1 单片机串口接收数据处理 xff0c 这个代码已经过很多项目验证 xff0c 没有问题 用这个代码帮了好几个同事解决数据接收久了就异常 2 这个代码做到接收和处理分开 避免不必要的处理逻辑问题 3 也可用于网口tcp xff0c u
  • odroid Xu4介绍

    Odroid xu4介绍 下面对这块开发板做一下简单的介绍 xff0c 共需要用到的人参考 从参数上来看 xff0c ODROID XU4的整体性能基本和目前的中端智能手机差不多 xff0c 它搭载了主频
  • OdroidXu4开发环境搭建

    OdroidXu4开发环境搭建 一 烧录镜像 1 SD卡烧录 首先准备一张至少16G的sd卡 镜像可以在官网 xff1a http odroid com dokuwiki doku php id 61 en odroid xu4 softw
  • 大小端:字节序与比特序

    https blog csdn net fzy0201 article details 26876711 https blog csdn net qq 40334837 article details 89042607 前言 前两天被问到一
  • VLC Buffering机制介绍

    一 简介 了解一定播放器知识的同学应该都知道 xff0c 播放器内部是有缓存的 xff08 非直播场景 xff09 缓存的作用主要是解决生产者和消费者速度的不匹配 xff0c 给用户更好的使用体验 例如 xff0c 在网络不稳定的情况下 x
  • Linux静态库和动态库学习总结

    一 废话 之前由于工作需要 xff0c 要封装一个Linux加密解密转换的动态库 xff0c 这个之前只做过Windows下面的 xff0c Linux下面还真没有做过 xff0c 之后做了整一个晚上才算做好 xff0c 不过其中也学到了不
  • UART的FIFO功能

    经常听到UART的FIFO功能 xff0c 但是从来没有真正使用过和认真思考过它的作用 正好有客户用到这个功能 xff0c 在这里做个总结 FIFO 是 First In First Out 的缩写 xff0c 它是一个具有先入先出特点的缓
  • 《C语言内核深度解析》笔记(3):指针才是C语言的精髓

    第03章 指针才是C语言的精髓 3 2 指针 int a 61 10 int p 61 amp a 指针变量p和普通变量之间没有本质区别 xff0c 都是变量空间放了一个数值 xff0c 只是p里面的数值比较特殊 xff0c 是a空间的地址
  • 相机针孔模型----从世界坐标系,到相机坐标系,再到图像物理坐标系,最后到图像像素坐标系的转换过程解析

    看了很多讲解针孔相机模型中从世界坐标系 gt 到相机坐标系 gt 图像坐标系的文章 xff0c 心里的疑惑也逐渐展开 xff0c 现在总结一下自己的理解 xff1a 世界坐标系 相机坐标系 图像物理坐标系 图像像素坐标系在我的另一篇博文里已
  • D1 R32 – ESP32+Arduino CNC Shield控制步进电机

    陈拓 2023 04 01 2023 04 05 1 简介 在 Arduino Uno开发板 43 电机驱动扩展版CNC Shield V3 0硬件说明 https blog csdn net chentuo2000 article det
  • pixhawk当中关于NMEA类型的gps数据处理流程

    1 启动跟新gps的数据的任务是在ArduCopter cpp中scheduler tasks中 调用的速度是50hz 2 通过执行update GPS方法中的 3 调转到ap gps cpp中的update方法中 4 在update中通过
  • C++Eigen库的配置和基本使用

    1 配置 1 下载 http bitbucket org eigen eigen get 3 2 5 tar bz2 2 配置 文件夹名字较长 xff0c 解压后可重命名 xff0c 如我命名为eigen3 xff0c 把D program
  • C++:extern "c"用法解析

    引言 C 43 43 保留了一部分过程式语言的特点 xff0c 因而它可以定义不属于任何类的全局变量和函数 但是 xff0c C 43 43 毕竟是一种面向对象的程序设计语言 xff0c 为了支持函数的重载 xff0c C 43 43 对全
  • 堆栈的作用,以及存放的数据

    在计算机领域 xff0c 堆栈是一个不容忽视的概念 xff0c 但是很多人甚至是计算机专业的人也没有明确堆栈其实是两种数据结构 堆栈都是一种数据项按序排列的数据结构 xff0c 只能在一端 称为栈顶 top 对数据项进行插入和删除 要点 x
  • STM32 姿态传感器mpu6050的使用

    文章目录 特性引脚说明使用I2C软件 xff0c 驱动mpu6050手册中寄存器描述MPU6050初始化的步骤 xff1a 数据读取mpu6050输出的值 特性 MPU6050 xff0c 能同时检测三轴加速度 三轴陀螺仪 三轴角速度 的运
  • STM32 GPS定位

    文章目录 ATGM332D简介特性引脚接入串口通信NMEA 协议解析串口输出nmealib在linux下使用 ATGM332D简介 高性能 低功耗 GPS 北斗双模定位模块 特性 特性说明基本功能三维位置定位 经纬度 海拔 xff0c 测速
  • 树莓派笔记13:舵机云台(一)

    最近买了个小型舵机云台模块来玩 xff0c 淘宝上卖这个的挺多的 xff0c 一般三四十块钱 xff0c 很多还卖配套的摄像头 说是云台 xff0c 其实就是用两个舵机结合固定板做的支撑模块 xff0c 两个舵机分别控制左右和上下的转动 1
  • STM32F103ZET6串口使用USAR_TFLAG_IDLE空闲中断实现UART_DMA接收和发送不定长数据

    本文是实现STM32F103ZET6串口通过使用STM32的IDLE空闲中断 xff08 USAR TFLAG IDLE 实现UART DMA接收和发送 xff08 Rx和Tx均通过DMA通道 xff09 不定长数据 本文实现了UART1