前言
- 本次使用的os为threadx,版本为6.4
- 芯片使用的是gd32f425,开发库为GD官方提供的标准库
- 开发环境使用的使用clion
- 参考驱动程序为arm硬汉的stm32f4 串口驱动程序编写而成
- 目前驱动只做了串口0的中断收发,如需其他串口请自行添加,根据实际情况可以在此基础上增加dma和空闲中断的方式
串口驱动
头文件
#ifndef TX_GD32F425_DRV_USART_H
#define TX_GD32F425_DRV_USART_H
#define UART0_FIFO_EN (1)
typedef struct uart_struct {
uint32_t uart_periph;
uint8_t *pTxBuf;
uint8_t *pRxBuf;
uint16_t usTxBufSize;
uint16_t usRxBufSize;
__IO uint16_t usTxWrite;
__IO uint16_t usTxRead;
__IO uint16_t usTxCount;
__IO uint16_t usRxWrite;
__IO uint16_t usRxRead;
__IO uint16_t usRxCount;
void (*RS485Init)(struct uart_struct *uart);
void (*SendBefore)(struct uart_struct *uart);
void (*SendOver)(struct uart_struct *uart);
void (*ReceiveNew)(struct uart_struct *uart, uint8_t _byte);
uint8_t Sending;
} uart_t;
#ifdef UART0_FIFO_EN
#define UART0_BAUD 115200
#define UART0_TX_BUF_SIZE 1024
#define UART0_RX_BUF_SIZE 1024
#endif
void drv_usart_callback_set(uint32_t uart_periph,
void (*pRS485Init)(uart_t *uart),
void (*pSendBefore)(uart_t *uart),
void (*pSendOver)(uart_t *uart),
void (*pReceiveNew)(uart_t *uart, uint8_t _byte)
);
void drv_usart_init(void);
uart_t *uart_get_by_periph(uint32_t uart_periph);
void uart_send(uint32_t uart_periph, uint8_t *_ucaBuf, uint16_t _usLen);
void uart_send_block(uint32_t uart_periph, uint8_t *_ucaBuf, uint16_t _usLen);
uint8_t uart_get_byte(uint32_t uart_periph, uint8_t *_pByte);
uint16_t uart_get_bytes(uint32_t uart_periph, uint8_t *_pBuf, uint16_t _usLen);
#endif
源文件
#include "board.h"
#include "drv_usart.h"
#define USART0_TX_CLK RCU_GPIOA
#define USART0_TX_PORT GPIOA
#define USART0_TX_PIN GPIO_PIN_9
#define USART0_TX_AF GPIO_AF_7
#define USART0_RX_CLK RCU_GPIOA
#define USART0_RX_PORT GPIOA
#define USART0_RX_PIN GPIO_PIN_10
#define USART0_RX_AF GPIO_AF_7
static void usart_gpio_init(uint32_t tx_port, uint32_t tx_pin, uint32_t tx_af,
uint32_t rx_port, uint32_t rx_pin, uint32_t rx_af) {
gpio_af_set(tx_port, rx_af, rx_pin);
gpio_af_set(rx_port, tx_af, tx_pin);
gpio_mode_set(tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, tx_pin);
gpio_output_options_set(tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, tx_pin);
gpio_mode_set(rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, rx_pin);
gpio_output_options_set(rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, rx_pin);
}
#if UART0_FIFO_EN == 1
static uart_t g_tUart0 = {0};
static uint8_t g_TxBuf0[UART0_TX_BUF_SIZE];
static uint8_t g_RxBuf0[UART0_RX_BUF_SIZE];
#endif
static void usart_var_init(void);
static void usart_hard_init(void);
static void usart_rs485_init(void);
static void uart_real_send(uart_t *_pUart, const uint8_t *_ucaBuf, uint16_t _usLen);
static uint8_t uart_real_get_byte(uart_t *_pUart, uint8_t *_pByte);
static uint16_t uart_real_get_bytes(uart_t *_pUart, uint8_t *_pucaBuf, uint16_t _usLen);
void drv_usart_callback_set(uint32_t uart_periph,
void (*pRS485Init)(uart_t *uart),
void (*pSendBefore)(uart_t *uart),
void (*pSendOver)(uart_t *uart),
void (*pReceiveNew)(uart_t *uart, uint8_t _byte)
) {
uart_t *pUart;
pUart = uart_get_by_periph(uart_periph);
if (pUart == 0) {
return;
}
pUart->RS485Init = pRS485Init;
pUart->SendBefore = pSendBefore;
pUart->SendOver = pSendOver;
pUart->ReceiveNew = pReceiveNew;
}
void drv_usart_init(void) {
usart_var_init();
usart_hard_init();
usart_rs485_init();
}
uart_t *uart_get_by_periph(uint32_t uart_periph) {
#if UART0_FIFO_EN == 1
if (uart_periph == USART0) return &g_tUart0;
#endif
return NULL;
}
void uart_send(uint32_t uart_periph, uint8_t *_ucaBuf, uint16_t _usLen) {
uart_t *pUart;
pUart = uart_get_by_periph(uart_periph);
if (pUart == 0) {
return;
}
if (pUart->SendBefore != 0) {
pUart->SendBefore(pUart);
}
uart_real_send(pUart, _ucaBuf, _usLen);
}
void uart_send_block(uint32_t uart_periph, uint8_t *_ucaBuf, uint16_t _usLen) {
uart_t *pUart;
pUart = uart_get_by_periph(uart_periph);
if (pUart == 0) {
return;
}
if (pUart->SendBefore != 0) {
pUart->SendBefore(pUart);
}
for (int i = 0; i < _usLen; ++i) {
usart_data_transmit(uart_periph, _ucaBuf[i]);
while (!usart_flag_get(uart_periph, USART_FLAG_TBE));
}
if (pUart->SendOver) {
pUart->SendOver(pUart);
}
}
uint8_t uart_get_byte(uint32_t uart_periph, uint8_t *_pByte) {
uart_t *pUart;
pUart = uart_get_by_periph(uart_periph);
if (pUart == 0) {
return 0;
}
return uart_real_get_byte(pUart, _pByte);
}
uint16_t uart_get_bytes(uint32_t uart_periph, uint8_t *_pBuf, uint16_t _usLen) {
uart_t *pUart;
pUart = uart_get_by_periph(uart_periph);
if (pUart == 0) {
return 0;
}
return uart_real_get_bytes(pUart, _pBuf, _usLen);
}
static void usart_var_init(void) {
#if UART0_FIFO_EN == 1
g_tUart0.uart_periph = USART0;
g_tUart0.pTxBuf = g_TxBuf0;
g_tUart0.pRxBuf = g_RxBuf0;
g_tUart0.usTxBufSize = UART0_TX_BUF_SIZE;
g_tUart0.usRxBufSize = UART0_RX_BUF_SIZE;
#endif
}
static void usart_hard_init(void) {
#if UART0_FIFO_EN == 1
nvic_irq_enable(USART0_IRQn, 0, 0);
rcu_periph_clock_enable(USART0_TX_CLK);
rcu_periph_clock_enable(USART0_RX_CLK);
rcu_periph_clock_enable(RCU_USART0);
usart_gpio_init(USART0_TX_PORT, USART0_TX_PIN, USART0_TX_AF,
USART0_RX_PORT, USART0_RX_PIN, USART0_RX_AF);
usart_deinit(USART0);
usart_baudrate_set(USART0, UART0_BAUD);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
usart_interrupt_enable(USART0, USART_INT_RBNE);
#endif
}
static void usart_rs485_init(void) {
#if UART0_FIFO_EN == 1
if (g_tUart0.RS485Init) g_tUart0.RS485Init(&g_tUart0);
#endif
}
static void uart_real_send(uart_t *_pUart, const uint8_t *_ucaBuf, uint16_t _usLen) {
uint16_t i;
BSP_DEF_CRITICAL_SECTION
for (i = 0; i < _usLen; i++) {
while (1) {
__IO uint16_t usCount;
BSP_ENTER_CRITICAL;
usCount = _pUart->usTxCount;
BSP_EXIT_CRITICAL;
if (usCount < _pUart->usTxBufSize) {
break;
} else if (usCount == _pUart->usTxBufSize) {
if (RESET == usart_interrupt_flag_get(_pUart->uart_periph, USART_INT_FLAG_TBE)) {
usart_interrupt_enable(_pUart->uart_periph, USART_INT_TBE);
}
}
}
_pUart->pTxBuf[_pUart->usTxWrite] = _ucaBuf[i];
BSP_ENTER_CRITICAL;
if (++_pUart->usTxWrite >= _pUart->usTxBufSize) {
_pUart->usTxWrite = 0;
}
_pUart->usTxCount++;
BSP_EXIT_CRITICAL;
}
usart_interrupt_enable(_pUart->uart_periph, USART_INT_TBE);
}
static uint8_t uart_real_get_byte(uart_t *_pUart, uint8_t *_pByte) {
uint16_t usCount;
BSP_DEF_CRITICAL_SECTION
BSP_ENTER_CRITICAL;
usCount = _pUart->usRxCount;
BSP_EXIT_CRITICAL;
if (usCount == 0)
{
return 0;
} else {
*_pByte = _pUart->pRxBuf[_pUart->usRxRead];
BSP_ENTER_CRITICAL;
if (++_pUart->usRxRead >= _pUart->usRxBufSize) {
_pUart->usRxRead = 0;
}
_pUart->usRxCount--;
BSP_EXIT_CRITICAL;
return 1;
}
}
static uint16_t uart_real_get_bytes(uart_t *_pUart, uint8_t *_pucaBuf, uint16_t _usLen) {
if (_usLen == 0) {
return 0;
}
uint16_t bytes_read = 0;
while (bytes_read < _usLen) {
uint8_t byte;
if (uart_real_get_byte(_pUart, &byte) > 0) {
_pucaBuf[bytes_read] = byte;
bytes_read++;
} else {
break;
}
}
return bytes_read;
}
static void UartIRQ(uart_t *_pUart);
void USART0_IRQHandler(void) {
UartIRQ(&g_tUart0);
}
static void UartIRQ(uart_t *_pUart) {
BSP_DEF_CRITICAL_SECTION
BSP_ENTER_CRITICAL
if ((RESET != usart_interrupt_flag_get(_pUart->uart_periph, USART_INT_FLAG_RBNE)) &&
(RESET != usart_flag_get(_pUart->uart_periph, USART_FLAG_RBNE))) {
while (1) {
uint8_t ch;
ch = usart_data_receive(_pUart->uart_periph);
_pUart->pRxBuf[_pUart->usRxWrite] = ch;
if (++_pUart->usRxWrite >= _pUart->usRxBufSize) {
_pUart->usRxWrite = 0;
}
if (_pUart->usRxCount < _pUart->usRxBufSize) {
_pUart->usRxCount++;
}
{
if (_pUart->ReceiveNew) {
_pUart->ReceiveNew(_pUart, ch);
}
}
if (RESET == usart_interrupt_flag_get(_pUart->uart_periph, USART_INT_FLAG_RBNE) ||
RESET == usart_flag_get(_pUart->uart_periph, USART_FLAG_RBNE)) {
break;
}
}
}
if (
(RESET != usart_interrupt_flag_get(_pUart->uart_periph, USART_INT_FLAG_TBE))) {
if (_pUart->usTxCount == 0) {
usart_interrupt_disable(_pUart->uart_periph, USART_INT_TBE);
usart_interrupt_enable(_pUart->uart_periph, USART_INT_TC);
} else {
_pUart->Sending = 1;
usart_data_transmit(_pUart->uart_periph, _pUart->pTxBuf[_pUart->usTxRead]);
if (++_pUart->usTxRead >= _pUart->usTxBufSize) {
_pUart->usTxRead = 0;
}
_pUart->usTxCount--;
}
}
if ((RESET != usart_interrupt_flag_get(_pUart->uart_periph, USART_INT_FLAG_TC)) &&
(RESET != usart_flag_get(_pUart->uart_periph, USART_FLAG_TC))) {
if (_pUart->usTxCount == 0) {
usart_interrupt_disable(_pUart->uart_periph, USART_INT_TC);
if (_pUart->SendOver) {
_pUart->SendOver(_pUart);
}
_pUart->Sending = 0;
} else {
usart_data_transmit(_pUart->uart_periph, _pUart->pTxBuf[_pUart->usTxRead]);
if (++_pUart->usTxRead >= _pUart->usTxBufSize) {
_pUart->usTxRead = 0;
}
_pUart->usTxCount--;
}
}
BSP_EXIT_CRITICAL
}
测试
#include "tx_task.h"
TX_THREAD my_thread;
static UCHAR my_thread_stack[4096] = {0};
VOID my_thread_entry(ULONG thread_input);
VOID tx_application_define(VOID *first_unused_memory) {
ULONG status;
status = tx_thread_create(&my_thread,
"MyThread",
my_thread_entry,
(ULONG) 0,
my_thread_stack,
4096, 2, 2,
TX_NO_TIME_SLICE,
TX_AUTO_START);
if (status != TX_SUCCESS) {
log_printf("Thread creation failed with status: %d\n", status);
}
}
VOID my_thread_entry(ULONG thread_input) {
uint8_t data[128];
while (1) {
uint16_t len = uart_get_bytes(USART0, data, 128);
if (len > 0) {
uart_send(USART0, data, len);
}
tx_thread_sleep(10);
}
}
测试结果(ok)