#include "usart1.h" static struct queue usart1_rx_queue; /* * IO 管脚 * 接收管脚 PA10 USART1_RX (悬空输入) * 发送管脚 PA9 USART1_TX (复用推挽输出) * 另外一个线 VSS(共地) */ // 初始化 usart1, baud 为波特率 void usart1_init(uint32_t baud) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; // 初始化接收队列 queue_init(&usart1_rx_queue); // 使能 PA9 和 PA10 的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能 USART1 外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 设置 PA9 为发送管脚 // 复用推挽输出 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); // 设置 PA10 为接收管脚 // 悬空输入 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStruct); // 初始化 USART1 控制器 // 设置波特率 USART_InitStruct.USART_BaudRate = baud; // 字长 8bit USART_InitStruct.USART_WordLength = USART_WordLength_8b; // 停止位 1bit USART_InitStruct.USART_StopBits = USART_StopBits_1; // 校验位(无) USART_InitStruct.USART_Parity = USART_Parity_No; // 收发 USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 硬件流控制(无) USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_InitStruct); // 使能串口 1 USART_Cmd(USART1, ENABLE); // 初始化接受中断(暂不接收) USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 清除中断标志位 USART_ClearFlag(USART1, USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 中断通道 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); // 开启接收寄存器非空中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); } // 编写冲断处理函数 void USART1_IRQHandler(void) { uint8_t ch; // 如果是接收寄存器非空中断,则读取数据 if (USART_GetFlagStatus(USART1, USART_IT_RXNE) != RESET) { ch = USART_ReceiveData(USART1); // 将接收到的字符放入接收队列 // 如果队列已满会丢掉此字节 queue_enqueue(&usart1_rx_queue, ch); } } // 用于串口发送一个字节的数据 void usart1_put_char(uint8_t ch) { // 发送数据 USART_SendData(USART1, ch); // 等待发送数据完毕 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); } // 用于串口发送一段数据,遇到 '\0' 结束 void usart1_output(const char *buf) { const char *pchar; for (pchar = buf; *pchar; ++pchar) { usart1_put_char((uint8_t)*pchar); } } // 用于串口发送一段数据,遇到 '\0' 结束,末尾添加 '\r\n' 换行符结束 void usart1_output_aline(const char *buf) { usart1_output(buf); usart1_output("\r\n"); } // 从串口读取一行数据放入 buf, buf 的最大长度为 buf_len int usart1_input(char *buf, int buf_len) { int i = 0; int ch = '\0'; for (i = 0; i < buf_len - 1; i++) { if (queue_is_empty(&usart1_rx_queue)) { delay_ms(1); if (queue_is_empty(&usart1_rx_queue)) { break; } } queue_dequeue(&usart1_rx_queue, &ch); buf[i] = ch; } buf[i] = '\0'; return i; } // 从串口读取一行数据放入 buf, 当遇到 '\r\n' 时结束读取,并添加尾零 '\0' int usart1_input_aline(char *buf, int buf_len) { int i; int ch = '\0'; for ( i = 0; i < buf_len; i++) { // 等待,直到有数据读取 while (queue_is_empty(&usart1_rx_queue)) { delay_ms(1); } queue_dequeue(&usart1_rx_queue, &ch); buf[i] = ch; // 遇到换行符 if (ch == '\n') { buf[i] = '\0'; // 检查前一个字符是否是回车符 if (i >= 1 && buf[i - 1] == '\r') { i--; buf[i] = '\0'; } break; } } return i; } // 清空串口的接收队列 void usart1_clear_rx_queue(void) { } // 添加 fputc 函数,实现 printf 重定向 int fputc(int ch, FILE *f) { usart1_put_char(ch); return ch; } // 添加 fgetc 函数,实现 scanf 重定向 int fgetc(FILE *f) { int ch = '\0'; while (queue_is_empty(&usart1_rx_queue)) { delay_ms(1); } queue_dequeue(&usart1_rx_queue, &ch); return ch; }