GD32 USART 高级编程 让你的串口不在阻塞发送
typedef struct {
uint32_t usart_periph;
uint8_t *tx_buf;
uint16_t tx_buf_size;
uint16_t tx_rd;
uint16_t tx_wr;
uint8_t *rx_buf;
uint16_t rx_buf_size;
uint16_t rx_rd;
uint16_t rx_wr;
void (*config)(void);
void (*deconfig)(void);
} usart_context_t;
void usart_config_init(usart_context_t *pusart_context, uint32_t baud_rate);
void usart_config_deinit(usart_context_t *pusart_context);
void usart_send_it(usart_context_t *pusart_context, const void *_send_buf, const uint16_t send_count);
void usart_wait_sned_finished(usart_context_t *pusart_context);
void usart_it(usart_context_t *pusart_context);
int usart_receive_read(usart_context_t *pusart_context, void *_receive_buf, const int receive_count);
void usart_printf(usart_context_t *pusart_context, char *arg, ...);
void u_tm_log(char *arg, ...);
void u_log(char *arg, ...);
extern usart_context_t usart0_context;
extern usart_context_t usart1_context;
extern usart_context_t usart3_context;
extern usart_context_t usart4_context;
/*
* Copyright (C) 2017, 2020 huohongpeng
* Author: huohongpeng <1045338804@qq.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Change logs:
* Date Author Notes
* 2017-02-29 huohongpeng First add
* 2020-09-19 huohongpeng add u_tm_log()
*/
static uint8_t usart0_tx_buf[1024];
static uint8_t usart0_rx_buf[16];
static uint8_t usart1_tx_buf[128];
static uint8_t usart1_rx_buf[128];
static uint8_t usart3_tx_buf[128];
static uint8_t usart3_rx_buf[128];
static uint8_t usart4_tx_buf[128];
static uint8_t usart4_rx_buf[128];
static void usart0_config(void)
{
nvic_irq_enable(USART0_IRQn, 0, 1);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_USART0);
/* connect port to USARTx_Tx */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
/* connect port to USARTx_Rx */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
}
static void usart1_config(void)
{
nvic_irq_enable(USART1_IRQn, 1, 1);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_USART1);
rcu_periph_clock_enable(RCU_AF);
gpio_pin_remap_config(GPIO_USART1_REMAP, ENABLE);
/* connect port to USARTx_Tx */
gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5);
/* connect port to USARTx_Rx */
gpio_init(GPIOD, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
}
static void usart3_config(void)
{
nvic_irq_enable(UART3_IRQn, 1, 1);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_UART3);
/* connect port to USARTx_Tx */
gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/* connect port to USARTx_Rx */
gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
}
static void usart4_config(void)
{
nvic_irq_enable(UART4_IRQn, 1, 1);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_UART4);
/* connect port to USARTx_Tx */
gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
/* connect port to USARTx_Rx */
gpio_init(GPIOD, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
}
static void usart0_deconfig(void)
{
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
nvic_irq_disable(USART0_IRQn);
rcu_periph_clock_disable(RCU_GPIOA);
rcu_periph_clock_disable(RCU_USART0);
}
static void usart1_deconfig(void)
{
}
static void usart3_deconfig(void)
{
}
static void usart4_deconfig(void)
{
}
usart_context_t usart0_context = {
USART0,
usart0_tx_buf,
sizeof(usart0_tx_buf),
0,
0,
usart0_rx_buf,
sizeof(usart0_rx_buf),
0,
0,
usart0_config,
usart0_deconfig
};
usart_context_t usart1_context = {
USART1,
usart1_tx_buf,
sizeof(usart1_tx_buf),
0,
0,
usart1_rx_buf,
sizeof(usart1_rx_buf),
0,
0,
usart1_config,
usart1_deconfig,
};
usart_context_t usart3_context = {
UART3,
usart3_tx_buf,
sizeof(usart3_tx_buf),
0,
0,
usart3_rx_buf,
sizeof(usart3_rx_buf),
0,
0,
usart3_config,
usart3_deconfig,
};
usart_context_t usart4_context = {
UART4,
usart4_tx_buf,
sizeof(usart4_tx_buf),
0,
0,
usart4_rx_buf,
sizeof(usart4_rx_buf),
0,
0,
usart4_config,
usart4_deconfig,
};
void usart_config_init(usart_context_t *pusart_context, uint32_t baud_rate)
{
pusart_context->config();
/* USART configure */
usart_deinit(pusart_context->usart_periph);
usart_baudrate_set(pusart_context->usart_periph, baud_rate);
usart_receive_config(pusart_context->usart_periph, USART_RECEIVE_ENABLE);
usart_transmit_config(pusart_context->usart_periph, USART_TRANSMIT_ENABLE);
usart_word_length_set(pusart_context->usart_periph, USART_WL_8BIT);
usart_stop_bit_set(pusart_context->usart_periph, USART_STB_1BIT);
usart_enable(pusart_context->usart_periph);
usart_interrupt_enable(pusart_context->usart_periph, USART_INT_RBNE);
}
void usart_config_deinit(usart_context_t *pusart_context)
{
usart_disable(pusart_context->usart_periph);
usart_deinit(pusart_context->usart_periph);
pusart_context->deconfig();
}
/*
* Rewrite fputc for printf
* NOTE: IAR options->C/C++ compiler->preprocessor add symbal _DLIB_FILE_DESCRIPTOR
*/
int fputc(int ch, FILE *f)
{
usart_send_it(&usart0_context, &ch, 1);
return ch;
}
void usart_send(usart_context_t *pusart_context, const void *_send_buf, const uint16_t send_count)
{
const uint8_t *send_buf = (const uint8_t *)_send_buf;
uint16_t i;
for(i = 0; i < send_count; i++) {
while(RESET == usart_flag_get(pusart_context->usart_periph, USART_FLAG_TBE));
usart_data_transmit(pusart_context->usart_periph, (uint8_t)send_buf[i]);
}
while(RESET == usart_flag_get(pusart_context->usart_periph, USART_FLAG_TC));
}
/*
* Usart send base on usart send interrupt
*/
void usart_send_it(usart_context_t *pusart_context, const void *_send_buf, const uint16_t send_count)
{
const uint8_t *send_buf = (const uint8_t *)_send_buf;
uint16_t i;
/*
* Write send data to send buffer and use interrupt send data.
* Wait buffer effective when send buffer is full.
*/
for(i = 0; i < send_count; i++) {
while((pusart_context->tx_wr+1) % pusart_context->tx_buf_size == pusart_context->tx_rd);
pusart_context->tx_buf[pusart_context->tx_wr++] = send_buf[i];
pusart_context->tx_wr %= pusart_context->tx_buf_size;
usart_interrupt_enable(pusart_context->usart_periph, USART_INT_TBE);
}
}
void usart_wait_sned_finished(usart_context_t *pusart_context)
{
while(pusart_context->tx_wr != pusart_context->tx_rd);
while(RESET == usart_flag_get(pusart_context->usart_periph, USART_FLAG_TC));
}
/*
* read data from receive buffer
*/
int usart_receive_read(usart_context_t *pusart_context, void *_receive_buf, const int receive_count)
{
uint8_t *receive_buf = (uint8_t *)_receive_buf;
int i, receive_count_real;
/*
* Read data from receive buffer.
* The buffer have data that received from usart.
*/
for(i = 0, receive_count_real = 0; i < receive_count; i++) {
if(pusart_context->rx_rd == pusart_context->rx_wr) {
return receive_count_real;
} else {
receive_buf[i] = pusart_context->rx_buf[pusart_context->rx_rd++];
pusart_context->rx_rd %= pusart_context->rx_buf_size;
receive_count_real++;
}
}
return receive_count_real;
}
static void usart_rbne_it(usart_context_t *pusart_context)
{
pusart_context->rx_buf[pusart_context->rx_wr++] = usart_data_receive(pusart_context->usart_periph);
pusart_context->rx_wr %= pusart_context->rx_buf_size;
/*
* overflow handle
*/
if(pusart_context->rx_wr == pusart_context->rx_rd) {
pusart_context->rx_rd++;
pusart_context->rx_rd %= pusart_context->rx_buf_size;
}
}
static void usart_tbe_it(usart_context_t *pusart_context)
{
if(pusart_context->tx_rd != pusart_context->tx_wr) {
usart_data_transmit(pusart_context->usart_periph, pusart_context->tx_buf[pusart_context->tx_rd++]);
pusart_context->tx_rd %= pusart_context->tx_buf_size;
} else {
usart_interrupt_disable(pusart_context->usart_periph, USART_INT_TBE);
}
}
void usart_it(usart_context_t *pusart_context)
{
if(usart_interrupt_flag_get(pusart_context->usart_periph, USART_INT_FLAG_RBNE) == SET) {
usart_interrupt_flag_clear(pusart_context->usart_periph, USART_INT_FLAG_RBNE);
usart_rbne_it(pusart_context);
}
if(usart_interrupt_flag_get(pusart_context->usart_periph, USART_INT_FLAG_TBE) == SET) {
usart_interrupt_flag_clear(pusart_context->usart_periph, USART_INT_FLAG_TBE);
usart_tbe_it(pusart_context);
}
if(usart_interrupt_flag_get(pusart_context->usart_periph, USART_INT_FLAG_ERR_ORERR) == SET) {
usart_interrupt_flag_clear(pusart_context->usart_periph, USART_INT_FLAG_ERR_ORERR);
}
}
void USART0_IRQHandler(void)
{
usart_it(&usart0_context);
}
void USART1_IRQHandler(void)
{
usart_it(&usart1_context);
}
void UART3_IRQHandler(void)
{
usart_it(&usart3_context);
}
void UART4_IRQHandler(void)
{
usart_it(&usart4_context);
}
/*
* usart printf function
*/
void usart_printf(usart_context_t *pusart_context, char *arg, ...)
{
char buf[256], len;
va_list vl;
__va_start(vl, arg);
len = vsprintf(buf, arg, vl);
__va_end(vl);
usart_send_it(pusart_context, buf, len);
}
void u_tm_log(char *arg, ...)
{
char buf[512];
uint32_t s, ms, len , n;
uint32_t tm = get_systick_ms();
s = tm / 1000;
ms = tm % 1000;
n = sprintf(buf, "[%d.%03d] ", s, ms);
va_list vl;
__va_start(vl, arg);
len = vsprintf(buf+n, arg, vl);
__va_end(vl);
len = len+n;
usart_send_it(&usart0_context, buf, len);
}
void u_log(char *arg, ...)
{
char buf[512];
uint32_t len;
va_list vl;
__va_start(vl, arg);
len = vsprintf(buf, arg, vl);
__va_end(vl);
usart_send_it(&usart0_context, buf, len);
}
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧ END ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
关注我的微信公众号,回复“加群”按规则加入技术交流群。
点击下面图片,有星球具体介绍,新用户有新人优惠券,老用户半价优惠,期待大家一起学习一起进步。
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。
评论