20200726-DMA串口收发-stm32

串口+DMA初始化配置

USART_Configuration(9600,ENABLE);//串口数据
DMA1_Channel5_Configuration();

Usart1:

void USART_Configuration(u32 baudrate,FunctionalState NewState)
{
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef    GPIO;        //声明一个结构体变量
    NVIC_InitTypeDef NVIC_InitStructure;

//时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);    //使能USART1,GPIOA时钟
//nvic中断优先级配置
    /* ?? USART ???? */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);//根据指定的参数初始化NVIC寄存器

//USART1_TX   PA.9
//USART1_RX      PA.10
    GPIO.GPIO_Pin = GPIO_Pin_10;     //选择PX.3
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;     //管脚频率为50MHZ
    GPIO.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //
    GPIO_Init(GPIOA,&GPIO);                 //初始化GPIOA寄存器

    GPIO.GPIO_Pin = GPIO_Pin_9;
    GPIO.GPIO_Speed = GPIO_Speed_50MHz;     //管脚频率为50MHZ
    GPIO.GPIO_Mode = GPIO_Mode_AF_PP;     //输出模式为推挽复用输出
    GPIO_Init(GPIOA,&GPIO);                 //初始化GPIOA寄存器
//usart
    USART_DeInit(USART1);
    USART_InitStructure.USART_BaudRate = 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_Tx | USART_Mode_Rx;
    USART_Init(USART1, &USART_InitStructure);

 //   USART_ITConfig(USART1, USART_IT_RXNE,NewState);//开接收中断
    USART_Cmd(USART1, NewState);

}

DMA:

//channel5 接收
//channel4 发送
#define USART1_DR_Base (u32)(0x40013804)
void DMA1_Channel5_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    DMA_InitTypeDef    DMA_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQChannel;      //DMA中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

 /* DMA1 Channel5 (triggered by USART1 Rx event) Config */
    DMA_DeInit(DMA1_Channel5);    // 将DMA1_Channel5寄存器重设为初始值 ;
    DMA_InitStructure.DMA_PeripheralBaseAddr =USART1_DR_Base ;     //用来定义DMA外设的基地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_Buffer_Rx;                //用来定义DMA内存的基地址
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                    //传输方向
    DMA_InitStructure.DMA_BufferSize = USART1_Buffer_Rx_Size;                        //传输数据的大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //DMA外设地址
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                //DMA内存地址+1
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//传输的字节宽度HalfWord
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;           //字节宽度
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                           //传输模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                       //优先级
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                               //使能内存到内存的传输
    DMA_Init(DMA1_Channel5,&DMA_InitStructure);                              //初始化
    DMA_Cmd(DMA1_Channel5,ENABLE);                           //使能DMA

/* DMA1 Channel4 (triggered by USART1 Tx event) Config */
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQChannel;      //DMA中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    DMA_DeInit(DMA1_Channel4);
//        DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;  // 外设地址,串口1
//        DMA_InitStructure.DMA_MemoryBaseAddr =(u32)USART1_Buffer_Rx;// 发送内存地址
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//传输的字节宽度HalfWord
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;           //字节宽度

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;// 外设为传送数据目的地,即发送数据
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           //传输模式
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);//初始化
    DMA_Cmd(DMA1_Channel4,ENABLE);                        while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));    //使能DMA

//    DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);                         // 接收传输完成中断
    DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);                         // 发送传输完成中断
//        USART_ITConfig(USART1, USART_IT_TC, ENABLE);            // 使能串口发送完成中断
    USART_DMACmd(USART1,USART_DMAReq_Tx|USART_DMAReq_Rx,ENABLE);
}

DMA接收通道优先级似乎应高于发送通道,否则会出现接收问题(待验证)

DMA通道的使用

查看DMA请求映像可知USART1对应
//channel5 接收
//channel4 发送
在这里插入图片描述

USART1_DR_Base

这是外设USART1的数据寄存器(USART_DR) 地址偏移:0x04
在这里插入图片描述
查看存储器映像得外设起始地址
在这里插入图片描述
相加即为USART1_DR_Base

开启一次DMA传输

1.得到DMA对应数字。判断等待DMA传输和串口传输完成
2.
DMA_CHx->CCR&=~(1<<0); //关闭DMA传输
DMA_CHx->CNDTR=DMA1_MEM_LEN; //DMA1,传输数据量
DMA_CHx->CCR|=1<<0; //开启DMA传输
3.清除传输完成标志

