DMA学习笔记 M2M M2P 代码实现
编程要点
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--);
}
DMA学习笔记 M2M M2P 代码实现相关推荐
- 【学习笔记】低代码平台(LCAP:Low-Code Application Platform)
学习笔记:低代码平台(LCAP:Low-Code Application Platform) [概念] 开发者写很少的代码,通过低代码平台提供的界面.逻辑.对象.流程等可视化编排工具来完成大量的开发工 ...
- 吴恩达《机器学习》学习笔记十一——神经网络代码
吴恩达<机器学习>学习笔记十一--神经网络代码 数据准备 神经网络结构与代价函数· 初始化设置 反向传播算法 训练网络与验证 课程链接:https://www.bilibili.com/v ...
- 0037 Java学习笔记-多线程-同步代码块、同步方法、同步锁
什么是同步 在上一篇0036 Java学习笔记-多线程-创建线程的三种方式示例代码中,实现Runnable创建多条线程,输出中的结果中会有错误,比如一张票卖了两次,有的票没卖的情况,因为线程对象被多条 ...
- 【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)
文章目录 什么是代理模式 一. 代理模式简介 二. 静态代理模式 三. 动态代理模式 万能模版 前言:笔记基于狂神设计模式视频.<大话设计模式>观后而写 (最近一直在更新之前的刷题博客,今 ...
- fmri学习笔记|SPM 代码 循环
目录 SPM 用代码跑操作(上) 第一步生成脚本 第二步 看一下生成的脚本结构 temp_smooth_job temp_smooth SPM 用代码跑操作(下) 下面记录怎么修改输入input和fo ...
- 卷起来了,写了一套计算机视觉学习笔记(20G/代码/PPT/视频)
AI 显然是最近几年非常火的一个新技术方向,从几年前大家认识到 AI 的能力,到现在产业里已经在普遍的探讨 AI 如何落地了. 我们可以预言未来在很多的领域,很多的行业,AI 都会在里边起到重要的作用 ...
- 李航统计学习方法----感知机章节学习笔记以及python代码
目录 1 感知机模型 2 感知机学习策略 2.1 数据集的线性可分性 2.2 感知机学习策略 3 感知机学习算法 3.1 感知机学习算法的原始形式 3.2 感知机算法的对偶形式 4 感知机算法pyth ...
- 【学习笔记】Tensorflow-ENet代码学习(一)
针对Tensorflow版ENet,记录一下自己对代码的理解. *非代码解读(因为水平不足),仅作为自己理解的备忘 **理解有误的地方,希望可以得到大牛的指点 一.文件夹内容(结构) (图片截取自作者 ...
- 正点原子STM32F103综合课程操作学习笔记(包含代码)
整理资料来源 [正点原子] 手把手教你学STM32单片机教学视频 嵌入式 之 F103-基于新战舰V NANO_STM32F103开发指南-HAL库版本_V1.0.pdf 其它网络操作等 词汇解释 p ...
最新文章
- 北京清华长庚医院与数据院签约,医工结合促医疗大健康发展
- 【面试】Java集合篇--图解HashMap的put方法的具体流程
- php创建windos用户,window_Win7系统创建及开启隐藏账户图文教程, 在电脑操作中有时候因为 - phpStudy...
- 服务器Ubuntu Import Error:cannot import name main
- HDOJ(HDU) 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
- Python 爬取了猫眼 47858 万条评论,告诉你《飞驰人生》值不值得看?!
- [BZOJ3696][FJSC2014]化合物(异或规则下的母函数)
- html执行严格语法标准,JS语法(ES6)
- springboot进行微信公众号相关开发:(二)获取微信公众号access_token用以微信公众号各功能接口的调用
- QT串口助手(五):文件操作
- 2012年8月编程语言排行榜-C领衔称霸Obj-C强势爬升
- 「冰狐智能辅助」如何实现在线实时调试?
- 微信声音锁会上传到服务器吗,微信声音锁:你再也不用担心忘记密码了
- 带“小弟”其实是一种投资
- 【ACWing】4246. 最短路径和
- python基础以及面向对象
- php联想输入,联想笔记本电脑键盘功能基础知识
- Excel转PDF如何解决显示不全的问题?
- 【嵌入式模块】常用扩展芯片及数据手册总结
- php函数有什么用,有用的的PHP函数