ST芯片使用串口 + DMA接收 + 空闲中断处理,有USART1和LPUART

2023-11-13

普通串口:USART1

首先是DMA初始化

//DMA初始化
void MX_DMA_Init(void) 
{
  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB_EnableClock(LL_AHB_PERIPH_DMA); 
  
  /* DMA interrupt init */
  /* DMA_IRQn interrupt configuration */
  NVIC_SetPriority(DMA_IRQn, IRQ_CRITICAL_PRIORITY);
  NVIC_EnableIRQ(DMA_IRQn);  
	
	  /* USART1_RX Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_6, LL_DMAMUX_REQ_USART1_RX);
  
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
  
  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_HIGH);
  
  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_CIRCULAR);
  
  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT);
  
  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT);
  
  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_BYTE);
  
  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_BYTE);
	
	LL_DMA_ConfigAddresses(DMA1, 
                         LL_DMA_CHANNEL_6,
                         LL_USART_DMA_GetRegAddr(USART1, LL_USART_DMA_REG_DATA_RECEIVE),
                         (uint32_t)RamPara.RxBuffer,
                         LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6));

  LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_6, DMA_DATA_LEN);
	LL_DMA_ClearFlag_TC6(DMA1);	
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_6);
}

再是串口初始化:

void BSP_COM_init(void)
{
	
	LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

	LL_AHB_EnableClock(LL_AHB_PERIPH_GPIOA);

	LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_10);

	
	GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
	LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	 
  
  LL_APB1_EnableClock(LL_APB1_PERIPH_USART);
  
  GPIO_InitStruct.Pin = LL_GPIO_PIN_8|LL_GPIO_PIN_9;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	NVIC_SetPriority(USART1_IRQn, IRQ_HIGH_PRIORITY);
  NVIC_EnableIRQ(USART1_IRQn);
	}

再来个可以更改波特率的配置:

void BSP_COM_config(uint32_t BaudRate)
{

  LL_USART_DeInit(USART1);

	
	LL_USART_SetTransferDirection(USART1,LL_USART_DIRECTION_TX_RX);
	LL_USART_ConfigCharacter(USART1,LL_USART_DATAWIDTH_8B,LL_USART_PARITY_NONE,LL_USART_STOPBITS_1);
  LL_USART_SetBaudRate(USART1,LL_USART_PRESCALER_DIV1,LL_USART_OVERSAMPLING_16,BaudRate);

	

	
	
	LL_USART_Enable(USART1);

		  /* Enable DMA RX Interrupt */
	LL_USART_EnableIT_IDLE(USART1);
  LL_USART_EnableDMAReq_RX(USART1);
	

	
	USART2_485_reset();//这个是用485的时候才要

}

再来一个空闲中断处理:

#define DMA_DATA_LEN 8

static void USART_RxIdleCallback(void)
{

	if(LL_USART_IsActiveFlag_IDLE(USART1) != RESET)
	{
		LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_6);
		LL_USART_ClearFlag_IDLE(USART1);		
		LL_DMA_ClearFlag_TC6(DMA1);
		RamPara.DMA_Rx_Length = LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_6);
		if(RamPara.DMA_Rx_Length == DMA_DATA_LEN && (RamPara.RxBuffer[0] == 0x01 && RamPara.RxBuffer[1] == 0x03))
		{
			Uart_RxHandle(&UartAr.Prv.UartDrCB[UART_id_uart1],UART_id_uart1);		
		}
		else
		{
			RamPara.RxBuffer[0] = 0x0;
			RamPara.RxBuffer[1] = 0x0;
			LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_6,DMA_DATA_LEN);
		}		
		LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_6);
	}
		
}


//RamPara.RxBuffer这个就是全局变量,,设置一个大小就可以了,比如RxBuffer[10]


//最后丢进去就行了
void USART1_IRQHandler(void)
{

	USART_RxIdleCallback();

	BSP_Uart1IRQ();  //这个是发送中断的处理,,就是正常的那种,没用DMA,可以自行写一个
	
}

最后一个初始化顺序:

