自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(47)
  • 收藏
  • 关注

原创 HAL库通过FATFS和SDIO+DMA写入SD卡数据错误

由于DMA 每次取 4 字节写入,而我的缓冲区是字节排列,这就导致可能访问未分配内存,这也解释了我上面数据错乱的问题,而且每次错乱的部分都不超过三字节;后面测试,当DMA配置的内存date witdh仍然保持为word类型时,如果char类型写入缓冲区大小小于512字节时写入也不会出现错误,大于512字节时就会出现和前面描述的一样的错误情况;最后在cubemx中发现我的。排除掉缓冲区的问题后,将问题定位到HAL库的FATFS和SDIO+DMA驱动上,后再次测试,连续写入1M字节未出现任何问题;

2025-04-18 23:57:29 576

原创 LVGL源码(8):自定义渲染(手动设置Table控件单元格颜色)

lv_obj_draw_part_dsc_t是LVGL 中用于的绘图事件描述结构体,允许你在控件的绘制过程中插手,对某个“绘制部件”进行修改、替换或自定义绘制。需要注意的是,在修改lv_obj_draw_part_dsc_t这个结构体参数之前,我们首先需要看控件的绘制用到了其中的哪些参数,我们只需要对控件使用到的参数进行修改,就比如Table控件的单元格绘制就用到了矩形绘制描述符lv_draw_rect_dsc_t *rect_dsc;

2025-04-17 00:58:10 785

原创 LVGL源码(9):学会控件的使用(自定义弹窗)

在LVGL中,用户界面的基本构建块是对象,也称为Widgets。例如Button、Label、Image、List、图表或文本区域。LVGL 中的所有控件(对象)都是基于 lv_obj_t 的。通过模块化和面向对象设计,lv_obj_t 是 LVGL 中所有可视化对象的基类,它提供了对象的基本属性和方法,如大小、位置、父子关系、样式、事件回调等。每种控件都是 lv_obj_t 的派生类型,都直接或间接继承自 lv_obj_t,通过扩展其基础功能实现特定的控件功能。#endif。

2025-04-16 00:44:58 1109

原创 LVGL源码(7):渲染

lv_disp_t管理的是一个显示屏的“运行时上下文”,它是渲染逻辑、屏幕状态管理、无效区域控制、双缓冲处理等的核心。/***//**显示器使用的驱动配置结构体(lv_disp_drv_t),包含绘图函数、刷新策略、分辨率等*//**刷新定时器,周期性检查无效区域invalidate(也叫dirty区域)并调用驱动进行渲染*//**当前显示器使用的主题指针(控制颜色、字体、样式等)*//**主题与屏幕管理*//**显示器上所有屏幕对象的数组(包括历史、当前、待加载的屏幕)*/

2025-04-13 17:10:18 868 1

原创 LVGL源码(6):Style样式介绍

关于样式对象lv_style_t的成员定义,主要包含三类样式,分别为单属性样式、多属性样式和只读属性样式,只读属性样式的存在我们可以知道是为了减少RAM的占用以及保证程序运行过程中的不可修改性,但为什么还要分单属性样式和多属性样式两者存储方式呢,这不是会增加操作样式时的复杂度吗?在查阅了相关资料后,个人认为这是出于空间和性能优化的考量,从空间角度来说,绝大部分样式实例只会存储 1~2 个属性,如果所有样式都使用动态分配,那么每个样式对象至少需要malloc一块内存,即使它只存储一个属性,由于malloc。

2025-04-08 23:35:30 1004

原创 HAL库 通过USB Boot进行APP程序升级

硬件:stm32f407VET6芯片;软件:STM32CubeMx、Keil5上位机:Dfuse DemoV3.06这里给出通过在Bootlaoder中使用USB方式来更新APP程序的方法,首先我们编写一个自己的bootloader,关于bootloader的大致原理可以参考我之前的文章,这里boot升级我采用单APP升级的方式 ,主要分为三部分讲解:一、程序配置和Bootlaoder编写;二、Dfuse DemoV3.06上位机和对应USB驱动安装;

