STM32F1xx DMA+USART1发送+接收+USART1空闲中断

STM32F1xx DMA+USART1发送+接收+USART1空闲中断

文章目录

  • STM32F1xx DMA+USART1发送+接收+USART1空闲中断
  • 编译器平台及例程说明
    • 编译器平台说明
    • 例程说明
  • 一、 DMA简介
  • 二、 DMA框图
  • 三、 DMA1/DMA2请求映像
  • 四、 DMA1/DMA2通道请求
  • 五、 DMA相关宏定义
    • 5.1 DMA传输方向
    • 5.2 DMA外设/存储器基地址自增模式
    • 5.3 DMA外设/存储器传输数据格式
    • 5.4 DMA传输模式
    • 5.4 DMA传输优先级
    • 5.5 DMA储存器与存储器间传输
    • 5.6 DMA状态标志
    • 5.7 DMA中断标志
  • 六、 DMA初始化
    • 6.1 DMA源文件
      • 6.1.1 DMA初始化
      • 6.1.2 DMA配置
      • 6.1.3 启动DMA通道传输
    • 6.2 DMA头文件
  • 七、 USART1初始化
    • 7.1 USART1源文件
      • 7.1.1 USARTx GPIO配置
      • 7.1.2 USARTx 波特率配置
      • 7.1.3 USARTx 初始化
      • 7.1.4 USART1 中断配置
      • 7.1.5 USART1 DMA配置
      • 7.1.6 IRQ NVIC配置
      • 7.1.7 USART初始化
      • 7.1.8 printf()重映射
      • 7.1.9 USART1中断服务
    • 7.2 USART1头文件
  • 八、 STM32F1xx DMA+USART1发送+接收+USART1空闲中断测试代码
  • 九、 运行结果

编译器平台及例程说明

编译器平台说明

1. Toolchain : MDK-ARM Community Version: 5.30.0.0(Kile V5)
2. Encoding  : Chinese GB2312(Simplified)
3. Device Specific Packs : Keil.STM32F1xx_DFP.2.3.0.pack
4. C/C++ Preprocessor Symbols : STM32F10X_HD,USE_STDPERIPH_DRIVER
   USE_STDPERIPH_DRIVER :允许使用标准外设驱动
   STM32F10X_HD         :STM32F10x大容量产品
5. Chip Type :STM32F103RET6, Flash:512KByte, ROM:48KByte, LQFP64
6. 在stm32hf10x.h文件中HSE_VALUE为外部高速振荡器,默认8MHZ。此值必须与硬件保持一致。

例程说明

1. 使用DMA1通道5,来传输USART1接收的数据,将数据存储在RXD1BUF中。
2. 使用DMA1通道4,来传输USART1发送的数据,要发送的数据存储在RXD1BUF中。
3. 使用USART1空闲中断,来通知数据已接收完成待处理,将接收到的数据原样转发到USART1,便于在串口调试助手中显示。
4. USART1空闲中断标志位无法直接用USART_ClearITPendingBit(USART1, USART_IT_IDLE)清除,必须读取SR和DR寄存器值可清除。
5. 使用DMA_GetCurrDataCounter()前,必须将DMA失能。

一、 DMA简介

DMA全称Direct Memory Access,即直接存储器访问。用来提供外设和存储器之间,或者存储器和存储器之间的高速数据传输。无须CPU控制,数据可以通过DMA传输,它通过硬件为RAM与I/O设备之间开辟一条直接传送数据的通道,这节省CPU的资源,使CPU效率提高。

二、 DMA框图

1. DMA2仅存在于大容量产品和互联型产品。
2. SPI/I2S3、 UART4、 TIM5、 TIM6、 TIM7和DAC的DMA请求仅存在于大容量产品和互联型产品。
3. ADC3、 SDIO和TIM8的DMA请求仅存在于大容量产品。
STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第1张图片

三、 DMA1/DMA2请求映像

DMA1控制器
从外设(TIMx[x=1、 2、 3、 4]、 ADC1、 SPI1、 SPI/I2S2、 I2Cx[x=1、 2]和USARTx[x=1、 2、 3])产生的7个请求,通过逻辑或输入到DMA1控制器,这意味着同时只能有一个请求有效。参见下图的DMA1请求映像。外设的DMA请求,可以通过设置相应外设寄存器中的控制位,被独立地开启或关闭。
STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第2张图片

DMA2控制器
从外设(TIMx[5、 6、 7、 8]、 ADC3、 SPI/I2S3、 UART4、 DAC通道1、 2和SDIO)产生的5个请求,经逻辑或输入到DMA2控制器,这意味着同时只能有一个请求有效。参见下图的DMA2请求映像。外设的DMA请求,可以通过设置相应外设寄存器中的DMA控制位,被独立地开启或关闭。

注意: DMA2控制器及相关请求仅存在于大容量产品和互联型产品中。

STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第3张图片

四、 DMA1/DMA2通道请求

DMA1通道请求
STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第4张图片

DMA2通道请求
STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第5张图片

五、 DMA相关宏定义

