环形队列+DMA空闲中断+接收串口数据

这篇具有很好参考价值的文章主要介绍了环形队列+DMA空闲中断+接收串口数据。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.序言

本次实验利用环形队列+DMA空闲中断+串口。。通过这个实验可以非常深入的理解队列,DMA,串口的知识。如果你能自己实现掌握这个实验,那么你应该基本掌握了队列,DMA,串口的知识。

二.实验原理

本次使用的是用环形队列当缓冲器区接收串口数据。我们可以先区了解DMA的空闲中断。本次实验就是使用DMA空闲中断。这里就简单介绍一下,当串口接收到一帧数据后就会产生中断,那么如何判断数据是一帧呢?这里的判断机制就是,如果收到数据后,大概接收一个字节的时间,都没有接收到数据的话,就判断已经接收的数据是一帧。接收一帧数据后,串口就会产生空闲中断。同时DMA会把串口DR移位寄存器的值搬运到环形队列缓冲区。我们只需要在环形队列缓冲器拿数据即可。

三.实战是检验真理的唯一标准

仅仅通过理论,只能说你知道有这个东西,但是你可能并不会。下面我通过代码讲解也帮助深入理解理论。

3.1 usart1.c


void Usart1_Init(void)
{

    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	
  
	//USART1_TX   GPIOA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
    GPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA.9
   
  //USART1_RX	  GPIOA.10³õʼ»¯
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);//
  //Usart1 NVIC ÅäÖÃ
 	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=5 ;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷
  
  

	USART_InitStructure.USART_BaudRate = 115200
	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); 
    //使能空闲中断
    USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);
    //使能发送完成中断--通过串口发送数据
    USART_ITConfig(USART1, USART_IT_TC , ENABLE);
    USART_DMACmd(USART1, USART_DMAReq_Tx|USART_DMAReq_Rx, ENABLE);
    USART_Cmd(USART1, ENABLE);                    

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);		

	DMA_DeInit(DMA1_Channel5);
	//外设地址--串口1 的DR寄存器
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart1_Rx_Buffer; 
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 
	DMA_InitStructure.DMA_BufferSize = BSP_UART1_RX_SIZE; 
	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_InitStructure.DMA_Mode = DMA_Mode_Circular;  
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	//串口1的接收引脚为DAM1的通道5
	DMA_Init(DMA1_Channel5, &DMA_InitStructure);
	DMA_Cmd (DMA1_Channel5,ENABLE); 
   //初始化环形队列
	Fifo_Init(&Uart1_Rx_Fifo,Uart1_Rx_Buffer,BSP_UART1_RX_SIZE);

3.2 串口中断

void USART1_IRQHandler(void)
{ 
 //加上volatile 关键字只是为了防止警告
	volatile uint32_t temp = 0;
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	if(USART_GetITStatus(USART1,USART_IT_IDLE)!= RESET)//¿ÕÏÐÖжÏ
	{
	    //根据数据量数据入队列
	    //DMA_GetCurrDataCounter(DMA1_Channel5); 通道5还剩下多少个数据应该传输。
	    //初始化的时候设置的通道5传输多少数据。
		Uart1_Rx_Fifo.in = BSP_UART1_RX_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5);
	 //先读SR 再读DR 只是为了消除空闲中断标志位。手册上有说明
		temp = USART1->SR; 
		temp = USART1->DR;
		USART_ClearITPendingBit(USART1,USART_IT_IDLE);
	}

三.队列代码

代码可能看起来简单,但是不是那么容易理解。得自己慢慢体会,才能真正掌握,
而不是一昧的copy,不然出了问题也解决不了,自己代码水平也不能提高。

4.1 fifo.c

#include "sys.h"
#include "app_fifo.h"

//初始化
void Fifo_Init(FIFO_Type* fifo, uint8_t* buffer, uint16_t size)
{
	fifo->buffer = buffer;
	fifo->in = 0 ;
	fifo->out = 0;
	fifo->size = size;
}
//从队列中拿数据
uint16_t Fifo_Get(FIFO_Type* fifo, uint8_t* buffer, uint16_t len)
{
	uint16_t lenght;
	uint16_t in = fifo->in;	
	uint16_t i;
	lenght = (in + fifo->size - fifo->out)%fifo->size;
	if(lenght > len)
		lenght = len;
	for(i = 0; i < lenght; i++)
	{
		buffer[i] = fifo->buffer[(fifo->out + i)%fifo->size];
	}
	fifo->out = (fifo->out + lenght)%fifo->size;
	return lenght;
}

4.2 fifo.h

#ifndef	FIFO_H
#define	FIFO_H
#include "stm32f10x.h"
typedef struct {
	uint8_t* buffer;	
	uint16_t in;			
	uint16_t out;			
	uint16_t size;		
}FIFO_Type;

void Fifo_Init(FIFO_Type* fifo, uint8_t* buffer, uint16_t size);

uint16_t Fifo_Get(FIFO_Type* fifo, uint8_t* buffer, uint16_t len);

#endif	

五.结语