void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx,u16 DMA1_MEM_LEN)
{
    u8 num=255;
    u32 tc=0;
    switch (*(u32*)&DMA_CHx)
    {
    case DMA1_Channel1_BASE:
        num=11;
        break;
    case DMA1_Channel2_BASE:
        num=12;
        break;
    case DMA1_Channel3_BASE:
        num=13;
        break;
    case DMA1_Channel4_BASE:
        num=14;
        break;
    case DMA1_Channel5_BASE:
        num=15;
        break;
    case DMA1_Channel6_BASE:
        num=16;
        break;
    case DMA1_Channel7_BASE:
        num=17;
        break;
    case DMA2_Channel1_BASE:
        num=21;
        break;
    case DMA2_Channel2_BASE:
        num=22;
        break;
    case DMA2_Channel3_BASE:
        num=23;
        break;
    case DMA2_Channel4_BASE:
        num=24;
        break;
    case DMA2_Channel5_BASE:
        num=25;
        break;
    default:
        break;
    }
    if(num>10&&num<20)
        tc|=1<<((num%10-1)*4+1);
    else if(num>20)
    {
        tc=0x10000000;
        tc|=1<<((num%10-1)*4+1);
    }
//	while(!DMA_GetFlagStatus(tc));  //判断传输是否完成与dma中断互斥。不能同时用。
    switch(num%10)
    {
    case 2:
    case 3:
        while(!USART_GetFlagStatus(USART3, USART_FLAG_TC));
        break;//判断发送完成
    case 4:
    case 5:
        while(!USART_GetFlagStatus(USART1, USART_FLAG_TC));
        break;
    case 6:
    case 7:
        while(!USART_GetFlagStatus(USART2, USART_FLAG_TC));
        break;
    default:
        break;
    }
    DMA_CHx->CCR&=~(1<<0);                    //关闭DMA传输
    DMA_CHx->CNDTR=DMA1_MEM_LEN;  //DMA1,传输数据量
    DMA_CHx->CCR|=1<<0;                         //开启DMA传输
		DMA_ClearFlag(DMA_FLAG_TC); //清除传输完成标志
		DMA_CHx->IFCR|=1<<13;
    tc= ((u32)0x00000000);
		if(num>10&&num<20)
		{
			tc|=(0xf)<<(num%10-1)*4;
			DMA1->IFCR |=tc;
		}
		else if(num>20)
		{
						tc|=(0xf)<<(num%10-1)*4;
				DMA2->IFCR |=tc;
		}

//	  switch (*(u32*)&DMA_CHx)//标志全部清除
//  {
//    case DMA1_Channel1_BASE:num=11;DMA1->IFCR |= ((u32)0x0000000F);break;
//    case DMA1_Channel2_BASE:num=12;
//      DMA1->IFCR |= ((u32)0x000000F0);
//      break;
//    case DMA1_Channel3_BASE:num=13;
//      DMA1->IFCR |= DMA1_Channel3_IT_Mask;
//      break;
//    case DMA1_Channel4_BASE:num=14;
//      DMA1->IFCR |= DMA1_Channel4_IT_Mask;
//      break;
//    case DMA1_Channel5_BASE:num=15;
//      DMA1->IFCR |= DMA1_Channel5_IT_Mask;
//      break;
//    case DMA1_Channel6_BASE:num=16;
//      DMA1->IFCR |= DMA1_Channel6_IT_Mask;
//      break;
//    case DMA1_Channel7_BASE:num=17;
//      DMA1->IFCR |= DMA1_Channel7_IT_Mask;
//      break;
//    case DMA2_Channel1_BASE:num=21;
//      DMA2->IFCR |= DMA2_Channel1_IT_Mask;
//      break;
//    case DMA2_Channel2_BASE:num=22;
//      DMA2->IFCR |= DMA2_Channel2_IT_Mask;
//      break;
//    case DMA2_Channel3_BASE:num=23;
//      DMA2->IFCR |= DMA2_Channel3_IT_Mask;
//      break;
//    case DMA2_Channel4_BASE:num=24;
//      DMA2->IFCR |= DMA2_Channel4_IT_Mask;
//      break;
//    case DMA2_Channel5_BASE:num=25;
//      DMA2->IFCR |= DMA2_Channel5_IT_Mask;
//      break;
//    default:
//      break;
//  }
}

it.c文件

中断处理【清理完成标志。标记自己的CurrDataCounter_End】

extern u16 CurrDataCounter_End;
void DMA1_Channel4_IRQHandler(void)
{
  if(DMA_GetITStatus(DMA1_IT_TC4))  // 通道4发送传输完成中断 ;
  {
    CurrDataCounter_End =1;  
    DMA_ClearITPendingBit(DMA1_IT_GL4);	// 清除DMA通道4中断全局标志位 ;
  }
}
void DMA1_Channel5_IRQHandler(void)//接收
{
//		if(DMA_GetITStatus(DMA1_IT_TC5))  // 通道5传输完成中断 ;
//  	{
//   	 	/* Get Current Data Counter value after complete transfer */
//    //	CurrDataCounter_End = DMA_GetCurrDataCounter(DMA1_Channel5);  // 返回当前DMA通道5剩余的待传输数据数目 ;
//    	/* Clear DMA Channel6 Half Transfer, Transfer Complete and Global interrupt pending bits */
//    	DMA_ClearITPendingBit(DMA1_IT_GL5);	// 清除DMA通道5中断全局标志位 ;
//  	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心超人dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值