5.1 DMA传输方向

//DMA_data_transfer_direction 
#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)
#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)

5.2 DMA外设/存储器基地址自增模式

//DMA_peripheral_incremented_mode 
#define DMA_PeripheralInc_Enable           ((uint32_t)0x00000040)
#define DMA_PeripheralInc_Disable          ((uint32_t)0x00000000)


//DMA_memory_incremented_mode 
#define DMA_MemoryInc_Enable               ((uint32_t)0x00000080)
#define DMA_MemoryInc_Disable              ((uint32_t)0x00000000)

5.3 DMA外设/存储器传输数据格式

//DMA_peripheral_data_size 
#define DMA_PeripheralDataSize_Byte        ((uint32_t)0x00000000)
#define DMA_PeripheralDataSize_HalfWord    ((uint32_t)0x00000100)
#define DMA_PeripheralDataSize_Word        ((uint32_t)0x00000200)


//DMA_memory_data_size
#define DMA_MemoryDataSize_Byte            ((uint32_t)0x00000000)
#define DMA_MemoryDataSize_HalfWord        ((uint32_t)0x00000400)
#define DMA_MemoryDataSize_Word            ((uint32_t)0x00000800)

5.4 DMA传输模式

//DMA_circular_normal_mode 
#define DMA_Mode_Circular                  ((uint32_t)0x00000020)
#define DMA_Mode_Normal                    ((uint32_t)0x00000000)

5.4 DMA传输优先级

//DMA_priority_level 
#define DMA_Priority_VeryHigh              ((uint32_t)0x00003000)
#define DMA_Priority_High                  ((uint32_t)0x00002000)
#define DMA_Priority_Medium                ((uint32_t)0x00001000)
#define DMA_Priority_Low                   ((uint32_t)0x00000000)

5.5 DMA储存器与存储器间传输

//DMA_memory_to_memory 
#define DMA_M2M_Enable                     ((uint32_t)0x00004000)
#define DMA_M2M_Disable                    ((uint32_t)0x00000000)

5.6 DMA状态标志

// DMA1_FLAG_GL1: DMA1 Channel1 global flag.
// DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag.
// DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag.
// DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag.
// DMA1_FLAG_GL2: DMA1 Channel2 global flag.
// DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag.
// DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag.
// DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag.
// DMA1_FLAG_GL3: DMA1 Channel3 global flag.
// DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag.
// DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag.
// DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag.
// DMA1_FLAG_GL4: DMA1 Channel4 global flag.
// DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag.
// DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag.
// DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag.
// DMA1_FLAG_GL5: DMA1 Channel5 global flag.
// DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag.
// DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag.
// DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag.
// DMA1_FLAG_GL6: DMA1 Channel6 global flag.
// DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag.
// DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag.
// DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag.
// DMA1_FLAG_GL7: DMA1 Channel7 global flag.
// DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag.
// DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag.
// DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag.
// DMA2_FLAG_GL1: DMA2 Channel1 global flag.
// DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag.
// DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag.
// DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag.
// DMA2_FLAG_GL2: DMA2 Channel2 global flag.
// DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag.
// DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag.
// DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag.
// DMA2_FLAG_GL3: DMA2 Channel3 global flag.
// DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag.
// DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag.
// DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag.
// DMA2_FLAG_GL4: DMA2 Channel4 global flag.
// DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag.
// DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag.
// DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag.
// DMA2_FLAG_GL5: DMA2 Channel5 global flag.
// DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag.
// DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag.
// DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag.


//DMA_flags_definition
#define DMA1_FLAG_GL1                      ((uint32_t)0x00000001)
#define DMA1_FLAG_TC1                      ((uint32_t)0x00000002)
#define DMA1_FLAG_HT1                      ((uint32_t)0x00000004)
#define DMA1_FLAG_TE1                      ((uint32_t)0x00000008)
#define DMA1_FLAG_GL2                      ((uint32_t)0x00000010)
#define DMA1_FLAG_TC2                      ((uint32_t)0x00000020)
#define DMA1_FLAG_HT2                      ((uint32_t)0x00000040)
#define DMA1_FLAG_TE2                      ((uint32_t)0x00000080)
#define DMA1_FLAG_GL3                      ((uint32_t)0x00000100)
#define DMA1_FLAG_TC3                      ((uint32_t)0x00000200)
#define DMA1_FLAG_HT3                      ((uint32_t)0x00000400)
#define DMA1_FLAG_TE3                      ((uint32_t)0x00000800)
#define DMA1_FLAG_GL4                      ((uint32_t)0x00001000)
#define DMA1_FLAG_TC4                      ((uint32_t)0x00002000)
#define DMA1_FLAG_HT4                      ((uint32_t)0x00004000)
#define DMA1_FLAG_TE4                      ((uint32_t)0x00008000)
#define DMA1_FLAG_GL5                      ((uint32_t)0x00010000)
#define DMA1_FLAG_TC5                      ((uint32_t)0x00020000)
#define DMA1_FLAG_HT5                      ((uint32_t)0x00040000)
#define DMA1_FLAG_TE5                      ((uint32_t)0x00080000)
#define DMA1_FLAG_GL6                      ((uint32_t)0x00100000)
#define DMA1_FLAG_TC6                      ((uint32_t)0x00200000)
#define DMA1_FLAG_HT6                      ((uint32_t)0x00400000)
#define DMA1_FLAG_TE6                      ((uint32_t)0x00800000)
#define DMA1_FLAG_GL7                      ((uint32_t)0x01000000)
#define DMA1_FLAG_TC7                      ((uint32_t)0x02000000)
#define DMA1_FLAG_HT7                      ((uint32_t)0x04000000)
#define DMA1_FLAG_TE7                      ((uint32_t)0x08000000)

