194 lines
5.1 KiB
C
194 lines
5.1 KiB
C
#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;
|
||
}
|