STM32F103-入门基础实验-DMA_USART实验核心代码(固件库版)

1、DMA 简介

DMA(Direct Memory Access)—直接存储器存取,是单片机的一个外设,它的主要功能是用来搬数据,但是不需要占用 CPU,即在传输数据的时候,CPU 可以干其他的事情,数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道,DMA2 有 5 个通道。

2、编程要点
  1. 配置 USART 通信功能;
  2. 设置串口 DMA 工作参数;
  3. 使能 DMA;
  4. DMA 传输同时 CPU 可以运行其他任务。
3、实验目的

我们先定义一个要发送数据,存于 SRAM 中,然后通过 DMA 的方式传输到串口的数据寄存器,然后通过串口把这些数据发送到电脑的上位机显示出来。

话不多说,直接上代码~
上节讲过的知识点,在这节就不多讲了~
咱们重点是USART如何使用DMA传输~
/*=====================dma_usart.h==================*/
#ifndef __DMA_USART_H
#define __DMA_USART_H

#include "stm32f10x.h"
#include <stdio.h>


// 串口工作参数宏定义
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
    
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  USART_TX_DMA_CLK								RCC_AHBPeriph_DMA1// 串口发送的时钟
#define  USART_TX_DMA_CHANNEL           DMA1_Channel4		  // 串口对应的DMA请求通道4
#define  USART_DR_ADDRESS              (USART1_BASE+0x04)	// 外设寄存器地址
#define  USART_TX_DMA_FLAG_TC			DMA1_FLAG_GL4     // DMA1 通道4的转换标志
#define  SENDBUFF_SIZE           		5000							// 一次发送的数据量

void USART_Config(void);
void USARTx_DMA_Config(void);

#endif /* __DMA_USART_H */
/*=====================dma_usart.c==================*/
#include "dma_usart.h"

//定义8位的发送数据缓冲区
uint8_t SendBuff[SENDBUFF_SIZE];

/**
  * @brief  USART GPIO 配置,工作参数配置
  * @param  无
  * @retval 无
  */
void USART_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	// 打开串口GPIO的时钟
	DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
	
	// 打开串口外设的时钟
	DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

	// 将USART Tx的GPIO配置为推挽复用模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
	GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
	
	// 配置串口的工作参数
	// 配置波特率
	USART_InitStructure.USART_BaudRate = DEBUG_USART_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(DEBUG_USARTx, &USART_InitStructure);	
	
	// 使能串口
	USART_Cmd(DEBUG_USARTx, ENABLE);	    
}

void USARTx_DMA_Config(void)
{
		DMA_InitTypeDef DMA_InitStructure;
	
		// 开启串口DMA时钟
		RCC_AHBPeriphClockCmd(USART_TX_DMA_CLK, ENABLE);
		// 设置DMA源地址:串口数据寄存器地址*/
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;
		// 内存地址(要传输的变量的指针)
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SendBuff;
		// 方向:从内存到外设	
		DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	
		// 传输大小	
		DMA_InitStructure.DMA_BufferSize = SENDBUFF_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模式,一次或者循环模式
		DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
		//DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
		// 优先级:中	
		DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 
		// 禁止内存到内存的传输
		DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
		// 配置DMA通道		   
		DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStructure);	
		// 清除DMA1 通道4的转换标志
		DMA_ClearFlag(USART_TX_DMA_FLAG_TC	);
		// 使能DMA
		DMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
}

//重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
		/* 发送一个字节数据到串口 */
		USART_SendData(DEBUG_USARTx, (uint8_t) ch);
		
		/* 等待发送完毕 */
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}
//重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
		/* 等待串口输入数据 */
		while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(DEBUG_USARTx);
}

/*======================main.c=====================*/
// DMA 存储器到外设(串口)数据传输实验
#include "stm32f10x.h"   
#include "dma_usart.h"

extern uint8_t SendBuff[SENDBUFF_SIZE];

static void Delay(__IO uint32_t nCount)	 //简单的延时函数
{
	for(; nCount != 0; nCount--);
}

int main(void)
{
	uint16_t i;

	/* 初始化USART */
  USART_Config();
  /* 配置使用DMA模式 */
  USARTx_DMA_Config();
	
	/*填充将要发送的数据*/
  for(i=0;i<SENDBUFF_SIZE;i++)
  {
    SendBuff[i]	 = 'X';
  }
	
	/* USART1 向 DMA发出TX请求 */
  USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE);
	
	/* 此时CPU是空闲的,可以干其他的事情 */  
	while(1)
	{
			;
    }
}
如果大家觉得实验中一些寄存器的配置不是很明白,大家就拿出咱们吃饭的家伙数据手册来把实验中出现的寄存器在手册中查找,去理解。

欢迎大家的留言和评论我会在看到的第一时间内答复。

看完后感觉得到帮助的小伙伴,要点点赞哦~

给笔者一些动力嘛!谢谢啦~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: FreeRTOS是一个常用的嵌入式系统实时操作系统,它提供了多任务支持、时钟管理、任务切换等常见的操作系统功能。USART是串行通信接口,用于实现串行通信,DMA是直接内存访问。在使用FreeRTOS和USART进行数据发送时,如果使用DMA进行发送,可能会出现丢数据的情况。 造成丢数据的原因可能有很多,其中最常见的是DMA传输速度不能跟上CPU时间的速度,导致丢失部分数据。此时,可以通过调整DMA的传输速率或者增加内存大小的方式来解决。另外,还有可能是在数据发送过程中由于任务优先级的问题导致数据被中断,甚至任务切换时出现了问题,需要通过分析硬件、调整任务优先级等方式来解决。 为了避免丢数据问题,建议在使用FreeRTOS和USART进行数据发送时,需要注意以下几点: 1、配置好DMAUSART的中断使能和优先级设置。 2、DMA发送速率要保证跟上CPU的时间,避免数据丢失。 3、设置好任务优先级,优化任务调度,防止数据发送时被中断或间隔。 4、增加校验处理,保证数据发送的准确性和完整性。 在实际开发中,需要根据具体情况调整以上几个方面,以保证USART数据发送的准确性和稳定性。 ### 回答2: FreeRTOS是一个基于RTOS的嵌入式系统,它支持多个处理器安装,包括ARM,MIPS,PIC32等。USART是通用同步异步收发传输器的英文缩写,它是嵌入式系统中用来管理串行通信的基本部件。DMA是直接存储器访问的英文缩写,用于在系统内存和外设之间传输数据。 当使用FreeRTOS和USART DMA发送数据时,如果丢失一些数据,这可能是由于以下几个原因: 1.代码问题:可能存在一些代码问题,例如在发送调用之前或之后未正确初始化USARTDMA寄存器。 2.数据速率问题:数据传输的速率可能超出了USARTDMA的处理速率,导致一些数据未能及时传输。 3.数据传输过程中出现了中断:在数据传输过程中,如果发生过多的中断或错误中断,可能会导致数据丢失、传输失败等问题。 4.检查DMA缓冲区:在DMA缓冲区中可能存在数据未被正确清除的情况,导致数据丢失。 因此,为了避免数据丢失问题,需要仔细检查代码、数据传输速率、中断处理以及DMA缓冲区等方面,以确保数据能够正常传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数字梦想家

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值