2025-03-30 16:11:18 1170 1

原创 HAL库BootLoader通过FLASH进行双APP升级

之前提到的IAP双app升级流程用到了w25q64存放app副本,AT24C02用于存放OTA结构体,这次我们把boot程序、app程序、app副本程序和OTA结构体信息在一个单片机flash中分区存放。硬件:正点原子mini开发板v3.0,使用的硬件为f103RCT6芯片;BOOT具体程序:已上传到本文章对应绑定资源。软件:STM32CubeMx、Keil5。上位机:SecureCRT、sscom。

2025-03-29 00:08:06 224

原创 C语言 Float、double、定点数计算浮点数精度

编程语言:C语言编译器平台:keil MDK 5.36单片机型号:Stm32F407VET6根据float单精度浮点数和Double双精度浮点数遵循的IEEE 754规则我们可以知道,前者的有效位数为6-7位,后者的有效位数为15-16位,在有效位数内能够无误差的表示数值,这里我们通过keil MDK编译器做一个实验,观察Float、double、定点数三类的表示精度和计算精度怎样,以及不同计算方法对计算精度的影响,首先我们先了解一下浮点数的规则,大致如下:浮点数规则。

2025-03-02 22:08:18 1077

原创 Gui-Guider1.8.1 数字时钟控件找不到定义,无法编译

这里我们移植的源码其实是没有lv_conf_internal.h这个文件的,这个应该是Gui-guider管理自己的控件使用的配置头文件,我们在lv_dclock.c和lv_dclock.h中都看到了关于宏定义LV_USE_DCLOCK的使用,其配置就在lv_conf_internal.h这个文件中,我们打开该文件直接搜索LV_USE_DCLOCK,可以看到在下面这个地方有关该宏定义的使用,然后琢磨琢磨,把dclock控件要用的宏定义单独拿出来自己#define就可以了;

2025-02-12 22:25:10 747

原创 Cubemx文件系统挂载多设备

这样就有一个问题,由于我们自己编写底层驱动函数时如果涉及到多个不同存储设备的使用,那么我们往往会在user_diskio.c中通过传入的参数pdrv结合switch判断来切换不同的存储设备底层驱动,这里传入的参数pdrv为该设备对应的lun参数,但我们看到FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path)设备驱动绑定函数时都默认lun参数为0,因此当用switch对存储设备底层驱动进行切换时,如果case的值不为0就不会执行其中的代码。

2025-02-01 21:22:30 1303

原创 HAL库W25Qxx系列芯片驱动

【代码】HAL库W25Qxx系列芯片驱动。

2025-02-01 19:48:41 230

原创 STM32CubeMX6.13.0打开后不显示界面,但是任务管理器显示该程序正在运行

最近在更新了CubeMX6.13.0版本后,刚开始还能正常使用,后面突然就出现打开后不显示界面这个问题,但是任务管理器显示该程序正在运行,其他版本的Cubemx能正常打开。最后认为可能是自己的Windows账户名称为中文导致路径有问题,然后选择另一个英文名的Windows管理员账户进行登录并打开STM32CubeMX6.13.0,一切正常成功解决问题。

2025-01-31 15:59:42 1178 5

原创 用Guiguider生成的字体代替LVGL默认字体

Guiguider版本:1.8.1LVGL版本:8.3 最近使用LVGL时,由于flash不太够用了,观察编译的map图发现一直有一个LV_FONT_MONTSERRAT_14的字体被编译,占用了我十几KB的Flash,由于我是用guider生成的界面和字体,我寻思我也没在guider中使用LV_FONT_MONTSERRAT_14啊,后面在lv_conf.h中发现了原因,在LVGL中,其必须要有一个默认的字体,默认字体可以从下面通过宏定义来修改,而这里默认的字体就是LV_FONT_MON

