ID.LODA

  • 2025-07-13
  • 回复了主题帖: 【STM32H73BI-DK评测】适配 SDIO 驱动及 Fatfs 文件系统

    Jacktang 发表于 2025-7-12 08:56 通过楼主的测试,感觉RTThread 对 STM32 的驱动支持确实比较友好 是的,旧的系列支持都比较完善了。  

  • 2025-07-11
  • 发表了主题帖: 【STM32H73BI-DK评测】适配 LCD 及 Touch 驱动

    本帖最后由 ID.LODA 于 2025-7-17 09:39 编辑 ## 适配 LCD 及 Touch 驱动 [开箱体验](https://bbs.eeworld.com.cn/thread-1319973-1-1.html) [适配 RTThread 系统](https://bbs.eeworld.com.cn/thread-1320428-1-1.html) [RTThread 适配 SDRAM 驱动 ](https://bbs.eeworld.com.cn/thread-1320434-1-1.html) [适配 SDIO 驱动及 Fatfs 文件系统](https://bbs.eeworld.com.cn/thread-1320437-1-1.html) 工程代码路径 [bsp/stm32/stm32h7b3i-dk - 码云 - 开源中国](https://gitee.com/morphlings2014/rt-thread-private/tree/master/bsp/stm32/stm32h7b3i-dk) ### 移植 Touch 驱动 touch 型号是 ft5336,使用 i2c 通讯,地址为 0x70 与 mcu 连接的引脚是 PD12,PD13,对应的是 I2C4 #### 修改 RTThread 配置 1. 打开 board\Kconfig 文件,加入如下配置信息 在 menu "Onboard Peripheral Drivers" 下加入如下配置 ```python config BSP_USING_FT5336 bool "Enable LCD Touch" select RT_USING_TOUCH select BSP_USING_I2C select BSP_USING_I2C4 default y ``` 在 menu "On-chip Peripheral Drivers" 下加入 I2C 配置 ```python menuconfig BSP_USING_I2C bool "Enable I2C BUS" select RT_USING_I2C default n if BSP_USING_I2C choice prompt "i2c mode" default BSP_USING_HARD_I2C config BSP_USING_HARD_I2C bool "hardware" select BSP_USING_I2C4 config BSP_USING_SOFT_I2C bool "software simulation" select RT_USING_I2C_BITOPS select RT_USING_PIN endchoice if BSP_USING_HARD_I2C menuconfig BSP_USING_I2C4 bool "Enable I2C4 BUS (hardware)" default n endif if BSP_USING_SOFT_I2C menuconfig BSP_USING_I2C4 bool "Enable I2C4 BUS (software simulation)" default n if BSP_USING_I2C4 comment "Notice: PD12 --> 60; PD13 --> 61" config BSP_I2C4_SCL_PIN int "i2c4 scl pin number" range 0 175 default 60 config BSP_I2C4_SDA_PIN int "I2C4 sda pin number" range 0 175 default 61 endif endif endif ``` 2. 在 board\ports 目录下创建文件 drv_ft5336.c 文件,并修改 board\SConscript ,加入如下配置 ```python if GetDepend(['BSP_USING_FT5336']): src += Glob('ports/drv_ft5336.c') ``` 3. 在 env 控制台输入 `menuconfig` 进行配置,使用 LCD Touch 4. 在 env 控制台输入 `scon --target=mdk5` 更新工程 #### 修改代码 1. rtthread touch 相关的定义和需要实现的接口如下 ```c struct rt_touch_device { struct rt_device parent; /* The standard device */ struct rt_touch_info info; /* The touch info data */ struct rt_touch_config config; /* The touch config data */ const struct rt_touch_ops *ops; /* The touch ops */ rt_err_t (*irq_handle)(rt_touch_t touch); /* Called when an interrupt is generated, registered by the driver */ }; struct rt_touch_data { rt_uint8_t event; /* The touch event of the data */ rt_uint8_t track_id; /* Track id of point */ rt_uint8_t width; /* Point of width */ rt_uint16_t x_coordinate; /* Point of x coordinate */ rt_uint16_t y_coordinate; /* Point of y coordinate */ rt_tick_t timestamp; /* The timestamp when the data was received */ }; struct rt_touch_ops { rt_size_t (*touch_readpoint)(struct rt_touch_device *touch, void *buf, rt_size_t touch_num); rt_err_t (*touch_control)(struct rt_touch_device *touch, int cmd, void *arg); }; int rt_hw_touch_register(rt_touch_t touch, const char *name, rt_uint32_t flag, void *data); ``` 2. ft5336 获取触摸信息的相关寄存器, 首先通过 02 寄存器获取触点数量,然后通过 03-06 四个寄存器可以获取触点1 的触摸事件,x,y 位置以及 触摸 id 值,ft5336 最大支持 5点触摸,其他几个点的数据格式和 1 是一致。 3. 了解基本的框架和寄存器操作之后我们就可以开始编码了。打开 drv_ft5336.c,先实现 i2c 读写寄存器的操作 ```c static struct rt_i2c_client touch_i2c_client; static rt_err_t ft5336_write_reg(struct rt_i2c_client *client, rt_uint8_t reg, rt_uint8_t value) { struct rt_i2c_msg msg = {0}; rt_uint8_t buf[2]; buf[0] = reg; buf[1] = value; msg.addr = client->client_addr; msg.flags = RT_I2C_WR; msg.buf = buf; msg.len = 2; if (rt_i2c_transfer(client->bus, &msg, 1) != 1) { LOG_E("ft5336 write register error"); return -RT_ERROR; } return RT_EOK; } static rt_err_t ft5336_read_reg(struct rt_i2c_client *client, rt_uint8_t reg, rt_uint8_t *buf, rt_uint8_t len) { struct rt_i2c_msg msgs[2]; msgs[0].addr = client->client_addr; msgs[0].flags = RT_I2C_WR; msgs[0].buf = ® msgs[0].len = 1; msgs[1].addr = client->client_addr; msgs[1].flags = RT_I2C_RD; msgs[1].buf = buf; msgs[1].len = len; if (rt_i2c_transfer(client->bus, msgs, 2) == 2) { return RT_EOK; } else { LOG_E("ft5336 read register error"); return -RT_ERROR; } } ``` 4. 实现 touch 框架需要的接口,完成 ft5336 初始化,并加入自动初始化流程 ```c static void ft5336_init(struct rt_i2c_client *client) { ft5336_write_reg(client, FT5336_DEV_MODE_REG, FT5336_DEV_MODE_WORKING); ft5336_write_reg(client, FT5336_GMODE_REG, FT5336_G_MODE_INTERRUPT_POLLING); } int rt_hw_ft5336_init(const char *name, struct rt_touch_config *cfg) { struct rt_touch_device *touch_device = RT_NULL; touch_device = (struct rt_touch_device *)rt_malloc(sizeof(struct rt_touch_device)); if(touch_device == RT_NULL) { LOG_E("touch device malloc failed"); return -RT_ERROR; } rt_memset((void *)touch_device, 0, sizeof(struct rt_touch_device)); touch_i2c_client.client_addr = TOUCH_I2C_ADDRESS >> 1; touch_i2c_client.bus = (struct rt_i2c_bus_device *)rt_device_find(cfg->dev_name); if(touch_i2c_client.bus == RT_NULL) { LOG_E("Can't find %s device", cfg->dev_name); return -RT_ERROR; } if(rt_device_open((rt_device_t)touch_i2c_client.bus, RT_DEVICE_FLAG_RDWR) != RT_EOK) { LOG_E("open %s device failed", cfg->dev_name); return -RT_ERROR; } ft5336_init(&touch_i2c_client); /* register touch device */ touch_device->info.type = RT_TOUCH_TYPE_CAPACITANCE; touch_device->info.vendor = RT_TOUCH_VENDOR_FT; touch_device->info.point_num = 1; touch_device->info.range_x = 480; touch_device->info.range_y = 272; rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config)); touch_device->ops = &ops; if (rt_hw_touch_register(touch_device, name, RT_DEVICE_FLAG_RDONLY, &touch_i2c_client) != RT_EOK) { return -RT_EIO; } return RT_EOK; } int drv_touch_hw_init(void) { struct rt_touch_config cfg; cfg.dev_name = "i2c4"; rt_hw_ft5336_init("touch_ft", &cfg); return RT_EOK; } INIT_DEVICE_EXPORT(drv_touch_hw_init); ``` 5. 再编写触摸信息的读取 ```c static int16_t pre_x[FT5336_MAX_NB_TOUCH] = {-1, -1, -1, -1, -1}; static int16_t pre_y[FT5336_MAX_NB_TOUCH] = {-1, -1, -1, -1, -1}; static int16_t pre_w[FT5336_MAX_NB_TOUCH] = {-1, -1, -1, -1, -1}; static rt_uint8_t s_tp_down[FT5336_MAX_NB_TOUCH]; static struct rt_touch_data *touch_data; static void ft5336_touch_up(void *buf, int8_t id) { touch_data = (struct rt_touch_data *)buf; if(s_tp_down[id] == 1) { s_tp_down[id] = 0; touch_data[id].event = RT_TOUCH_EVENT_UP; } else { touch_data[id].event = RT_TOUCH_EVENT_NONE; } touch_data[id].timestamp = rt_touch_get_ts(); touch_data[id].width = pre_w[id]; touch_data[id].x_coordinate = pre_x[id]; touch_data[id].y_coordinate = pre_y[id]; touch_data[id].track_id = id; pre_x[id] = -1; /* last point is none */ pre_y[id] = -1; pre_w[id] = -1; } static void ft5336_touch_down(void *buf, int8_t id, int16_t x, int16_t y, int16_t w) { touch_data = (struct rt_touch_data *)buf; if (s_tp_down[id] == 1) { touch_data[id].event = RT_TOUCH_EVENT_MOVE; } else { touch_data[id].event = RT_TOUCH_EVENT_DOWN; s_tp_down[id] = 1; } touch_data[id].timestamp = rt_touch_get_ts(); touch_data[id].width = w; touch_data[id].x_coordinate = x; touch_data[id].y_coordinate = y; touch_data[id].track_id = id; pre_x[id] = x; /* save last point */ pre_y[id] = y; pre_w[id] = w; } static rt_size_t ft5336_readpoint(struct rt_touch_device *touch, void *data, rt_size_t touch_num) { struct rt_i2c_client *i2c_client = (struct rt_i2c_client *)touch->parent.user_data; if (touch_num > FT5336_TD_STATUS_BIT_POSITION; /* point num is not correct */ if ((nb_touch > FT5336_MAX_NB_TOUCH) || (nb_touch == 0)) { nb_touch = 0; goto exit_; } if (nb_touch > touch_num) { nb_touch = touch_num; } /* read point num is touch_num */ if (ft5336_read_reg(i2c_client, FT5336_P1_XH_REG, read_buf, touch_num * FT5336_ONE_TOUCH_REG_CNT) != RT_EOK) { LOG_E("read point failed"); nb_touch = 0; goto exit_; } /* point up */ if(pre_touch > nb_touch) { for (read_index = 0; read_index < pre_touch; read_index++) { rt_uint8_t j; /* this time touch num */ for (j = 0; j < nb_touch; j++) { read_id = read_buf[j * 8] & 0x0F; /* this id is not free */ if (pre_id[read_index] == read_id) break; if (j >= nb_touch - 1) { rt_uint8_t up_id; up_id = pre_id[read_index]; ft5336_touch_up(read_buf, up_id); } } } } /* point down */ if (nb_touch) { uint8_t ts_event; for(read_index = 0; read_index < nb_touch; read_index++) { /* Send back first ready X position to caller */ input_y = ((read_buf[read_index*6U] & FT5336_P1_XH_TP_BIT_MASK) FT5336_P1_XH_EF_BIT_POSITION); /* Send back first ready Weight to caller */ input_w = (read_buf[(read_index*6U) + 4U] & FT5336_P1_WEIGHT_BIT_MASK); /* Send back first ready Area to caller */ // State->TouchArea = (read_buf[(read_index*6U) + 5U] & FT5336_P1_MISC_BIT_MASK) >> FT5336_P1_MISC_BIT_POSITION; read_id = ((read_buf[(read_index*6U) + 2U] & FT5336_P1_YH_TID_BIT_MASK) >> FT5336_P1_YH_TID_BIT_POSITION); pre_id[read_index] = read_id; LOG_D("%d touch info x=%03d y=%03d w=%03d event=%d read_id %d", read_id, input_x, input_y, input_w, ts_event, read_id); ft5336_touch_down(data, read_id, input_x, input_y, input_w); } } else if (pre_touch) { for(read_index = 0; read_index < pre_touch; read_index++) { ft5336_touch_up(data, pre_id[read_index]); } } pre_touch = nb_touch; exit_: return nb_touch; } ``` 6. 因为 CubeMx 工程用的官方板卡示例,全部外设引脚都已初始化,如果是其他板子,还需要在 stm32h7xx_hal_msp.c 中加入 I2C 相应的引脚配置 7. 编写测试代码验证 ```c rt_thread_t ft5336_thread; rt_device_t touch; void ft5336_thread_entry(void *parameter) { struct rt_touch_info info; struct rt_touch_data *read_data; rt_device_control(touch, RT_TOUCH_CTRL_GET_INFO, &info); LOG_I("type :%d", info.type); LOG_I("vendor :%d", info.vendor); LOG_I("point_num :%d", info.point_num); LOG_I("range_x :%d", info.range_x); LOG_I("range_y :%d", info.range_y); read_data = (struct rt_touch_data *)rt_calloc(1, sizeof(struct rt_touch_data)); while(1) { if (rt_device_read(touch, 0, read_data, info.point_num) == info.point_num) { for (rt_uint8_t i = 0; i < info.point_num; i++) { if (read_data->event == RT_TOUCH_EVENT_DOWN) { rt_kprintf("%d, down x: %03d y: %03d", read_data->track_id, read_data->x_coordinate, read_data->y_coordinate); rt_kprintf(" t: %d\n", read_data->timestamp); } else if (read_data->event == RT_TOUCH_EVENT_MOVE) { rt_kprintf("%d move x: %03d y: %03d", read_data->track_id, read_data->x_coordinate, read_data->y_coordinate); rt_kprintf(" t: %d\n", read_data->timestamp); } else if (read_data->event == RT_TOUCH_EVENT_UP) { rt_kprintf("%d up x: %03d y: %03d", read_data->track_id, read_data->x_coordinate, read_data->y_coordinate); rt_kprintf(" t: %d\n", read_data->timestamp); } } } rt_thread_delay(10); } } int ft5336_example(void) { touch = rt_device_find("touch_ft"); rt_device_open(touch, RT_DEVICE_FLAG_RDONLY); ft5336_thread = rt_thread_create("touch", ft5336_thread_entry, RT_NULL, 800, 10, 20); if (ft5336_thread == RT_NULL) { LOG_E("create touch thread err"); return -RT_ENOMEM; } rt_thread_startup(ft5336_thread); return RT_EOK; } //INIT_APP_EXPORT(ft5336_example); MSH_CMD_EXPORT(ft5336_example, ft5336 tc...); ``` #### 测试运行 经过上述修改之后,编译下载代码,打开对应的串口,可以看到 touch 设置正常挂载 输入测试指令 ft5336_example,触摸屏幕,可以看到有触摸事件产生 ### 移植 LCD 驱动 rthread\bsp\stm32\libraries\HAL_Drivers\drivers 带了 lcd 相关的驱动实现,我们只要添加头文件描述,并根据使用的芯片型号 RK043FN48H 配置一些宏参数就可以运行 #### 修改 RTThread 配置 1. 打开 board\Kconfig 文件,加入如下配置信息 在 menu "Onboard Peripheral Drivers" 下加入如下配置 ```python config BSP_USING_LCD bool "Enable LCD" select BSP_USING_LTDC select BSP_USING_FT5336 default n ``` 在 menu "On-chip Peripheral Drivers" 下加入 I2C 配置 ```python config BSP_USING_LTDC bool "Enable LTDC" default n ``` 2. 在 board\ports 目录下创建文件 lcd_port.h 文件 3. 在 env 控制台输入 `menuconfig` 进行配置更新,使能 lcd 4. 在 env 控制台输入 `scon --target=mdk5` 更新工程 #### 修改代码 1. 打开 lcd_port.h,写入 LCD 长宽等相关参数,时序参数需要参考对应的手册 ```c #define LCD_WIDTH 480 #define LCD_HEIGHT 272 #define LCD_BITS_PER_PIXEL 16 #define LCD_BUF_SIZE (LCD_WIDTH * LCD_HEIGHT * LCD_BITS_PER_PIXEL / 8) #define LCD_PIXEL_FORMAT RTGRAPHIC_PIXEL_FORMAT_RGB565 #define LCD_HSYNC_WIDTH 41 #define LCD_HBP 2//13 #define LCD_HFP 32 #define LCD_VSYNC_HEIGHT 10 #define LCD_VBP 2 #define LCD_VFP 2 #define LCD_BACKLIGHT_USING_GPIO #define LCD_BL_GPIO_NUM GET_PIN(A, 1) #define LCD_DISP_GPIO_NUM GET_PIN(A, 2) ``` 2. 显示屏 RK043FN48H 典型工作频率是 9.7 MHz, 我们在 stm32h7xx_hal_msp.c 里设置的是 96Mhz,所以需要修改下,因为 LTDC 时钟是固定连接在 PLL3R 上,最简单的方式是将 PLL3R 改为 20,根据公式换算下来是 9.6Mhz,可以用 >计算公式 > >PLL3_VCO Input = HSE_VALUE/PLL3M = 1 Mhz > >PLL3_VCO Output = PLL3_VCO Input * PLL3N = 1*192 = 192Mhz > >PLLLCDCLK = PLL3_VCO Output/PLL3R = 192/20 = 9.6 Mhz > >LTDC clock frequency = PLLLCDCLK = 9.6 Mhz */ ```c PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; PeriphClkInitStruct.PLL3.PLL3M = 24; PeriphClkInitStruct.PLL3.PLL3N = 192; PeriphClkInitStruct.PLL3.PLL3P = 17; PeriphClkInitStruct.PLL3.PLL3Q = 2; PeriphClkInitStruct.PLL3.PLL3R = 20; PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_0; PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE; PeriphClkInitStruct.PLL3.PLL3FRACN = 0; ``` 如果要追求更接近的匹配,也可以按如下或者其他配置,主要不影响其他外设即可 ```c PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; PeriphClkInitStruct.PLL3.PLL3M = 6; PeriphClkInitStruct.PLL3.PLL3N = 200; PeriphClkInitStruct.PLL3.PLL3P = 10; PeriphClkInitStruct.PLL3.PLL3Q = 10; PeriphClkInitStruct.PLL3.PLL3R = 83; PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_0; PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE; PeriphClkInitStruct.PLL3.PLL3FRACN = 0; ``` 3. 除此之外,还要单独设置下 LCD_DE 控制脚,默认将其置低 ```c /* USER CODE BEGIN LTDC_MspInit 1 */ LCD_DISP_EN_GPIO_CLK_ENABLE(); /* LCD_DISP_EN GPIO configuration */ GPIO_InitStruct.Pin = LCD_DISP_EN_PIN; /* LCD_DISP pin has to be manually controlled */ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(LCD_DISP_EN_GPIO_PORT, &GPIO_InitStruct); /* De-assert display enable LCD_DISP_EN pin */ HAL_GPIO_WritePin(LCD_DISP_EN_GPIO_PORT, LCD_DISP_EN_PIN, GPIO_PIN_RESET); ``` #### 测试运行 经过上述修改之后,编译下载代码,打开对应的串口,可以看到 lcd 设备正常挂载 输入测试指令 `lcd_test 指令,屏幕会自动刷单色背景

  • 2025-07-10
  • 发表了主题帖: 【STM32H73BI-DK评测】适配 SDIO 驱动及 Fatfs 文件系统

    ## 适配 SDIO 驱动及 Fatfs 文件系统 [开箱体验](https://bbs.eeworld.com.cn/thread-1319973-1-1.html) [适配 RTThread 系统](https://bbs.eeworld.com.cn/thread-1320428-1-1.html) [RTThread 适配 SDRAM 驱动 ](https://bbs.eeworld.com.cn/thread-1320434-1-1.html) 工程代码路径 [bsp/stm32/stm32h7b3i-dk - 码云 - 开源中国](https://gitee.com/morphlings2014/rt-thread-private/tree/master/bsp/stm32/stm32h7b3i-dk) ### 移植 rthread\bsp\stm32\libraries\HAL_Drivers\drivers 带了 sdio 相关的驱动实现,我们只需要在 Kconfig 中加入相关配置即可 #### 修改 RTThread 配置 1. 打开 board\Kconfig 文件,加入如下配置信息 在 menu "Onboard Peripheral Drivers" 下加入如下配置 ```python menuconfig BSP_USING_FS bool "Enable filesystem" select RT_USING_DFS default n if BSP_USING_FS config BSP_USING_SDCARD_FS bool "Enable SDCARD filesystem" select BSP_USING_SDIO select RT_USING_DFS_ELMFAT default n endif ``` 在 menu "On-chip Peripheral Drivers" 下加入如下配置 ```python config BSP_USING_SDIO bool "Enable SDIO" select RT_USING_SDIO default n if BSP_USING_SDIO config BSP_USING_SDIO1 bool "Enable SDIO1" default y endif ``` 2. 在 env 控制台输入 `menuconfig` 进行配置,打开文件系统支持 3. 需要支持中文目录的话,还需要修改文件系统的配置 4. 在 board\ports 目录下创建文件 filesystem.c 文件,并修改 board\SConscript ,加入如下配置 ```python if GetDepend(['BSP_USING_FS']): src += Glob('ports/filesystem.c') ``` 5. 在 env 控制台输入 `scon --target=mdk5` 更新工程 #### 修改代码 1. 打开 filesystem.c ,加入文件系统挂载代码,创建挂载现在支持动态插拔 ```c #include #ifdef BSP_USING_FS #if DFS_FILESYSTEMS_MAX < 4 #error "Please define DFS_FILESYSTEMS_MAX more than 4" #endif #if DFS_FILESYSTEM_TYPES_MAX < 4 #error "Please define DFS_FILESYSTEM_TYPES_MAX more than 4" #endif #include #ifdef BSP_USING_SDCARD_FS #include #include "drv_sdmmc.h" #endif #ifdef BSP_USING_SPI_FLASH_FS #include "fal.h" #endif #define DBG_TAG "app.filesystem" #define DBG_LVL DBG_INFO #include #ifdef RT_USING_DFS_ROMFS #include "dfs_romfs.h" #ifdef RT_USING_DFS_ELMFAT static const struct romfs_dirent _romfs_root[] = { {ROMFS_DIRENT_DIR, "flash", RT_NULL, 0}, {ROMFS_DIRENT_DIR, "sdcard", RT_NULL, 0} }; #endif const struct romfs_dirent romfs_root = { ROMFS_DIRENT_DIR, "/", (rt_uint8_t *)_romfs_root, sizeof(_romfs_root) / sizeof(_romfs_root[0]) }; #endif #ifdef BSP_USING_SDCARD_FS /* SD Card hot plug detection pin */ #define SD_CHECK_PIN GET_PIN(I, 8) static void _sdcard_mount(void) { rt_device_t device; device = rt_device_find("sd"); if (device == NULL) { mmcsd_wait_cd_changed(0); stm32_mmcsd_change(); mmcsd_wait_cd_changed(RT_WAITING_FOREVER); device = rt_device_find("sd"); } if (device != RT_NULL) { if (dfs_mount("sd", "/sdcard", "elm", 0, 0) == RT_EOK) { LOG_I("sd card mount to '/sdcard'"); } else { LOG_W("sd card mount to '/sdcard' failed!"); } } } static void _sdcard_unmount(void) { rt_thread_mdelay(200); dfs_unmount("/sdcard"); LOG_I("Unmount \"/sdcard\""); mmcsd_wait_cd_changed(0); stm32_mmcsd_change(); mmcsd_wait_cd_changed(RT_WAITING_FOREVER); } static void sd_mount(void *parameter) { rt_uint8_t re_sd_check_pin = 1; rt_thread_mdelay(200); if (rt_pin_read(SD_CHECK_PIN) == 0) { _sdcard_mount(); } while (1) { rt_thread_mdelay(200); if (re_sd_check_pin && (re_sd_check_pin = rt_pin_read(SD_CHECK_PIN)) == 0) { _sdcard_mount(); } if (!re_sd_check_pin && (re_sd_check_pin = rt_pin_read(SD_CHECK_PIN)) != 0) { _sdcard_unmount(); } } } #endif /* BSP_USING_SDCARD_FS */ int mount_init(void) { #ifdef RT_USING_DFS_ROMFS if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) != 0) { LOG_E("rom mount to '/' failed!"); } #endif /* RT_USING_DFS_ROMFS */ #ifdef BSP_USING_SDCARD_FS rt_thread_t tid; rt_pin_mode(SD_CHECK_PIN, PIN_MODE_INPUT_PULLUP); tid = rt_thread_create("sd_mount", sd_mount, RT_NULL, 2048, RT_THREAD_PRIORITY_MAX - 2, 20); if (tid != RT_NULL) { rt_thread_startup(tid); } else { LOG_E("create sd_mount thread err!"); } #endif /* BSP_USING_SDCARD_FS */ return RT_EOK; } INIT_ENV_EXPORT(mount_init); #endif /* BSP_USING_FS */ ``` 2. 因为 CubeMx 工程用的官方板卡示例,全部外设引脚都已初始化,如果是其他板子,还需要在 stm32h7xx_hal_msp.c 中加入 SDIO 相应的引脚配置 ### 运行 经过上述修改之后,编译下载代码,打开对应的串口,实际运行效果如下 查看中文目录 ### 总结 介于 RTThread 对 STM32 的驱动支持相对比较完善,我们要加入 SDIO 的支持也是相对比较容易,挂载文件系统也是比较容易

  • 2025-07-04
  • 回复了主题帖: 【STM32H73BI-DK评测】开箱体验

    wangerxian 发表于 2025-7-2 10:02 应该上800x480或以上的。 新出的板子好像都升级了,h7rs7,n6 的 dk 都是 800*480 的

  • 发表了主题帖: 【STM32H73BI-DK评测】RTThread 适配 SDRAM 驱动

    # 适配 SDRAM 驱动 [开箱体验](https://bbs.eeworld.com.cn/thread-1319973-1-1.html) [适配 RTThread 系统](https://bbs.eeworld.com.cn/thread-1320428-1-1.html) 工程代码路径 [bsp/stm32/stm32h7b3i-dk - 码云 - 开源中国](https://gitee.com/morphlings2014/rt-thread-private/tree/master/bsp/stm32/stm32h7b3i-dk) ## 移植 rthread\bsp\stm32\libraries\HAL_Drivers\drivers 带了 sdram 相关的驱动实现,我们只要添加头文件,并根据使用的芯片型号配置一些宏参数就可以运行 ### 修改 RTThread 配置 1. 打开 board\Kconfig 文件,加入如下配置信息 ```python config BSP_USING_SDRAM bool "Enable SDRAM" select BSP_USING_FMC default y ``` 2. 在 env 控制台输入 `menuconfig` 进行配置更新,因为默认打开就直接保存 3. 在 env 控制台输入 `scon --target=mdk5` 更新工程 ### 修改代码 1. 在 board\port 添加 sdram_port.h 文件,写入如下配置,具体参数可以查看板载 SDRAM 芯片 is42s16800j 的手册 ```c #ifndef __SDRAM_PORT_H__ #define __SDRAM_PORT_H__ /* parameters for sdram peripheral */ /* Bank1 or Bank2 */ #define SDRAM_TARGET_BANK 2 /* stm32h7 Bank1:0xC0000000 Bank2:0xD0000000 */ #define SDRAM_BANK_ADDR ((uint32_t)0xD0000000) /* data width: 8, 16, 32 */ #define SDRAM_DATA_WIDTH 16 /* column bit numbers: 8, 9, 10, 11 */ #define SDRAM_COLUMN_BITS 9 /* row bit numbers: 11, 12, 13 */ #define SDRAM_ROW_BITS 12 /* burst length: 1, 2, 4 */ #define SDRAM_BURST_LENGTH 1 /* cas latency clock number: 1, 2, 3 */ #define SDRAM_CAS_LATENCY 2 /* read pipe delay: 0, 1, 2 */ #define SDRAM_RPIPE_DELAY 2 /* clock divid: 2, 3 */ #define SDCLOCK_PERIOD 3 /* refresh rate counter */ #define SDRAM_REFRESH_COUNT ((uint32_t)0x0603) #define SDRAM_SIZE ((uint32_t)0x1000000) /* Timing configuration for IS42S16800F */ /* 100 MHz of HCKL3 clock frequency (200MHz/2) */ /* TMRD: 2 Clock cycles */ #define LOADTOACTIVEDELAY 2 /* TXSR: 7x10ns */ #define EXITSELFREFRESHDELAY 7 /* TRAS: 4x10ns */ #define SELFREFRESHTIME 4 /* TRC: 7x10ns */ #define ROWCYCLEDELAY 7 /* TWR: 2 Clock cycles */ #define WRITERECOVERYTIME 2 /* TRP: 2x10ns */ #define RPDELAY 2 /* TRCD: 2x10ns */ #define RCDDELAY 2 /* memory mode register */ #define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) #define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) #define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) #define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) #define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) #define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) #define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) #define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) #define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) #endif ``` 2. 修改 drv_sdram.c 文件,里面有个参数原先是按 SDRAM_DATA_WIDTH 配置,不是很合理,重新定义个 SDRAM_BURST_LENGTH 宏配置下 3. 因为 CubeMx 工程用的官方板卡示例,全部外设引脚都已初始化,如果是其他板子,还需要在 stm32h7xx_hal_msp.c 中加入相应的引脚配置 ## 运行 经过上述修改之后,编译下载代码,打开对应的串口,实际运行效果如下 - 初始化映射的地址为 0xD000000 - 输入 `free` 查看内存,可以看到有 sdram 池的信息 - 可以输入 sdram_test 进行测试 ## 总结 介于 RTThread 对 STM32 的驱动支持相对比较完善,我们要加入 SDRAM 的支持也是相对比较容易

  • 发表了主题帖: 【STM32H73BI-DK评测】适配 RTThread 系统

    # STM32H7B3I-DK [STM32H73BI-DK评测](https://bbs.eeworld.com.cn/thread-1319973-1-1.html) ## 移植 操作系统选择 rtthread,集成的软件包比较丰富,同时对 stm32 的驱动支持已经比较完善。版本方面建议选择打 TAG 的版本,master 更新比较快,每次同步对工程的影响可能比较大。 BSP 工程这里我们以 stm32h743-st-nucleo 为模板,复制并修改目录名为 stm32h7b3i-dk,后续按如下步骤进行修改 ### 创建 CubeMX 工程 1. 首先删除 board\CubeMX_Config 目录下的文件,用 STM32CubeMx 重新创建一个基于 stm32h7b3i 芯片的工程,因为我们用的官方板卡,可以偷懒直接使用板卡的配置 2. 创建工程之后,切换到 Project Manager 选型,对工程命名,并保存到 BSP 目录下 board\CubeMX_Config ,点击保存 ### 修改 RTThread 配置 主要包含 SConstruct, SConscript, Kconfig 等配置的修改,keil 工程的设置,以及启动配置相关的调整 1. 修改 Kconfig 文件,配置芯片宏和相关依赖 2. 修改 board/SConscript 脚本,将对应的启动文件改成 stm32h7b3i 对应的,芯片宏也替换成 STM32H7B3xxQ 3. 修改board/Kconfig 文件,将控制台串口修改为板卡对应的 UART1 4. 修改 template.uvprojx 将默认的芯片型号改成 stm32h7b3i 5. 修改 board\linker_scripts\link.sct 链接脚本 6. 打开 env 工具,输入 `menuconfig` 进行配置 7. 保存退出,输入 `scons --target=mdk5` 重新生成工程 ### 修改代码 更新 mdk 工程之后,还需要修改一些初始化代码 1. 打开 board.c 对时钟配置进行修改,如果开启 MPU 也可以在这里进行相应的配置 ```c void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /*AXI clock gating */ RCC->CKGAENR = 0xFFFFFFFF; /** Supply configuration update enable */ HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY); /** Configure the main internal regulator output voltage */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0); while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {} /** Configure LSE Drive Capability */ HAL_PWR_EnableBkUpAccess(); __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW); /* Enable HSE Oscillator and activate PLL with HSE as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE |RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.HSIState = RCC_HSI_DIV1; RCC_OscInitStruct.HSICalibrationValue = 64; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 12; RCC_OscInitStruct.PLL.PLLN = 280; RCC_OscInitStruct.PLL.PLLP = 2; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 2; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; RCC_OscInitStruct.PLL.PLLFRACN = 0; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) { Error_Handler(); } __HAL_RCC_SYSCFG_CLK_ENABLE() ; HAL_EnableCompensationCell(); HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); /* MPU Configuration--------------------------------------------------------*/ MPU_Config(); return; } ``` 2. 打开 board.h 对内存配置进行响应修改,影响内存管理 3. 修改 main.c 中 LED 引脚的配置,改成板卡实际的引脚 ```c #include #include #include /* defined the LED0 pin: G11 */ #define LED_PIN GET_PIN(G, 11) int main(void) { rt_uint32_t count = 1; rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); while(count++) { rt_thread_mdelay(500); rt_pin_write(LED_PIN, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(LED_PIN, PIN_LOW); } return RT_EOK; } ``` ## 运行 经过上述修改之后,编译下载代码,打开对应的串口,实际运行效果如下 ## 总结 RTThread 对 STM32 的驱动支持相对比较完善,我们创建新的板卡工程也是有很多模板可以参考,相对也是比较容易快速的搭建。 移植好的示例代码地址如下 [示例](https://gitee.com/morphlings2014/rt-thread-private/tree/master/bsp/stm32/stm32h7b3i-dk "示例")

  • 2025-07-02
  • 回复了主题帖: 【STM32H73BI-DK评测】开箱体验

    秦天qintian0303 发表于 2025-7-1 10:09 为什么要设计一个STMod+ 的扩展板卡,有什么硬性要求吗? 定义个标准接口,方便设计小模块,又比在板子上引出排针显得好看写

  • 回复了主题帖: 【STM32H73BI-DK评测】开箱体验

    wangerxian 发表于 2025-6-30 18:03 这个开发板就适合做GUI,主频和内存都够用。 确实,芯片自带 1M+ SRAM,板载又加了 16M SDRAM,就是屏幕还是老掉牙的 480*272

  • 2025-06-30
  • 发表了主题帖: 【STM32H73BI-DK评测】开箱体验

    本帖最后由 ID.LODA 于 2025-6-30 16:31 编辑 # STM32H7B3I-DK 经过两周的等待,也是成功收到了 STM32H7B3I-DK 板卡。现在 ST 的包装也是采用了纸盒,和原先的塑料比起来,简约了不少,也更方便收藏了 拆开包装里面包含了一块 STM32H7B3I-DK 板卡和一个 STMod+ 的扩展板卡,一份说明书 ## 板卡介绍 板卡主控用的 STM32H7B3LIH6QU 基于ARM®架构的微控制器,提供 2M 字节的 FLASH 存储器和 1.4MB RAM,BGA225封装。但是主频只有 280M 和其他 H7 系类相比,低了不少,不知道是出于什么考量。 [官网介绍]: https://www.st.com.cn/zh/evaluation-tools/stm32h7b3i-dk.html#overview 板载资源如下 - 4.3英寸(480x272像素)TFT彩色LCD模块,包含带RGB接口的电容式触摸屏 - Wi‑Fi®模块符合802.11 b/g/n - USB OTG HS - 音频编解码器 - 512-Mbit Octo-SPI NOR 闪存 - 128-Mbit SDRAM - 2个用户LED - 用户按钮和复位按钮 - Fanout子板 - 1x FDCAN - 板连接器: - 摄像头(8位) - 带Micro-AB的USB - 立体声耳机插孔,包括模拟麦克风输入 - 用于外部扬声器的音频插孔 - microSD™卡 - TAG-Connect10引脚尺寸 - Arm® Cortex® 10引脚 1.27mm螺距调试连接器,STDC14尺寸 - ARDUINO® Uno V3扩展连接器 - STMod+ 扩展连接器 - 音频子板扩展接口 - External I2C扩展连接器 ## 示例测试 出场固件提供了丰富的示例代码,包含了 touchgfx,emwin,embededwizard 多个图形库示例 - 设备信息描述, 280Mhz 主频,固件版本 1.0.1 - 天气 app 界面展示,左右滑动可以查看不同地区,右上角设置包含了 wifi 的连接控制,不过我试了下一直显示连接失败 - touchgfx 实现的是智能家居的示例,包含一个 bashroom 和 kitchen 的房间控制 Bathroom 洗衣机的控制界面 - stemwin 实现的是一个游戏界面,类似小鸟快飞,可以上下前后拖动,整体运行非常流畅 - embeded wizard 提供的是一套综合示例,包含一些空间的基本使用展示 - 其他还有一些音视频的 APP 等,因为没有放置 sd 卡等一些原因无法正常运行就没展示,整体出厂示例是我遇到过最丰富的 ## 总结 STM32H7B系列具有 280MHz Arm®Cortex®-M7 的处理性能、高存储容量和节能技术,尤为适用于设计下一代智能产品设备。高达1.4MB的SRAM 配合内嵌图像处理引擎,Chrom-ART™ 图形处理加速器和JEPG硬件加速器,不仅可以节省内核处理能力,同时可以加速图形内容的创建,从而释放MCU的占用,提高其他应用程序的处理速度

  • 2025-06-06
  • 回复了主题帖: 测评入围名单:STM32H7B3I-DK探索套件

    已查看我的测评计划,可在活动期间内完成并发帖分享

  • 2025-03-03
  • 加入了学习《2024digikey多功能旋钮》,观看 2024digikey多功能旋钮

  • 2025-01-08
  • 回复了主题帖: 24年年终盘点来啦!精选强推:原创、测评、拆解、视频、资料

    关注一下

  • 2024-11-07
  • 回复了主题帖: 【得捷电子Follow me第1期】+ 提交贴

    damiaa 发表于 2024-11-6 08:46 不知道这个室内效果如何。 不太行,至少得放窗边

  • 2024-08-01
  • 回复了主题帖: 【瑞萨RA8D1板卡】 修复板卡按键

    nmg 发表于 2024-8-1 08:59 看你接线那里,似乎没有焊盘? 最后是用什么补焊上脱落地方的,没看明白 应该连走线上了,绿油刮掉就行

学过的课程

统计信息

已有149人来访过

  • 芯积分:423
  • 好友:2
  • 主题:50
  • 回复:79

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言