Go to file
dufresneisme c3c3d8deb4 注释drv_usart 2025-09-14 00:48:46 +08:00
.vscode 非DMA,连续转换,扫描模式,双通道 2025-09-13 18:04:22 +08:00
EWARM 注释drv_usart 2025-09-14 00:48:46 +08:00
GD32F4xx_Firmware_Library GD32F470空工程 2025-08-13 14:08:31 +08:00
applications/main 非DMA,连续转换,扫描模式,双通道 2025-09-13 18:04:22 +08:00
drivers readme添加内容 2025-09-13 18:15:31 +08:00
rtthread 注释drv_usart 2025-09-14 00:48:46 +08:00
.gitignore GD32F470空工程 2025-08-13 14:08:31 +08:00
readme.md no message 2025-09-12 17:53:32 +08:00

readme.md

代码文件管理与组织

对于嵌入式项目良好的文件管理结构至关重要。下面我将为您规划一个清晰的文件组织结构适用于基于RT-Thread和GD32F470VET6的项目。

推荐的文件结构

your_project_root/
├── rt-thread/                 # RT-Thread内核源码作为子模块或直接复制
├── bsp/
│   └── gd32/
│       └── gd32f4xx/          # 您的BSP目录
│           ├── applications/  # 应用层代码
│           │   ├── main.c     # 主入口文件
│           │   ├── adc_app.c  # ADC应用代码
│           │   ├── adc_app.h
│           │   ├── i2c_app.c  # I2C应用代码
│           │   ├── i2c_app.h
│           │   └── SConscript # 应用层构建脚本
│           ├── drivers/       # 驱动层代码
│           │   ├── drv_adc.c  # ADC驱动
│           │   ├── drv_adc.h
│           │   ├── drv_i2c.c  # I2C驱动
│           │   ├── drv_i2c.h
│           │   ├── drv_usart.c # 串口驱动(调试用)
│           │   ├── drv_usart.h
│           │   ├── drv_gpio.c # GPIO驱动如果需要
│           │   ├── drv_gpio.h
│           │   └── SConscript # 驱动层构建脚本
│           ├── libraries/     # 芯片厂商库
│           │   ├── GD32F4xx_Standard_peripheral/
│           │   │   ├── Include/
│           │   │   └── Source/
│           │   └── CMSIS/
│           ├── board.c        # 板级初始化
│           ├── board.h        # 板级相关定义
│           ├── Kconfig        # 配置选项
│           ├── SConstruct     # 构建脚本
│           └── rtconfig.h     # RT-Thread配置
├── packages/                  # RT-Thread软件包
├── tools/                     # 工具脚本
└── documents/                 # 项目文档

各文件内容示例

1. 驱动层文件 (drivers/drv_usart.c)

#include "drv_usart.h"
#include "gd32f4xx.h"

// 串口配置结构体
static struct gd32_usart_config usart_config[] = {
    {
        .name = "uart0",
        .usart_periph = USART0,
        .rcu_periph_clock = RCU_USART0,
        .gpio_port = GPIOA,
        .rcu_gpio_clock = RCU_GPIOA,
        .tx_pin = GPIO_PIN_9,
        .rx_pin = GPIO_PIN_10,
        .baud_rate = 115200,
        .irq_type = USART0_IRQn
    },
    // 可以添加更多串口配置
};

// 初始化所有配置的串口
void gd32_usart_init(void)
{
    for (int i = 0; i < sizeof(usart_config) / sizeof(usart_config[0]); i++) {
        gd32_usart_configure(&usart_config[i]);
    }
}

