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构建系统
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef UART_DRIVER_H__
|
||||
#define UART_DRIVER_H__
|
||||
|
||||
#include "common_types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
UART_ID_USART1 = 0,
|
||||
UART_ID_UART1,
|
||||
UART_ID_LPUART1,
|
||||
UART_ID_COUNT,
|
||||
} uart_id_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tx_bytes;
|
||||
uint32_t rx_bytes;
|
||||
uint32_t overflow_errors;
|
||||
} uart_stats_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t baudrate;
|
||||
uint8_t data_bits;
|
||||
uint8_t stop_bits;
|
||||
uint8_t parity;
|
||||
} uart_config_t;
|
||||
|
||||
ret_code_t uart_init(uart_id_t id, const uart_config_t *config);
|
||||
ret_code_t uart_deinit(uart_id_t id);
|
||||
ret_code_t uart_send(uart_id_t id, const uint8_t *data, uint32_t len);
|
||||
ret_code_t uart_receive(uart_id_t id, uint8_t *data, uint32_t len, uint32_t timeout);
|
||||
ret_code_t uart_send_dma(uart_id_t id, const uint8_t *data, uint32_t len);
|
||||
ret_code_t uart_receive_dma(uart_id_t id, uint8_t *data, uint32_t len);
|
||||
uint32_t uart_available(uart_id_t id);
|
||||
ret_code_t uart_set_rs485_dir(uart_id_t id, uint8_t tx_mode);
|
||||
const uart_stats_t* uart_get_stats(uart_id_t id);
|
||||
void uart_reset_stats(uart_id_t id);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user