2025-01-15 23:51:58 717 1

原创 HAL库 SPI+DMA接收 通讯速率高就读取失败

最近在写一个读取ad7691数据的驱动时,SPI2设置为Receiveonlymaster模式,此时发现用SPI+DMA的HAL库函数HAL_SPI_Receive_DMA(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize)接收数据时(DMA为normal模式,以字节单位传输),通讯速率在300K以下时能够正常接收数据,而高于这个速率接收的数据就很乱,甚至收不到数据;此时好像只会进入发送完成中断而不会进入接收完成中断。

2025-01-15 23:29:59 527 1

原创 STM32Cubemx配置SD卡、FATFS和USB

我们通过USB就能让电脑像操作U盘一样对单片机上的SD卡进行操作,从而读出单片机写入到SD卡中的文件,同时也能向SD卡中写入文件,然后单片机通过自身的FATFS去读取。在SD卡的SDIO驱动和FATFS都验证完毕后,我们需要编写USB的驱动,主要就是修改usbd_storage_if.c中的函数,把SD卡的相关操作填入usbd_storage_if.c中对应的函数中,然后将单片机和电脑用USB线连接,电脑中识别出有U盘插入,且能读里面的文件并向里面写入文件即可;,一般手动调用该函数我们放在任务中调用。

2025-01-15 22:47:05 941 4

原创 LVGL源码(5):Group概念以及导航态和编辑态、编码器模式驱动编写

在 indev_encoder_proc函数最后还有一个判断,这个判断就决定了编码器模式下,处于导航态时,按下LV_KEY_LEFT或者LV_KEY_RIGHT就切换焦点,处于编辑态时按下LV_KEY_LEFT或者LV_KEY_RIGHT就发送LV_EVENT_KEY事件,传递键值LV_KEY_LEFT或者LV_KEY_RIGHT,从而可以改变控件数值。用keypad模式的话键值就是LV_KEY_ENTER、LV_KEY_PREV/LV_KEY_NEXT、LV_KEY_UP、LV_KEY_DOWN。

2025-01-13 00:32:55 1232 1

原创 LVGL源码(4):LVGL关于EVENT事件的响应逻辑

函数内部逻辑主要为:首先通过lv_obj_allocate_spec_attr(obj);因此这里我们发现_lv_event_dsc_t * event_dsc结构体指针实际上是指向一个以_lv_event_dsc_t 数据类型的数据为元素的动态数组,这里通过event_dsc_cnt表示数组元素个数,每次控件obj新绑定一个EVENT事件回调函数event_dsc_cnt就加一,且用lv_mem_realloc函数来分配一个新的数组空间,新的数组内容在原数组基础上不变,空间比原数组大一个数组元素的大小;

2025-01-08 00:18:44 961

原创 LVGL源码(3):通过LVGL显示屏刷新进一步理解lv_task_handler()函数

在上一篇文章中我们结合keypad输入设备的输入监测来理解lv_task_handler()函数的工作逻辑,这篇文章中我们又结合了显示屏的定时刷新来进一步理解lv_task_handler()函数,由此我们可以发现在LVGL中链表管理是一个非常重要的点,负责不同功能的部分都抽象成了链表,不同功能链表的节点又和定时器绑定,通过定时器和lv_timer_ll链表产生连接,最后用一个lv_task_handler()函数统一进行LVGL不同功能的处理;然后调用lv_port_disp_init();

2025-01-05 19:06:10 575

原创 LVGL源码(2):LVGL的lv_task_handler()函数工作逻辑

和输入设备初始化lv_port_indev_init();可以看到这里有初始化在lv_gc.c中定义的一些链表,其实我们现在已经大概能知道lv_task_handler()工作逻辑了,就是定义并初始化_lv_timer_ll这个链表,然后把LVGL要实现的功能写入定时器的回调函数中,然后创建定时器并加入到_lv_timer_ll链表,在lv_task_handler()遍历判断是否要调用该定时器对应的回调函数,我们只需要每隔一段时间调用一次lv_task_handler()函数即可。

