DMA学习笔记 M2M M2P 代码实现

news/2024/12/29 16:48:30/

编程要点

1-初始化DMA初始化结构体。
2-熟读参考手册DMA章节(非常重要

M To M 编程要点
 1-在FLASH中定义好要传输的数据,在SRAM中定
义好用来接收FLASH数据的变量。
 2-初始化DMA,主要是配置DMA初始化结构体。
 3-编写比较函数。
 4-编写main函数。

bsp_dma_mtm.c:

#include "bsp_dma_mtm.h"/* 定义aSRC_Const_Buffer数组作为DMA传输数据源* const关键字将aSRC_Const_Buffer数组变量定义为常量类型* 表示数据存储在内部的FLASH中*/
const uint32_t aSRC_Const_Buffer[BUFFER_SIZE]= {0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80};
/* 定义DMA传输目标存储器* 存储在内部的SRAM中																		*/
uint32_t aDST_Buffer[BUFFER_SIZE];//typedef struct
//{
//  uint32_t DMA_PeripheralBaseAddr;   // 外设地址
//  uint32_t DMA_MemoryBaseAddr;       // 存储器地址
//  uint32_t DMA_DIR;                  // 传输方向
//  uint32_t DMA_BufferSize;           // 传输数目
//  uint32_t DMA_PeripheralInc;        // 外设地址增量模式
//  uint32_t DMA_MemoryInc;            // 存储器地址增量模式
//  uint32_t DMA_PeripheralDataSize;   // 外设数据宽度
//  uint32_t DMA_MemoryDataSize;       // 存储器数据宽度
//  uint32_t DMA_Mode;                 // 模式选择
//  uint32_t DMA_Priority;             // 通道优先级
//  uint32_t DMA_M2M;                  // 存储器到存储器模式
//}DMA_InitTypeDef;void MtM_DMA_Config(void)  //配置DMA	
{DMA_InitTypeDef DMA_InitStruct;RCC_AHBPeriphClockCmd(MTM_DMA_CLK, ENABLE); //开DMA1时钟DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)aSRC_Const_Buffer;  //外设即数组FLASH地址DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)aDST_Buffer;  //存储器即内部SRAM地址DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;  //方向P2MDMA_InitStruct.DMA_BufferSize = BUFFER_SIZE;  //一次传输32个DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable;  //发送数组,地址要增加DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;	//数据宽度-字DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;  //地址递增DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;  //也是字DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;  //模式:传一次DMA_InitStruct.DMA_Priority = DMA_Priority_High;  //高优先级DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;  //M2M使能DMA_Init(MTM_DMA_CHANNEL, &DMA_InitStruct);  //初始化 &取地址DMA_ClearFlag(MTM_DMA_FLAG_TC);  //清楚标志位DMA_Cmd(MTM_DMA_CHANNEL, ENABLE);  //使能DMA
}/** 比较函数* 判断指定长度的两个数据源是否完全相等,* 如果完全相等返回1,只要其中一对数据不相等返回0*/
uint8_t Buffercmp(const uint32_t* pBuffer, uint32_t* pBuffer1, uint16_t BufferLength)
{/* 数据长度递减 */while(BufferLength--){/* 判断两个数据源是否对应相等 */if(*pBuffer != *pBuffer1){/* 对应数据源不相等马上退出函数,并返回0 */return 0;}/* 递增两个数据源的地址指针 */pBuffer++;pBuffer1++;}/* 完成判断并且对应数据相对 */return 1;  
}

bsp_dma_mtm.h:

#ifndef __BSP_DMA_MTM_H
#define __BSP_DMA_MTM_H#include "stm32f10x.h"// 要发送的数据大小
#define BUFFER_SIZE     32#define  MTM_DMA_CLK       RCC_AHBPeriph_DMA1
#define  MTM_DMA_CHANNEL   DMA1_Channel6
#define  MTM_DMA_FLAG_TC   DMA1_FLAG_TC6void MtM_DMA_Config(void);
uint8_t Buffercmp(const uint32_t* pBuffer, uint32_t* pBuffer1, uint16_t BufferLength);#endif  /* __BSP_DMA_MTM_H */

main.c:

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_dma_mtm.h"extern const uint32_t aSRC_Const_Buffer[BUFFER_SIZE];
extern uint32_t aDST_Buffer[BUFFER_SIZE];#define SOFT_DELAY Delay(0x0FFFFF);void Delay(__IO u32 nCount); int main(void)
{	uint8_t status=0;/* LED 端口初始化 */LED_GPIO_Config();LED_YELLOW;  //黄灯等待Delay(0xFFFFFF);  //初始化延迟MtM_DMA_Config();  //DMA配置while( DMA_GetFlagStatus(MTM_DMA_FLAG_TC) == RESET );  //检查标志位  //传输是否完成status = Buffercmp(aSRC_Const_Buffer,aDST_Buffer,BUFFER_SIZE);if( status == 0 ){LED_RED;  //红灯失败}else{LED_GREEN;  //绿灯成功}while (1){}
}void Delay(__IO uint32_t nCount)	 //简单的延时函数
{for(; nCount != 0; nCount--);
}

M To P 编程要点
 1-初始化串口(从现有的例程移植过来)
 2-配置DMA初始化结构体。
 3-编写主函数(开启串口发送DMA请求)。

bsp_dma_mtp.c:

#include "bsp_dma_mtp.h"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);	    
}///重定向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);
}// Memory -> P (USART->DR) 发到串口DR寄存器配置
void USARTx_DMA_Config(void)
{DMA_InitTypeDef DMA_InitStruct;RCC_AHBPeriphClockCmd(USART_TX_DMA_CLK, ENABLE);  //开时钟DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)USART_DR_ADDRESS;  //串口地址DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)SendBuff;DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;DMA_InitStruct.DMA_BufferSize = SENDBUFF_SIZE;DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //地址不用增加DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	//字节单位DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;  //一次DMA_InitStruct.DMA_Priority = DMA_Priority_High;DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;  //no m2mDMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStruct);DMA_ClearFlag(USART_TX_DMA_FLAG_TC);  //清除标志位DMA_Cmd(USART_TX_DMA_CHANNEL, ENABLE);
}

