(STM32)从零开始的RT-Thread之旅--SPI驱动ST7735(2)

news2025/7/28 3:07:12

上一篇:

(STM32)从零开始的RT-Thread之旅--PWM驱动ST7735调光

本篇使用的驱动来自ST官方提供:

https://github.com/STMicroelectronics/stm32-st7735.git

需要的可以直接git clone下来移植,核心代码无关芯片型号,可移植性很不错!本篇用的ST7735库比官方新添加了一些内容,是开发板卖家提供的,地址:

https://github.com/WeActTC

第一篇中我们打通了SPI,读取到了芯片ID,这一篇只要完善几个接口函数就可以直接使用官方的驱动库了。至于要完善哪几个接口,需要看一下官方驱动库需要哪些函数。

1.添加官方源代码

可以参照我上图的结构把几个源文件添加进去,其中font.h可以在WeAct那个github上找到。

添加完后记得把头文件路径也包含进去。

2.官方库使用方法

在添加完成后,新建lcd相关源文件,比如我的文件结构:

修改 st7735.h 中一处地方:

这个变量在st7735.c中被定义。 怎么使用库如下:

其中ST7735Ctx是库里面定义好的,我们直接使用即可。但是还需要两个变量:

st7735_pObj就是设备驱动实例,实际在屏幕上显示都是操作的它。关键是st7735_pIO这个变量,它负责提供底层接口。它里面包含的一些函数指针正是我们需要完成的。

在上一章的基础上,使用了两套SPI使用方式,如果定义 USE_RTT_SPI ,就是用RTT驱动框架提供的SPI接口函数,如果把它注释掉,则直接使用HAL库的SPI函数,具体实现我会附在后面。

实际我们使用的时候调用的函数是:

比如要填充整个屏幕为黑色:

 

 

 

 

 

 

附:

mspi.c

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-11-14     cx       the first version
 */
#include <rtthread.h>
#include <rtdevice.h>
#include <stm32h7xx.h>
#include <drv_spi.h>
#include <mspi.h>
#include "st7735_reg.h"
#include "st7735.h"

#define USE_RTT_SPI

SPI_HandleTypeDef *spi_handle;

#ifdef USE_RTT_SPI

static struct rt_spi_device *spi_lcd;

#define LCD_RD_HIGH rt_pin_write(SPI_RD_PIN_NUM, PIN_HIGH)
#define LCD_RD_LOW  rt_pin_write(SPI_RD_PIN_NUM, PIN_LOW)
#else
SPI_HandleTypeDef hspi4;
#define SPI_Drv (&hspi4)
#define LCD_CS_HIGH HAL_GPIO_WritePin(GPIOE,GPIO_PIN_11,GPIO_PIN_SET)
#define LCD_CS_LOW  HAL_GPIO_WritePin(GPIOE,GPIO_PIN_11,GPIO_PIN_RESET)

#define LCD_RD_HIGH HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET)
#define LCD_RD_LOW  HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET)
#endif