2025-01-05 15:40:12 1370

原创 LVGL源码(1):LVGL Keypad键值介绍以及禁止长按连续触发方法

另外开一个坑,前面我们提到了一个特别长的函数为static void indev_keypad_proc(lv_indev_t * i, lv_indev_data_t * data),这个是关于keypad设备的键值处理函数,同时还有其他例如encoder编码器的键值处理函数等,他们都在设备定时器回调函数lv_indev_read_timer_cb()函数中被调用,我大概看了一下,我们的事件处理函数lv_task_handler();我们看一下lv_event_get_key(e);

2024-12-31 09:14:14 951

原创 LVGL同时支持多种输入设备

【代码】LVGL同时支持多种输入设备。

2024-12-17 10:33:36 300

原创 STM32 HAL库 ST7789驱动

【代码】STM32 HAL库 ST7789驱动。

2024-11-13 16:32:00 300

原创 STM32HAL库定时器无法进入中断问题

当两个一起使用是会导致无法正常进入中断,要开启定时器和中断只用。

2024-11-01 22:04:41 879

原创 FreeRTOS和Systemview联合调试——M0内核

最近想用Systemview分析FreeRTOS,参考了网上很多大佬的教程,但是大多是armM3、M4内核的芯片,而本人用的是M0内核,systemview配置有所不同,也是踩了一些坑,在这里记录一下,也希望后来看到的小伙伴能够顺利配置;

2024-10-10 23:59:51 1221 2

原创 STM32 ADC+DMA导致写FLASH失败

网上有人说写FLASH之前需要__disable_irq()禁用中断,写FLASH结束再恢复中断,我这么做了但是还是无法写成功(不开启ADC+DMA连续转换前是可以写FLASH的),于是就把连续转换改成了手动软件触发,每次需要ADC数据的时候就软件触发一次,这样才可以正常写入FLASH,也不知道为什么;将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size);

2024-09-08 13:06:12 722

原创 STM32G0系列配置Freertos所管理的最高中断优先级

我们可以发现在F103RCT6上是可以选择这两个优先级限制的,在生成的代码中的FreeRTOSConfig.h中也能找到对应的配置,但是g070KBT6中就无法对该值进行选择,生成的代码中也没有,我又找了几款同样是M0+内核的芯片如g070CBT6、L010和L031等,发现都无法配置该选项,推测M0+系列芯片的FreeRTOS不支持配置最高和最低优先级,位于FreeRTOS管理下的中断优先级默认为3;且中断优先级位数是固定的,无法通过寄存器进行更改。0 表示最高优先级,3 表示最低优先级。

2024-08-17 17:34:43 377

原创 STM32G070KBT6的RTC HAL库使用

根据我们选择的功能,我们需要配置上述参数,首先Asynchronous Predivider value和Synchronous Predivider value用于将RTC的时钟分频,我们一般进行秒级计数,所以将其分频到1HZ,计算方法为:时钟源频率/(Asynchronous Predivider value+1)/(Synchronous Predivider value),这里为32.768KHZ/128/256 = 1HZ;在夏令时期间,时钟会提前一小时,以便在白天更长的时间内利用自然光。

2024-08-09 00:42:23 1233

原创 STM32G070系列芯片擦除、写入Flash错误解决

在用G070KBT6芯片调用HAL_FLASHEx_Erase(&EraseInitStruct, &PageError)时,调试发现该函数返回HAL_ERROR,最后定位到FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE)函数出现错误,pFlash.ErrorCode为0xA0,即FLASH错误标志位 FLASH_SR_PGSERR和FLASH_SR_PGAERR被置位;在网上找半天找不到问题原因,最后在。

