GD32 USART 高级编程 让你的串口不在阻塞发送


#ifndef __PLATFORM_USART_H__
#define __PLATFORM_USART_H__

#include "stdio.h"

#include <stdint.h>

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;
#endif


/*
 * 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()
 */
#include <gd32f30x.h>
#include "platform_usart.h"


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);
}


#include <stdarg.h>
#include <stdio.h>

/*
 * 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);
} 


#include <platform_systick.h>

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);
}


 

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
GD32E103的Keil编程中,串口发送数据可以通过如下步骤实现: 1. 初始化串口:首先需要初始化串口,设置串口的波特率、数据位、停止位、校验位等参数。 ```c usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_enable(USART0); ``` 2. 写入数据:使用`usart_data_transmit()`函数将数据写入串口缓冲区。 ```c uint8_t data[] = "Hello, world!"; for (int i = 0; i < strlen(data); i++) { usart_data_transmit(USART0, data[i]); while (usart_flag_get(USART0, USART_FLAG_TBE) == RESET) { // Wait until transmit complete } } ``` 在上述代码中,使用`usart_data_transmit()`函数将数据一个字节一个字节地写入串口缓冲区,并使用循环等待数据发送完成。在每个字节写入完成后,需要等待上一个字节发送完成,才能继续写入下一个字节,以确保数据的正确发送。 需要注意的是,如果要发送的数据较长,可以考虑使用DMA方式发送数据,以提高发送效率。同时,为了避免出现数据溢出等问题,需要根据实际情况设置合适的缓冲区大小,并进行数据校验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值