串口模板V1.0
源码
#ifndef __USART0_H__
#define __USART0_H__
#include "gd32f4xx.h"
#include <stdio.h>
#define USART0_RX_ENABLE 1
void Usart0_init();
void Usart0_send_byte(uint8_t data);
void Usart0_send_string(char* data);
#if USART0_RX_ENABLE
extern void Usart0_recv(uint8_t* data, uint32_t len);
#endif
#endif
#include "Usart0.h"
#if USART0_RX_ENABLE
#define USART_RECEIVE_LENGTH 1024
//串口接收缓冲区大小
uint8_t g_recv_buff[USART_RECEIVE_LENGTH]; // 接收缓冲区
//接收到字符存放的位置
uint32_t g_recv_length = 0;
#endif
//1. 初始化
void Usart0_init() {
// 哪个串口
uint32_t usartx = USART0;
uint32_t usartx_rcu = RCU_USART0;
uint32_t usartx_irq = USART0_IRQn;
// 波特率
uint32_t usartx_p_baudrate = 115200;
// tx和rx,用了哪个引脚
uint32_t usartx_tx_port_rcu = RCU_GPIOA;
uint32_t usartx_tx_port = GPIOA;
uint32_t usartx_tx_pin = GPIO_PIN_9;
// 复用功能编号
uint32_t usartx_tx_af = GPIO_AF_7;
// tx和rx,用了哪个引脚
uint32_t usartx_rx_port_rcu = RCU_GPIOA;
uint32_t usartx_rx_port = GPIOA;
uint32_t usartx_rx_pin = GPIO_PIN_10;
// 复用功能编号
uint32_t usartx_rx_af = GPIO_AF_7;
/*************** gpio *****************/
// TX
// 配置时钟
rcu_periph_clock_enable(usartx_tx_port_rcu);
// 配置模式: 复用功能
gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
// 配置复用功能
gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
// RX
// 配置时钟
rcu_periph_clock_enable(usartx_rx_port_rcu);
gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
// 配置输出参数
gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
/*************** usart ****************/
// 串口时钟
rcu_periph_clock_enable(usartx_rcu);
// USART复位
usart_deinit(usartx);
// 波特率
usart_baudrate_set(usartx, usartx_p_baudrate);
// 校验位
usart_parity_config(usartx, USART_PM_NONE);
// 数据位数
usart_word_length_set(usartx, USART_WL_8BIT);
// 停止位
usart_stop_bit_set(usartx, USART_STB_1BIT);
// 先发送高位还是低位
usart_data_first_config(usartx, USART_MSBF_LSB);
// 发送功能配置
usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
#if USART0_RX_ENABLE
// 接收功能配置
usart_receive_config(usartx, USART_RECEIVE_ENABLE);
// 接收中断配置
nvic_irq_enable(usartx_irq, 2, 2);
// usart int rbne
usart_interrupt_enable(usartx, USART_INT_RBNE);
usart_interrupt_enable(usartx, USART_INT_IDLE);
#endif
// 使能串口
usart_enable(usartx);
}
//2. 发送
void Usart0_send_byte(uint8_t data) {
//通过USART发送
usart_data_transmit(USART0, data);
//判断缓冲区是否已经空了
//FlagStatus state = usart_flag_get(USART_NUM,USART_FLAG_TBE);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
void Usart0_send_string(char* data) {
while(data && *data) {
Usart0_send_byte((uint8_t)(*data));
data++;
}
}
// printf打印功能
int fputc(int ch, FILE *f){
Usart0_send_byte((uint8_t)ch);
return ch;
}
#if USART0_RX_ENABLE
// 名称不能随意改,串口0的中断,就是这个名字
void USART0_IRQHandler(void) {
if ((usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) == SET) {
uint16_t value = usart_data_receive(USART0);
g_recv_buff[g_recv_length] = value;
g_recv_length++;
}
if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) == SET) {
//读取缓冲区,清空缓冲区
usart_data_receive(USART0);
g_recv_buff[g_recv_length] = '\0';
// TODO: g_recv_buff为接收的数据,g_recv_length为接收的长度
// printf("recv: %s\r\n", g_recv_buff);
Usart0_recv(g_recv_buff, g_recv_length);
g_recv_length = 0;
}
}
#endif
使用
Usart0_init();
Usart0_send_byte(0x00);
Usart0_send_string("");
串口底层
初始化
// 哪个串口
uint32_t usartx = USART0;
uint32_t usartx_rcu = RCU_USART0;
uint32_t usartx_irq = USART0_IRQn;
// 波特率
uint32_t usartx_p_baudrate = 115200;
// tx和rx,用了哪个引脚
uint32_t usartx_tx_port_rcu = RCU_GPIOA;
uint32_t usartx_tx_port = GPIOA;
uint32_t usartx_tx_pin = GPIO_PIN_9;
// 复用功能编号
uint32_t usartx_tx_af = GPIO_AF_7;
// tx和rx,用了哪个引脚
uint32_t usartx_rx_port_rcu = RCU_GPIOA;
uint32_t usartx_rx_port = GPIOA;
uint32_t usartx_rx_pin = GPIO_PIN_10;
// 复用功能编号
uint32_t usartx_rx_af = GPIO_AF_7;
/*************** gpio *****************/
// TX
// 配置时钟
rcu_periph_clock_enable(usartx_tx_port_rcu);
// 配置模式: 复用功能
gpio_mode_set(usartx_tx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_tx_pin);
// 配置复用功能
gpio_af_set(usartx_tx_port, usartx_tx_af, usartx_tx_pin);
gpio_output_options_set(usartx_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_tx_pin);
// RX
// 配置时钟
rcu_periph_clock_enable(usartx_rx_port_rcu);
gpio_mode_set(usartx_rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, usartx_rx_pin);
gpio_af_set(usartx_rx_port, usartx_rx_af, usartx_rx_pin);
// 配置输出参数
gpio_output_options_set(usartx_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, usartx_rx_pin);
/*************** usart ****************/
// 串口时钟
rcu_periph_clock_enable(usartx_rcu);
// USART复位
usart_deinit(usartx);
// 波特率
usart_baudrate_set(usartx, usartx_p_baudrate);
// 校验位
usart_parity_config(usartx, USART_PM_NONE);
// 数据位数
usart_word_length_set(usartx, USART_WL_8BIT);
// 停止位
usart_stop_bit_set(usartx, USART_STB_1BIT);
// 先发送高位还是低位
usart_data_first_config(usartx, USART_MSBF_LSB);
// 发送功能配置
usart_transmit_config(usartx, USART_TRANSMIT_ENABLE);
// 接收功能配置
usart_receive_config(usartx, USART_RECEIVE_ENABLE);
// 接收中断配置
nvic_irq_enable(usartx_irq, 2, 2);
// usart int rbne
usart_interrupt_enable(usartx, USART_INT_RBNE);
usart_interrupt_enable(usartx, USART_INT_IDLE);
// 使能串口
usart_enable(usartx);
发送字节
static void send_byte(uint8_t data) {
//通过USART发送
usart_data_transmit(USART0, data);
//判断缓冲区是否已经空了
//FlagStatus state = usart_flag_get(USART_NUM,USART_FLAG_TBE);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
发送字符串
static void send_string(char* data) {
while(data && *data){
send_byte((uint8_t)(*data));
data++;
}
}
配置Printf
int fputc(int ch, FILE *f){
send_byte((uint8_t)ch);
return ch;
}
中断接收
void USART0_IRQHandler(void) {
if ((usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) == SET) {
uint16_t value = usart_data_receive(USART0);
g_recv_buff[g_recv_length] = value;
g_recv_length++;
}
if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE) == SET) {
//读取缓冲区,清空缓冲区
usart_data_receive(USART0);
g_recv_buff[g_recv_length] = '\0';
// TODO: g_recv_buff为接收的数据,g_recv_length为接收的长度
printf("recv: %s\r\n", g_recv_buff);
g_recv_length = 0;
}
}