当前位置:首页 > > 嵌入式云IOT技术圈
[导读]上篇分享了事件驱动型的菜单框架,也实现了一个基本的小项目。但是怎么看怎么都觉得界面不爽,单纯显示文字的方式实在是太单调了,如果想要显示颜色丰富的图片,MCU资源受限又很难直接在程序中直接定义图片大数组。于是,这次选择在SD卡中放图片,通过Fatfs去读取SD卡中的图片来进行显示……

上次我们分享了事件驱动型的菜单框架,也实现了一个基本的小项目,如下:

基于事件型表驱动法菜单框架之小熊派简易气体探测器实战项目开发(上)

但是怎么看怎么都觉得界面不爽,单纯显示文字的方式实在是太单调了,如果想要显示颜色丰富的图片,MCU资源受限又很难直接在程序中直接定义图片大数组。

于是,我选择在SD卡中放图片,通过Fatfs去读取SD卡中的图片来进行显示,图片都是我自己在阿里图库上找的开源素材,然后用PS自己P的:

废话不多说,来看看实际效果吧!演示视频如下:

这样看起来效果就舒服一点啦。

1、新增功能项

本节分享的内容相较于上篇文章修改/增加了如下功能:

底层配置

  • 修改LCD寄存器,提升LCD刷屏速度
  • 增加Fatfs、SD卡读写功能

应用逻辑

  • 增加模拟长按开机识别
  • 增加开机LOGO以及其它UI的显示
  • 增加菜单(阈值设置、设置、调试模式、仪器信息)

1.1、关于底层配置

1.1.1、提升屏刷新速度

由于要刷图,所以只能想办法尽量提升屏的刷新速度,于是在LCD手册里有这么一个寄存器,可以提升屏的刷新速度:

在LCD驱动初始化代码里,这个寄存器默认配置的是60Hz,也就是0x0F这个值

/* Frame Rate Control in Normal Mode */
LCD_Write_Cmd(0xC6);
// LCD_Write_Data(0x0F); //60HZ
LCD_Write_Data(0x01);  //111Hz 提升屏的刷新速度

本来设置为0x00为119Hz,但是设置完LCD就黑屏了,改为0x01就不会,目前没找到具体原因,将就着用吧。

1.1.2、增加Fatfs、SD卡读写功能


之前也分享了配置方法,详情可以看以下文章:

基于小熊派SD卡+Fatfs+移植开源iniparse解析库并使用

1.2、关于应用逻辑

1.2.1、增加模拟长按开机识别

由于开机前需要加载整幅图片,会存在刷新慢的问题,我们可以先关掉LCD背光,然后等图刷完了再开背光,这样看到就是一张完整的图,这个过程可以用长按一个按键开机的方式来代替,代码实现如下:

void PowerOn(void)
{
    static uint32_t power_press_count = 0;
    HAL_Delay(500);
    while(1)
    {
        if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
        {
            power_press_count ++;
      
            if(power_press_count >= 100)
            {
                //开指示灯
                HAL_GPIO_WritePin(GPIOC, LED_Pin, GPIO_PIN_SET);
                while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
                {
                    HAL_Delay(10);
                }
                break;
            }
        }
        else
        {
            power_press_count = 0;
        }

        HAL_Delay(10);
    }
}

然后在显示开机LOGO前调用即可,显示开机LOGO调用完毕后打开背光显示。

1.2.2、增加开机LOGO以及其它UI的显示

图片资源采用的是24位bmp图,这些图片都存放在SD卡根目录下的LOGO文件夹的子文件夹中:

(1)开机LOGO


(2)主页面UI

(3)检测页面动画LOGO

显示接口移植了硬石科技提供的bsp_bmp.c,他们用的是320*480的RGB屏,小熊派用的是240*240的屏,根据现有的屏我做了一些修改:

uint8_t pColorData[960];     /* 一行真彩色数据缓存 320 * 3 = 960 */
//uint8_t pColorData[720];     /* 一行真彩色数据缓存 240 * 3 = 720 */

显示bmp函数:

/**
  * 函数功能: 显示bmp图片, 24位真彩色
  * 输入参数: x:显示图片左上角x轴坐标
  *           y:显示图片左上角y轴坐标
  *           pic_name:显示图片文件名称
  * 返 回 值: 无
  * 说    明:图片宽度和高度根据图片大小而定
  */