// 配置单个串口
void gd32_usart_configure(struct gd32_usart_config *config)
{
    // 启用时钟
    rcu_periph_clock_enable(config->rcu_periph_clock);
    rcu_periph_clock_enable(config->rcu_gpio_clock);
  
    // 配置GPIO
    gpio_af_set(config->gpio_port, GPIO_AF_7, config->tx_pin);
    gpio_af_set(config->gpio_port, GPIO_AF_7, config->rx_pin);
    gpio_mode_set(config->gpio_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->tx_pin);
    gpio_mode_set(config->gpio_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, config->rx_pin);
    gpio_output_options_set(config->gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, config->tx_pin);
    gpio_output_options_set(config->gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, config->rx_pin);
  
    // 配置USART
    usart_deinit(config->usart_periph);
    usart_baudrate_set(config->usart_periph, config->baud_rate);
    usart_word_length_set(config->usart_periph, USART_WL_8BIT);
    usart_stop_bit_set(config->usart_periph, USART_STB_1BIT);
    usart_parity_config(config->usart_periph, USART_PM_NONE);
    usart_hardware_flow_rts_config(config->usart_periph, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(config->usart_periph, USART_CTS_DISABLE);
    usart_receive_config(config->usart_periph, USART_RECEIVE_ENABLE);
    usart_transmit_config(config->usart_periph, USART_TRANSMIT_ENABLE);
  
    // 启用USART
    usart_enable(config->usart_periph);
  
    // 配置中断(如果需要)
    // nvic_irq_enable(config->irq_type, 0, 0);
    // usart_interrupt_enable(config->usart_periph, USART_INT_RBNE);
}

// 发送字符
void gd32_usart_putchar(struct gd32_usart_config *config, char ch)
{
    usart_data_transmit(config->usart_periph, (uint16_t)ch);
    while (usart_flag_get(config->usart_periph, USART_FLAG_TBE) == RESET);
}

// 发送字符串
void gd32_usart_puts(struct gd32_usart_config *config, const char *str)
{
    while (*str) {
        gd32_usart_putchar(config, *str++);
    }
}

// 获取串口配置 by name
struct gd32_usart_config *gd32_usart_get_config(const char *name)
{
    for (int i = 0; i < sizeof(usart_config) / sizeof(usart_config[0]); i++) {
        if (rt_strcmp(usart_config[i].name, name) == 0) {
            return &usart_config[i];
        }
    }
    return RT_NULL;
}

2. 驱动层头文件 (drivers/drv_usart.h)

#ifndef __DRV_USART_H__
#define __DRV_USART_H__

#include <rtthread.h>
#include <rtdevice.h>
#include "gd32f4xx.h"

// 串口配置结构体
struct gd32_usart_config {
    const char *name;
    uint32_t usart_periph;
    uint32_t rcu_periph_clock;
    uint32_t gpio_port;
    uint32_t rcu_gpio_clock;
    uint32_t tx_pin;
    uint32_t rx_pin;
    uint32_t baud_rate;
    uint8_t irq_type;
};

// 函数声明
void gd32_usart_init(void);
void gd32_usart_configure(struct gd32_usart_config *config);
void gd32_usart_putchar(struct gd32_usart_config *config, char ch);
void gd32_usart_puts(struct gd32_usart_config *config, const char *str);
struct gd32_usart_config *gd32_usart_get_config(const char *name);

#endif /* __DRV_USART_H__ */

3. 应用层文件 (applications/adc_app.c)

#include "adc_app.h"
#include "drv_usart.h"
#include "drv_adc.h"
#include <rtthread.h>
#include <rtdevice.h>

// 定义调试串口
#define DEBUG_USART "uart0"

// ADC调试线程
static void adc_debug_thread_entry(void *parameter)
{
    struct gd32_usart_config *usart_cfg = gd32_usart_get_config(DEBUG_USART);
  
    if (usart_cfg == RT_NULL) {
        rt_kprintf("Error: Debug USART not found!\n");
        return;
    }
  
    // 初始化ADC
    if (gd32_adc_init() != RT_EOK) {
        gd32_usart_puts(usart_cfg, "Error: ADC initialization failed!\r\n");
        return;
    }
  
    gd32_usart_puts(usart_cfg, "ADC Debug Started\r\n");
    gd32_usart_puts(usart_cfg, "Sampling ADC channel 0 every second...\r\n");
  
    while (1) {
        // 读取ADC值
        uint16_t adc_value = gd32_adc_read(0); // 假设读取通道0
        float voltage = (adc_value * 3.3f) / 4095.0f;
      
        // 通过串口输出
        char buffer[64];
        rt_snprintf(buffer, sizeof(buffer), "ADC Value: %d, Voltage: %.2fV\r\n", adc_value, voltage);
        gd32_usart_puts(usart_cfg, buffer);
      
        // 延时1秒
        rt_thread_mdelay(1000);
    }
}

// 启动ADC调试
int adc_debug_start(void)
{
    rt_thread_t tid;
  
    tid = rt_thread_create("adc_dbg",
                           adc_debug_thread_entry,
                           RT_NULL,
                           1024,
                           RT_THREAD_PRIORITY_MAX / 2,
                           20);
    if (tid != RT_NULL) {
        rt_thread_startup(tid);
        return RT_EOK;
    }
  
    return -RT_ERROR;
}

// 导出到MSH命令
MSH_CMD_EXPORT(adc_debug_start, Start ADC debug);

4. 应用层头文件 (applications/adc_app.h)

#ifndef __ADC_APP_H__
#define __ADC_APP_H__

#include <rtthread.h>

// 函数声明
int adc_debug_start(void);

#endif /* __ADC_APP_H__ */

5. 板级初始化 (board.c)

#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include "drv_usart.h"

// 系统时钟配置
void system_clock_config(void)
{
    // 配置系统时钟为200MHz
    // ... GD32特定的时钟配置代码
}

// 板级初始化
void rt_hw_board_init(void)
{
    // 配置系统时钟
    system_clock_config();
  
    // 初始化调试串口
    gd32_usart_init();
  
    // 打印启动信息
    struct gd32_usart_config *usart_cfg = gd32_usart_get_config("uart0");
    if (usart_cfg != RT_NULL) {
        gd32_usart_puts(usart_cfg, "\r\nRT-Thread GD32F470 Board Initialized\r\n");
    }
  
    // 其他硬件初始化...
  
    // 显示RT-Thread版本信息
    rt_show_version();
  
    // 初始化系统堆内存
#ifdef RT_USING_HEAP
    rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif
}

6. 构建脚本 (drivers/SConscript)

from building import *

cwd = GetCurrentDir()
src = Glob('*.c')
path = [cwd]

# 定义编译组
group = DefineGroup('Drivers', src, depend = [''], path = path)

Return('group')

7. 应用层构建脚本 (applications/SConscript)

from building import *

cwd = GetCurrentDir()
src = Glob('*.c')
path = [cwd]

# 定义编译组
group = DefineGroup('Applications', src, depend = [''], path = path)

Return('group')

编译和调试流程

  1. 环境设置

    • 确保RT-Thread Env工具已正确设置
    • 配置工具链路径对于IAR需要在Env中设置相关路径
  2. 配置项目

    # 在BSP目录下打开Env
    menuconfig
    
    • 启用USART设备驱动
    • 启用ADC设备驱动
    • 配置其他需要的组件
  3. 编译项目

    scons
    

    或使用IAR工程文件如果已创建

  4. 下载和调试

    • 使用J-Link、GD-Link或ST-Link等调试器下载程序
    • 通过串口调试助手查看输出信息

调试建议

  1. 分层调试

    • 首先确保串口驱动正常工作
    • 然后调试ADC驱动
    • 最后实现应用逻辑
  2. 使用RT-Thread的Finsh控制台

    • 可以通过串口直接输入命令控制应用程序
    • 使用 list_device命令查看已注册的设备
    • 使用 adc_debug_start命令启动ADC调试
  3. 添加调试宏

    #define DEBUG_ADC
    #ifdef DEBUG_ADC
    #define ADC_DEBUG(fmt, ...) rt_kprintf("[ADC] " fmt, ##__VA_ARGS__)
    #else
    #define ADC_DEBUG(fmt, ...)
    #endif
    

这样的文件组织结构清晰便于维护和扩展也符合RT-Thread的推荐实践。随着项目的发展您可以轻松地添加新的驱动和应用模块。