Files
stm32-iot-sensor-node/mylib/usart1.c
T
2026-10-19 15:47:18 +08:00

194 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}