#define DMA2_FLAG_GL1                      ((uint32_t)0x10000001)
#define DMA2_FLAG_TC1                      ((uint32_t)0x10000002)
#define DMA2_FLAG_HT1                      ((uint32_t)0x10000004)
#define DMA2_FLAG_TE1                      ((uint32_t)0x10000008)
#define DMA2_FLAG_GL2                      ((uint32_t)0x10000010)
#define DMA2_FLAG_TC2                      ((uint32_t)0x10000020)
#define DMA2_FLAG_HT2                      ((uint32_t)0x10000040)
#define DMA2_FLAG_TE2                      ((uint32_t)0x10000080)
#define DMA2_FLAG_GL3                      ((uint32_t)0x10000100)
#define DMA2_FLAG_TC3                      ((uint32_t)0x10000200)
#define DMA2_FLAG_HT3                      ((uint32_t)0x10000400)
#define DMA2_FLAG_TE3                      ((uint32_t)0x10000800)
#define DMA2_FLAG_GL4                      ((uint32_t)0x10001000)
#define DMA2_FLAG_TC4                      ((uint32_t)0x10002000)
#define DMA2_FLAG_HT4                      ((uint32_t)0x10004000)
#define DMA2_FLAG_TE4                      ((uint32_t)0x10008000)
#define DMA2_FLAG_GL5                      ((uint32_t)0x10010000)
#define DMA2_FLAG_TC5                      ((uint32_t)0x10020000)
#define DMA2_FLAG_HT5                      ((uint32_t)0x10040000)
#define DMA2_FLAG_TE5                      ((uint32_t)0x10080000)

5.7 DMA中断标志

// DMA1_IT_GL1: DMA1 Channel1 global interrupt.
// DMA1_IT_TC1: DMA1 Channel1 transfer complete interrupt.
// DMA1_IT_HT1: DMA1 Channel1 half transfer interrupt.
// DMA1_IT_TE1: DMA1 Channel1 transfer error interrupt.
// DMA1_IT_GL2: DMA1 Channel2 global interrupt.
// DMA1_IT_TC2: DMA1 Channel2 transfer complete interrupt.
// DMA1_IT_HT2: DMA1 Channel2 half transfer interrupt.
// DMA1_IT_TE2: DMA1 Channel2 transfer error interrupt.
// DMA1_IT_GL3: DMA1 Channel3 global interrupt.
// DMA1_IT_TC3: DMA1 Channel3 transfer complete interrupt.
// DMA1_IT_HT3: DMA1 Channel3 half transfer interrupt.
// DMA1_IT_TE3: DMA1 Channel3 transfer error interrupt.
// DMA1_IT_GL4: DMA1 Channel4 global interrupt.
// DMA1_IT_TC4: DMA1 Channel4 transfer complete interrupt.
// DMA1_IT_HT4: DMA1 Channel4 half transfer interrupt.
// DMA1_IT_TE4: DMA1 Channel4 transfer error interrupt.
// DMA1_IT_GL5: DMA1 Channel5 global interrupt.
// DMA1_IT_TC5: DMA1 Channel5 transfer complete interrupt.
// DMA1_IT_HT5: DMA1 Channel5 half transfer interrupt.
// DMA1_IT_TE5: DMA1 Channel5 transfer error interrupt.
// DMA1_IT_GL6: DMA1 Channel6 global interrupt.
// DMA1_IT_TC6: DMA1 Channel6 transfer complete interrupt.
// DMA1_IT_HT6: DMA1 Channel6 half transfer interrupt.
// DMA1_IT_TE6: DMA1 Channel6 transfer error interrupt.
// DMA1_IT_GL7: DMA1 Channel7 global interrupt.
// DMA1_IT_TC7: DMA1 Channel7 transfer complete interrupt.
// DMA1_IT_HT7: DMA1 Channel7 half transfer interrupt.
// DMA1_IT_TE7: DMA1 Channel7 transfer error interrupt.
// DMA2_IT_GL1: DMA2 Channel1 global interrupt.
// DMA2_IT_TC1: DMA2 Channel1 transfer complete interrupt.
// DMA2_IT_HT1: DMA2 Channel1 half transfer interrupt.
// DMA2_IT_TE1: DMA2 Channel1 transfer error interrupt.
// DMA2_IT_GL2: DMA2 Channel2 global interrupt.
// DMA2_IT_TC2: DMA2 Channel2 transfer complete interrupt.
// DMA2_IT_HT2: DMA2 Channel2 half transfer interrupt.
// DMA2_IT_TE2: DMA2 Channel2 transfer error interrupt.
// DMA2_IT_GL3: DMA2 Channel3 global interrupt.
// DMA2_IT_TC3: DMA2 Channel3 transfer complete interrupt.
// DMA2_IT_HT3: DMA2 Channel3 half transfer interrupt.
// DMA2_IT_TE3: DMA2 Channel3 transfer error interrupt.
// DMA2_IT_GL4: DMA2 Channel4 global interrupt.
// DMA2_IT_TC4: DMA2 Channel4 transfer complete interrupt.
// DMA2_IT_HT4: DMA2 Channel4 half transfer interrupt.
// DMA2_IT_TE4: DMA2 Channel4 transfer error interrupt.
// DMA2_IT_GL5: DMA2 Channel5 global interrupt.
// DMA2_IT_TC5: DMA2 Channel5 transfer complete interrupt.
// DMA2_IT_HT5: DMA2 Channel5 half transfer interrupt.
// DMA2_IT_TE5: DMA2 Channel5 transfer error interrupt.



