串口模板V1.0
源码
#ifndef __USART0_H__#define __USART0_H__#include "gd32f4xx.h"#include <stdio.h>#define USART0_RX_ENABLE 1void Usart0_init();void Usart0_send_byte(uint8_t data);void Usart0_send_string(char* data);#if USART0_RX_ENABLEextern 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 rbneusart_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; }}