1、开发环境
(1)Keil MDK: V5.38.0.0
(2)MCU: mm320163D7P
2、实验目的&原理图
2.1、实验目的
(1)上位机串口助手给MCU发送信息,MCU串口通过通过串口助手接收后,将接收到的内容通过串口助手发送到上位机。
(2)串口在whil循环中每隔1秒发送一次 hello world.\r\n
2.2、原理图
3、Keil 工程的创建
(1)打开Keil MDK。
(2)点击“Project”→“New μVision Project...”。
(3)选择工程保存地址及工程文件名,然后点击确定。
(4)选择相应的单片机型号,然后点击“OK”即可。
(5)弹出“管理运行时环境”对话框,保持默认,点击OK即可。
3、移植库文件
参考文章 三、LED闪烁-CSDN博客
4、编写代码
4.1、UART相关函数
(1)UART2引脚初始化
补充:
- 根据个人实际开发经验,串口Rx引脚浮空输入和上拉输入都能接收到数据。
- 参考网友建议配置为上拉输入。如果配置成浮空时会存在一定收到杂乱数据情况。
- 参考地址:stm32 串口RX上拉还是浮空_串口 上拉-CSDN博客
/**功能:UART2引脚初始化*参数:无*返回值:无*/
static void UART2_GPIO_Init(void)
{// 定义一个GPIO结构体,用于配置GPIO参数GPIO_InitTypeDef GPIO_InitStruct;// 使能GPIOA时钟RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);/** #define GPIO_AF_0 (0x00U) ///< Alternative function 0 内部振荡器* #define GPIO_AF_1 (0x01U) ///< Alternative function 1 UART(通用异步收发器)* #define GPIO_AF_2 (0x02U) ///< Alternative function 2 SPI(串行外设接口)* #define GPIO_AF_3 (0x03U) ///< Alternative function 3 I2C(双向串行总线)* #define GPIO_AF_4 (0x04U) ///< Alternative function 4 ADC(模数转换器)* #define GPIO_AF_5 (0x05U) ///< Alternative function 5 DAC(数模转换器)* #define GPIO_AF_6 (0x06U) ///< Alternative function 6 PWM(脉宽调制)* #define GPIO_AF_7 (0x07U) ///< Alternative function 7 定时器/计数器*/GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1); // 复用功能GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); // 复用功能//UART2_TX GPIOA.2GPIO_StructInit(&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽输出GPIO_Init(GPIOA, &GPIO_InitStruct);//UART2_RX GPIOA.3GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
// GPIO_InitStruct.GPIO_Mode = GPIO_Mode_FLOATING; // 浮空输入GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入,接收引脚配置为该模式也可以GPIO_Init(GPIOA, &GPIO_InitStruct);
}
(2)UART2初始化配置
/**功能:串口2初始化配置*参数:波特率*返回值:无*/
void UART2_Init(u32 baudrate)
{UART_InitTypeDef UART_InitStruct; // 定义一个UART结构体,用于配置UART参数 NVIC_InitTypeDef NVIC_InitStruct; // 定义一个中断控制器结构体,用于配置串口中断RCC_APB1PeriphClockCmd(RCC_APB1ENR_UART2, ENABLE); // 使能时钟UART_StructInit(&UART_InitStruct); // 初始化UART结构体UART_InitStruct.BaudRate = baudrate; // 设置波特率UART_InitStruct.WordLength = UART_WordLength_8b; // 8位数据位UART_InitStruct.StopBits = UART_StopBits_1; // 1位停止位UART_InitStruct.Parity = UART_Parity_No; // 无校验位UART_InitStruct.HWFlowControl = UART_HWFlowControl_None; // 不使用硬件流控制UART_InitStruct.Mode = UART_Mode_Rx | UART_Mode_Tx; // 设置UART模式为接收和发送 UART_Init(UART2, &UART_InitStruct); // 根据上述配置初始化UART2// 对GPIO进行初始化UART2_GPIO_Init(); //UART2 NVIC(中断控制器)NVIC_InitStruct.NVIC_IRQChannel = UART2_IRQn; // 中断通道为UART2NVIC_InitStruct.NVIC_IRQChannelPriority = 1; // 中断优先级为1NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 使能中断通道NVIC_Init(&NVIC_InitStruct); // 根据上述配置初始化NVICUART_ITConfig(UART2, UART_IT_RXIEN, ENABLE); // 使能串口接收中断UART_Cmd(UART2, ENABLE); // 使能UART2
}
(3)prinf重定义函数
- #include "stdio.h"
- 勾选包含微库
/**功能:重定义fput函数*参数:x*返回值:x*/
int fputc(int ch, FILE *f)
{UART_SendData(UART2, (uint8_t)ch);while (RESET == UART_GetFlagStatus(UART2, UART_FLAG_TXEPT));
// while((UART2->CSR & UART_IT_TXIEN) == 0); // 和上面一句等效return (ch);
}
(4)UART2中断接收函数
/**功能:串口2中断函数*参数:无*返回值:无*/
void UART2_IRQHandler(void)
{uint8_t RxData = 0;// 检查指定的串口中断是否发生:接收数据中断if (RESET != UART_GetITStatus(UART2, UART_IT_RXIEN)){RxData = UART_ReceiveData(UART2); // 接收数据printf("%c",RxData); // 打印接收到的数据UART_ClearITPendingBit(UART2, UART_IT_RXIEN); // 清空中断挂起标志位 }
}
(4)main函数
int main(void)
{SysTick_InitDelay();UART2_Init(115200);while (1){printf("hello world.\r\n");SysTick_DelayMS(1000); }
// return 0;
}
4.2、总结:串口配置流程
(1)串口GPIO初始化配置
(2)串口结构体初始化配置
(3)串口中断控制配置
(4)使能串口中断
(5)使能串口
4.3、完整工程下载地址
(1)完整工程存储在码云。
(2)MM32: 灵动微电子mm32单片机CSDN对应示例程序