//DMA_interrupts_definition 
#define DMA1_IT_GL1                        ((uint32_t)0x00000001)
#define DMA1_IT_TC1                        ((uint32_t)0x00000002)
#define DMA1_IT_HT1                        ((uint32_t)0x00000004)
#define DMA1_IT_TE1                        ((uint32_t)0x00000008)
#define DMA1_IT_GL2                        ((uint32_t)0x00000010)
#define DMA1_IT_TC2                        ((uint32_t)0x00000020)
#define DMA1_IT_HT2                        ((uint32_t)0x00000040)
#define DMA1_IT_TE2                        ((uint32_t)0x00000080)
#define DMA1_IT_GL3                        ((uint32_t)0x00000100)
#define DMA1_IT_TC3                        ((uint32_t)0x00000200)
#define DMA1_IT_HT3                        ((uint32_t)0x00000400)
#define DMA1_IT_TE3                        ((uint32_t)0x00000800)
#define DMA1_IT_GL4                        ((uint32_t)0x00001000)
#define DMA1_IT_TC4                        ((uint32_t)0x00002000)
#define DMA1_IT_HT4                        ((uint32_t)0x00004000)
#define DMA1_IT_TE4                        ((uint32_t)0x00008000)
#define DMA1_IT_GL5                        ((uint32_t)0x00010000)
#define DMA1_IT_TC5                        ((uint32_t)0x00020000)
#define DMA1_IT_HT5                        ((uint32_t)0x00040000)
#define DMA1_IT_TE5                        ((uint32_t)0x00080000)
#define DMA1_IT_GL6                        ((uint32_t)0x00100000)
#define DMA1_IT_TC6                        ((uint32_t)0x00200000)
#define DMA1_IT_HT6                        ((uint32_t)0x00400000)
#define DMA1_IT_TE6                        ((uint32_t)0x00800000)
#define DMA1_IT_GL7                        ((uint32_t)0x01000000)
#define DMA1_IT_TC7                        ((uint32_t)0x02000000)
#define DMA1_IT_HT7                        ((uint32_t)0x04000000)
#define DMA1_IT_TE7                        ((uint32_t)0x08000000)

#define DMA2_IT_GL1                        ((uint32_t)0x10000001)
#define DMA2_IT_TC1                        ((uint32_t)0x10000002)
#define DMA2_IT_HT1                        ((uint32_t)0x10000004)
#define DMA2_IT_TE1                        ((uint32_t)0x10000008)
#define DMA2_IT_GL2                        ((uint32_t)0x10000010)
#define DMA2_IT_TC2                        ((uint32_t)0x10000020)
#define DMA2_IT_HT2                        ((uint32_t)0x10000040)
#define DMA2_IT_TE2                        ((uint32_t)0x10000080)
#define DMA2_IT_GL3                        ((uint32_t)0x10000100)
#define DMA2_IT_TC3                        ((uint32_t)0x10000200)
#define DMA2_IT_HT3                        ((uint32_t)0x10000400)
#define DMA2_IT_TE3                        ((uint32_t)0x10000800)
#define DMA2_IT_GL4                        ((uint32_t)0x10001000)
#define DMA2_IT_TC4                        ((uint32_t)0x10002000)
#define DMA2_IT_HT4                        ((uint32_t)0x10004000)
#define DMA2_IT_TE4                        ((uint32_t)0x10008000)
#define DMA2_IT_GL5                        ((uint32_t)0x10010000)
#define DMA2_IT_TC5                        ((uint32_t)0x10020000)
#define DMA2_IT_HT5                        ((uint32_t)0x10040000)
#define DMA2_IT_TE5                        ((uint32_t)0x10080000)

六、 DMA初始化

6.1 DMA源文件

6.1.1 DMA初始化

