自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 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 1057 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 203

原创 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 823

原创 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 499

原创 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 1135

原创 HAL库W25Qxx系列芯片驱动

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

2025-02-01 19:48:41 203

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

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

2025-01-31 15:59:42 838 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 514

原创 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 428 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 727

原创 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 1060

原创 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 859

原创 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 458

原创 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 1138

原创 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 721

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

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

2024-12-17 10:33:36 263

原创 STM32 HAL库 ST7789驱动

【代码】STM32 HAL库 ST7789驱动。

2024-11-13 16:32:00 188

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

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

2024-11-01 22:04:41 639

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

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

2024-10-10 23:59:51 1079 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 658

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

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

2024-08-17 17:34:43 344

原创 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 1141

原创 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 1331

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

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

2024-07-31 22:30:44 1003 1

原创 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 821

原创 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 968

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

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

2024-04-05 18:23:07 1337 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 427 1

原创 HAL库使用FreeRTOS队列集

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

2024-03-27 00:12:35 698

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

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

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

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

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

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

原创 HAL库软件IIC读取DS3231

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

2024-03-01 16:32:20 471

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

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

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

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

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

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

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

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

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

原创 自定义串口DMA打印函数和串口接收缓冲区

简单数组:由于HAL库DMA的接收是设定一个目标地址再设定一个接收长度,如果要接收多次DMA的数据,该目标地址则会不断向数组后面移动,如果目标地址+数据长度超过了数组最后一位的地址的话就会造成数组越界,这是我们不希望看到的。环形数组:通过设置指针作为DMA接收目标地址和数据最大接受长度,每次接受完数据都判断该指针+数据最大接收长度是否超过数组末尾地址,不超过就将接收指针后移,如果超过就执行回卷操作,即将该目标地址指针重新指向缓冲区起始地址。串口空闲中断DMA接收不定长数据。串口DMA接收缓冲区。

2024-02-15 12:34:04 320 1

原创 STM32G070KBT6最小系统板绘制和晶振配置、BOOT模式配置

那么还有一种方法可以下载程序在SRAM中并且在SRAM中运行程序,那就是选择主闪存存储器模式启动,然后再闪存flash开头我们自己编写一个bootloader,这个bootloader包含官方bootloader的串口下载功能(当然也可以添加一些其他功能),当App程序运行时检测到要下载程序就跳转到自己编写的bootloader中去,然后通过串口用代码指定程序下载到SRAM中(也可以指定下载到flash中),下载完再跳转到SRAM(或者跳转到flash)中,就可以运行刚刚下载的app程序;

2024-01-20 19:09:53 3143

原创 UCC3803电源芯片使用

BAT54和C11、R3构成了外部电压软启动电路,上电开始前几ms5V电源给C11充电,同时芯片内部完成4ms软起动,但是COMP端电压要到2V芯片才能工作,此时由于C11电压还没充到2V-管压降,因此COMP也要通过BAT54给C11充电,直到C11充够电压让COMP端达到2V,这个充电时间不好算;(4V的REF电压)FB和COMP之间连接一个电阻和电容,其中电容取值为几十-几百pf用于滤波,而电阻则是用于负反馈,最终FB的电压和REF/2=2V相等,(注意上图中运放带圆圈的输入端是反相输入端);

2024-01-18 14:58:29 750

原创 INA220电流电压采样方案

RSHUNT为采样电阻的值,这里我们通过设置Cal的值来控制电流寄存器的分辨率Current_LSB,例如当采样电阻为0.1欧姆的时候,我们设置Cal = 2000h = 8192 ,那么Current_LSB = 0.05mA,而由于电流寄存器数据位只有15位,最大值为32767(这里作者不明白为什么上述公式2的分母是2^15,作者认为应该是2^15-1才对),因此量程为32767*Current_LSB = 1.638A;16位只读寄存器,最高位为正负位,其他位为数据位,复位后清零;

2024-01-16 13:34:19 3911 3

原创 HAL库数字电位器MCP41010的使用(SPI通讯)

设备将在 CS为低电平时,设备将跟踪时钟数(上升沿),如果时钟数不是 16 的倍数,则将终止所有命令。我们将PA0和PB0看成电位器的两端(哪一端为高电压端都行),而PW0则看作电位器的抽头(抽头有256个档位),由数据手册我们可以知道,抽头电流应该小于1mA;在变阻器模式下,电阻具有正温度系数。随温度变化最大的在数据字节的的前 6%(数据字节为 00h 至 0Fh)中变化最大,原因是刮环电阻系数会影响总电阻。在这两种模式下,数据在 SCK 上升沿时进入设备,而在 SCK 下降沿时从 SO 引脚输出数据。

2024-01-14 23:11:44 4392 4

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关注的人

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