提示:本文内容仅作参考
前言
本文提出基于CubeMX的STM32芯片配置串口DMA模式的方法,本文方法仅供参考。
一、串口简介
串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口 (Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。
二、CubeMX配置详解
1.配置串口
此处使用串口1作为测试工具,具体来说使用PA9和PA10作为串口发送引脚。
①.在新建的工程里面配置PA9和PA10分别为串口的发送与接收引脚,如下图所示,此时引脚显示为黄色,表示暂未激活。
②.下一步需要对串口模式进行选择以激活,找到Connectivity下的USART1选项并点击,界面如下.
③.选择通信模式
在右上角配置界面的第一个配置为异步通信模式即可,即为Asynchronous。除了通讯模式的配置外,此界面还有一些常用工业接口(RS232\RS585)的硬件流控,在此无需使用。配置图如下。
在配置为异步通信模式后,引脚变为绿色,表示已经配置。
④.基本参数设置
a) 通信波特率为115200,数据长度8个字节,停止位1位,双向传输模式。
b) 设置中断模式:打开全局中断
此外,需要在NVIC Setting里面设置打开串口的全局中断,部分型号不打开此中断会出现传输失败的问题(如下图,在方框勾选即可)。
c) 配置DMA
找到DMA Settings这一栏,点击ADD添加DMA数据流,这里把发送和接收的DMA全部打开,同时注意DMA的配置,一般的串口都是8位,因此使用默认的DMA配置即可(也就是指针自增为BYTE)。
此处可以对串口接收的DMA进行更多设置,比如设置DMA模式为Circular,使DMA在一次接收完成后自动开启下一次接收。
d) gpio配置
CUBEMX配置到此结束,点击生成代码即可,然后可以直接在框架中使用串口DMA通信了。
2.代码参考
①.中断函数修改
在stm32f1xx_it.c文件中修改函数USART1_IRQHandler,打开DMA中断接收。
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
//userUart1Handler();
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
//USART1_IRQ_Func();
//#if uart_DMA_chonse
USART_DMA_IDLE_Func();//开启DMA接收中断
//#endif
/* USER CODE END USART1_IRQn 1 */
}
②.中断函数体修改
在文件usart.c文件中修改函数USART_DMA_IDLE_Func(void)
extern uint8_t uart1RxState;
extern uint8_t uart1RxBuf[usartFifoLength];
extern uint8_t uart1RxCounter;
void USART_DMA_IDLE_Func(void)
{
uint32_t temp;
uint8_t flag=0;
int i = 0;
if(USART1 == huart1.Instance)//判断是否为串口1中断
{
flag=__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE);
if(flag!=RESET)
{
huart1.gState = HAL_UART_STATE_READY;
__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除中断标志位
HAL_UART_DMAStop(&huart1);//停止DMA接收
temp = __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);//获取DMA当前还有多少未填充
DMA_Rx_len = DAM_Buff_Cnt - temp; //计算接收到的串口数据个数
for(i = 0;i<DMA_Rx_len;i++)
{
uart1RxBuf[uart1RxCounter++] = DMA_Rx_Buff[i];
}
uart1RxState = UART_RX_STATE_DEAL;//主函数While循环查询到这个标志位就会解析数据
}
}
}
③.串口发送及接收代码参考
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
unsigned char s_buf[]="hello world\r\n";
HAL_UART_Transmit_DMA(&huart1,s_buf,sizeof(s_buf));//发送DMA数据
while (1)
{
if(uart1RxState==UART_RX_STATE_DEAL)//接收DMA数据
{
for(i = 0;i<uart1RxCounter;i++)
{
usartRxFIFOMeg.usart1RxFIFO[usartRxFIFOMeg.usart1RxFIFOIndex++] = uart1RxBuf[i];
}
uart1RxCounter = 0;
memset(uart1RxBuf,0,sizeof(uart1RxBuf));
uart1RxState=UART_RX_STATE_READY;
DMA_Rx_len=0;//接收数据长度清零
HAL_UART_Receive_DMA(&huart1,DMA_Rx_Buff,DAM_Buff_Cnt);//开启下一次接收
}
}
}
此处介绍下下面这个函数:
HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
//其中huart为句柄,代表调用的串口名称
//pData为数组的指针
//Size为要发送的数据大小
2.异常处理
a) DMA不通
初始化顺序有要求
MX_DMA_Init();
MX_USART1_UART_Init();
DMA要放在串口初始化之前!!
b) DMA数据接收数据异常
usartRxFIFOMeg.usart1RxFIFO[usartRxFIFOMeg.usart1RxFIFOIndex++] = uart1RxBuf[i];放在主函数中,不要放在DMA数据接收中断中处理外部数组索引等,因为会引起异常错误。
总结
以上就是今天要讲的内容,本文提出基于CubeMX的STM32芯片配置串口DMA模式的方法,本文方法仅供参考,整理资料不易,麻烦留下小爱心。