u8 RXD1BUF[RXD1_BUF_SIZE] = {
     0};
/**********************************************************************************************************************************************
 * 函数名 : vDMA_Init
 * 描  述 : DMA初始化
 * 说  明 : 1. DMA1_Channel5 ==> USART1_RXD
 * 			2. DMA1_Channel4 ==> USART1_TXD
 **********************************************************************************************************************************************/
void vDMA_Init(void)
{
     
	//USART1 RXD DMA enable
    vDMA_Config(DMA1_Channel5, (u32)(&USART1->DR), (u32)RXD1BUF, RXD1_BUF_SIZE, DMA_DIR_PeripheralSRC, DMA_Priority_High);
	
	//USART1 TXD DMA enable
    vDMA_Config(DMA1_Channel4, (u32)(&USART1->DR), (u32)RXD1BUF, 0, 			DMA_DIR_PeripheralDST, DMA_Priority_Medium);
}

6.1.2 DMA配置

/**********************************************************************************************************************************************
 * 函数名 : vDMA_Config
 * 描  述 : DMA配置
 * 输  入 : channel		: 通道
 * 			perBaseAddr : 外设基地址
 * 			memBaseAddr : 存储器基地址
 * 			memSize     : 存储器大小
 * 			perDir		: 外设方向(DMA_DIR_PeripheralDST/DMA_DIR_PeripheralSRC)
 * 			priority	: 优先级(DMA_Priority_VeryHigh/DMA_Priority_High/DMA_Priority_Medium/DMA_Priority_Low)
 * 说  明 : 1. 外设基地址不变,储存器基地址自增长。
 * 			2. 外设和存储器数据宽度字节对齐。
 * 			3. DMA正常模式,不开启存储器到存储器传输。
 **********************************************************************************************************************************************/
static void vDMA_Config(DMA_Channel_TypeDef * channel, u32 perBaseAddr, u32 memBaseAddr, u16 memSize, u8 perDir, u16 priority)
{
     
    DMA_InitTypeDef DMA_InitStructure;


	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  					//Enable DMA1 clock

    DMA_DeInit(channel);                                                    //Reset MDA channel
    DMA_InitStructure.DMA_PeripheralBaseAddr = perBaseAddr;					//Peripheral base address
	DMA_InitStructure.DMA_MemoryBaseAddr 	 = memBaseAddr;					//Memory base address
	DMA_InitStructure.DMA_DIR 			     = perDir;						//DMA transmit direction
	DMA_InitStructure.DMA_BufferSize 		 = memSize;						//MDA Channel buffer size
	DMA_InitStructure.DMA_PeripheralInc 	 = DMA_PeripheralInc_Disable;	//Peripheral address incremented 
	DMA_InitStructure.DMA_MemoryInc 		 = DMA_MemoryInc_Enable;		//Memory address incremented 
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	//Peripheral data width
	DMA_InitStructure.DMA_MemoryDataSize 	 = DMA_MemoryDataSize_Byte;		//Memory data width
	DMA_InitStructure.DMA_Mode 				 = DMA_Mode_Normal;				//DMAy Channe mode
	DMA_InitStructure.DMA_Priority 			 = priority;					//MDA Channel priority
	DMA_InitStructure.DMA_M2M 				 = DMA_M2M_Disable;				//Memory-to-memory transfer
	DMA_Init(channel, &DMA_InitStructure);									//DMA init

	DMA_Cmd(channel, ENABLE);   //Enable DMA channel
}

6.1.3 启动DMA通道传输

/**********************************************************************************************************************************************
 * 函数名 : vDMA_Start_Channel_Transfer
 * 描  述 : 开始DMA通道传输
 * 输  入 : channel : 通道
 * 			lenDat  : 数据长度
 * 说  明 : 1. DMA_SetCurrDataCounter()只在DMA失能下有效
 **********************************************************************************************************************************************/
void vDMA_Start_Channel_Transfer(DMA_Channel_TypeDef * channel, u16 lenDat)
{
     
	DMA_Cmd(channel, DISABLE);					//Disable DMA channel
	DMA_SetCurrDataCounter(channel, lenDat);	//Set data count
	DMA_Cmd(channel, ENABLE);					//Enable DMA channel
}

6.2 DMA头文件

#define RXD1_BUF_SIZE                                                       200

extern u8 RXD1BUF[RXD1_BUF_SIZE];

void vDMA_Start_Channel_Transfer(DMA_Channel_TypeDef * channel, u16 lenDat);    //vDMA_Start_Channel_Transfer
void vDMA_Init(void);                                                           //vDMA_Init

七、 USART1初始化

7.1 USART1源文件

7.1.1 USARTx GPIO配置

#define USE_USART1_ENABLE									                        1	//Use USART1 Enable
#define USE_USART1_RXD_ENABLE								                        1	//Use USART1 receive enable
#define USE_USART1_TXD_ENABLE								                        1	//Use USART1 transmit enable