MX_DMA_Init();
	
BSP_COM_init(); 

BSP_COM_config(9600);

接下来是低功耗串口:LPUART

全部一起放了:跟上面结构一样

void MX_DMA_Init(void) 
{
  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB_EnableClock(LL_AHB_PERIPH_DMA); 
  
  /* DMA interrupt init */
  /* DMA_IRQn interrupt configuration */
  NVIC_SetPriority(DMA_IRQn, IRQ_CRITICAL_PRIORITY);
  NVIC_EnableIRQ(DMA_IRQn);  
	
	  /* USART1_RX Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_6, LL_DMAMUX_REQ_USART1_RX);
  
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
  
  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PRIORITY_HIGH);
  
  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MODE_CIRCULAR);
  
  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PERIPH_NOINCREMENT);
  
  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MEMORY_INCREMENT);
  
  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_PDATAALIGN_BYTE);
  
  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_6, LL_DMA_MDATAALIGN_BYTE);
	
	LL_DMA_ConfigAddresses(DMA1, 
                         LL_DMA_CHANNEL_6,
                         LL_USART_DMA_GetRegAddr(USART1, LL_USART_DMA_REG_DATA_RECEIVE),
                         (uint32_t)RamPara.RxBuffer,
                         LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_6));

  LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_6, DMA_DATA_LEN);
	LL_DMA_ClearFlag_TC6(DMA1);	
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_6);


	/* LPUART1_RX Init */
	LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_7, LL_DMAMUX_REQ_LPUART1_RX);
  
  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_7, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
  
  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PRIORITY_HIGH);
  
  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MODE_CIRCULAR);
  
  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PERIPH_NOINCREMENT);
  
  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MEMORY_INCREMENT);
  
  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_PDATAALIGN_BYTE);
  
  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_7, LL_DMA_MDATAALIGN_BYTE);
	
	LL_DMA_ConfigAddresses(DMA1, 
                         LL_DMA_CHANNEL_7,
                         LL_USART_DMA_GetRegAddr(LPUART1, LL_LPUART_DMA_REG_DATA_RECEIVE),
                         (uint32_t)RamPara.LPRxBuffer,
                         LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_7));

  LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_7, DMA_DATA_LEN);
	LL_DMA_ClearFlag_TC7(DMA1);
	
	LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_7);
	 
}


void BSP_COM_config(uint32_t BaudRate)
{

  LL_USART_DeInit(USART1);
	LL_LPUART_DeInit(LPUART1);

	
	LL_USART_SetTransferDirection(USART1,LL_USART_DIRECTION_TX_RX);
	LL_USART_ConfigCharacter(USART1,LL_USART_DATAWIDTH_8B,LL_USART_PARITY_NONE,LL_USART_STOPBITS_1);
  LL_USART_SetBaudRate(USART1,LL_USART_PRESCALER_DIV1,LL_USART_OVERSAMPLING_16,BaudRate);

	
	LL_LPUART_SetTransferDirection(LPUART1, LL_LPUART_DIRECTION_TX_RX);
  LL_LPUART_ConfigCharacter(LPUART1, LL_LPUART_DATAWIDTH_8B, LL_LPUART_PARITY_NONE, LL_LPUART_STOPBITS_1);
	LL_LPUART_SetBaudRate(LPUART1, LL_LPUART_PRESCALER_DIV1, BaudRate); 
	
	
	LL_USART_Enable(USART1);
	LL_LPUART_Enable(LPUART1);
		  /* Enable DMA RX Interrupt */
	LL_USART_EnableIT_IDLE(USART1);
  LL_USART_EnableDMAReq_RX(USART1);
	
	LL_LPUART_EnableIT_IDLE(LPUART1);
  LL_LPUART_EnableDMAReq_RX(LPUART1);
	
	USART2_485_reset();
	LP_UART1_485_reset();
}