2024-08-03 23:36:45 1605

原创 STM32上电后串口能发送数据,但无法接收处理数据,需手动复位(DMA无法正常工作)

今天在用一块自己画的板子的时候,发现给板子上电之后,可以接收到串口发出来的数据,但给芯片串口发数据,芯片没反应,只有手动再按一次复位按钮后串口才能正常工作;百思不得其解,上网查询后发现可能是上电时序的问题:芯片的电源、时钟、外设都各自有一个上电稳定时间,即上电后这些组件的电压需要在一定时间内达到稳定才能正常工作。

2024-07-31 22:30:44 1184 2

原创 RTthread挂载外部Flash W25Q64并加入FATFS文件系统

这个说明RTthread的SFUD 组件在尝试初始化和识别 W25Q64 设备时遇到了问题,特别是与 JEDEC SFDP(Serial Flash Discoverable Parameters)相关的参数读取失败。如果设备不支持 SFDP,就需要手动配置设备的参数,但是百度了一下是支持的,然后我就在RTthread里的cubemx中把片选引脚CS即PA2也初始化了,然后再次生成代码就可以了;(有个问题就是后面再取消cubemx的PA2初始化,生成代码后,仍然可以正常使用FATFS)

2024-07-18 23:58:40 957

原创 RT-Thread定时器管理

我们看下面有一个#ifdef RT_USING_TIMER_SOFT宏,如果该定时器是用户自定义的软件定时器就插入rt_soft_timer_list,否则插入rt_timer_list,那rt_thread_sleep()挂起线程肯定不是插入rt_soft_timer_list,那只能是插入rt_timer_list,再结合线程自带的软件定时器,我们就能得出rt_timer_list是用于管理线程软件定时器;

2024-07-07 15:19:31 1013

原创 HAL库freertos对一块内存连续释放两次会导致程序卡死

于是我进入内存释放函数vPortFree( )中一探究竟,根据下图代码我们可以发现,使用内存释放函数时首先会判断内存块首地址是否为NULL,不为NULL再判断内存块大小是否符合规范以及pxNextFreeBlock是否为NULL(当内存块不为空闲时pxNextFreeBlock为NULL);判断条件为0执行函数内容,进入了死循环了;在学习freertos的内存管理函数时,我跟着哔站正点原子的视频代码学习时发现,当我对一块内存进行两次内存释放时会导致整个程序卡死,而视频中的例程却不会卡死只会报错。

2024-04-05 18:23:07 1388 1

原创 关于freertos任务通知模拟队列无法传输任务值为0的问题

最近在学习freertos任务通知的时候,跟着正点原子教程做了个用任务通知模拟队列和事件标志组的小实验,结果发现用队列是可以传递为0的数据的,而用任务通知模拟队列就无法传递为0的数据,在用xTaskNotify(myTask01Handle, key ,eSetValueWithoutOverwrite);传递为值0的数据key时,此时任务通知模拟队列的接收函数xTaskNotifyWait(0,0xFFFFFFFF,&value,portMAX_DELAY);硬件:正点原子miniV3.0开发板。

2024-03-31 20:52:20 440 1

原创 HAL库使用FreeRTOS队列集

参考教程:【【正点原子】手把手教你学FreeRTOS实时系统】https://www.bilibili.com/video/BV19g411p7UT?由于本人在使用stm32cubemx的freertos时,没有发现队列集配置的选项,因此记录一下如何手动在cubemx生成的freertos中创建和使用队列集。这里拿添加二值信号量和队列为例子,注意cubemx生成的二值信号量默认值为1,因此需要在代码中将其初始值修改为0,否则无法对其进行监听。任务一功能就是对队列集中的队列和信号量进行监听,有有效值就打印。

2024-03-27 00:12:35 775

原创 FreeRTOS相同优先级任务可以相互打断吗?