#define USE_USART0_ENABLE									                        0	//Use USART0 Enable                       
#define USE_USART2_ENABLE									                        0	//Use USART2 Enable                                             
#define USE_USART3_ENABLE									                        0	//Use USART3 Enable                      
#define USE_USART4_ENABLE									                        0	//Use USART4 Enable                 
#define USE_USART5_ENABLE									                        0	//Use USART5 Enable


/*************************
*********************************************************************************************************************
 * 函数名 : vUSART_GPIO_Config
 * 描  述 : USART GPIO配置
 * 输  入 : USARTx : 串口对象
 * 说  明 : Pin42 -- PA9  -- USRT1_TXD
 * 		    Pin43 -- PA10 -- USRT1_RXD
 * 
 * 			Pin16 -- PA2  -- USRT2_TXD
 * 		    Pin17 -- PA3  -- USRT2_RXD
 * 
 * 			Pin29 -- PB10 -- USRT3_TXD
 * 		    Pin30 -- PB11 -- USRT3_RXD
 * 
 * 			Pin51 -- PC10 -- USART4_TXD
 * 			Pin52 -- PC11 -- USART4_RXD
 **********************************************************************************************************************************************/
static void vUSART_GPIO_Config(USART_TypeDef * USARTx)
{
     
	GPIO_InitTypeDef GPIO_InitStructure;

	#if ( USE_USART1_ENABLE > 0)
	if(USARTx == USART1)
	{
     
		// Pin42 -- PA9  -- USRT1_TXD
		// Pin43 -- PA10 -- USRT1_RXD
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	//Enable USARTx clock
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//Enable GPIO clock

		//USART1_TXD
		GPIO_InitStructure.GPIO_Pin   = USART1_TXD_Pin; 		//GPIO pin
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//Speed 50MHZ
		GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;		//Reuse Push pull output
		GPIO_Init(USART1_GPIO, &GPIO_InitStructure);			//Init GPIO pin

		//USART1_RXD
		GPIO_InitStructure.GPIO_Pin  = USART1_RXD_Pin;			//GPIO pin
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//Float input
		GPIO_Init(USART1_GPIO, &GPIO_InitStructure);			//Init GPIO pin 
	}
	#endif


	#if ( USE_USART2_ENABLE > 0)
	if(USARTx == USART2)
	{
     
		// Pin16 -- PA2  -- USRT2_TXD
		// Pin17 -- PA3  -- USRT2_RXD
		RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART2, ENABLE);	//Enable USARTx clock
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,  ENABLE);	//Enable GPIO clock

		//USRT2_TXD
		GPIO_InitStructure.GPIO_Pin   = USART2_TXD_Pin; 		//GPIO pin
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//Speed 50MHZ
		GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;		//Reuse Push pull output
		GPIO_Init(USART2_GPIO, &GPIO_InitStructure);			//Init GPIO pin

		//USRT2_RXD
		GPIO_InitStructure.GPIO_Pin  = USART2_RXD_Pin;			//GPIO pin
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//Float input
		GPIO_Init(USART2_GPIO, &GPIO_InitStructure);			//Init GPIO pin 
	}
	#endif


	#if ( USE_USART3_ENABLE > 0)
	if(USARTx == USART3)
	{
     
		// Pin29 -- PB10 -- USRT3_TXD
		// Pin30 -- PB11 -- USRT3_RXD
		RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART3, ENABLE);	//Enable USARTx clock
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,  ENABLE);	//Enable GPIO clock

		//USRT3_TXD
		GPIO_InitStructure.GPIO_Pin   = USART3_TXD_Pin; 		//GPIO pin
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//Speed 50MHZ
		GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;		//Reuse Push pull output
		GPIO_Init(USART3_GPIO, &GPIO_InitStructure);			//Init GPIO pin
   
		//USRT3_RXD
		GPIO_InitStructure.GPIO_Pin  = USART3_RXD_Pin;			//GPIO pin
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//Float input
		GPIO_Init(USART3_GPIO, &GPIO_InitStructure);			//Init GPIO pin 
	}
	#endif


	#if ( USE_USART4_ENABLE > 0)
	if(USARTx == UART4)
	{
     
		// Pin51 -- PC10 -- USART4_TXD
		// Pin52 -- PC11 -- USART4_RXD
		RCC_APB1PeriphClockCmd(RCC_APB2Periph_UART4, ENABLE);	//Enable USARTx clock
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);	//Enable GPIO clock

		//USART4_TXD
		GPIO_InitStructure.GPIO_Pin   = USART4_TXD_Pin; 		//GPIO pin
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		//Speed 50MHZ
		GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;		//Reuse Push pull output
		GPIO_Init(USART4_GPIO, &GPIO_InitStructure);			//Init GPIO pin

		//USART4_RXD
		GPIO_InitStructure.GPIO_Pin  = USART4_RXD_Pin;			//GPIO pin
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//Float input
		GPIO_Init(USART4_GPIO, &GPIO_InitStructure);			//Init GPIO pin 
	}
	#endif


	#if ( USE_USART5_ENABLE > 0)
	if(USARTx == UART5)
	{
     
	}
	#endif
}

7.1.2 USARTx 波特率配置

