c++ 成员变量初始化推断数组大小

需求 cpp 发现直接使用 const char str[] ="test"; 作为成员变量,编译会报错: error: array bound cannot be deduced from an in-class initializer. 解决 这个报错的原因是,作为成员变量,可能会被构造函数中的 类内初始化列表重新初始化。比如: Foo() : str({'a','b', 'c', 'd'}) {} // str ="abcd0". 所以,如果这个成员变量本身是不变的情况,可以使用 constexpr 这个关键字, static constexpr char str[] ="test"; 这样,变成类变量。 参考 关于c ++:不能从成员变量的初始化字符串中推断出数组大小的原因是什么? C++11关键字constexpr看这篇就够了

<span title='2023-11-30 15:30:00 +0800 CST'>2023-11-30</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;43 words&nbsp;·&nbsp;RamLife

STM32 DMA2D 使用

需求 stm32 使用 dma2d 来加速显示 解决 DMA2D 的优点 主要就是图像中的局部矩形区域的硬件数据传输。比 DMA 的好处,就是局部矩形区域中,换行的时候,自动计算地址,并转到局部区域第二行的首地址。 其他的就是颜色格式转换和透明度混合。 DMA2D 加速 lcd 显示 DMA2D 加速 LCD 显示的前提是,LCD 的驱动是硬件驱动,比如说,使用 FMC 或者 LTDC 之类的硬件驱动 LCD,程序只需要向地址写入数据,就可以显示。 能够加速的主要是: 图像数据,直线,清屏等。主要需要实现的其实就是两个函数: Dma2dCopy, Dma2dFill. // fill color void Dma2dFill(void * dest, uint32_t width, uint32_t height, uint32_t line_offset, uint32_t color, uint32_t pixel_format) { DMA2D->CR = DMA2D_R2M;//0x00030000UL | (1 << 9); DMA2D->OCOLR = color; DMA2D->OMAR = (uint32_t)dest; DMA2D->OOR = line_offset; DMA2D->OPFCCR = pixel_format; //LTDC_PIXEL_FORMAT_RGB565; DMA2D->NLR = (uint32_t)(width << 16) | (uint16_t)height; DMA2D->CR |= DMA2D_CR_START; while (DMA2D->CR & DMA2D_CR_START) {} } // copy color data void Dma2dCopy(void * dest, const void * src, uint32_t width, uint32_t height, uint32_t dest_line_offset, uint32_t src_line_offset, uint32_t pixel_format) { DMA2D->CR = DMA2D_M2M;//0x00000000UL | (1 << 9); DMA2D->FGMAR = (uint32_t)src; DMA2D->OMAR = (uint32_t)dest; DMA2D->FGOR = src_line_offset; DMA2D->OOR = dest_line_offset; DMA2D->FGPFCCR = pixel_format; //LTDC_PIXEL_FORMAT_RGB565; DMA2D->OPFCCR = pixel_format; //LTDC_PIXEL_FORMAT_RGB565; DMA2D->NLR = (uint32_t)(width << 16) | (uint16_t)height; DMA2D->CR |= DMA2D_CR_START; while (DMA2D->CR & DMA2D_CR_START) {} } DMA2D 加速显存 主要是用在实现各种 gui 的接口函数,实现中用于加速内存复制和颜色混合。...

<span title='2023-11-22 18:59:00 +0800 CST'>2023-11-22</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;167 words&nbsp;·&nbsp;RamLife

stm32使用FMC控制 LCD 时,图像不正常

需求 stm32 使用 fmc 来控制 Lcd 显示时,碰到了两个问题: 图像变小了,并且是双份显示 屏幕只显示了 4/5,最下面花屏 解决 经过网络搜索和反复的调试,终于找到问题。 图像变小 这个是 fmc 的时序配置有问题,导致使用 DMA2D 进行数据传输时,lcd 会丢数据,然后图像就变小了。这个解决只需要对照 lcd 的芯片中的时间参数,重新设置 fmc 的时序参数即可解决。 图像只显示 4/5 这个是 FMC 的地址线的问题。 我们需要重新考虑一下为什么可以使用 fmc 来控制 lcd 显示,理论上来说, DMA2D 写入数据的时候,地址是自动增长的啊! 其实因为我们只使用了一根地址线,那么写入数据的时候,这个地址线的低位就算增长也没有关系,毕竟我们只使用了最高位作为地址线,只要使用 DMA2D 写入的数据不会超过最高位,那么就不会有影响。 所以这次的错误就是 DMA2D 在全屏写入的时候, 320*240 = 76800, 而当前的地址线使用的是 A16,那么能够提供的空间只有 2的16次方 = 65536,已经溢出了。解决的方法也很简单,使用 A17 地址线即可。 参考 DMA2D skips pixels when sending directly to display over FMC STM32 FMC Display STM32的FSMC时序解析 【12】、STM32F767——————>FMC之LCD屏 STM32H755BIT DMA2D + FMC + External SRAM Write Issue

<span title='2023-11-22 18:59:00 +0800 CST'>2023-11-22</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;76 words&nbsp;·&nbsp;RamLife