void Configure_LPUART1(void)
{
	LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

	LL_AHB_EnableClock(LL_AHB_PERIPH_GPIOB);

	LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);

	//485¿ØÖÆÒý½ÅB0
	GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
	GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
	LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	LL_APB1_EnableClock(LL_APB1_PERIPH_LPUART);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_4|LL_GPIO_PIN_5;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  NVIC_SetPriority(LPUART1_IRQn, IRQ_HIGH_PRIORITY);
  NVIC_EnableIRQ(LPUART1_IRQn);

//  LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);  
//  LL_LPUART_EnableIT_ERROR(LPUART1);
}

static void LPUART_RxIdleCallback(void)
{

	if(LL_LPUART_IsActiveFlag_IDLE(LPUART1) != RESET)
	{
		LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_7);
		LL_LPUART_ClearFlag_IDLE(LPUART1);		
		LL_DMA_ClearFlag_TC7(DMA1);
		RamPara.LP_DMA_Rx_Length = LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_7);
		if(RamPara.LP_DMA_Rx_Length == DMA_DATA_LEN && (RamPara.LPRxBuffer[0] == 0x01 && RamPara.LPRxBuffer[1] == 0x03))
		{
			Uart_RxHandle(&UartAr.Prv.UartDrCB[UART_id_uart2] , UART_id_uart2);		
		}
		else
		{
			RamPara.LPRxBuffer[0] = 0x0;
			RamPara.LPRxBuffer[1] = 0x0;
			LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_7,DMA_DATA_LEN);
		}		
		LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_7);
	}	
}

void LPUART1_IRQHandler(void)
{
	LPUART_RxIdleCallback();
	
	BSP_Uart2IRQ();
}

//初始化

        MX_DMA_Init();
	
		BSP_COM_init();  				//usartºÍ485¿ØÖÆÒý½Å³õʼ»¯
	
		Configure_LPUART1();  	//lp_uartºÍ485¿ØÖÆÒý½Å³õʼ»¯
	
		BSP_COM_config(BaudRate_Talble[OptPara.BasePara.BaudRate]); //´®¿Ú²¨ÌØÂÊÅäÖÃ

 

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

ST芯片使用串口 + DMA接收 + 空闲中断处理,有USART1和LPUART 的相关文章

