06_串口通信
6.1 概述
6.2 串口设置
6.2.1 初始化
PA9 作为串口1 的输出
PA10 作为串口1的输入
void UART_Init(void){ // 1.打开GPIOA/USART1控制器时钟 - APB2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 2.配置PA9 - 推挽复用输出, 50MHz GPIO_InitTypeDef GPIO_Config; GPIO_Config.GPIO_Pin = GPIO_Pin_9; GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Config.GPIO_Mode = GPIO_Mode_AF_PP; // 需要设置成 复用推挽输出 模式 GPIO_Init(GPIOA, &GPIO_Config); // 3.配置PA10 - 浮空输入 GPIO_Config.GPIO_Pin = GPIO_Pin_10; GPIO_Config.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(GPIOA, &GPIO_Config); // 4.配置工作参数: 115200 8n1 TX+RX USART_InitTypeDef UART_Config; UART_Config.USART_BaudRate = 115200; UART_Config.USART_WordLength = USART_WordLength_8b; UART_Config.USART_Parity = USART_Parity_No; UART_Config.USART_StopBits = USART_StopBits_1; UART_Config.USART_Mode = USART_Mode_Tx|USART_Mode_Rx; UART_Config.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &UART_Config); // 5.使能串口1 USART_Cmd(USART1, ENABLE); }
6.2.2 串口输出
// 发送一个字符 void UART_Putc(char c){ // 循环的判断 // TC, SET, 可以发送; RESET, 不能发送 while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); // 将字符c放入到串口1的DR中 USART_SendData(USART1, c); } // 发送一个字符串 // char* pstr = "hello"; void UART_Puts(char* pstr){ while(*pstr){ UART_Putc(*pstr); pstr++; } }
6.2.3 串口输入
// 获取一个字符 char UART_Getc(void) { // RXNE // RESET, DR没有数据, 陷入循环; SET, 有数据, 跳出循环 while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET); // 从串口1中获取一个字符 return (char)USART_ReceiveData(USART1); } // char buf[len]; // 上位机 - "xxxx\r\n" -> "xxxx" // "hello\r\n" -> "hello\0\n" -> "hello" // 对接收的字符串做了 调整 void UART_Gets(char* buf, u32 len) { int i = 0; for( i = 0; i < (len-1); i++) { buf[i] = UART_Getc(); if (buf[i] == '\n') break; } buf[i-1] = '\0'; }
6.3 串口使用中断
6.3.1 在uart初始化中设置中断
void UART_Init(void){ // 1.打开GPIOA/USART1控制器时钟 - APB2 // 2.配置PA9 - 推挽复用输出, 50MHz // 3.配置PA10 - 浮空输入 // 4.配置工作参数: 115200 8n1 TX+RX // 5.使能串口1 // ....... // 6.配置NVIC支持串口1的中断 NVIC_InitTypeDef NVIC_Config; NVIC_Config.NVIC_IRQChannel = USART1_IRQn;// 串口1的中断通道 NVIC_Config.NVIC_IRQChannelPreemptionPriority = 0; NVIC_Config.NVIC_IRQChannelSubPriority = 2; NVIC_Config.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_Config); // 7.配置USART1控制器支持RXNE中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 外设数据-> 串口1的DR // 串口1 -> RXNE中断 -> NVIC -> CPU核 -> 中断处理函数 // 触发了多次中断 -> 多次调用中断处理函数 }
6.3.2 串口中断处理函数
一般我们对串口接收 设置中断, 中断到达后, 设置flag. 然后在main中检查 该flag,
// 定义串口1接收数组长度 #define UART_RXBUFF_SIZE 1024 // 声明串口1的接收数组 char UART_RxBuff[UART_RXBUFF_SIZE]; // 用于计数 / 下标 int UART_RxCounter = 0; // 声明变量表示数据是否读取结束 // 0,数据正在读取; 1,数据读取完毕; int UART_Send_Flag = 0; // 串口1的中断处理函数 // "led on\r\n" // 0123456 7 // ^-counter void USART1_IRQHandler(void) { char c; // 判断是否是RXNE中断 if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { // 清除中断到来位 USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 从DR寄存器中读取数据 c = USART_ReceiveData(USART1); UART_RxBuff[UART_RxCounter++] = c; if ('\n' == c) { // 读取结束 UART_RxBuff[UART_RxCounter-2] = '\0'; // 将UART_RxCounter清0 UART_RxCounter = 0; // 数据读取结束 UART_Send_Flag = 1; } } }