#ifdef USE_RTT_SPI
int32_t mspi_send_reg(uint8_t reg,uint8_t *data,uint32_t len)
{
    struct rt_spi_message msg;
    uint32_t remsg = RT_NULL;
    msg.send_buf = &reg;
    msg.recv_buf = RT_NULL;
    msg.length = 1;
    msg.cs_take = 1;
    msg.cs_release = 0;
    msg.next = RT_NULL;
    LCD_RD_LOW;
    remsg = (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
    LCD_RD_HIGH;
    if(len > 0)
    {
        msg.send_buf = data;
        msg.recv_buf = RT_NULL;
        msg.length = len;
        msg.cs_take = 0;
        msg.cs_release = 1;
        msg.next = RT_NULL;
        remsg += (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
    }
    if(remsg!=RT_NULL)
        return -1;
    else
        return 0;
}
int32_t mspi_read_reg(uint8_t reg,uint8_t *data)
{
    struct rt_spi_message msg;
    uint32_t remsg = RT_NULL;
    uint8_t reg1 = reg;
    msg.send_buf = &reg1;
    msg.recv_buf = RT_NULL;
    msg.length = 1;
    msg.cs_take = 1;
    msg.cs_release = 0;
    msg.next = RT_NULL;
    LCD_RD_LOW;
    remsg = (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
    LCD_RD_HIGH;
    if(remsg == 0)
    {
        msg.send_buf = RT_NULL;
        msg.recv_buf = data;
        msg.length = 1;
        msg.cs_take = 0;
        msg.cs_release = 1;
        msg.next = RT_NULL;
        remsg += (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
    }
    if(remsg!=RT_NULL)
        return -1;
    else
        return 0;
}
int32_t mspi_send_data(uint8_t *data,uint32_t len)
{
    struct rt_spi_message msg;
    msg.send_buf = data;
    msg.recv_buf = RT_NULL;
    msg.length = len;
    msg.cs_take = 1;
    msg.cs_release = 1;
    msg.next = RT_NULL;
    return (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
}
int32_t mspi_read_data(uint8_t *data,uint32_t len)
{
    struct rt_spi_message msg;
    msg.send_buf = RT_NULL;
    msg.recv_buf = data;
    msg.length = len;
    msg.cs_take = 1;
    msg.cs_release = 1;
    msg.next = RT_NULL;
    return (uint32_t)rt_spi_transfer_message(spi_lcd,&msg);
}

#else
int32_t mspi_send_reg(uint8_t reg,uint8_t *data,uint32_t len)
{
    int32_t result;
    LCD_CS_LOW;
    LCD_RD_LOW;
    result = HAL_SPI_Transmit(SPI_Drv,&reg,1,100);
    LCD_RD_HIGH;
    if(len > 0)
        result += HAL_SPI_Transmit(SPI_Drv,data,len,500);
    LCD_CS_HIGH;
    if(result>0){
        result = -1;}
    else{
        result = 0;}
    return result;
}

int32_t mspi_read_reg(uint8_t reg,uint8_t *data)
{
    int32_t result;
    LCD_CS_LOW;
    LCD_RD_LOW;

    result = HAL_SPI_Transmit(SPI_Drv,&reg,1,100);
    LCD_RD_HIGH;
    result += HAL_SPI_Receive(SPI_Drv,data,1,500);
    LCD_CS_HIGH;
    if(result>0){
        result = -1;}
    else{
        result = 0;}
    return result;
}

int32_t mspi_send_data(uint8_t *data,uint32_t len)
{
    int32_t result;
    LCD_CS_LOW;
    //LCD_RD_HIGH;
    result =HAL_SPI_Transmit(SPI_Drv,data,len,100);
    LCD_CS_HIGH;
    if(result>0){
        result = -1;}
    else{
        result = 0;}
    return result;
}

int32_t mspi_read_data(uint8_t *data,uint32_t len)
{
    int32_t result;
    LCD_CS_LOW;
    //LCD_RD_HIGH;
    result = HAL_SPI_Receive(SPI_Drv,data,len,500);
    LCD_CS_HIGH;
    if(result>0){
        result = -1;}
    else{
        result = 0;}
    return result;
}
#endif
int32_t mspi_get_tick(void)
{
    return HAL_GetTick();
}
void mspi_rw_gpio_init(void)
{
#ifdef USE_RTT_SPI
    rt_pin_mode(SPI_RD_PIN_NUM, PIN_MODE_OUTPUT);
    rt_pin_write(SPI_RD_PIN_NUM, PIN_HIGH);
#else
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOE_CLK_ENABLE();
    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11|GPIO_PIN_13, GPIO_PIN_SET);
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
#endif
}
void mspi_init(void)
{
    mspi_rw_gpio_init();
#ifdef USE_RTT_SPI
    struct rt_spi_configuration cfg;
    rt_hw_spi_device_attach("spi4", "spi40", GPIOE, GPIO_PIN_11);
    spi_lcd = (struct rt_spi_device *)rt_device_find("spi40");
    if(!spi_lcd)
    {
        rt_kprintf("spi40 can't find\n");
    }
    else
    {
        spi_lcd->bus->owner = spi_lcd;
        cfg.data_width = 8;
        cfg.mode = RT_SPI_MASTER | RT_SPI_3WIRE | RT_SPI_MODE_0 | RT_SPI_MSB;
        cfg.max_hz = 12.5 * 1000 * 1000;
        rt_spi_configure(spi_lcd, &cfg);
    }
    //也可以初始化使用框架提供的函数,发送接收使用HAL库函数,操作对象就是下面的 spi_handle
//    struct stm32_spi *spi_drv =  rt_container_of(spi_lcd->bus, struct stm32_spi, spi_bus);
//    spi_handle = &spi_drv->handle;
#else
    hspi4.Instance = SPI4;
    hspi4.Init.Mode = SPI_MODE_MASTER;
    hspi4.Init.Direction = SPI_DIRECTION_1LINE;
    hspi4.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi4.Init.NSS = SPI_NSS_SOFT;
    hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
    hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi4.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi4.Init.CRCPolynomial = 0x0;
    hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
    hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
    hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
    hspi4.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
    hspi4.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
    hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
    hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
    hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
    hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
    hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE;
    if (HAL_SPI_Init(&hspi4) != HAL_OK)
    {
      rt_kprintf("ERROR\n");
    }
#endif
}

mlcd.c

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-11-15     cx       the first version
 */
#include <stdio.h>
#include <rtthread.h>
#include <rtdevice.h>
#define DBG_TAG "mlcd"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "mpwm.h"
#include "mspi.h"
#include "st7735_reg.h"
#include "st7735.h"
#include "mlcd.h"
#include "font.h"
#include <stm32h7xx.h>

int32_t mlcd_st7735_init(void);

ST7735_IO_t st7735_pIO = {
    mlcd_st7735_init,
    NULL,
    0,
    mspi_send_reg,
    mspi_read_reg,
    mspi_send_data,
    mspi_read_data,
    mspi_get_tick
};

ST7735_Object_t st7735_pObj;

int32_t mlcd_st7735_init(void)
{
    int32_t result = ST7735_OK;
    mpwm_init();
    mspi_init();
    return result;
}

int mlcd_init(void)
{
    uint32_t st7735_id;
    uint8_t text[50];
    #ifdef TFT96
    ST7735Ctx.Orientation = ST7735_ORIENTATION_LANDSCAPE_ROT180;
    ST7735Ctx.Panel = HannStar_Panel;
    ST7735Ctx.Type = ST7735_0_9_inch_screen;
    #elif TFT18
    ST7735Ctx.Orientation = ST7735_ORIENTATION_PORTRAIT;
    ST7735Ctx.Panel = BOE_Panel;
    ST7735Ctx.Type = ST7735_1_8_inch_screen;
    #else
    LOG_E("Unknown Screen");
    #endif
    ST7735_RegisterBusIO(&st7735_pObj,&st7735_pIO);
    ST7735_LCD_Driver.Init(&st7735_pObj,ST7735_FORMAT_RBG565,&ST7735Ctx);
    ST7735_LCD_Driver.ReadID(&st7735_pObj,&st7735_id);
    rt_kprintf("LCD ID:%08X\n",st7735_id);

    ST7735_LCD_Driver.FillRect(&st7735_pObj, 0, 0, ST7735Ctx.Width,ST7735Ctx.Height, BLACK);

    sprintf((char *)&text, "Something V1.0");
    LCD_ShowString(4, 4, ST7735Ctx.Width, 16, 16, text);

    return 0;
}

uint16_t POINT_COLOR=0xFFFF;    //画笔颜色
uint16_t BACK_COLOR=BLACK;  //背景色
//在指定位置显示一个字符
//x,y:起始坐标
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16
//mode:叠加方式(1)还是非叠加方式(0)

void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint8_t size,uint8_t mode)
{
  uint8_t temp,t1,t;
    uint16_t y0=y;
    uint16_t x0=x;
    uint16_t colortemp=POINT_COLOR;
  uint32_t h,w;

    uint16_t write[size][size==12?6:8];
    uint16_t count;

  ST7735_GetXSize(&st7735_pObj,&w);
    ST7735_GetYSize(&st7735_pObj,&h);

    //设置窗口
    num=num-' ';//得到偏移后的值
    count = 0;

    if(!mode) //非叠加方式
    {
        for(t=0;t<size;t++)
        {
            if(size==12)temp=asc2_1206[num][t];  //调用1206字体
            else temp=asc2_1608[num][t];         //调用1608字体

            for(t1=0;t1<8;t1++)
            {
                if(temp&0x80)
                    POINT_COLOR=(colortemp&0xFF)<<8|colortemp>>8;
                else
                    POINT_COLOR=(BACK_COLOR&0xFF)<<8|BACK_COLOR>>8;

                write[count][t/2]=POINT_COLOR;
                count ++;
                if(count >= size) count =0;

                temp<<=1;
                y++;
                if(y>=h){POINT_COLOR=colortemp;return;}//超区域了
                if((y-y0)==size)
                {
                    y=y0;
                    x++;
                    if(x>=w){POINT_COLOR=colortemp;return;}//超区域了
                    break;
                }
            }
        }
    }
    else//叠加方式
    {
        for(t=0;t<size;t++)
        {
            if(size==12)temp=asc2_1206[num][t];  //调用1206字体
            else temp=asc2_1608[num][t];         //调用1608字体
            for(t1=0;t1<8;t1++)
            {
                if(temp&0x80)
                    write[count][t/2]=(POINT_COLOR&0xFF)<<8|POINT_COLOR>>8;
                count ++;
                if(count >= size) count =0;

                temp<<=1;
                y++;
                if(y>=h){POINT_COLOR=colortemp;return;}//超区域了
                if((y-y0)==size)
                {
                    y=y0;
                    x++;
                    if(x>=w){POINT_COLOR=colortemp;return;}//超区域了
                    break;
                }
            }
        }
    }
    ST7735_FillRGBRect(&st7735_pObj,x0,y0,(uint8_t *)&write,size==12?6:8,size);
    POINT_COLOR=colortemp;
}

//显示字符串
//x,y:起点坐标
//width,height:区域大小
//size:字体大小
//*p:字符串起始地址
void LCD_ShowString(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint8_t size,uint8_t *p)
{
    uint8_t x0=x;
    width+=x;
    height+=y;
    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
    {
        if(x>=width){x=x0;y+=size;}
        if(y>=height)break;//退出
        LCD_ShowChar(x,y,*p,size,0);
        x+=size/2;
        p++;
    }
}












本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/16487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

销量上不去?跨境电商出现这5种迹象,你需要Starday了!

随着2015年"互联网"时代的来临&#xff0c;跨境电商行业逐步走进了资本市场的视野中&#xff0c;跨境电商成为了有望对抗出口增速下台阶的利器。近年来&#xff0c;随着国际贸易条件的恶化&#xff0c;以及欧洲、日本的需求持续疲弱&#xff0c;中国出口贸易增速出现…

[附源码]Python计算机毕业设计jspm郫县兼职信息系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Egg实现用户注册登录以及使用jwt进行token鉴权

目录 什么是用户鉴权 注册接口 登录接口 jwt解密token 在一个后台服务中&#xff0c;用户鉴权是一个重点&#xff0c;几乎所有的需求都是围绕用户&#xff08;token&#xff09;去进行设计的&#xff0c;所以在用户鉴权也是我们必须要重视的课程&#xff0c;本章我们就利用…

【踩坑日记 · 前端】为 Excalidraw 添加中文手写字体

前言 Excalidraw 是一款完全免费的手绘风格绘图在线应用&#xff0c;能快速画出漂亮的流程图、示意图和图表&#xff0c;地址&#xff1a; Excalidraw | Hand-drawn look & feel • Collaborative • Secure 但美中不足的是&#xff0c;Excalidraw 只支持英文手写字体&…

[附源码]Python计算机毕业设计爱行无忧旅游票务管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

一文搞定,JMeter的三种参数化方式

1、Test Plan 中添加变量 可以在 Test Plan 中设置好添加变量&#xff0c;变量名可以在任意的位置使用&#xff0c;比如说在线程组中直接用${ 变量名 }方式引用&#xff0c;步骤如下&#xff1a; 1&#xff09;设置变量名和变量值 2&#xff09;添加线程组 3&#xff09;添…

记一场vue面试

Vue 修饰符有哪些 事件修饰符 .stop 阻止事件继续传播.prevent 阻止标签默认行为.capture 使用事件捕获模式,即元素自身触发的事件先在此处处理&#xff0c;然后才交由内部元素进行处理.self 只当在 event.target 是当前元素自身时触发处理函数.once 事件将只会触发一次.pass…

AcWing 数据结构

单链表 邻接表用的多 存储树和图 new()速度慢 数组模拟 模板 -1代表头节点 const int N 1e6 5; // head存储链表头 //e[]存储节点的值 //ne[]存储节点的next指针 //idx表示当前用到了哪个节点 int head, e[N], ne[N], idx;// 初始化 void init() {head -1;idx 0; }// 将…

皕杰报表之控件元素

在皕杰报表中&#xff0c;填报操作时&#xff0c;控件类型分为无输入控件、文本框、文本域、下拉框、下拉树、单选框、复选框、日期、时间、日期时间、自定义控件类型。如图所示&#xff1a; 1 无输入控件 选中此控件的单元格在页面生成无任何变化&#xff1b; 2 文本框 选中…

加拿大海运专线怎么选?加拿大海运专线有哪些费用

由于全球经济的发展&#xff0c;近年来&#xff0c;越来越多的国内跨境电商卖家向加拿大和、墨西哥、欧洲、美国等出口货物&#xff0c;而海运的运输方式相对比较划算。那么加拿大海运专线怎么选?又有哪些费用呢?一、加拿大海运专线怎么选 加拿大海运专线运输方式有整柜运输和…

Linux-----网络套接字编程

文章目录铺垫一下概念知识基于UDP协议下的套接字编程基于TCP协议下的套接字编程铺垫一下概念知识 我们知道IP地址是用来标识主机唯一性的。 而源IP地址表示从哪个主机来&#xff0c; 目的IP地址表示去哪个主机。 端口号&#xff08;port&#xff09;&#xff1a; 1&#xff0…

C++之继承、派生

目录 1.继承的概念与定义 2.层次概念是计算机的重要概念: 3.私有的能被继承&#xff0c;不能被访问 4.继承的三步骤 1.继承语法 2.继承例子 5.有继承和组合的构造顺序---内存布局 6.继承之下的赋值运算符重载 1.基础知识 2.Person、Student例子 7.一个类被多个类继承 …

22.11.18打卡 [传智杯 #3 初赛] 部分题

森林图论懒得写, 等搞完dp之后再来复习图论, 还有一题数据有问题没写 [传智杯 #3 初赛] 课程报名 - 洛谷 哇真的签到, 第一眼还想着推公式呢, 看这数据范围直接暴力了 /* ⣿⣿⣿⣿⣿⣿⡷⣯⢿⣿⣷⣻⢯⣿⡽⣻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠸⣿⣿⣆⠹⣿⣿⢾⣟⣯⣿⣿…

LiveGBS/LiveNVR组合实现GB35114平台端和GB35114设备端的GB35114的交互流程

概述&#xff1a; GB35114是在GB28181基础上扩展而来&#xff0c;增加了身份认证和数据加密。LiveNVR设备通过GB35114注册到LiveGBS时&#xff0c;LiveGBS平台端需要校验LiveNVR设备的身份&#xff0c;这是单向认证。同时可选LiveNVR也检验LiveGBS平台的身份&#xff0c;如果互…

[Howto] Pytorch Window GPU 环境配置

注&#xff1a; how to 系列只有基本的操作&#xff0c;不涉及原理&#xff0c;类似于操作手册。 Linux&#xff0c;MacOS和Window配置方法差不多&#xff0c;就是环境变量的修改方式不太一样&#xff0c;就不单独说明了。 1. 确定Pytorch版本 估计像我一样的初学者&#xf…

关于commonjs、AMD、UMD、ESM以及ts模块之间的使用差异

commonjs 特点&#xff1a;一个文件就是一个模块&#xff0c;拥有独立的作用域&#xff0c;适用于服务端不适合浏览器端。导出模块内部数据通过module.exports或exports对象默认导出&#xff1a; // true const a 1 const b 2 module.exports {a, b }或者 // true const …

【跨境电商卖家】Instagram营销初学者指南(二):方法与技巧

关键词&#xff1a;跨境电商卖家、instagram营销 1.为 Instagram营销设定目标 在你开始在 Instagram 上发帖之前&#xff0c;问问你自己&#xff08;或你的团队&#xff09;一件事&#xff1a;你为什么在 Instagram 上&#xff1f;尽管该平台很受欢迎&#xff0c;但您的回答不…

linux笔记(6):东山哪吒D1H显示HDMI测试-命令行调试

文章目录1.测试流程和结果2.测试过程详解2.1 挂载测试工具1.2 设置参数1.2.1设置name1.2.2选择命令1.2.3 设置命令参数1.3开启显示3.还没搞清楚怎么在应用中显示字符测试开发板的HDMI输出。 参考文档&#xff1a;全志官方文档。 1.测试流程和结果 测试结果&#xff1a; 2.测…

如何实现一键全选

利用复选框的激活、非激活实现一键全选功能 效果展示 前置准备 投票列表素材 具体步骤 添加素材 制作列表复选框 制作一件全选按钮 创建复选框相关行为触发器 制作一键全选触发器 步骤分解 添加素材 拖拽 图片组件 到 根容器 选中 图片组件 铺满父级容器 点击 检查面板 中的 …

一种新的群体智能优化算法:麻雀搜索算法(SSA)(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…