随机推荐

  • android 手机网络接入点名称及WAP、NET模式的区别

    移动 电信 联通 APN cmwap cmnet ctwap ctnet 3gwap uniwap 3gnet uninet设置 APN Access Point Name 即 接入点名称 用来标识GPRS的业务种类 目前分为两大类 CMW
  • PACS系统源码 PACS源码 基于VC + MSSQL开发

    基于VC MSSQL开发的一套大型医院医学影像PACS系统源码 有演示 文末获取联系 PACS系统可以覆盖医院现有放射 CT MR 核医学 超声 内镜 病理 心电等绝大部分DICOM和非DICOM检查设备 支持从科室级 全院级 集团医院级乃
  • @RequestMapping注解和Controller方法建立映射的流程

    当你的才华还撑不起你的野心的时候 唯有静下心来学习 有没有想过 为什么在controller类的方法上 添加一个 RequestMapping toIndex 注解的时候 从浏览器的输入localhost 8080 toIndex请求就可以
  • vscode 配置c/c++环境,与python共用。

    每个人的电脑路径因人而异 下面只是我的配置 仅供参 参考 vscode的安装以及插件软件的安装根据另一个博主的帖子 https blog csdn net weixin 44049923 article details 103619882
  • 小黄的刷题之路(十七)——码题集OJ赛-循环移位

    文章目录 一 题目 二 分析思路 2 1 审题理解 2 2 思路 三 代码实现 3 1 C 实现 四 总结 一 题目 二 分析思路 2 1 审题理解 给我们一个正整数序列 如果能够通过若干次循环左移调整成一个升序序列 那就输出 YES 否则
  • Unity2D--给动画添加关键帧并绑定事件

    关键帧 一添加关键帧 在Animation面板中添加关键帧 二给关键帧绑定事件 添加关键帧后可以先点击关键帧 然后在Inspector面板中绑定事件 Function为方法名
  • Filter实现权限过滤

    有这么一个简单的要求 用户只有登录才能进入主页 一旦退出就无法进入主页 看似好像生来就该如此但代码层次却不简单 首先要判断用户登录状态 然后拦截判断 后面还会学习拦截器 web文件夹下新建一个文件夹名为sys 该文件夹新建jsp页面名为su
  • Linux 查看磁盘空间

    1 查看当前目录的总大小 du sh ps du disk usage 2 查看某个目录的总大小 du sh 目录名 du后面可以跟的参数含义 a 列出所有的文件与目录容量 因为默认仅统计目录底下的文件量而已 h 以人们较易读的容量格式 G
  • Deep Learning 大体概念和事情

    0 深度学习为什么可能 因为一个事物的发生 其背后总有一个理型 或者叫做规律性 这个规律性就体现在原因与结果的作用关系里 把大多数原因和结果进行量化之后 结果与原因间存在一个数量关系方程 使得 结果 f 众原因 找出来这个大致的方程 f 便
  • 前端 Websocket + Stomp.js 的使用

    什么是Stomp STOMP即Simple or Streaming Text Orientated Messaging Protocol 简单 流 文本定向消息协议 它提供了一个可互操作的连接格式 允许STOMP客户端与任意STOMP消息
  • 【蓝桥OJ——C语言】顺子日期、特殊时间、乘积尾零

    文章目录 顺子日期 特殊时间 乘积尾零 总结 顺子日期 小明特别喜欢顺子 顺子指的就是连续的三个数字 123 456 等 顺子日期指的就是在日期的 yyyymmdd 表示法中 存在任意连续的三位数是一个顺子的日期 例如 20220123 就
  • 【Vue学习笔记】- 模板语法

    Vue模板语法分为两大类 插值语法 指令语法 插值语法 功能 作用于标签体内 目的是解析内容 写法 xxx xxx 是js表达式或data中的数据 指令语法 功能 作用于标签自身 可解析 标签属性 标签体内容 绑定事件 举例 v bind
  • java调第三方接口

    目录 背景 Spring的RestTemplate 1 引入依赖 2 RestTemplate配置类 3 RestTemplate实现类 背景 java调第三方接口我百度的有三种方法 第一种 通过JDK网络类Java net HttpURL
  • SpringBoot jar包的部署方式

    centos版本 CentOS Linux release 7 6 1810 Core JDK1 8 一 SpringBoot jar包的部署方式 nohup 后台进程形式 Linux脚本 启动形式 systemd 优雅系统服务形式 sys
  • Tomcat的日志切分和定时删除

    在我负责的一个小系统中 Linux环境下 由于默认日志都是写入在 cattalina out中 我查看日志catalina out 竟然已经到了 40G了 我想做一下 文件内容检索来追踪问题都无法进行 于是我决定删除以前的无用日志 以每日作
  • Qt 与外部exe进程间通信-基于操作系统的消息传递

    步骤 进程A 通过WindowAPI找到需要传递信息的窗口 然后通过windowAPI发送自定义的消息 其实本质上还是window操作系统定义的消息结构 只不过其中有个字段的值被设置成了自己特有的值 const ULONG PTR CUST
  • Java分割字符串(spilt())

    String 类的 split 方法可以按指定的分割符对目标字符串进行分割 分割后的内容存放在字符串数组中 该方法主要有如下两种重载形式 str split String sign str split String sign int lim
  • 学好了Python可以干什么?

    随着我国对编程的重视程度上升 Python编程的学习趋势逐渐低龄化 在全国掀起Python编程热的同时 还是有许多人对于学习Python抱有怀疑 那么我们就来看看学好了Python究竟可以干什么 根据目前就业市场的反馈 我们可以看到Pyth
  • Cscope的使用

    转载自 http blog csdn net dengxiayehu article details 6330200 首先在目录下建立cscope索引文件 find name c gt cscope file cscope Rbkq 这个命
  • ST芯片使用串口 + DMA接收 + 空闲中断处理,有USART1和LPUART

    普通串口 USART1 首先是DMA初始化 DMA初始化 void MX DMA Init void Init with LL driver DMA controller clock enable LL AHB EnableClock LL