功能:采用DMA进行USART的发送,程序运行时,LED1亮灭交替,表示程序正在运行。
当按下KEY0时,产生一个下降沿触发中断,在中断函数中实现DMA的数据传输到USART1上。
//key.h
#ifndef __KEY_H__ #define __KEY_H__ #include "stm32f10x.h" void Key_Configuration(void); void EXTI4_IRQHandler(void); //中断 #endif
//key.c
#include "key.h" #include "MyTime.h" #include "bitband.h" #include "dma.h" void Key_Configuration(void) { GPIO_InitTypeDef GPIO_InitStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO,ENABLE); //GPIO_DeInit(GPIOE); //此处绝对不能使用GPIO_DeInit进行默认初始化,因为GPIOE在前的其他地方已经对其某些引脚进行初始化了,这里若使用默认初始化,则会清除之前进行的配置。切记切忌 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU ; //上拉输入 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; GPIO_Init(GPIOE,&GPIO_InitStruct); GPIO_SetBits(GPIOE,GPIO_Pin_4); GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);//将中断线4与GPIO引脚联系起来 EXTI_DeInit(); //第一次配置中断,可用默认配置,若之前有配置过EXTI,这里最好不要在用默认配置 EXTI_InitStruct.EXTI_Line = EXTI_Line4; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt ; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling ; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组 NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); } extern u32 DMA1_MEM_LEN; //传输数据长度 void EXTI4_IRQHandler(void) { MyDelay_ms(10); if(EXTI_GetITStatus(EXTI_Line4) == SET) { LED0 = !LED0; USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送 DMA_Start(DMA1_Channel4,DMA1_MEM_LEN); //开始一次DMA传输 while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET); //传输未结束 DMA_ClearFlag(DMA1_FLAG_TC4); EXTI_ClearITPendingBit(EXTI_Line4); } }
//dma.h
#ifndef __DMA_H__ #define __DMA_H__ #include "stm32f10x.h" void DMA_Configuration(u32 DMA_PeripheralBaseAddr,u32 DMA_MemoryBaseAddr,u32 DMA_BufferSize); void DMA_Start(DMA_Channel_TypeDef*DMA_CHx,u32 DMA1_MEM_LEN); #endif
//dma.c
#include "dma.h" void DMA_Configuration(u32 DMA_PeripheralBaseAddr,u32 DMA_MemoryBaseAddr,u32 DMA_BufferSize) { DMA_InitTypeDef DMA_InitStruct; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 ,ENABLE); DMA_DeInit(DMA1_Channel4); DMA_InitStruct.DMA_PeripheralBaseAddr = DMA_PeripheralBaseAddr; DMA_InitStruct.DMA_MemoryBaseAddr = DMA_MemoryBaseAddr; DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST ; DMA_InitStruct.DMA_BufferSize = DMA_BufferSize; DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable ; DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte ; DMA_InitStruct.DMA_Mode = DMA_Mode_Normal ; DMA_InitStruct.DMA_Priority = DMA_Priority_Medium ; DMA_InitStruct.DMA_M2M = DMA_M2M_Disable ; DMA_Init(DMA1_Channel4,&DMA_InitStruct); } void DMA_Start(DMA_Channel_TypeDef*DMA_CHx,u32 DMA1_MEM_LEN) { DMA_Cmd(DMA_CHx,DISABLE);//关闭 USART1 TX DMA1所指示的通道 DMA_SetCurrDataCounter(DMA1_Channel4,DMA1_MEM_LEN);//DMA通道的DMA缓存大小 DMA_Cmd(DMA_CHx,ENABLE);//开启 USART1 TX DMA1所指示的通道 }
//main.c
#include "bitband.h" #include "MyTime.h" #include "key.h" #include "gpio.h" #include "dma.h" #include "usart.h" u32 DMA1_MEM_LEN = 0; int main(void) { const unsigned char buf[]={"dma with usart demo!!\r\n"}; DMA1_MEM_LEN = sizeof(buf)/sizeof(buf[0]); MySysTick_Init(); GPIO_Configuration(); Key_Configuration(); USART_Configuration(); DMA_Configuration((u32)&USART1->DR,(u32)buf,DMA1_MEM_LEN); while(1) { LED1 = !LED1; MyDelay_ms(1000); } }
这样,当按下KEY0时,LED0就会翻转之前的状态,串口也能接受到字符串。
本文出自 “whatever957” 博客,请务必保留此出处http://whatever957.blog.51cto.com/6835003/1641888
原文地址:http://whatever957.blog.51cto.com/6835003/1641888