usart.h
#ifndef UART_H
#define UART_H
#include "at32f403a_407_clock.h"
#define USART_QUEUE_SIZE 10
#define USART_BUF_SIZE 1024
// 队列结构体
typedef struct {
uint8_t buffer[USART_QUEUE_SIZE][USART_BUF_SIZE]; // 存储队列数据的缓冲区
uint16_t len[USART_QUEUE_SIZE]; // 存储队列数据的缓冲区
uint16_t front; // 队头
uint16_t rear; // 队尾
} Usart_Queue;
extern Usart_Queue usart1_queue;
void usart1_init(void);
void usart2_init(void);
void usart_send_byte( usart_type * pUSARTx, uint8_t ch);
void usart_send_string( usart_type * pUSARTx, char *str);
void usart_send_bytes( usart_type * pUSARTx, uint8_t* ch,int len);
void usart_queue_init(Usart_Queue* q);
int usart_queue_enqueue(Usart_Queue* q, uint8_t* data,uint16_t len);
int usart_queue_dequeue(Usart_Queue* q, uint8_t* data);
#endif
usart.c
#include "usart.h"
#include <string.h>
#define USART_HEADER 0X15
#define USART_TAIL 0X16
uint8_t usart1_receive_data[USART_BUF_SIZE];
uint16_t usart1_receive_index=0;
uint8_t usart1_is_receive_header=0;
Usart_Queue usart1_queue;
//串口1初始化
void usart1_init()
{
gpio_init_type gpio_init_struct;
usart_queue_init(&usart1_queue);
/* 使能对应端口的时钟 */
crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
/* 默认填充配置 */
gpio_default_para_init(&gpio_init_struct);
/* 设置 GPIO 驱动能力较大电流推动/吸入能力 */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
/* 设置 GPIO 输出类型为推挽输出模式 */
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
/* 设置 GPIO 模式为复用模式 */
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
/* 配置 GPIO 引脚 */
gpio_init_struct.gpio_pins = GPIO_PINS_9|GPIO_PINS_10;
/* 设置 GPIO 无上下拉模式 */
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
/* 初始化 GPIO 外设 */
gpio_init(GPIOA, &gpio_init_struct);
/* 波特率 数据位 停止位配置 */
usart_init(USART1, 9600, USART_DATA_8BITS, USART_STOP_1_BIT);
/* 中断优先级分组配置 */
nvic_priority_group_config(NVIC_PRIORITY_GROUP_1);
/* 中断使能及优先级配置 */
nvic_irq_enable(USART1_IRQn, 0,1);
/* 发送使能 */
usart_transmitter_enable(USART1, TRUE);
/* 接收使能 */
usart_receiver_enable(USART1, TRUE);
/* 中断使能 */
usart_interrupt_enable(USART1,USART_RDBF_INT, TRUE);
/* 串口使能 */
usart_enable(USART1, TRUE);
}
//串口2初始化
void usart2_init()
{
gpio_init_type gpio_init_struct;
/* 使能对应端口的时钟 */
crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
/* 默认填充配置 */
gpio_default_para_init(&gpio_init_struct);
/* 设置 GPIO 驱动能力较大电流推动/吸入能力 */
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
/* 设置 GPIO 输出类型为推挽输出模式 */
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
/* 设置 GPIO 模式为复用模式 */
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
/* 配置 GPIO 引脚 */
gpio_init_struct.gpio_pins = GPIO_PINS_2;
/* 设置 GPIO 无上下拉模式 */
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
/* 初始化 GPIO 外设 */
gpio_init(GPIOA, &gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_3;
gpio_init(GPIOA, &gpio_init_struct);
/* 波特率 数据位 停止位配置 */
usart_init(USART2, 9600, USART_DATA_8BITS, USART_STOP_1_BIT);
/* 中断优先级分组配置 */
nvic_priority_group_config(NVIC_PRIORITY_GROUP_1);
/* 中断使能及优先级配置 */
nvic_irq_enable(USART2_IRQn, 0,1);
/* 发送使能 */
usart_transmitter_enable(USART2, TRUE);
/* 接收使能 */
usart_receiver_enable(USART2, TRUE);
/* 中断使能 */
usart_interrupt_enable(USART2,USART_RDBF_INT, TRUE);
/* 串口使能 */
usart_enable(USART2, TRUE);
}
/***************** 发送一个字符 **********************/
void usart_send_byte( usart_type * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
usart_data_transmit(pUSARTx,ch);
/* 等待发送数据寄存器为空 */
while (usart_flag_get(pUSARTx, USART_TDBE_FLAG) == RESET);
}
/***************** 发送多个字符 **********************/
void usart_send_bytes( usart_type * pUSARTx, uint8_t* ch,int len)
{
int i;
for(i=0;i<len;i++)
{
usart_send_byte( pUSARTx, *(ch + i) );
}
}
/***************** 发送字符串 **********************/
void usart_send_string( usart_type * pUSARTx, char *str)
{
unsigned int k=0;
do
{
usart_send_byte( pUSARTx, *(str + k) );
k++;
} while(*(str + k)!='\0');
/* 等待发送完成 */
while(usart_flag_get(pUSARTx,USART_TDC_FLAG)==RESET)
{}
}
//串口1中断 接收
void USART1_IRQHandler(void)
{
uint8_t uc;
if(usart_flag_get(USART1, USART_RDBF_FLAG) != RESET)
{
uc = usart_data_receive(USART1);
usart1_receive_data[usart1_receive_index]=uc;
usart1_receive_index++;
if(uc==USART_HEADER)usart1_is_receive_header=1;
if((uc==USART_TAIL&&usart1_receive_index>=6&&usart1_is_receive_header)||usart1_receive_index>=USART_BUF_SIZE)
{
usart_queue_enqueue(&usart1_queue,usart1_receive_data,usart1_receive_index);
//usart_send_bytes(USART1,usart1_receive_data,usart1_receive_index);
usart1_receive_index=0;
usart1_is_receive_header=0;
}
}
}
//串口2中断 接收
void USART2_IRQHandler(void)
{
uint8_t uc;
if(usart_flag_get(USART2, USART_RDBF_FLAG) != RESET)
{
uc = usart_data_receive(USART2);
usart_data_transmit(USART2, uc);
}
}
// 初始化队列
void usart_queue_init(Usart_Queue* q) {
q->front = 0;
q->rear = 0;
}
// 判断队列是否为空
int usart_queue_is_empty(Usart_Queue* q) {
return q->front == q->rear;
}
// 判断队列是否为满
int usart_queue_is_full(Usart_Queue* q) {
return ((q->rear + 1) % USART_QUEUE_SIZE) == q->front;
}
// 入队操作
int usart_queue_enqueue(Usart_Queue* q, uint8_t* data,uint16_t len) {
if (usart_queue_is_full(q)) {
return -1; // 队列已满,无法入队
}
q->len[q->rear]=len;
memcpy(q->buffer[q->rear], data, USART_BUF_SIZE); // 复制数据到队列
q->rear = (q->rear + 1) % USART_QUEUE_SIZE; // 更新队尾索引
return 0;
}
// 出队操作
int usart_queue_dequeue(Usart_Queue* q, uint8_t* data) {
int len=0;
if (usart_queue_is_empty(q)) {
return 0; // 队列为空,无法出队
}
len=q->len[q->front];
memcpy(data, q->buffer[q->front], USART_BUF_SIZE); // 复制队头数据
q->front = (q->front + 1) % USART_QUEUE_SIZE; // 更新队头索引
return len;
}
main.c
while(1)
{
data_len = usart_queue_dequeue(&usart1_queue, item);
// 从队列中出队一个项
if (data_len != 0)
{
usart_send_bytes(USART1,item,data_len);
}
delay_ms(10);
}