目录
文章目录
一、前期准备:
- CubeMx软件;
- Keil或MDK;
- STM32F103C8T6;(Ps:其他型号单片机也行,STM32的型号用起来都差不多)
二、配置CubeMX部分:
1.配置烧录方式:
2.选择外部晶振:
3.配置时钟树:
- 这里可以在72Mhz max那里直接输入72M然后选择自动配置时钟。
4.配置串口:
-
默认就是115200,其他设置一般不用动,默认就好。
5.配置工程文件生成:
- 设置好工程名称和路径,注意:步骤4那里需要看自己的IDE设置,我用的是Keil所以选MDK-ARM。
- 第一栏选择只复制需要用到的库文件;
- 第二栏选择生成单独的.c/.h文件;
- 点击右上角生成即可;
- 生成成功,打开工程;
三、代码部分:
1、串口printf输出:
- 勾选Use Micro LIB;
- 勾选Reset and Run,这样程序下载后可以自动重启;
- 在main.h文件添加 #include <stdio.h>
- main.c文件加入printf重定向函数;这里注意,如果你是串口1就用和我一样的&huart1,串口2就用&huart2,以此推类。
/* Redirect printf function */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return (ch);
}
- while循环中加入延时和串口打印;
- 串口成功打印;
2、串口接收中断配置:
- 打开串口中断;并且重新生成一下代码;
- 定义一个接收字符的变量;初始化的时候开启串口接收中断;
HAL_UART_Receive_IT(&huart1, &Rx1ch, 1);
- main.c文件中加入串口接收中断处理函数,这里中断的功能是收到什么就回什么。最后记得要再重新开启一下串口接收中断;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UNUSED(huart);
if (huart->Instance == USART1)
{
// HAL_UART_Transmit(&huart1, &Rx1ch, 1, 100);
huart1.Instance->DR = Rx1ch; /* 这里建议直接操作寄存器,不然速度慢,容易丢包 */
HAL_UART_Receive_IT(&huart1, &Rx1ch, 1); // 因为接收中断使用了一次即关闭,所以在最后加入这行代码即可实现无限使用
}
}
- 编译运行,可以看到我们发送"Troubadour1-Troubadour2-Troubadou3",单片机返回同样的数据;
3、DMA+串口空闲中断配置:
- CubeMX中添加DMA,速度设置最大,最后生成代码;
- 把之前串口接收中断的代码注释掉或者删除,加上以下变量和DMA数据处理的代码:
#define UART_RX1_BUFFSIZE (1024)
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;
uint8_t Uart1Flag = 0;
uint8_t Uart1_RxBuff[UART_RX1_BUFFSIZE] = {0};
uint8_t Uart1_Data[UART_RX1_BUFFSIZE] = {0};
uint16_t uartCnt = 0;
/* uart IDLE DMAHandler interrupt */
void USART1_DMAHandler(void)
{
if (RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) // 判断是否是空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除空闲中断标志
HAL_UART_DMAStop(&huart1); // 停止本次DMA传输
uartCnt = UART_RX1_BUFFSIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); // 计算接收到的数据长度
memcpy(Uart1_Data, Uart1_RxBuff, uartCnt);
Uart1Flag = 1;
HAL_UART_Receive_DMA(&huart1, (uint8_t *)Uart1_RxBuff, UART_RX1_BUFFSIZE); // 重启开始DMA传输
}
}
- 主函数里面把串口接收中断的部分删掉,加入空闲中断和使能DMA;while循环中检查DMA接收完成后的标志位,一旦接受完一帧数据就将这帧数据发送出去。
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); /* 开启串口空闲中断 */
HAL_UART_Receive_DMA(&huart1, (uint8_t*)Uart1_RxBuff, UART_RX1_BUFFSIZE); /* 开启DMA传输 */
while (1)
{
if (Uart1Flag)
{
Uart1Flag = 0;
HAL_UART_Transmit(&huart1, Uart1_Data, uartCnt, 1000); /* 将接收到的数据发送出去 */
}
}
- 最后去到stm32f1xx_it.c文件中,在串口中断函数中调用刚才添加的DMA数据处理函数,记得在这个文件声明外部调用此函数;
- 编译运行,看看效果;这里用出师表试试,收发都没问题。