STM32F429HAL库串口MDA配置

.c文件

#include "usart.h"
//#include "delay.h"

/*
1、STM32F429有2个DMA控制器(DMA1和DMA2),每个控制器有8个数据流,每个数据流有8个通道(请求)。
2、支持外设到存储器、存储器到外设、存储器到存储器传输的常规通道。(仅DMA2支持存储器到存储器的传输)
//Author:zcr 7_9
*/
volatile uint8_t USART1_DMATX_FLAG=0;
UART_HandleTypeDef UART1_DMA_HD;
DMA_HandleTypeDef UART1_DMATX_HD;
DMA_HandleTypeDef UART1_DMARX_HD;



uint8_t RX_BUF[RXBUF_SIZE]= {0};
uint8_t TX_BUF[RXBUF_SIZE]= {0};
volatile uint8_t USART1_RX_OK = 0;
volatile uint16_t USART1_RX_CNT = 0;

#if 1
//#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
    int handle;
};

FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
    x = x;
}
int fputc(int ch, FILE *f)
{
//    while((USART3->SR&0X40)==0);//循环发送,直到发送完毕
//    USART3->DR = (u8) ch;
    USART1_DMA_TxTransmit((uint8_t *)&ch,1);
    return ch;

}
#endif

//初始化
void USART1_DMA_Configuration(uint32_t bRate)
{
    UART1_DMA_HD.Instance = USART3;                  //串口编号
    UART1_DMA_HD.Init.BaudRate = bRate;                  //波特率
    UART1_DMA_HD.Init.WordLength = UART_WORDLENGTH_8B;   //字长为8位格式
    UART1_DMA_HD.Init.StopBits = UART_STOPBITS_1;        //一个停止位
    UART1_DMA_HD.Init.Parity = UART_PARITY_NONE;         //无奇偶校验位
    UART1_DMA_HD.Init.HwFlowCtl = UART_HWCONTROL_NONE;   //无硬件流控制
    UART1_DMA_HD.Init.Mode = UART_MODE_TX_RX;            //全双工收发模式
    UART1_DMA_HD.Init.OverSampling = UART_OVERSAMPLING_16;   //16倍过采样获取更好的容错性
    HAL_UART_Init(&UART1_DMA_HD);                        //内部调用__HAL_UART_ENABLE(handler);函数

    //------------------------------------------------------------------
    __HAL_DMA_ENABLE_IT(&UART1_DMATX_HD, DMA_IT_TC);     //开启DMA传输完成中断
    __HAL_DMA_ENABLE_IT(&UART1_DMARX_HD, DMA_IT_TC);

    __HAL_UART_ENABLE_IT(&UART1_DMA_HD, UART_IT_IDLE);   //开启IDLE中断,以帧方式接收不定长数据
    HAL_UART_Receive_DMA(&UART1_DMA_HD, RX_BUF, RXBUF_SIZE);

}
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART3)
    {
        USART1_LINKDMA(huart);
    }

}
//连接DMA
void USART1_LINKDMA(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    __HAL_RCC_GPIOD_CLK_ENABLE();     //使能GPIOA时钟
    __HAL_RCC_USART3_CLK_ENABLE();    //使能USART1时钟
    __HAL_RCC_DMA1_CLK_ENABLE();      //DMA2时钟使能

    GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9;			//PA9(USART1_TX)\PA10(USART1_RX)
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;              //复用推挽输出
    GPIO_InitStructure.Pull = GPIO_PULLUP;                  //上拉
    GPIO_InitStructure.Speed = GPIO_SPEED_FAST;						 //高速
    GPIO_InitStructure.Alternate = GPIO_AF7_USART3;         //复用为USART1
    HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);              //初始化

    //Tx DMA配置
    //数据流选择
    UART1_DMATX_HD.Instance = DMA1_Stream3;
    //通道选择
    UART1_DMATX_HD.Init.Channel = DMA_CHANNEL_4;
    //存储器到外设
    UART1_DMATX_HD.Init.Direction = DMA_MEMORY_TO_PERIPH;
    //外设非增量模式,UART只有一个DR寄存器,地址不能变化
    UART1_DMATX_HD.Init.PeriphInc = DMA_PINC_DISABLE;
    //存储器增量模式
    UART1_DMATX_HD.Init.MemInc = DMA_MINC_ENABLE;
    //外设数据长度:8位一个字节
    UART1_DMATX_HD.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    //存储器数据长度:8位
    UART1_DMATX_HD.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    //外设普通模式
    UART1_DMATX_HD.Init.Mode = DMA_NORMAL;
    //中等优先级
    UART1_DMATX_HD.Init.Priority = DMA_PRIORITY_LOW;
    //关闭FIFO
    UART1_DMATX_HD.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    //FIFO阀值选择
    UART1_DMATX_HD.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    //存储器突发单次传输
    UART1_DMATX_HD.Init.MemBurst = DMA_MBURST_SINGLE;
    //外设突发单次传输
    UART1_DMATX_HD.Init.PeriphBurst = DMA_PBURST_SINGLE;
    //恢复默认配置
    HAL_DMA_DeInit(&UART1_DMATX_HD);
    //初始化DMA
    HAL_DMA_Init(&UART1_DMATX_HD);
    //将DMA与USART1联系起来(发送DMA)
    __HAL_LINKDMA(huart, hdmatx, UART1_DMATX_HD);

    //Rx DMA配置
    UART1_DMARX_HD.Instance = DMA1_Stream1;
    UART1_DMARX_HD.Init.Channel = DMA_CHANNEL_4;
    UART1_DMARX_HD.Init.Direction = DMA_PERIPH_TO_MEMORY;
    UART1_DMARX_HD.Init.PeriphInc = DMA_PINC_DISABLE;
    UART1_DMARX_HD.Init.MemInc = DMA_MINC_ENABLE;
    UART1_DMARX_HD.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    UART1_DMARX_HD.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    UART1_DMARX_HD.Init.Mode = DMA_CIRCULAR;
    UART1_DMARX_HD.Init.Priority = DMA_PRIORITY_LOW;
    UART1_DMARX_HD.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_DeInit(&UART1_DMARX_HD);
    HAL_DMA_Init(&UART1_DMARX_HD);
    __HAL_LINKDMA(huart, hdmarx, UART1_DMARX_HD);