/**********************************************************************************************************************************************
 * 函数名 : vUSART_BaudRate_Config
 * 描  述 : 串口波特率配置
 * 输  入 : USARTx   : 串口对象
 * 			baudRate : 波特率
 * 说  明 : 1. 8Bit数据位+1Bit停止位+无校验+无硬件控制流+使能收发
 **********************************************************************************************************************************************/
static void vUSART_BaudRate_Config(USART_TypeDef * USARTx, u32 baudRate)
{
     
	USART_InitTypeDef USART_InitStructure;
	
	USART_InitStructure.USART_BaudRate   		  = baudRate;	
	USART_InitStructure.USART_WordLength 		  = USART_WordLength_8b;				//8Bit data
	USART_InitStructure.USART_StopBits   		  = USART_StopBits_1;					//1Bit stop
	USART_InitStructure.USART_Parity     		  = USART_Parity_No;					//No odd-even check
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//No Hardware Flow Contro
	USART_InitStructure.USART_Mode       		  = USART_Mode_Tx | USART_Mode_Rx;		//Enable Txd and Rxd
	USART_Init(USARTx, &USART_InitStructure);											//USARTx init

	USART_Cmd(USARTx, ENABLE);															//Enable USART 
}

7.1.3 USARTx 初始化

/**********************************************************************************************************************************************
 * 函数名 : vUSART_Peripheral_Init
 * 描  述 : 串口外设初始化
 * 输  入 : USARTx   : 串口对象
 * 			baudRate : 波特率
 **********************************************************************************************************************************************/
static void vUSART_Peripheral_Init(USART_TypeDef * USARTx, u32 baudRate)
{
     
	vUSART_GPIO_Config(USARTx);
	vUSART_BaudRate_Config(USARTx, baudRate);
}

7.1.4 USART1 中断配置

/**********************************************************************************************************************************************
 * 函数名 : vUSART1_ITConfig
 * 描  述 : 串口1中断配置
 * 输  入 : prePriority : 抢占优先级
 * 		    subPriority : 从优先级
 * 说  明 : 1. 清除空闲标志需要读SR和DR寄存器方可清除
 **********************************************************************************************************************************************/
static void vUSART1_ITConfig(u8 prePrio, u8 subPrio)
{
     
	USART_Cmd(USART1, DISABLE);							//Disable USART1
	vIRQ_NVIC_Config(USART1_IRQn, prePrio, subPrio);	//Config priority
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);		//Enables Idle interrupt

	//Clear Idle flag
	USART_GetFlagStatus(USART1, USART_FLAG_IDLE);		//Get Idle flag
	USART_ReceiveData(USART1);							//Get receive data

	USART_Cmd(USART1, ENABLE);							//Enable USART1
}

7.1.5 USART1 DMA配置

/**********************************************************************************************************************************************
 * 函数名 : vUSART1_DMAConfig
 * 描  述 : 串口1DMA配置
 * 说  明 : 1. USART_DMAReq_Tx : USART DMA transmit request
 * 			2. USART_DMAReq_Rx : USART DMA receive request
 **********************************************************************************************************************************************/
static void vUSART1_DMAConfig(void)
{
     
	USART_DMACmd(USART1, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);	//Enable DMA receive/transmit request	
}

7.1.6 IRQ NVIC配置

/**********************************************************************************************************************************************
 * 函数名 : vIRQ_NVIC_Config
 * 描  述 : 中断NVIC配置
 * 输  入 : perIRQ  : 中断通道
 *          prePrio : 抢占优先级
 *          subPrio : 从优先级
 **********************************************************************************************************************************************/
void vIRQ_NVIC_Config(IRQn_Type perIRQ, u8 prePrio, u8 subPrio)
{
     
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_InitStructure.NVIC_IRQChannel 					 = perIRQ;	//IRQ Channel
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = prePrio;	//Preemption Priority 
	NVIC_InitStructure.NVIC_IRQChannelSubPriority        = subPrio;	//SubPriority Priority
	NVIC_InitStructure.NVIC_IRQChannelCmd 			     = ENABLE;	//Enable IRQ Channe
	NVIC_Init(&NVIC_InitStructure);									//Init NVIC 
}

7.1.7 USART初始化

/**********************************************************************************************************************************************
 * 函数名 : vUSART_Init
 * 描  述 : USART 初始化
 **********************************************************************************************************************************************/
void vUSART_Init(void)
{
     
	vUSART_Peripheral_Init(USART1, 115200);
	vUSART1_ITConfig(3, 0);
	vUSART1_DMAConfig();

	printf("USART Init OK......\r\n");
}

7.1.8 printf()重映射

/**********************************************************************************************************************************************
 * printf()重定义
 **********************************************************************************************************************************************/
#pragma import(__use_no_semihosting)                      
struct __FILE   
{
      
	int handle; 
}; 

FILE __stdout; 

void _sys_exit(int x)  
{
      
	x = x; 
} 

int fputc(int ch, FILE *f)
{
           
	while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);
	USART_SendData(DEBUG_USART, (u8)ch);
	return (ch);
}

