DMA存储器到外设代码讲解
实验目的:
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 void USARTx_DMA_Config(void); void USART_Config(void); #endif /* __BSP_DMA_MTP_H */
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) 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; DMA_Init(USART_TX_DMA_CHANNEL, &DMA_InitStruct); DMA_ClearFlag(USART_TX_DMA_FLAG_TC); DMA_Cmd(USART_TX_DMA_CHANNEL, ENABLE); }
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'; } USARTx_DMA_Config(); USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE); while (1) { LED1_TOGGLE Delay(0xFFFFF); } } void Delay(__IO uint32_t nCount) //简单的延时函数 { for(; nCount != 0; nCount--); }