bsp_dma_mtp.h:

#ifndef __BSP_DMA_MTP_H
#define __BSP_DMA_MTP_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
#define  USART_TX_DMA_FLAG_TC           DMA1_FLAG_TC4
#define  USART_DR_ADDRESS               (USART1_BASE+0x04)#define  SENDBUFF_SIZE                  5000  //发送5000个void USARTx_DMA_Config(void);
void USART_Config(void);
#endif  /* __BSP_DMA_MTP_H */

main.c:

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_dma_mtp.h"extern uint8_t SendBuff[SENDBUFF_SIZE];#define SOFT_DELAY Delay(0x0FFFFF);void Delay(__IO u32 nCount); /*** @brief  主函数* @param  无  * @retval 无*/
int main(void)
{	uint16_t i=0;/* LED 端口初始化 */LED_GPIO_Config();USART_Config();  //配置串口for(i=0; i<SENDBUFF_SIZE; i++){SendBuff[i] = 'P'; //初始化成字符 P}USARTx_DMA_Config();   //配置DMA //在这一步,DMA等待串口请求USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE);  //串口请求发送while (1){LED1_TOGGLEDelay(0xFFFFF);		}
}void Delay(__IO uint32_t nCount)	 //简单的延时函数
{for(; nCount != 0; nCount--);
}

http://www.ppmy.cn/news/647031.html

相关文章

【HTML+CSS兼容性】 li中插入img元素之间存在空隙BUG问题+解决方案 前端零基础必须知道的事情!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&#x1…

RA4M2开发(4)----读取HS3003数据,并在OLED上显示,串口打印

概述 HS3003是一种数字式温湿度传感器&#xff0c;可以测量环境中的温度和湿度。读取HS3003的数据需要连接传感器到一个数据采集系统&#xff0c;一般是微处理器或者单片机。以下是一个简单的读取HS3003数据的概述&#xff1a; 连接电路&#xff1a;将HS3003传感器连接到微处…

PHY M2

一些芯片资料常常遇到MAC MODE 和PHY MODE 不知什么意思&#xff1f; 一般以太网芯片中涉及&#xff0c;一般交换芯片&#xff08;比如ks8993吗&#xff0c;8305sb等&#xff09;可以选择两种模式&#xff0c;mac和phy。 应该就是针对不同的外部接口采用的不同模式吧&#xf…

Renesas瑞萨RA4M2和STM32 CAN通信

刚好拿到一块瑞萨开发板&#xff0c;捣鼓玩下CAN&#xff0c;顺便试下固件升级。 A4M2 工程创建 详细可以参考&#xff0c;我之前写的文章 Renesa 瑞萨 A4M2 移植文件系统FAT32 CAN0 配置信息&#xff0c;使能FIFO&#xff0c;接收标准帧 ID为0x50&#xff0c;数据帧。 代…

【算法】Reconstruct a 2-Row Binary Matrix 重构 2 行二进制矩阵

文章目录 Reconstruct a 2-Row Binary Matrix 重构 2 行二进制矩阵问题描述&#xff1a;分析代码 Tag Reconstruct a 2-Row Binary Matrix 重构 2 行二进制矩阵 问题描述&#xff1a; 给你一个 2 行 n 列的二进制数组&#xff1a; 矩阵是一个二进制矩阵&#xff0c;这意味着…

Flink 自定义源算子之 读取MySQL

1、功能说明&#xff1a; 在Flink 自定义源算子中封装jdbc来读取MySQL中的数据 2、代码示例 Flink版本说明&#xff1a;flink_1.13.0、scala_2.12 自定义Source算子&#xff0c;这里我们继承RichParallelSourceFunction&#xff0c;因为要使用open方法来初始化数据库连接对…

debian10新建文档_图解Debian 10(Buster)安装步骤

Debian 项目发布了它的最新稳定版 Debian 10&#xff0c;其代号是 “Buster”&#xff0c;这个发布版将获得 5 年的支持。Debian 10 可用于 32 位和 64 位系统。这个发布版带来很多新的特色&#xff0c;列出下面一些特色&#xff1a; 引入新的 Debian 10 的主题 “FutureProtot…

三星台式机计算机编号怎么看,[图文解析]手把手教你如何看懂硬盘编号

硬盘作为电脑传统三大零配件之一&#xff0c;直接负责存储用户的全部数据资料&#xff0c;一旦损坏或者出现故障&#xff0c;后果将非常严重。同时&#xff0c;硬盘在IT配件里算是一个精密产品&#xff0c;制造难度比内存、板卡等高出许多。硬盘内部是由机械和电子两大部件组成…