STM32F4的USART1+DMA收发操作

具体原理我也不是很懂,经过不停的百度查阅资料最后终于成功了。

废话不多说,上代码:

 

  1 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  2 函数名称:DriveUsart1GpioInit
  3 函数功能:串口1GPIO初始化
  4 输入参数:BaudRate波特率
  5 返回参数:无
  6 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
  7 static void DriveUsart1GpioInit(uint32_t BaudRate)
  8 {
  9     GPIO_InitTypeDef  GPIO_InitStruct;
 10     USART_InitTypeDef  USART_InitStruct;
 11     NVIC_InitTypeDef NVIC_InitStructure;
 12 /****************************************初始化端口***********************************/
 13     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);                                    //使能GPIOA时钟
 14     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);                                    //使能USART1时钟
 15 
 16     GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);                                //将端口进行复用
 17     GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
 18 
 19     GPIO_InitStruct.GPIO_Mode     = GPIO_Mode_AF;
 20     GPIO_InitStruct.GPIO_OType  = GPIO_OType_PP;
 21     GPIO_InitStruct.GPIO_Pin         = GPIO_Pin_9 | GPIO_Pin_10;
 22     GPIO_InitStruct.GPIO_PuPd        = GPIO_PuPd_UP;
 23     GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
 24     GPIO_Init(GPIOA, &GPIO_InitStruct);                                                                            //初始化端口
 25 /****************************************初始化串口***********************************/
 26     USART_StructInit(&USART_InitStruct);
 27     USART_InitStruct.USART_BaudRate = BaudRate;
 28     USART_Init(USART1,&USART_InitStruct);                                                                        //初始化串口
 29     
 30     NVIC_InitStructure.NVIC_IRQChannel                                       = USART1_IRQn;     //IRQ通道
 31     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;                       //主优先级
 32     NVIC_InitStructure.NVIC_IRQChannelSubPriority               = 0;               //从优先级
 33     NVIC_InitStructure.NVIC_IRQChannelCmd                                  = ENABLE;          //使能通道
 34     NVIC_Init(&NVIC_InitStructure);
 35     USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);                                                        //配置串口中断
 36     USART_Cmd(USART1, ENABLE);
 37 }
 38 
 39 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 40 函数名称:DMA_USART1_TX_INIT
 41 函数功能:USART1+DMA发送初始化
 42 输入参数:无
 43 返回参数:无
 44 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
 45 static void  DMA_USART1_TX_INIT(void)
 46 {  
 47       DMA_InitTypeDef  DMA_InitStructure;
 48       NVIC_InitTypeDef NVIC_InitStructure;
 49       RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
 50     
 51       DMA_DeInit(DMA2_Stream7);
 52       while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);//等待DMA可配置 
 53         
 54     /* 配置DMA2 Stream7,USART1发送 */
 55       DMA_InitStructure.DMA_Channel            = DMA_Channel_4;               //通道选择
 56       DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;            //DMA外设地址
 57       DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)DMA_USART1_TX_BUF;      //DMA 存储器0地址
 58      DMA_InitStructure.DMA_DIR                = DMA_DIR_MemoryToPeripheral;  //存储器到外设模式
 59       DMA_InitStructure.DMA_BufferSize         = DMA_USART1_TX_BUF_LEN;       //数据传输量 
 60       DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;   //外设非增量模式
 61       DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;        //存储器增量模式
 62       DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位
 63       DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;     //存储器数据长度:8位
 64       DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;             //使用普通模式 
 65       DMA_InitStructure.DMA_Priority           = DMA_Priority_High;             //高等优先级
 66       DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;         
 67       DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull;
 68       DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;      //存储器突发单次传输
 69       DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;  //外设突发单次传输
 70         
 71       DMA_Init(DMA2_Stream7, &DMA_InitStructure);                             //初始化DMA Stream7
 72         DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);                                                    //DMA2传输完成中断
 73         USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);                               //使能USART1DMA发送
 74         
 75         NVIC_InitStructure.NVIC_IRQChannel                   = DMA2_Stream7_IRQn ;//串口1发送中断通道
 76         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;                 //抢占优先级
 77         NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;                          //子优先级
 78         NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;                      //IRQ通道使能
 79         NVIC_Init(&NVIC_InitStructure);
 80         
 81         while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE){}
 82         DMA_Cmd(DMA2_Stream7, DISABLE);                                                                                    //不使能
 83 }
 84 
 85 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 86 函数名称:DMA_USART1_RX_INIT
 87 函数功能:USART1+DMA接收初始化
 88 输入参数:无
 89 返回参数:无
 90 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
 91 static void  DMA_USART1_RX_INIT(void)
 92 {
 93         DMA_InitTypeDef  DMA_InitStructure;
 94         NVIC_InitTypeDef NVIC_InitStructure;
 95         RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能 
 96 
 97       DMA_DeInit(DMA2_Stream5);
 98         while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE);//等待DMA可配置 
 99       /* 配置 DMA2 Stream5,USART1接收 */