Guix 是否使用显存方案选择

需求 使用 guix,是否需要显存? 显存需要多大? 解决 是否需要显存? gui 显示一般就是两种方式,直驱或者显存刷新。 直驱 直驱的意思是,程序中界面需要变化时,直接向显示设备中对应的区域写入新的数据。 好处是: 不需要显存,那里变化改那里。适合于 RAM 小的情况。 坏处是: 因为没有显存,所以在更新时经历这样的过程: 1. 先清除相关区域; 绘制背景; 3. 绘制前景. 这种多步骤的实现方式,加上小容量 RAM 一般 使用的是接口屏本身的速度限制,很容易会造成整体时间过长,人眼看上去容易有闪烁和撕裂的情况。也就是闪屏的情况。 显存 显存的意思是,程序中界面需要变化时,把需要更新的数据先更新到显存中,然后 gui 会一次把最终结果写入到屏幕。 好处是: 这种情况下屏幕更新需要的时间很短,只有直驱的 1/3,显示稳定,没有闪烁的情况。 坏处是: 需要 RAM 足够大,能够容纳整个屏幕,这样才能作为显示缓冲来工作。 总结 如果 RAM 够大,推荐显存方式,不闪屏,体验好。如果 RAM 小,屏幕小,用户对于显示效果不敏感,就可以使用直驱方案。 显存容量计算 显存占用的 RAM 计算方式: 屏幕长 * 屏幕宽 * 单个像素点字节数。 比如: 320 * 240 的屏幕,使用 16bit 位宽的像素,那么显存大小就是 320 * 240 * 16 / 8 = 153.6 kB. 并且使用 gui + 显存的方案,一般会搭配 DAM2D 来加快数据传输,包括新数据写入显存,以及显存通过 fmc 更新到屏幕。...

<span title='2023-11-17 16:32:00 +0800 CST'>2023-11-17</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;90 words&nbsp;·&nbsp;RamLife

stm32 cube ide 编译提示 undefined reference to

需求 编译的时候,提示 undefined reference to 解决 这种问题经常会碰到,一般就是相关源文件没有在编译列表里面,结果经过仔细查找,都添加进去了。后来经过仔细查找,发现原来是 c++ 和 c 混合编译的问题,在 c++ 中文件里面调用的函数,其所在的头文件没有使用 extern "C" 包含,导致的。想要修改也很简单,不需要改动头文件,只需要在 c++ 文件中这样: #include "gx_api.h" extern "C" { #include "gx_display.h" } 而且其实在 map 文件中是有相关线索的,下面分别是没有用 extern 包含,和用了 extern 包含的 map 文件中的函数信息。可以明显看到有 extern 包含的,有相关地址。 .text._gx_display_driver_565rgb_setup 0x0000000000000000 0x260 ./guix/common/src/gx_display_driver_565rgb_setup.o .text._gx_display_driver_565rgb_setup 0x000000000801e6e8 0x260 ./guix/common/src/gx_display_driver_565rgb_setup.o 0x000000000801e6e8 _gx_display_driver_565rgb_setup 参考 gcc “undefined reference to” 问题解决方法

<span title='2023-11-17 16:17:00 +0800 CST'>2023-11-17</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;53 words&nbsp;·&nbsp;RamLife

Guix 移植

