.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