Files
hm b49c9ab0c6 Initial commit: PY32MD530H28U7TR步进电机控制器项目
完整实现了以下模块:
- 系统数据总线(sys_data_bus)模块间通信
- UART/USART/LPUART驱动 + RS485半双工
- I2C驱动(AS5600角度传感器 + AT24C02 EEPROM)
- Modbus RTU从站协议
- 步进电机微步进控制(正弦/余弦换相+S曲线加减速)
- 到位开关驱动(DI_MIN/DI_MAX)
- PGA+ADC电流检测
- 系统监控任务(内存/串口/传感器/任务状态)
- LED/Key外设驱动
- 基于CMake + arm-none-eabi-gcc构建系统
2026-05-11 19:55:43 +08:00

338 lines
8.5 KiB
C

#include "uart_driver.h"
#include "py32md530.h"
#include "system_py32md530.h"
#include "system_driver.h"
#include "config.h"
#include <string.h>
#define UART_FIFO_SIZE 256
typedef struct {
uint8_t buffer[UART_FIFO_SIZE];
volatile uint32_t head;
volatile uint32_t tail;
uint8_t initialized;
} uart_fifo_t;
static uart_fifo_t uart_fifos[UART_ID_COUNT];
static uart_stats_t uart_statistics[UART_ID_COUNT];
static void uart_fifo_init(uart_fifo_t *fifo)
{
fifo->head = 0;
fifo->tail = 0;
fifo->initialized = 1;
}
static void uart_stats_init(void)
{
uint32_t i;
for (i = 0; i < UART_ID_COUNT; i++) {
uart_statistics[i].tx_bytes = 0;
uart_statistics[i].rx_bytes = 0;
uart_statistics[i].overflow_errors = 0;
}
}
static void uart_fifo_push(uart_fifo_t *fifo, uint8_t data)
{
uint32_t next = (fifo->head + 1) % UART_FIFO_SIZE;
if (next != fifo->tail) {
fifo->buffer[fifo->head] = data;
fifo->head = next;
}
}
static uint32_t uart_fifo_pop(uart_fifo_t *fifo, uint8_t *data)
{
if (fifo->tail == fifo->head) {
return 0;
}
*data = fifo->buffer[fifo->tail];
fifo->tail = (fifo->tail + 1) % UART_FIFO_SIZE;
return 1;
}
static uint32_t uart_fifo_count(uart_fifo_t *fifo)
{
return (fifo->head - fifo->tail) % UART_FIFO_SIZE;
}
void USART1_IRQHandler(void)
{
if (USART1->SR & USART_SR_RXNE_Msk) {
uint8_t data = (uint8_t)(USART1->DR & 0xFF);
uart_statistics[UART_ID_USART1].rx_bytes++;
{
uint32_t next = (uart_fifos[UART_ID_USART1].head + 1) % UART_FIFO_SIZE;
if (next == uart_fifos[UART_ID_USART1].tail) {
uart_statistics[UART_ID_USART1].overflow_errors++;
}
}
uart_fifo_push(&uart_fifos[UART_ID_USART1], data);
}
if (USART1->SR & USART_SR_TC_Msk) {
USART1->SR &= ~USART_SR_TC_Msk;
}
}
void UART1_IRQHandler(void)
{
if (UART1->SR & USART_SR_RXNE_Msk) {
uint8_t data = (uint8_t)(UART1->DR & 0xFF);
uart_statistics[UART_ID_UART1].rx_bytes++;
{
uint32_t next = (uart_fifos[UART_ID_UART1].head + 1) % UART_FIFO_SIZE;
if (next == uart_fifos[UART_ID_UART1].tail) {
uart_statistics[UART_ID_UART1].overflow_errors++;
}
}
uart_fifo_push(&uart_fifos[UART_ID_UART1], data);
}
if (UART1->SR & USART_SR_TC_Msk) {
UART1->SR &= ~USART_SR_TC_Msk;
}
}
void LPUART1_IRQHandler(void)
{
if (LPUART1->ISR & (1UL << 5)) {
uint8_t data = (uint8_t)(LPUART1->DR & 0xFF);
uart_statistics[UART_ID_LPUART1].rx_bytes++;
{
uint32_t next = (uart_fifos[UART_ID_LPUART1].head + 1) % UART_FIFO_SIZE;
if (next == uart_fifos[UART_ID_LPUART1].tail) {
uart_statistics[UART_ID_LPUART1].overflow_errors++;
}
}
uart_fifo_push(&uart_fifos[UART_ID_LPUART1], data);
}
}
static ret_code_t usart1_init(const uart_config_t *config)
{
uint32_t brr;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
USART1->CR1 &= ~USART_CR1_UE_Msk;
brr = (SystemCoreClock + config->baudrate / 2) / config->baudrate;
USART1->BRR = brr;
USART1->CR1 = USART_CR1_UE_Msk
| USART_CR1_TE_Msk
| USART_CR1_RE_Msk
| USART_CR1_RXNEIE_Msk;
USART1->CR3 = USART_CR3_DMAR_Msk
| USART_CR3_DMAT_Msk;
NVIC_SetPriority(USART1_IRQn, 0x08);
NVIC_EnableIRQ(USART1_IRQn);
uart_stats_init();
uart_fifo_init(&uart_fifos[UART_ID_USART1]);
return RET_OK;
}
static ret_code_t uart1_init(const uart_config_t *config)
{
uint32_t brr;
RCC->APB1ENR |= RCC_APB1ENR_UART1EN;
UART1->CR1 &= ~USART_CR1_UE_Msk;
brr = (SystemCoreClock + config->baudrate / 2) / config->baudrate;
UART1->BRR = brr;
UART1->CR1 = USART_CR1_UE_Msk
| USART_CR1_TE_Msk
| USART_CR1_RE_Msk
| USART_CR1_RXNEIE_Msk;
UART1->CR3 = USART_CR3_DMAR_Msk
| USART_CR3_DMAT_Msk;
NVIC_SetPriority(UART1_IRQn, 0x08);
NVIC_EnableIRQ(UART1_IRQn);
uart_fifo_init(&uart_fifos[UART_ID_UART1]);
return RET_OK;
}
static ret_code_t lpuart1_init(const uart_config_t *config)
{
RCC->APB1ENR |= RCC_APB1ENR_LPUART1EN;
LPUART1->CR1 &= ~(1UL << 0);
LPUART1->BRR = (256 * SystemCoreClock + config->baudrate / 2) / config->baudrate;
LPUART1->CR1 = (1UL << 0)
| (1UL << 2)
| (1UL << 3)
| (1UL << 5);
NVIC_SetPriority(LPUART1_IRQn, 0x08);
NVIC_EnableIRQ(LPUART1_IRQn);
uart_fifo_init(&uart_fifos[UART_ID_LPUART1]);
return RET_OK;
}
ret_code_t uart_init(uart_id_t id, const uart_config_t *config)
{
if (id >= UART_ID_COUNT || config == NULL) {
return RET_INVALID_PARAM;
}
switch (id) {
case UART_ID_USART1:
return usart1_init(config);
case UART_ID_UART1:
return uart1_init(config);
case UART_ID_LPUART1:
return lpuart1_init(config);
default:
return RET_ERROR;
}
}
ret_code_t uart_deinit(uart_id_t id)
{
switch (id) {
case UART_ID_USART1:
NVIC_DisableIRQ(USART1_IRQn);
USART1->CR1 = 0;
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN;
break;
case UART_ID_UART1:
NVIC_DisableIRQ(UART1_IRQn);
UART1->CR1 = 0;
RCC->APB1ENR &= ~RCC_APB1ENR_UART1EN;
break;
case UART_ID_LPUART1:
NVIC_DisableIRQ(LPUART1_IRQn);
LPUART1->CR1 = 0;
RCC->APB1ENR &= ~RCC_APB1ENR_LPUART1EN;
break;
default:
return RET_INVALID_PARAM;
}
return RET_OK;
}
ret_code_t uart_send(uart_id_t id, const uint8_t *data, uint32_t len)
{
uint32_t i;
if (id == UART_ID_USART1) {
uart_set_rs485_dir(UART_ID_USART1, 1);
}
for (i = 0; i < len; i++) {
switch (id) {
case UART_ID_USART1:
while (!(USART1->SR & USART_SR_TXE_Msk));
USART1->DR = data[i];
while (!(USART1->SR & USART_SR_TC_Msk));
uart_statistics[UART_ID_USART1].tx_bytes++;
break;
case UART_ID_UART1:
while (!(UART1->SR & USART_SR_TXE_Msk));
UART1->DR = data[i];
while (!(UART1->SR & USART_SR_TC_Msk));
uart_statistics[UART_ID_UART1].tx_bytes++;
break;
case UART_ID_LPUART1:
while (!(LPUART1->ISR & (1UL << 0)));
LPUART1->DR = data[i];
uart_statistics[UART_ID_LPUART1].tx_bytes++;
break;
default:
return RET_INVALID_PARAM;
}
}
if (id == UART_ID_USART1) {
volatile uint32_t delay = (SystemCoreClock / 1000000) * 2;
while (delay--);
uart_set_rs485_dir(UART_ID_USART1, 0);
}
return RET_OK;
}
ret_code_t uart_receive(uart_id_t id, uint8_t *data, uint32_t len, uint32_t timeout)
{
uint32_t i;
uint32_t tick_start = 0;
if (timeout > 0) {
tick_start = system_get_tick();
}
for (i = 0; i < len; i++) {
while (uart_fifo_count(&uart_fifos[id]) == 0) {
if (timeout > 0) {
if ((system_get_tick() - tick_start) >= timeout) {
return RET_TIMEOUT;
}
}
}
uart_fifo_pop(&uart_fifos[id], &data[i]);
}
return RET_OK;
}
ret_code_t uart_send_dma(uart_id_t id, const uint8_t *data, uint32_t len)
{
return uart_send(id, data, len);
}
ret_code_t uart_receive_dma(uart_id_t id, uint8_t *data, uint32_t len)
{
return uart_receive(id, data, len, 0);
}
uint32_t uart_available(uart_id_t id)
{
return uart_fifo_count(&uart_fifos[id]);
}
ret_code_t uart_set_rs485_dir(uart_id_t id, uint8_t tx_mode)
{
if (id != UART_ID_USART1) {
return RET_NOT_SUPPORTED;
}
if (tx_mode) {
USART1_RS485_DIR_PORT->BSRR = (1UL << USART1_RS485_DIR_PIN);
} else {
USART1_RS485_DIR_PORT->BRR = (1UL << USART1_RS485_DIR_PIN);
}
return RET_OK;
}
const uart_stats_t* uart_get_stats(uart_id_t id)
{
if (id >= UART_ID_COUNT) {
return NULL;
}
return &uart_statistics[id];
}
void uart_reset_stats(uart_id_t id)
{
if (id >= UART_ID_COUNT) {
return;
}
uart_statistics[id].tx_bytes = 0;
uart_statistics[id].rx_bytes = 0;
uart_statistics[id].overflow_errors = 0;
}