而任务一打印四次之后,又差不多过了100ms,这时我们又人为调用了一次任务切换,相当于短时间内切了两次,任务一切任务二,任务二又切任务一,就导致任务一一直在打印。把TICK_RATE_HZ改为1,这时时间片应该为1s,同样调用实验一的代码,应该任务一打印几十次,完了任务二也打印几十次,以此类推,但实际结果如下:每个任务只打印了几次。把TICK_RATE_HZ改为5,这时时间片应该为200ms,同样调用实验一的代码,应该任务一打印8次左右,完了任务二也打印8次左右,以此类推,实际结果如下:和理论相符合。

2024-03-10 14:13:20 2544 3

原创 HAL库的FreeRTOS的任务时间和历史最小剩余堆栈获取

这样我们的任务时间获取函数就配置好了,总结一下就是首先设置一个比Systick中断周期小10-100倍的新的定时器时基,这个定时器可以为单片机的任何一个可用的定时器外设,中断优先级设置高一些,比FreeRTOS管辖范围大即可(即0-4之间)。由于本人在Stm32cubemx中配置FreeRTOS时未发现有开启任务时间获取函数的选项,在生成的代码中无法使用任务时间获取函数,因此决定参考网上的相关文章记录一下如何在HAL库生成的代码中使用任务时间获取函数vTaskGetRunTimeStats();

2024-03-07 00:47:32 1196 1

原创 HAL库软件IIC读取DS3231

DS3231驱动的具体C文件和头文件如下,软件IIC实现可参考我的上一篇博客。

2024-03-01 16:32:20 502

原创 HAL库软件IIC读取AT24C02/AT24C32

因为SDA线既要用作输出,也要用作输入(从机应答信号),使用开漏模式则可以解决这个问题。当然我们也可以使SDA为推挽输出模式,但是这样每次SDA输出和输入模式转变时都需要重新初始化SDA的GPIO口,比较麻烦。我们把程序分为三部分,第一部分是延时函数和软件IIC函数;main测试函数以及测试结果:(友情提醒,测试软件IIC时可以先从单字节写入读取开始,这样出问题了可以缩小查找范围)为了克服硬件IIC的缺点以及更好了了解IIC协议,下面让我来介绍一下HAL库环境下的软件IIC如何使用。

2024-02-28 19:12:31 1615 5

原创 HAL库执行bootloader串口IAP升级

硬件:正点原子mini开发板v3.0,使用的硬件有f103RCT6芯片、w25q64 flash芯片、AT24C02 EEPROM芯片。软件:STM32CubeMx、Keil5上位机:SecureCRT、野火上位机本程序主要参考哔站up主:超子说物联网,有具体视频可以学习,本人只是进行了一个HAL库的移植和一些逻辑的修改,如果有侵权会删除文章。还有就是本人的OTA逻辑可能存在疏漏,欢迎大家向我提出质疑。

2024-02-18 22:12:30 1460 1

原创 HAL库执行bootloader跳转操作:

这里我们设置bootloader的起始地址为:0x8000000,大小为0x10000,那么下载程序时擦除应该设置为按扇区擦除而不是整片擦除,app程序起始地址为0x8010000大小为0x30000,同理。参考网上一些博主说的,在调用复位函数和真正复位之间还有一段延迟,在这段时间单片机还是可以正常处理中断等程序的,为了避免这种情况,应该把相应的中断都屏蔽掉。注:想要跳转后成功执行app程序,app程序的起始位置和中断向量表位置应该和BOOT跳转后的位置对应上;并且应该在程序开始时开启总中断。

2024-02-15 13:31:09 998 1

HAL库BootLoader通过FLASH进行双APP升级

HAL库BootLoader通过FLASH进行双APP升级

2025-03-29

BootLoader+APP测试程序

学习BootLoader+APP串口IAP升级程序

2024-02-18

HAL库执行bootloader跳转操作:

bootloader程序和app程序

2024-02-15

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除