void Lcd_show_bmp(uint16_t x, uint16_t y,char *pic_name)
{
 uint16_t i, j, k;
 int width, height, l_width;
  
 BMP_FileHeader FileHeader;
 BMP_InfoHeader InfoHeader;
  
/*-------------------------------------------------------------------------------------------------------*/
 f_res=f_open(&file,pic_name, FA_OPEN_EXISTING|FA_READ); 
 if(f_res == FR_OK)
 {
  BMP_DEBUG_PRINTF("Open file success\r\n");

  /* 读取文件头信息  两个字节*/         
  f_res=f_read(&file,&FileHeader,sizeof(BMP_FileHeader),&f_num);     
    
  /* 判断是不是bmp文件 "BM"*/
  if(FileHeader.bfType!=0x4d42)
  {
   BMP_DEBUG_PRINTF("file is not .bmp file!\r\n");
   return;
  }
  else
  {
   BMP_DEBUG_PRINTF("Ok this is .bmp file\r\n"); 
  }
  /* 读取BMP文件头信息*/      
  showBmpHeader(&FileHeader);
   
  /* 读取位图信息头信息 */
  f_res=f_read(&file,&InfoHeader,sizeof(BMP_InfoHeader),&f_num);      
  showBmpInforHeader(&InfoHeader);
 }    
 else
 {
  BMP_DEBUG_PRINTF("file open fail!\r\n");
  return;
 }  
/*-------------------------------------------------------------------------------------------------------*/
 width  = InfoHeader.biWidth;
 height = InfoHeader.biHeight; 
  
 /* 计算位图的实际宽度并确保它为32的倍数 */
 l_width = WIDTHBYTES(width* InfoHeader.biBitCount);
  
 if((l_width>960)||(InfoHeader.biBitCount!=24))
 {
  BMP_DEBUG_PRINTF("\n SORRY, PIC IS TOO BIG (X<=320 and bit!=16)\n");
  return;
  }
  f_lseek(&file,FileHeader.bfOffBits);
   
  if(InfoHeader.biBitCount == 24)
  {
    for(i=0;i    {
      /* 开一个图片大小的窗口*/
      LCD_OpenWindow(x, y+height-i-1, width, 1);
   LCD_Write_Cmd(0x2C);
      /* 读取一行bmp的数据到数组pColorData里面 */
      f_read(&file,pColorData,l_width,&f_num);      
      for(j=0;j      {        
        k = j*3;                  //一行中第K个像素的起点        
        //LCD_WRITE_DATA(RGB24TORGB16(pColorData[k+2],pColorData[k+1],pColorData[k])); //写入LCD-GRAM
        //这里调用的是写一次写两个字节的函数
        LCD_Write_2Byte(RGB24TORGB16(pColorData[k+2],pColorData[k+1],pColorData[k]));
      }
    }
  }
 f_close(&file);    
}

修改完后在如果需要图片显示则调用如下接口:

#define START_LOGO "0:/UI/start_logo/start_logo.bmp"

//最开始的时候调用挂载,只挂载一次就好了
//在串行FLASH挂载文件系统,文件系统挂载时会对串行FLASH初始化
f_res = f_mount(&fs, (TCHAR const*)SDPath, 1);
if(f_res == FR_OK)
  printf("》SD卡文件系统挂载成功\n");


//以后只需要调用显示即可
Lcd_show_bmp(0,0,START_LOGO);

注意:图片的路径是SD卡下存放的路径,一定要选对。

1.2.2、增加菜单(阈值设置、设置、调试模式、仪器信息)

在主页面长按右键进入菜单:

此时按左键可以切换选项,短按右键进入某一菜单项,长按右键退出回到主页面,这里只实现了仪器信息,其它项目还没有实现,但要添加也非常简单,期待后期分享。

菜单的实现也很简单,菜单项切换的逻辑和主页面的切换逻辑是一样的:

其余功能:后续还可以做报警记录存储、数据上传到OneNet或者华为云等平台、参数设置等等,总之这个项目可拓展性非常强,这些功能将在本项目开发的下一章节持续进行拓展并分享,欢迎及时关注我的码云仓库与微信公众号文章更新。

本节代码已同步到码云的代码仓库中:

获取方法如下:

1、新建一个文件夹

2、使用git clone远程获取小熊派所有案例代码

我还将之前做的一些项目以及练习例程在近期内全部上传完毕,与大家一起分享交流:

公众号粉丝福利时刻

这里我给大家申请到了福利,本公众号读者购买小熊派开发板可享受9折优惠,有需要购买小熊派以及腾讯物联网开发板的朋友,淘宝搜索即可,跟客服说你是公众号:嵌入式云IOT技术圈 的粉丝,立享9折优惠!

往期精彩

STM32系统bootloader应用

【C进阶】拿着"sizeof这些用法和坑"去吹牛吧!

基于事件型表驱动法菜单框架之小熊派简易气体探测器实战项目开发(上)

上海出差之行--领略外滩美景、RT-Thread总部之旅、嵌友面基、返程记录

觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