7.1.9 USART1中断服务

u16 txCount = 0;

#if ( USE_USART1_RXD_ENABLE > 0)
/**********************************************************************************************************************************************
 * 函数名 : USART1_IRQHandler
 * 描  述 : USART1中断服务
 **********************************************************************************************************************************************/
void USART1_IRQHandler(void) 
{
     
	u16 reCount = 0;

	OSIntEnter();  
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
	{
     
		USART_ClearFlag(USART1, USART_FLAG_RXNE);
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	} 


	if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//Idle interrupt set
	{
     
		// Clear idle interrupt 
		// rDat = USART1->SR;//Read state register
		// rDat = USART1->DR;//Read data register 
		USART_GetITStatus(USART1, USART_IT_IDLE);//Get idle interrupt state
		USART_ReceiveData(USART1);//Get USARTx received data

		reCount = DMA_GetCurrDataCounter(DMA1_Channel5);//Get remaining length 
		txCount = RXD1_BUF_SIZE - reCount;//Used length
		printf("Used:%d --> Remain:%d\r\n", txCount, reCount);
		vDMA_Start_Channel_Transfer(DMA1_Channel5, RXD1_BUF_SIZE);//Start transfer
	}
	OSIntExit();  
} 
#endif	

7.2 USART1头文件

// * Pin42 -- PA9  -- USRT1_TXD
// * Pin43 -- PA10 -- USRT1_RXD
#define USART1_GPIO                 								                GPIOA
#define USART1_TXD_Pin                                                              GPIO_Pin_9
#define USART1_RXD_Pin								                                GPIO_Pin_10

//  * Pin16 -- PA2  -- USRT2_TXD
//  * Pin17 -- PA3  -- USRT2_RXD
#define USART2_GPIO                 								                GPIOA
#define USART2_TXD_Pin                                                              GPIO_Pin_2
#define USART2_RXD_Pin								                                GPIO_Pin_3

//  * Pin29 -- PB10 -- USRT3_TXD
//  * Pin30 -- PB11 -- USRT3_RXD
#define USART3_GPIO                 								                GPIOB
#define USART3_TXD_Pin                                                              GPIO_Pin_10
#define USART3_RXD_Pin								                                GPIO_Pin_11

//  * Pin51 -- PC10 -- USART4_TXD
//  * Pin52 -- PC11 -- USART4_RXD
#define USART4_GPIO                 								                GPIOC
#define USART4_TXD_Pin                                                              GPIO_Pin_10
#define USART4_RXD_Pin								                                GPIO_Pin_11



void vUSART_BaudRate_Config(USART_TypeDef * USARTx, u32 baudRate);	//vUSART_BaudRate_Config
void vUSART_Peripheral_Init(USART_TypeDef * USARTx, u32 baudRate);	//vUSART_Peripheral_Init
void vUSART1_ITConfig(u8 prePrio, u8 subPrio);						//vUSART1_ITConfig
void vUSART1_DMAConfig(void);										//vUSART1_DMAConfig

八、 STM32F1xx DMA+USART1发送+接收+USART1空闲中断测试代码

extern u16 txCount;
/**********************************************************************************************************************************************
 * 函数名 : vQueue_Task
 * 描  述 : 
 **********************************************************************************************************************************************/
void vQueue_Task(void *pdata)
{
     
	while(1)
	{
     
		OSTimeDlyHMSM(0, 0, 1, 200);
		if(txCount)
		{
     
			// RXD1BUF[txCount] = 0;
			// printf("Rec Dat : %s\r\n", RXD1BUF);
			// txCount = 0;

			DMA_ClearFlag(DMA1_FLAG_TC4);//Clear DMA1 Channel4 transfer complete flag
			vDMA_Start_Channel_Transfer(DMA1_Channel4, txCount);//Start transfer
			while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET);//Wait transfer finish
			txCount = 0;
		}
	}
}

九、 运行结果

USART Init OK......
UID          : 0x05DAFF30 0x33385333 0x57087238
Flash Cap    : 512 KByte
Compile Date : Jan 22 2021 14:01:45
Hardware OK......
Debug Versions......

STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第6张图片

USART Init OK......
UID          : 0x05DAFF30 0x33385333 0x57087238
Flash Cap    : 512 KByte
Compile Date : Jan 22 2021 14:01:45
Hardware OK......
Debug Versions......
Used:15 --> Remain:185
uC/OS-II Idle
Used:14 --> Remain:186
uC/OS-II Tmr
Used:14 --> Remain:186
Used:46 --> Remain:154
STM32F1xx DMA+USART1发送+接收+USART1空闲中断
Used:15 --> Remain:185
Used:14 --> Remain:186
uC/OS-II Tmr
Used:14 --> Remain:186
Used:46 --> Remain:154
STM32F1xx DMA+USART1发送+接收+USART1空闲中断

STM32F1xx DMA+USART1发送+接收+USART1空闲中断_第7张图片

你可能感兴趣的:(STM32,stm32,串口通信,嵌入式,单片机,dma)