LVGL8_小型环境检测仪
前言
为了学习LVGL8
这是一个冗长的项目,中间很多问题,有使用STM32F411的VCAP引脚画错不能下载不能运行。
也有温湿度传感器,因为板子IC的发热影响了测量精度
修改SPI的DMA设置,实现刷屏无卡顿60hz的FPS
项目介绍
硬件资源
- STM32F411
- 盛思锐温湿度传感器 SHT31
- 盛思锐空气质量传感器 SGP40
- LCD屏
- SD卡
MCU资源
- 串口
- SPI+DMA
- 硬件IIC
- SD+FATFS
- ADC+DMA
软件资源
- STM32CubeMX
- SquareLine studio
- Keil
- Fusion360建模
原理描述,项目成品效果演示
这是一个Bilibili链接,视频还没做完
https://www.bilibili.com/video/BV1NU4y117Ah?spm_id_from=333.999.0.0
如果有兴趣制作,或者想要参考代码或者模型,请一键三连 B站私信我邮箱
资料发你。资料就不传CSDN了。原因你懂的。
项目开始
LVGL8移植
LVGL移植需要移植6个接口
使用SPI+DMA刷屏设置后,240*240的屏幕刷新无卡顿。
*初始化调用*
lv_init(); //lvgl初始化
lv_port_fs_init(); //lvgl文件系统初始化
lv_port_disp_init(); //lvgl显示初始化
lv_port_indev_init(); //lvgl输入初始化
*主循环*
lv_task_handler();//LittleVGL
*定时器调用*
lv_tick_inc(1);//lvgl 的 1ms 心跳
其中 lv_init(); 和 lv_task_handler();//LittleVGL是不需要移植修改代码的
显示移植
STM32CubeMX的设置
建议堆栈空间选大一点,以免显示出现花点
加入代码
void LVGL_LCD_Fill_DMA(void* pixels, uint32_t len)
{
LCD_CS_Clr();//片选拉低 准备SPI传输
LCD_DC_Set();//写数据
HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)pixels,len);
}
#include "lv_port_disp.h"
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)//传输完成中断回调函数
{
if(hspi==(&hspi1))
{
lv_disp_flush_ready(disp_drv_p); //刷新完成
LCD_CS_Set();//片选拉高 结束SPI传输
}
}
定义显示缓存
设定显示器的分辨率
#define LV_HOR_RES_MAX (240) //
#define LV_VER_RES_MAX (240) //
//全屏的大小 每次刷新所占屏幕的大小 1/10 每次刷新屏幕的10分之1
#define COLOR_BUF_SIZE (LV_HOR_RES_MAX*LV_VER_RES_MAX/10)
//LV_MEM_SIZE 是空间所需的缓存
static lv_color_t color_buf[COLOR_BUF_SIZE];//
static lv_color_t color_buf2[COLOR_BUF_SIZE];
修改函数
在 void lv_port_disp_init(void) 修改
双缓冲定义
lv_disp_draw_buf_init(&disp_buf, color_buf, color_buf2, COLOR_BUF_SIZE);
修改 显示刷新函数disp_flush
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
lv_coord_t w = (area->x2 - area->x1 + 1);
lv_coord_t h = (area->y2 - area->y1 + 1);
uint32_t size = w * h;
disp_drv_p = disp_drv;
//LCD设置刷屏位置
LCD_Address_Set((uint16_t)area->x1, (uint16_t)area->y1, (uint16_t)area->x2, (uint16_t)area->y2);
//DMA整刷
LVGL_LCD_Fill_DMA(color_p, size * sizeof(uint16_t));
//先不调用LVGL刷新完成函数lv_disp_flush_ready(disp_drv_p);,在DMA传输中断完成后再调用
}
LV_Conf.h的修改
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH 16 //设置颜色深度为16
/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP 1 //专为8字节配置的函数
//显示设备刷新时间
#define LV_DISP_DEF_REFR_PERIOD 15 /*[ms]*/ 1000ms/15ms=66FPS
编码器输入移植
这个需要移植的部分比较简单
void lv_port_indev_init(void)
{
static lv_indev_drv_t indev_drv;
/*------------------
* Encoder
* -----------------*/
/*Initialize your encoder if you have*/
encoder_init();
/*Register a encoder input device*/
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = encoder_read;
indev_encoder = lv_indev_drv_register(&indev_drv);
//group组创建,加入进入这个组的控件都可以被聚焦,选中操作,不在组内的不能选中
group = lv_group_create();
//注册输入设备到组内
lv_indev_set_group(indev_encoder, group);
//不适用默认模式
//lv_group_set_default(group);
}
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
data->enc_diff = encoder_diff;
data->state = encoder_state;
encoder_diff = 0;
encoder_state = 0;
}
拨轮设置
拨轮就是普通的输入IO口,到了触发电平就改变上面encoder_diff和encoder_state的值就可以了
if(Thumb_1.Event==Thumbwheel_Event_Front)//
{encoder_diff = -1;}
else if(Thumb_1.Event==Thumbwheel_Event_Rear)//
{encoder_diff = 1;}
else if(Thumb_1.Event==Thumbwheel_Event_Press)//
{encoder_state = 1;}
文件系统移植
STM32CubeMX的设置
SDIO设置
DMA设置
FATFS设置
这是一个IO作为SD卡插入检测,硬件里面其实没有
需要修改一下CubeMX生成的文件
文件系统设置,使能长文本,不使用中文–因为占用代码空间大
文件系统设置调用DMA来读写SDIO接口
在fatfs_platform.h中修改一下函数,取消掉SD卡插入检测引脚的输入
uint8_t BSP_PlatformIsDetected(void) {
uint8_t status = SD_PRESENT;
/* Check SD card detect pin */
// if(HAL_GPIO_ReadPin(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != GPIO_PIN_RESET)
// {
// status = SD_NOT_PRESENT;
// }
/* USER CODE BEGIN 1 */
/* user code can be inserted here */
/* USER CODE END 1 */
return status;
}
ADC+DMA
使用两个100K电阻分压锂电池测电压
但是这样结果不准,但也可以勉强凑合使用
使用规则通道转换
连续转换,扫描转换打开
然后代码里面调用
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)bat.BatAdc,2);//------启动ADC连续转换,DMA传输
然后转换成功的两通道ADC值,就会自动放在BatAdc往后的两个地址里面
PWM驱动蜂鸣器
电路上我用了一个超小的蜂鸣器需要4K的PWM
#define BUZ_ON(a,b) HAL_TIM_PWM_Start(a,b)
#define BUZ_OFF(a,b) HAL_TIM_PWM_Stop(a,b)
SquareLine
该软件是LVGL官方推出的一段可拖拽设置控件UI,并自动生成代码的软件。
官网可以下载试用版30天
工程设置属性要符合自己的硬件条件
都设置完成后在左上角Export里面选择 Export File导出代码
我们设置控件的代码就导出来了,将UI文件夹下面的文件都加入到工程中。然后修改下面两处并调用ui_init()函数就可以了
ui.h和ui_helpers.h中include修改成这样就行了
#ifdef __cplusplus
extern "C" {
#endif
#include "lvgl.h"
Fusion360建模
过程
略