代码放出来的就是以上这些,都放上去也比较麻烦,同时也没什么意义。写这篇博客是想让大家有大致的思路以及参考代码,从而根据自己的项目或者需求区进行改动。最后,如果真的需要全部代码的可以私信博主!最好点点关注!!!文章来源地址https://www.toymoban.com/news/detail-641393.html

到了这里,关于环形队列+DMA空闲中断+接收串口数据的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 cubemx配置DMA+空闲中断接收不定长数据

    本篇文章给大家讲解一下DMA+串口空闲中断接收串口不定长数据,之前我们也是讲解过串口接收不定长数据的,那么本篇文章的话将使用DMA来接收不定长数据。 串口空闲中断是指在串口接收到数据后,在数据的传输结束之后,在一段连续的空闲时间内没有接收到新数据时触发

    2024年02月19日
    浏览(56)
  • STM32_串口中断接收数据_空闲中断

    引言: 1、串口中断接收数据首先要保证完整性(设置串口中断优先级) 2、串口中断接收数据要保证实时性(打开串口空闲中断——空闲时间是2个字节的时间) 3、串口中断接收+DMA缓存,等到需要处理时候在进行处理数据 方法一:直接利用stm32的RXNE和IDLE中断进行接收不定字

    2024年02月13日
    浏览(51)
  • STM32 F4串口空闲中断 + DMA实现数据发送

    最近在做 STM32 + ROS车的项目,STM32与ROS之间通信由于数据量大,所以在 STM32端 使用 空闲中断 + DMA 的方案来减轻 CPU 的压力。 一、空闲中断 空闲中断 顾名思义为空了,闲了,没事了进的中断,在 没有数据流 的时候会进入进行读取。 在我们串口进行发送时实则为连续发送,两

    2024年02月16日
    浏览(64)
  • 关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

             串口1相关的设置及printf函数的使用,这里没放,建议先实现串口打印功能 可以参考:使用STM32 CUBE IDE配置STM32F7 用DMA传输多通道ADC数据_stm32cubeide 配置adc_一只小白啊的博客-CSDN博客         普通模式和循环模式的区别在于,普通模式下,DMA只会接收一次数据,

    2024年02月05日
    浏览(62)
  • STM32实战(三):利用空闲中断从串口接收任意长数据

    “ 想起密码了,终于想起密码了(´・ω・`) ” 这次我们利用STM32F103的UART内部的空闲中断来实现对串口任意长数据的接收,通过简洁的手段解决了接收端在事前无法得知数据长度的问题。本次教程我们需要一块STM32核心板与一个USB转TTL工具。 STM32的异步串口接收寄存器可以存放

    2024年02月13日
    浏览(46)
  • STM32使用DMA传输UART空闲中断中接收的数据遇到的问题以及解决方法

    STM32使用DMA传输UART空闲中断中接收的数据遇到的问题以及解决方法 CubeMX配置 串口配置:使用默认配置(传输数据长度为8 Bit,奇偶检验无,停止位为1 Bit, 接收和发送都使能),因为我的是LIN项目所以使用的时串口的LIN模式,一般就是异步通信 打开DMA传输 打开串口接收中断

    2024年02月05日
    浏览(42)
  • stm32串口空闲中断+DMA传输接受不定长数据+letter shell 实现命令行

    空闲中断(IDLE),俗称帧中断,即第一帧数据接收完毕到第二帧数据开始接收期间存在一个空闲状态(每接收一帧数据后空闲标志位置1),检测到此空闲状态后即执行中断程序。 空闲中断的优点在于省去了帧头帧尾的检测 ,进入中断程序即意味着已经接收到一组完整数据,仅需

    2024年02月03日
    浏览(60)
  • STM32 cubemx+串口空闲中断+DMA双缓冲

            写这篇文章是为了记录下之前做过的项目中用到的一部分关键技术,之前做过的项目中涉及到 采用最小开销来实时接收遥控器数据、能够准确验证传输过来数据的准确性 ,减小误差率,要求能稳定适用于不同的环境。 目录 1、为什么要用到串口空闲中断? 2、为

    2024年02月09日
    浏览(63)
  • Stm32407串口1空闲中断+DMA收发(基于标准库实现)

    stm32串口的配置很简单,这里就不赘述了,使用 USART_SendData() 阻塞模式发送数据,或是接收中断配置 “接收缓冲区非空” USART_IT_RXNE ,这种做法效率很低,而且来一个数据中断一次数据处理起来也麻烦。 这里基于STM32F407提供一种串口空闲中断+DMA接收的方式,通过库函数编程

    2024年02月16日
    浏览(54)
  • STM32:串口轮询模式、中断模式、DMA模式和接收不定长数据

           在STM32每个串口的内部都有两个寄存器:发送数据寄存器(TDR)/发送移位寄存器,当我们调用HAL_UART_Transmit 把数据发送出去时,CPU会将数据依次将数据发送到数据寄存器中,移位寄存器中的数据会根据我们设置的比特率传化成高低电平从TX引脚输出。待发送移位寄存器中发

    2024年02月07日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包