STM32 - DMA 编程实践2 M2P
1. 实验设计:
Memory to Peripheral , Memory to 外设, 把内部SRAM的数据传输到串口外设,同时LED灯闪烁,演示DMA传数据不需要占用CPU
2. 编程要点
1)初始化USART;
2)初始化DMA,注意也需要初始化DMA外设的时钟;
3)编写主函数(开启串口发送DMA请求);
3 源码
完成相关宏定义
// 串口工作参数宏定义
#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// 串口对应的DMA请求通道
#define USART_TX_DMA_CHANNEL DMA1_Channel4
// 外设寄存器地址
#define USART_DR_ADDRESS (USART1_BASE+0x04)
// 一次发送的数据量
#define SENDBUFF_SIZE 5000void USART_Config(void);
void USARTx_DMA_Config(void);
配置USART, DMA 模式
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 Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}/****************** 发送8位的数组 ************************/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{uint8_t i;for(i=0; i<num; i++){/* 发送一个字节数据到USART */Usart_SendByte(pUSARTx,array[i]); }/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{unsigned int k=0;do {Usart_SendByte( pUSARTx, *(str + k) );k++;} while(*(str + k)!='\0');/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET){}
}/***************** 发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{uint8_t temp_h, temp_l;/* 取出高八位 */temp_h = (ch&0XFF00)>>8;/* 取出低八位 */temp_l = ch&0XFF;/* 发送高八位 */USART_SendData(pUSARTx,temp_h); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);/* 发送低八位 */USART_SendData(pUSARTx,temp_l); while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}///重定向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);
}/*** @brief USARTx TX DMA 配置,内存到外设(USART1->DR)* @param 无* @retval 无*/
void USARTx_DMA_Config(void)
{DMA_InitTypeDef DMA_InitStructure;// 开启DMA时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 设置DMA源地址:串口数据寄存器地址*/DMA_InitStructure.DMA_PeripheralBaseAddr = USART_DR_ADDRESS;// 内存地址(要传输的变量的指针)DMA_InitStructure.DMA_MemoryBaseAddr = (u32)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); // 使能DMADMA_Cmd (USART_TX_DMA_CHANNEL,ENABLE);
}
main 函数中调用相关代码,演示DMA搬数据的同时,CPU还能干其他事
extern uint8_t SendBuff[SENDBUFF_SIZE];void Delay(__IO uint32_t nCount) //简单的延时函数
{for(; nCount != 0; nCount--);
}int main(void)
{uint16_t i;/* 初始化USART */USART_Config(); /* 配置使用DMA模式 */USARTx_DMA_Config();/* 配置RGB彩色灯 */LED_GPIO_Config();//printf("\r\n USART1 DMA TX 测试 \r\n");/*填充将要发送的数据*/for(i=0;i<SENDBUFF_SIZE;i++){SendBuff[i] = 'P';}/*为演示DMA持续运行而CPU还能处理其它事情,持续使用DMA发送数据,量非常大,*长时间运行可能会导致电脑端串口调试助手会卡死,鼠标乱飞的情况,*或把DMA配置中的循环模式改为单次模式*/ /* USART1 向 DMA发出TX请求 */USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE);/* 此时CPU是空闲的,可以干其他的事情 */ //例如同时控制LEDwhile(1){LED1_TOGGLEDelay(0xFFFFF);}
}
实测有效
STM32 - DMA 编程实践2 M2P相关推荐
- STM32 DMA传输
STM32 DMA(Direct Memory Access)直接存储器访问 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输.无须CPU干预,数据可以通过DMA ...
- 【组队学习】【29期】1. 编程实践(数据可视化)
1. 编程实践(数据可视化) 航路开辟者:杨剑砺.杨煜.耿远昊.李运佳.居凤霞 领航员:范佳慧 航海士:杨剑砺.伊雪.肖桐.李晴晴.蔡婧旎 基本信息 开源内容:https://github.com/d ...
- 【组队学习】【26期】编程实践(Python办公自动化)
编程实践(Python办公自动化) 论坛版块: http://datawhale.club/c/team-learning/29-category/29 开源内容: https://github.co ...
- 【组队学习】【26期】编程实践(Django网站开发)
编程实践(Django网站开发) 论坛版块: http://datawhale.club/c/team-learning/28-category/28 开源内容: https://github.com ...
- 【组队学习】【23期】Datawhale编程实践(区块链)
编程实践(区块链) 开源内容:https://github.com/datawhalechina/team-learning-program/tree/master/Blockchain 基本信息 贡 ...
- [Java 并发] Java并发编程实践 思维导图 - 第一章 简单介绍
阅读<Java并发编程实践>一书后整理的思维导图.
- 《Java并发编程实践》学习笔记之一:基础知识
<Java并发编程实践>学习笔记之一:基础知识 1.程序与进程 1.1 程序与进程的概念 (1)程序:一组有序的静态指令,是一种静态概念: (2)进程:是一种活动,它是由一个动作序列组成 ...
- 郑捷《机器学习算法原理与编程实践》学习笔记(第七章 预测技术与哲学)7.1 线性系统的预测...
7.1.1 回归与现代预测 7.1.2 最小二乘法 7.1.3 代码实现 (1)导入数据 def loadDataSet(self,filename): #加载数据集X = [];Y = []fr = ...
- 《深入理解大数据:大数据处理与编程实践》一一3.3 HDFS文件存储组织与读写...
本节书摘来自华章计算机<深入理解大数据:大数据处理与编程实践>一书中的第3章,第3.3节,作者 主 编:黄宜华(南京大学)副主编:苗凯翔(英特尔公司),更多章节内容可以访问云栖社区&quo ...
最新文章
- 磁盘文件目录罗列和list控件的使用
- Win7中如何删除word模板
- 线程池的介绍及简单实现
- springBoot探索(2)——构建手脚架
- esp32原理图设计_第十一章 ESP32的PWM全彩LED灯显示
- python中head_python学习笔记[headfirst]
- C语言: const关键字与指针
- jsp include指令标签
- fullCalendar:中文API
- 【chrome】谷歌chrome浏览器离线安装包的获取及使用技巧
- 深度时空3D卷积神经网络用于交通预测
- serialVersionUID 问题处理
- 规范第三方支付易加大竞合关系
- 办公自动化:PDF文件合并器,用Python将多个PDF文件进行合并
- Windows/Linux 系统纯净镜像分享【来自I Tell You】
- Android技能树 — 树基础知识小结(一),kotlin开源项目
- me511完美刷GMS,可以使用android market,同步gmail联系人,使用google导航
- 什么时候建立数据库,怎么建立数据库?
- 嵌入式Linux学习规划
- NTC负温度系数的热敏电阻——通过ADC检测计算出相应温度值
热门文章
- 权限分配 html,如何为LightSwitch HTML移动客户端分配用户角色和权限
- [转载]VBS入门教程 VBS基础教程
- LabVIEW矩阵的基本应用
- 2021极术通讯-2021半导体产业链EDA行业研究报告
- win10-microsoft store卸载了怎么安装回来
- FreeSurfer皮层分割软件初学者学习必看内容
- java制作网易邮箱登录页面_Page Object实例(一) - Java + Selenium 登录163邮箱
- Python爬虫笔记——Pycharm的官网下载与安装教程
- 网易python公开课_如何批量获取网易公开课Request Url?
- 【懒人专用系列】Xind2TestCase的初步探坑