100         DMA_InitStructure.DMA_Channel            = DMA_Channel_4;               //通道选择
101       DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;            //DMA外设地址
102       DMA_InitStructure.DMA_Memory0BaseAddr    = (u32)DMA_USART1_RX_BUF;      //DMA 存储器0地址
103     DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;  //外设到存储器模式
104       DMA_InitStructure.DMA_BufferSize         = DMA_USART1_RX_BUF_LEN;       //数据传输量 
105     DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;   //外设非增量模式
106       DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;        //存储器增量模式
107       DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位
108       DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;     //存储器数据长度:8位
109       DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;             //使用普通模式 
110       DMA_InitStructure.DMA_Priority           = DMA_Priority_VeryHigh;        //中等优先级
111       DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;         
112       DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull;
113       DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;      //存储器突发单次传输
114       DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;  //外设突发单次传输
115       DMA_Init(DMA2_Stream5, &DMA_InitStructure);                             //初始化DMA Stream
116         
117         USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);                               //使能USART1DMA接收
118         
119         while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE){}
120         DMA_Cmd(DMA2_Stream5, ENABLE);
121 }
122 
123 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
124 函数名称:DriveUsart1Init
125 函数功能:USART1+DMA初始化
126 输入参数:BaudRate
127 返回参数:无
128 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
129 void DriveUsart1Init(uint32_t BaudRate)
130 {
131         DriveUsart1GpioInit(BaudRate);
132         DMA_USART1_TX_INIT();
133         DMA_USART1_RX_INIT();
134 }
135 
136 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
137 函数名称:USART1_IRQHandler
138 函数功能:USART1中断函数
139 输入参数:无
140 返回参数:无
141 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
142 void USART1_IRQHandler(void)
143 {
144         if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
145         {
146                 u8 clear=clear;
147                 clear = USART1->SR;
148                 clear = USART1->DR;       
149                 DMA_Cmd(DMA2_Stream5, DISABLE);                                                                                                 //关闭DMA,防止处理其间有数据 
150                 USART_ClearFlag(USART1, USART_FLAG_IDLE);                                                                          //清除IDLE标志
151                 USART1_RX_LEN = DMA_USART1_RX_BUF_LEN - DMA_GetCurrDataCounter(DMA2_Stream5);
152                 DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//清除DMA2_Steam5传输完成标志  
153                 DMA_SetCurrDataCounter(DMA2_Stream5, DMA_USART1_RX_BUF_LEN);
154                 DMA_Cmd(DMA2_Stream5, ENABLE);
155         }
156 
157       if(USART_GetFlagStatus(USART1,USART_IT_TXE) == RESET)                                                                                //串口发送完成
158       {
159                 USART_ITConfig(USART1,USART_IT_TC,DISABLE);
160         }
161 }
162 
163 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
164 函数名称:DMA2_Stream7_IRQHandler
165 函数功能:DMA中断
166 输入参数:无
167 返回参数:无
168 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
169 void DMA2_Stream7_IRQHandler(void)
170 {
171     //清除标志
172     if(DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7)!=RESET)                                    //等待DMA2_Steam7传输完成
173     {
174             DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);                                                     //清除DMA2_Steam7传输完成标志
175            DMA_Cmd(DMA2_Stream7,DISABLE);
176         USART_ITConfig(USART1,USART_IT_TC,ENABLE);                                                      //打开串口发送完成中断
177     }
178 }
179 
180 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
181 函数名称:DMA_USART1_Send
182 函数功能:串口发送数据
183 输入参数:data待发送数据  , size 发送数据字节数
184 返回参数:无
185 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
186 void DMA_USART1_Send(u8 *data,u16 size)
187 {
188     memcpy(DMA_USART1_TX_BUF,data,size);                                                                            //复制数据到DMA发送缓存区
189     while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);                                                //确保DMA可以被设置
190     DMA_SetCurrDataCounter(DMA2_Stream7,size);                                                                //设置数据传输长度
191     DMA_Cmd(DMA2_Stream7,ENABLE);                                                                                            //打开DMA数据流,开始发送
192 }

不出意外的话直接复制就可以使用。

参考文章:

  1、(2条消息) STM32F4使用DMA收发数据_u010001130的博客-CSDN博客

  2、(2条消息) STM32F4 USART1 使用DMA发送、接收数据_iTech#51122的博客-CSDN博客

原文地址:https://www.cnblogs.com/jiayezi/p/15092739.html