🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》
⛺️心若有所向往,何惧道阻且长
文章目录
- 需求
- 串口数据发送
- 串口打印实现
- 复用功能
- 串口发送流程(了解)
- 串口的标志位
- 关心的内容
需求
串口循环输出内容到PC机。
串口数据发送
添加Usart功能。
首先,选中Firmware,鼠标右键,点击Manage Project Items
接着,将gd32f4xx_usart.c添加到依赖中
最后,观察Firmware
static void USART_config() {/************** gpio config **************/// 配置时钟rcu_periph_clock_enable(RCU_GPIOA);// 配置模式gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);// 配置复用功能gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);// 配置输出参数gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);/************** usart config **************/// 串口时钟rcu_periph_clock_enable(RCU_USART0);// USART复位usart_deinit(USART0);// 波特率usart_baudrate_set(USART0, 115200);// 校验位usart_parity_config(USART0, USART_PM_NONE);// 数据位数usart_word_length_set(USART0, USART_WL_8BIT);// 停止位usart_stop_bit_set(USART0, USART_STB_1BIT);// 先发送高位还是低位usart_data_first_config(USART0, USART_MSBF_LSB);// 发送功能配置usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);// 使能串口usart_enable(USART0);
}
//发送一byte数据
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));
}
// 发送多个byte数据
void send_data_array(uint8_t* data, uint32_t len) {while(data && len--) {send_byte(*data);data++;}
}
//发送字符串
static void send_string(char *data){//满足: 1.data指针不为空 2.发送的数据不是\0结束标记while(data && *data){send_byte((uint8_t)(*data));data++;}
}
串口打印实现
int fputc(int ch, FILE *f){send_byte((uint8_t)ch);return ch;
}
复用功能
串口为PA9和PA10,通过文档查询复用功能。
串口发送流程(了解)
寄存器与电路。
- 数据发送缓存寄存器
- 状态寄存器
数据发送的流程,就是向发送缓冲区里放数据,这个发送缓存区寄存器只要有数据,就会触发电路,电路就按照这个数据模拟出高低电平往外发数据。
发送缓存区寄存器有个特点:“小”,只有一个byte,但是超快,寄存器在芯片内部寸土寸金。
但是存在一个问题,如果发送大量数据,这个寄存器的数据还没发送完成,会覆盖掉,这时候有一个状态寄存器记录了当前发送缓冲去是否是闲置的。(GD32是USART_FLAG_TBE,STM32是UART_FLAG_TXE)
串口的标志位
关心的内容
将代码进行抽取
static void USART_config() {uint32_t usartx_tx_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;uint32_t usartx_rx_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;uint32_t usartx = USART0;uint32_t usartx_rcu = RCU_USART0;uint32_t usartx_p_baudrate = 115200;uint32_t usartx_p_parity = USART_PM_NONE;uint32_t usartx_p_wl = USART_WL_8BIT;uint32_t usartx_p_stop_bit = USART_STB_1BIT;uint32_t usartx_p_data_first = USART_MSBF_LSB;/************** gpio config **************/// txrcu_periph_clock_enable(usartx_tx_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);// rxrcu_periph_clock_enable(usartx_rx_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 config **************/// 串口时钟rcu_periph_clock_enable(RCU_USART0);// USART复位usart_deinit(usartx);usart_baudrate_set(usartx, usartx_p_baudrate); // 波特率usart_parity_config(usartx, usartx_p_parity); // 校验位usart_word_length_set(usartx, usartx_p_wl); // 数据位数usart_stop_bit_set(usartx, usartx_p_stop_bit); // 停止位usart_data_first_config(usartx, usartx_p_data_first); // 先发送高位还是低位// 发送功能配置usart_transmit_config(usartx, USART_TRANSMIT_ENABLE); // 使能串口usart_enable(usartx);
}
总结起来:
GPIO引脚配置
uint32_t usartx_tx_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;uint32_t usartx_rx_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;
串口配置
uint32_t usartx = USART0;
uint32_t usartx_rcu = RCU_USART0;uint32_t usartx_p_baudrate = 115200;
uint32_t usartx_p_parity = USART_PM_NONE;
uint32_t usartx_p_wl = USART_WL_8BIT;
uint32_t usartx_p_stop_bit = USART_STB_1BIT;
uint32_t usartx_p_data_first = USART_MSBF_LSB;
完整示例
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"static void USART_config() {uint32_t usartx_tx_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;uint32_t usartx_rx_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;uint32_t usartx = USART0;uint32_t usartx_rcu = RCU_USART0;uint32_t usartx_p_baudrate = 115200;uint32_t usartx_p_parity = USART_PM_NONE;uint32_t usartx_p_wl = USART_WL_8BIT;uint32_t usartx_p_stop_bit = USART_STB_1BIT;uint32_t usartx_p_data_first = USART_MSBF_LSB;/************** gpio config **************/// txrcu_periph_clock_enable(usartx_tx_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);// rxrcu_periph_clock_enable(usartx_rx_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 config **************/// 串口时钟rcu_periph_clock_enable(RCU_USART0);// USART复位usart_deinit(usartx);usart_baudrate_set(usartx, usartx_p_baudrate); // 波特率usart_parity_config(usartx, usartx_p_parity); // 校验位usart_word_length_set(usartx, usartx_p_wl); // 数据位数usart_stop_bit_set(usartx, usartx_p_stop_bit); // 停止位usart_data_first_config(usartx, usartx_p_data_first); // 先发送高位还是低位// 发送功能配置usart_transmit_config(usartx, USART_TRANSMIT_ENABLE); // 使能串口usart_enable(usartx);
}//发送一byte数据
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));
}// 发送多个byte数据
void send_data(uint8_t* data, uint32_t len) {while(data && len--) {send_byte(*data);data++;}
}//发送字符串
void send_string(char *data){//满足: 1.data指针不为空 2.发送的数据不是\0结束标记while(data && *data){send_byte((uint8_t)(*data));data++;}
}int fputc(int ch, FILE *f){send_byte((uint8_t)ch);return ch;
}int main(void)
{systick_config();USART_config();uint8_t cnt;while(1) {// send_byte(cnt++);// send_string("hello\r\n");// printf("hello %d\r\n", cnt++);delay_1ms(1000);}
}