//-----------------------------------------------------------
    HAL_NVIC_SetPriority(USART3_IRQn, 3, 3);   //抢占优先级0,子优先级0
    HAL_NVIC_EnableIRQ(USART3_IRQn);          //使能USART1中断通道

    HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 3, 2);
    HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 3, 1);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}


void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
    //回调函数
    huart->State=HAL_UART_STATE_READY;
}
//DMA发送中断处理
void DMA1_Stream3_IRQHandler(void)
{
    //DMA2_Steam7传输完成
    if(__HAL_DMA_GET_FLAG(&UART1_DMATX_HD, DMA_FLAG_TCIF3_7))
    {

        USART1_DMATX_FLAG=1;
        //清除DMA2_Steam7传输完成标志
        __HAL_DMA_CLEAR_FLAG(&UART1_DMATX_HD, DMA_FLAG_TCIF3_7);
        //传输完成以后关闭串口DMA
        HAL_UART_DMAStop(&UART1_DMA_HD);
    }
    //调用中断处理公共函数
    HAL_DMA_IRQHandler(&UART1_DMATX_HD);
}

//DMA接收断处理
void DMA1_Stream1_IRQHandler(void)
{
    //DMA2_Steam2传输完成
    if(__HAL_DMA_GET_FLAG(&UART1_DMARX_HD, DMA_FLAG_TCIF1_5))
    {

        //清DMA2_Steam2传输完成标志
        __HAL_DMA_CLEAR_FLAG(&UART1_DMARX_HD, DMA_FLAG_TCIF1_5);
        //传输完成以后关闭串口DMA
        HAL_UART_DMAStop(&UART1_DMA_HD);
    }
    //重新开启DMA接收
    HAL_UART_Receive_DMA(&UART1_DMA_HD, RX_BUF, RXBUF_SIZE);
    //调用中断处理公共函数
    HAL_DMA_IRQHandler(&UART1_DMARX_HD);
}

//使用DMA发送数据
void USART1_DMA_TxTransmit(uint8_t *pData,         //传输的数据指针
                           uint32_t DataLength)        //传输的数据量
{
//    memcpy(&TX_BUF[0],pData,Size);
//    HAL_DMA_Start(UART1_DMA_HD.hdmatx, (uint32_t)TX_BUF, (uint32_t)&UART1_DMA_HD.Instance->DR, Size);

//    //使能串口DMA发送,没有对应的函数只能直接使用寄存器
//    UART1_DMA_HD.Instance->CR3 |= USART_CR3_DMAT;
    USART1_DMATX_FLAG=0;
    HAL_DMA_Start(UART1_DMA_HD.hdmatx, (uint32_t)pData, (uint32_t)&UART1_DMA_HD.Instance->DR, DataLength);
    UART1_DMA_HD.Instance->CR3 |= USART_CR3_DMAT;
    while(USART1_DMATX_FLAG==0);
}


void USART3_IRQHandler(void)
{

    //当接收完一帧数据后标记接收完成
    if(__HAL_UART_GET_FLAG(&UART1_DMA_HD, UART_FLAG_IDLE) != RESET)  //判断是否为IDLE中断
    {

        //清除空闲中断标志
        __HAL_UART_CLEAR_IDLEFLAG(&UART1_DMA_HD);
        HAL_UART_DMAStop(&UART1_DMA_HD);
        //总计数减去DMA中未传输的数据个数(最多65535)
        USART1_RX_CNT = RXBUF_SIZE - UART1_DMARX_HD.Instance->NDTR;
        USART1_RX_OK = 1;      //标记接收完成

        //重新开启DMA接收
        HAL_UART_Receive_DMA(&UART1_DMA_HD, RX_BUF, RXBUF_SIZE);
    }
    //调用中断处理公共函数
    HAL_UART_IRQHandler(&UART1_DMA_HD);
}

.h文件

#ifndef _USART1_H
#define _USART1_H
#include "sys.h"
#include "stdio.h"	
#include <string.h>

 
#define RXBUF_SIZE  255               //接收缓存大小

extern UART_HandleTypeDef UART1_DMA_HD;    //UART句柄
extern DMA_HandleTypeDef UART1_DMATX_HD;
extern DMA_HandleTypeDef UART1_DMARX_HD;

extern uint8_t RX_BUF[RXBUF_SIZE];
extern uint8_t TX_BUF[RXBUF_SIZE];
extern u8 DMA_Flag;
//extern uint8_t RX_BUF[];              //接收缓存
extern volatile uint8_t USART1_RX_OK;                 //接收完成标志
extern volatile uint16_t USART1_RX_CNT;               //接收到数据长度


//初始化
void USART1_DMA_Configuration(uint32_t bRate);
//使用DMA发送数据
void USART1_DMA_TxTransmit(uint8_t *pData,  uint32_t DataLength);
//连接DMA
void USART1_LINKDMA(UART_HandleTypeDef *huart);
 

#endif

上一篇:【新手基础教程】片上外设之 UART 的使用


下一篇:(十)arm裸机开发---UART串口通信实验