通过DMA向串口发送数据

 
 
 
 
//DMA —- Directional Memory Access, 直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作
//串口初始化
void USART1_Init(u32 baud)
{
    GPIO_InitTypeDef GPIO_Initstructure;
    USART_InitTypeDef USART_Initstructure;
    NVIC_InitTypeDef NVIC_Initstructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);	//使能PA和USART1的时钟
    //USART1_TX  PA9
    GPIO_Initstructure.GPIO_Mode = GPIO_Mode_AF_PP;					//推挽复用输出
    GPIO_Initstructure.GPIO_Pin = GPIO_Pin_9;								//PA9
    GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;				//50MHz
    GPIO_Init(GPIOA, &GPIO_Initstructure);									//初始化
    //USART1_RX  PA10
    GPIO_Initstructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;		//浮空输入
    GPIO_Initstructure.GPIO_Pin = GPIO_Pin_10;							//PA10
    GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;				//50MHz
    GPIO_Init(GPIOA, &GPIO_Initstructure);

    USART_DeInit(USART1);

    
    NVIC_Initstructure.NVIC_IRQChannel = USART1_IRQn;						//串口1
    NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority = 3;		//抢占优先级3
    NVIC_Initstructure.NVIC_IRQChannelSubPriority = 0;					//子优先级3
    NVIC_Initstructure.NVIC_IRQChannelCmd = ENABLE;							//使能中断
    NVIC_Init(&NVIC_Initstructure);
    
    USART_Initstructure.USART_BaudRate = baud;																			//波特率
    USART_Initstructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件数据流控制
    USART_Initstructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;									//收发模式
    USART_Initstructure.USART_Parity = USART_Parity_No;															//无奇偶校验位
    USART_Initstructure.USART_StopBits = USART_StopBits_1;													//一位停止位
    USART_Initstructure.USART_WordLength = USART_WordLength_8b;											//8位数据位
    
    USART_Init(USART1, &USART_Initstructure);										//初始化

    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA1_Channel4_UseForUSART1_Config();

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);							//开启串口接受中断
    USART_Cmd(USART1, ENABLE);                    							//使能串口1
}
void DMA1_Channel4_UseForUSART1_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
    
    DMA_DeInit(DMA1_Channel4);																							//将DMA的通道寄存器重设为缺省值
    DMA_InitStructure.DMA_BufferSize = 0;																		//DMA缓存大小 暂时设置为6个字节
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;											//外设作为目的地
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;														//不设置为内存到内存
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SendBuff;													//内存地址暂时设置为0, 启动传输的时候再指定具体位置
    DMA_InitStructure.DMA_MemoryDataSize = SENDBUFF_SIZE;					
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;									//内存地址自增
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;														//正常模式 不循环
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;						//外设地址
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	//外设大小一个字节
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;				//外设地址不自增
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;											//高优先级
    
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);
    DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);								//开启传输完成中断
}
//通过DMA发送数据到串口
FlagStatus FlagStatus_DMA1_Channel4_Busy;										//DMA1_Channel4忙标志位
ErrorStatus USART1_SendDataByDMA(u32 memoryaddr, u16 buffersize)
{
    if(FlagStatus_DMA1_Channel4_Busy != SET)									//通道空闲
    {
        LED_TX_Onepulse();
        FlagStatus_DMA1_Channel4_Busy = SET;									//设置通道忙标志
        DMA_Cmd(DMA1_Channel4, DISABLE);
        DMA_SetCurrDataCounter(DMA1_Channel4, buffersize);			    //缓存大小
        DMA1_Channel4->CMAR = memoryaddr;								//内存地址
        DMA_Cmd(DMA1_Channel4, ENABLE);									//启动传输
        return SUCCESS;
    }
    else																								//通道忙
    {
        return ERROR;
    }
}

//通道4中断函数,用于清除忙标志位
void DMA1_Channel4_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_GL4) != RESET)
    {
        if(DMA_GetITStatus(DMA1_IT_TC4) != RESET)
        {
            FlagStatus_DMA1_Channel4_Busy = RESET;			//清除忙标志
            DMA_ClearITPendingBit(DMA1_IT_TC4);
        }
        DMA_ClearITPendingBit(DMA1_IT_GL4);
    }
}



猜你喜欢

转载自blog.csdn.net/qq_23194139/article/details/80203617