需求 使用 stm32cubeide 移植 guix 到 stm32u575 上面。 解决 简单界面设计 下载 guix studio 按照例子做个最简单界面 导出 resource 和 specification 源码 下载 guix studio 对应版本源码 把源码中的 common 整个文件夹放到工程中 把源码中的 port 中相应架构的 gx_port.h 放到工程中 开启 GX_INCLUDE_USER_DEFINE_FILE, 把 guix studio 的例子中的 gx_user.h 复制到工程中。 板级相关 在 port 文件夹中新增 gx_display_driver_rgb565_stm32u575 相关源文件和头文件。 在文件中新增: UINT GuixDriverSetupRgb565(GX_DISPLAY *display) { LcdInit(); _gx_display_driver_565rgb_setup(display, (VOID*)GUIX_SCREEN_HANDLE, GuixBufferToggleRgb565); display -> gx_display_driver_horizontal_line_draw = GuixHorizontalLineDirectDrawRgb565; display -> gx_display_driver_vertical_line_draw = GuixVerticalLineDirectDrawRgb565; display -> gx_display_driver_pixel_write = GuixPixelDirectWriteRgb565; display -> gx_display_driver_pixel_blend = GuixPixelDirectBlendRgb565; // display -> gx_display_driver_buffer_toggle = stm324xg_16bpp_buffer_toggle; display -> gx_display_handle = GUIX_SCREEN_HANDLE; return(GX_SUCCESS); } 新增上面相关的这些画点和线的函数。 线程 新增线程函数, 其中设置都是和 guix studio 导出的文件相关的。 GX_WINDOW *pScreen; GX_WINDOW_ROOT *root; void GuixMainEntry(ULONG thread_input) { (void)thread_input; gx_system_initialize(); // gx_system_memory_allocator_set(memory_allocate, memory_free); gx_studio_display_configure(PRIMARY, GuixDriverSetupRgb565, LANGUAGE_ENGLISH, PRIMARY_THEME_1, &root); gx_studio_named_widget_create((char *)"Button_Screen", (GX_WIDGET *)root, (GX_WIDGET **)&pScreen); gx_widget_show(root); gx_system_start(); while (1) { tx_thread_sleep(20); } } 把线程函数添加到启动线程中即可。 参考 {ThreadX全家桶} ThreadX GUIX直驱方案搞定,任何显示屏,低资源的MCU都可以跑了,不再需要画布,附工程下载 {ThreadX全家桶} 第3版emWin教程和ThreadX GUIX教程开工,双管齐下,GUIX更新至第30章,emWin更新至第57章(2022-04-04)

<span title='2023-11-16 16:32:00 +0800 CST'>2023-11-16</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;134 words&nbsp;·&nbsp;RamLife

QT mysql 里面的日期时间和 QDateTime 转换

需求 qt 使用 mysql 的时候,日期时间格式和 QDateTime 互相转换 解决 QDateTime 转 mysql 时间格式 QDateTime dateTime = QDateTime(QDate(2024, 5, 3), QTime(22, 0, 0)); QString dateTimeString = dateTime.toString("yyyy-MM-dd HH:mm:ss"); // 转换为 MySQL 理解的格式 QString insertQuery = "INSERT INTO version (version_no, version_datetime) VALUES (:version_no, :version_datetime)"; // 执行 SQL 插入语句 // QSqlQuery query; query.prepare(insertQuery); query.bindValue(":version_no", 3); query.bindValue(":version_datetime", dateTimeString); mysql 时间格式转 QDateTime data.time = query.value("analysis_datetime").toDateTime(); 参考 QT读取服务器mysql数据库中日期字段问题

<span title='2023-11-16 10:18:00 +0800 CST'>2023-11-16</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;61 words&nbsp;·&nbsp;RamLife

mipi, dsi, dbi, dpi

需求 mipi, dsi, dbi, dpi 分别是啥,有啥区别? 解决 mipi 是一整套的标准,包含了 dbi-2, dpi-2, dsi, dcs dbi DBI(Display Bus Interface), 一般叫做 MCU接口或 8080 接口。 DBI 的特点是: LCM 自带 framebuffer,存储 host 发过来的数据,并且内部的 Driver controller 会不断的把数据刷新到 LCD 上, host 只需要发送一次数据既可,没有同步时钟线。 一般的 MCU 按照时序发送数据就可以显示,可以使用 GPIO, SPI, FMC 等接口来驱动。 dpi DPI(Display Pixel Interface), 一般叫做 RGB 接口或者像素接口。 DPI 的特点是: LCM 没有 framebuffer, Host 有 framebuffer, 并且 Host 需要不断的把屏幕数据发送到 LCM 来显示,需要有 Vsync/Hsync 这样的同步信号。有点类似于以前的 CRT 显示器。如果 MCU 需要使用,必须要额外的外设来支持,比如说 STM32 部分高端芯片自带的 LTDC 外设,就是用来驱动这种接口的。...

<span title='2023-11-15 17:13:00 +0800 CST'>2023-11-15</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;77 words&nbsp;·&nbsp;RamLife

QT 使用mysql,提示 QSqlDatabasePrivate::database: requested database does not belong to the calling thread.

需求 qt 使用 mysql 的时候,提示: QSqlDatabasePrivate::database: requested database does not belong to the calling thread. 解决 使用 QSqlQuery 的时候,指明数据库连接。 int DataBaseProcess::ConnectDataBase(QSqlDatabase& db, const QString& name) { // if (db_.open()) { // return 1; // } qDebug() << "ConnectDataBase: " << name; if (QSqlDatabase::contains(name))//判断testConnect连接是否存在并连接 { db = QSqlDatabase::database(name); } else //未连接则新建数据库连接 { // QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db = QSqlDatabase::addDatabase("QMYSQL", name); db.setHostName("localhost"); // 设置数据库服务器地址 db.setPort(3306); db.setDatabaseName("ke_db"); // 设置数据库名 db.setUserName("root"); // 设置数据库用户名 db....

<span title='2023-11-15 10:18:00 +0800 CST'>2023-11-15</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;163 words&nbsp;·&nbsp;RamLife

QT 应用图标

需求 qt 需要设置应用图标替换默认的图标 解决 创建 rc 文件 项目目录新建文本文件 在文件中输入: IDI_ICON1 ICON DISCARDABLE "Icon/test1.ico" 修改文件名为: “项目名称”.rc 使用 rc 文件 项目.pro 文件中,加上 RC_FILE = IconTest.rc, 注意替换 rc 文件项目名称。 参考 Windows下QT设置应用程序(exe)图标、任务栏托盘图标、任务栏窗口图标 Qt学习之自定义修改exe应用程序图标(超简单)

<span title='2023-11-14 11:43:00 +0800 CST'>2023-11-14</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;29 words&nbsp;·&nbsp;RamLife