NUC980-OLED实现全中文字库的方法

news2024/12/29 9:06:56

1.背景

有一个产品,客户需要屏幕展示一些内容,要带一些中文,实现了OLED12864的驱动,但是它不带字库,现在要实现OLED全字库的显示

2.制作原始字库

下载软件pctolcd2002

设置

制作字库

打开原始文件

用软件自带的,或者自己去找字

生成字库文件

生成的内容如下

特别注意,保存的文件编码要是UTF-8的,不然后面会有点麻烦

3.转换

自行调整内容,字符"啊"之前的可以不要

目标格式应该是这样的

4.实现OLED驱动接口

oled.c

#include "oled.h"

/* ssd1306所对应的I2C控制器的设备节点 */ 
#define SSD1306_DEVICE      "/dev/i2c-0"    

/* ssd1306的I2C设备地址 */
#define SSD1306_ADDR    0x3C
 
uint8_t OLED_Display[128][8];
uint8_t OLED_Display_Cache[128][8];

static int oled_fd;

/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char command)
{
    unsigned char buf[2];
    buf[0] = 0x00;  // 控制字节,0x00表示接下来的字节是命令
    buf[1] = command;
    write(oled_fd, buf, 2);
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char data)
{
    unsigned char buf[2];
    buf[0] = 0x40;  // 控制字节,0x40表示接下来的字节是数据
    buf[1] = data;
    write(oled_fd, buf, 2);
}

void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
    if(cmd)
    {
        Write_IIC_Data(dat);
    }
    else {
        Write_IIC_Command(dat);
    }
}
 
/*        设置OLED屏的显示坐标
 *      X : 表示OLED的水平坐标(0—127)
 *      Y : 表示OLED的页(0—7)
*/
void OLED_Set_Pos(unsigned char x, unsigned char y) 
{   OLED_WR_Byte(0xb0+(y & 0x0f),OLED_CMD);
    OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
    OLED_WR_Byte((x&0x0f),OLED_CMD); 
}         
//开启OLED显示    
void OLED_Display_On(void)
{
    OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
    OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
    OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
    OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
    OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}                    
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!     
void OLED_Clear(void)  
{  
    uint8_t i,n;            
    for(i=0;i<8;i++)  
    {  
        OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
        OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
        OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
        for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); 
    } //更新显示
}

/*
函数功能:OLED打点函数
输入参数:点所在坐标 x=0~127 y = 0~63
输出参数:无
用到的全局变量:无
*/
void OLED_Dot(uint8_t x,uint8_t y,uint8_t state)
{
    if(state)
        OLED_Display_Cache[x][y>>3] |= 1 << (y%8); 
    else
        OLED_Display_Cache[x][y>>3]&= ~(1 << (y%8)); 
}

/*
函数功能:OLED刷屏任务
输入参数:OLED显示缓存数组
输出参数:无
用到的全局变量:无
*/
void OLED_Process()
{
    unsigned char x,y;
    
    for(y=0;y<8;y++)
    {                       
        for(x=0;x<128;x++)
        {   
            if(OLED_Display[x][y] != OLED_Display_Cache[x][y])  
            {
                OLED_Display[x] [y]= OLED_Display_Cache[x][y];      
                OLED_Set_Pos(x,y);
                OLED_WR_Byte(OLED_Display[x] [y],OLED_DATA);
            }
        }
    }
}

void OLED_Print(uint8_t x, uint8_t y, char *s)
{
    uint16_t targetIndex = sizeof(CN16_Msk)/35; // 目标汉字的内码
    printf("targetIndex:%d\r\n",targetIndex);
    fflush(stdout);

    uint16_t length = strlen(s);//取字符串总长
    printf("length:%d\r\n",length);
    fflush(stdout);
    uint16_t offset = x;

    for(uint16_t i=0;i<length;i++)
    {
        uint8_t first = *(s+i);
        if(first <= 127){//小于128是ASCII符号
            for(uint8_t n=0;n<8;n++)
            {
                OLED_Display_Cache[x+offset][y] = F8X16[first][n]; 
                OLED_Display_Cache[x+offset][y+1] = F8X16[first][8+n+3]; offset++;
            }
        }else if(first > 127){//大于127,为汉字
            uint8_t utf[4];
            utf[0] = first;i++;
            utf[1] = *(s+i);i++;
            utf[2] = *(s+i);
            for(uint16_t j=0;j<targetIndex;j++)
            {
                if(utf[0] == CN16_Msk[j][0] && utf[1] == CN16_Msk[j][1] && utf[2] == CN16_Msk[j][2])
                {
                    for(uint8_t n=0;n<16;n++)
                    {
                        OLED_Display_Cache[x+offset][y] = CN16_Msk[j][n]; 
                        OLED_Display_Cache[x+offset][y+1] = CN16_Msk[j][16+n+3]; offset++;
                    }
                }
            }
        }
    }
}

//初始化SSD1306                        
void OLED_Init(void)
{   
    /* 打开ssd1306对应的I2C控制器文件 */
    oled_fd =open(SSD1306_DEVICE, O_RDWR);
    if (oled_fd< 0) 
    {
        printf("open 0x%s failed \n",SSD1306_DEVICE);
    }

    /*设置ssd1306的I2C设备地址*/
    if (ioctl(oled_fd,I2C_SLAVE_FORCE, SSD1306_ADDR) < 0) 
    {            
        printf("set slave address failed \n");
    }
    
    usleep(50000);
    OLED_WR_Byte(0xAE,OLED_CMD);//--display off
    OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
    OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
    OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  
    OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
    OLED_WR_Byte(0x81,OLED_CMD); // contract control
    OLED_WR_Byte(0xFF,OLED_CMD);//--128   
    OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap 
    OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
    OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
    OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
    OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
    OLED_WR_Byte(0x00,OLED_CMD);//

    OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
    OLED_WR_Byte(0x80,OLED_CMD);//

    OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
    OLED_WR_Byte(0x05,OLED_CMD);//

    OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
    OLED_WR_Byte(0xF1,OLED_CMD);//

    OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
    OLED_WR_Byte(0x12,OLED_CMD);//

    OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
    OLED_WR_Byte(0x30,OLED_CMD);//

    OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
    OLED_WR_Byte(0x14,OLED_CMD);//

    OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel

    OLED_Clear();
}  
 
int main()
{
    OLED_Init();
    OLED_Print(8,2,"123和你啊");
    OLED_Process();
    while(1)
    {
        #if 0 //测试按点刷屏
        for(uint8_t i=0;i<128;i++)
        {
            for(uint8_t j=0;j<64;j++)
            {
                OLED_Dot( i,j,1);
                OLED_Process();
            }
        }
        #endif
        
    }
    return 0;
}
 

oled.h

#ifndef __OLED_H
#define __OLED_H                 
//#include "sys.h"
#include "stdlib.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <string.h>

#include "oledfont.h"  

#define OLED_MODE 0
#define SIZE 8
#define XLevelL     0x00
#define XLevelH     0x10
#define Max_Column  128
#define Max_Row     64
#define Brightness  0xFF 
#define X_WIDTH     128
#define Y_WIDTH     64                                
//-----------------OLED IIC端口定义----------------                                  
#define OLED_CMD  0 //写命令
#define OLED_DATA 1 //写数据
 
//OLED控制用函数
void OLED_Display_On(void);
void OLED_Display_Off(void);                                            
void OLED_Init(void);
void OLED_Clear(void);

#endif  

5.字库调整

利用python把ascii编码改为utf8编码

with open('input.txt', 'r', encoding='utf-8') as input_file:
    with open('output.txt', 'w', encoding='utf-8') as output_file:
        for line in input_file:
            char = line.strip()
            utf8_byte = char.encode("utf-8")
            hex_str = ", ".join([f"0x{x:02x}" for x in utf8_byte])
            output_file.write(hex_str + "\n")

输入文件是

输出信息是

截取字库片段

#ifndef __OLEDFONT_H
#define __OLEDFONT_H        

/****************************************8*16的点阵************************************/
const unsigned char F8X16[][16]=      
{
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0xF0,0x08,0xF0,0x80,0x60,0x18,0x00,0x00,0x00,0x31,0x0C,0x03,0x1E,0x21,0x1E,0x00},/*"%",37*/
{0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x2C,0x19,0x27,0x21,0x10},/*"&",38*/
{0x00,0x12,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",39*/
{0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},/*"(",40*/
{0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},/*")",41*/
{0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},/*"*",42*/
{0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x0F,0x01,0x01,0x01},/*"+",43*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x70,0x00,0x00,0x00,0x00,0x00},/*",",44*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x00},/*"-",45*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},/*".",46*/
{0x00,0x00,0x00,0x00,0xC0,0x38,0x04,0x00,0x00,0x60,0x18,0x07,0x00,0x00,0x00,0x00},/*"/",47*/
{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",48*/
{0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00},/*"1",49*/
{0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",50*/
{0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00},/*"3",51*/
{0x00,0x00,0x80,0x40,0x30,0xF8,0x00,0x00,0x00,0x06,0x05,0x24,0x24,0x3F,0x24,0x24},/*"4",52*/
{0x00,0xF8,0x88,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x20,0x20,0x20,0x11,0x0E,0x00},/*"5",53*/
};

// typedef struct {
//     // unsigned char Index[3];  // 汉字UTF-8内码
//     // unsigned char Msk[32];  // 字模
//     unsigned char Msk[35];
// } __attribute__((packed)) GB2312_GB16_t;

const unsigned char CN16_Msk[][35]={
{0xe5, 0x95, 0x8a,0xFC,0x04,0xFC,0x00,0xFE,0x42,0xBE,0x00,0xF2,0x12,0xF2,0x02,0xFE,0x02,0x00,0x00,0x0F,0x04,0x0F,0x00,0xFF,0x10,0x0F,0x00,0x0F,0x04,0x4F,0x80,0x7F,0x00,0x00,0x00},/*'啊',1410*/
{0xe9, 0x98, 0xbf,0x00,0xFE,0x02,0x22,0xDA,0x06,0x00,0xF2,0x12,0x12,0xF2,0x02,0xFE,0x02,0x02,0x00,0x00,0xFF,0x08,0x10,0x08,0x07,0x00,0x0F,0x04,0x04,0x4F,0x80,0x7F,0x00,0x00,0x00},/*'阿',1411*/
{0xe5, 0x9f, 0x83,0x20,0x20,0xFF,0x20,0x20,0x10,0x98,0xF4,0x92,0x91,0x90,0x94,0x98,0x30,0x00,0x00,0x10,0x30,0x1F,0x08,0x88,0x85,0x44,0x24,0x14,0x0F,0x14,0x24,0x44,0x84,0x84,0x00},/*'埃',1412*/
{0xe6, 0x8c, 0xa8,0x10,0x10,0xFF,0x10,0x00,0x10,0x98,0xF4,0x92,0x91,0x90,0x94,0x98,0x30,0x00,0x00,0x42,0x82,0x7F,0x01,0x84,0x85,0x44,0x24,0x14,0x0F,0x14,0x24,0x44,0x84,0x84,0x00},/*'挨',1413*/
{0xe5, 0x93, 0x8e,0x00,0xFC,0x04,0x04,0xFC,0x00,0xC4,0x1F,0x04,0x04,0x04,0x1F,0xC4,0x04,0x00,0x00,0x00,0x0F,0x04,0x04,0x8F,0x80,0x40,0x23,0x14,0x08,0x14,0x23,0x40,0x80,0x80,0x00},/*'哎',1414*/
{0xe5, 0x94, 0x89,0xFC,0x04,0x04,0xFC,0x00,0x10,0x98,0xF4,0x92,0x91,0x90,0x94,0x98,0x30,0x00,0x00,0x1F,0x08,0x08,0x1F,0x84,0x85,0x44,0x24,0x14,0x0F,0x14,0x24,0x44,0x84,0x84,0x00},/*'唉',1415*/
};
#endif
 

6.显示效果

7.优化

上面的代码,存在一个问题是,Y轴的步进必须是8个点,需要优化为任意位置的显示

void OLED_Dot_Line(uint8_t x, uint8_t y, uint8_t temp)
{
    for(uint8_t i=0;i<8;i++)
    {       
        if(temp&0x01)   
        {
            OLED_Dot(x,y,1);
        }  
        else{
            OLED_Dot(x,y,0);
        }
            
        temp = temp>>1;
        y++;
        if(y>=64)return;    //超区域了
    }    
}

void OLED_Print(uint8_t x, uint8_t y, char *s)
{
    uint16_t targetIndex = sizeof(CN16_Msk)/35; // 目标汉字的内码
    uint16_t length = strlen(s);//取字符串总长
    // printf("length:%d\r\n",length);
    // fflush(stdout);
    uint16_t offset = x;

    for(uint16_t i=0;i<length;i++)
    {
        uint8_t first = *(s+i);
        if(first <= 127){//小于128是ASCII符号
            for(uint8_t n=0;n<8;n++)
            {
                OLED_Dot_Line(x+offset,y,F8X16[first][n]);
                OLED_Dot_Line(x+offset,y+8,F8X16[first][n+8]);
                offset++;
            }
        }else if(first > 127){//大于127,为汉字
            uint8_t utf[4];
            utf[0] = first;i++;
            utf[1] = *(s+i);i++;
            utf[2] = *(s+i);
            for(uint16_t j=0;j<targetIndex;j++)
            {
                if(utf[0] == CN16_Msk[j][0] && utf[1] == CN16_Msk[j][1] && utf[2] == CN16_Msk[j][2])
                {
                    for(uint8_t n=0;n<16;n++)
                    {
                        OLED_Dot_Line(x+offset,y,CN16_Msk[j][n+3]);
                        OLED_Dot_Line(x+offset,y+8,CN16_Msk[j][n+16+3]);
                        offset++;
                    }
                }
            }
        }
    }
}

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

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

相关文章

MK米客方德SD NAND的掉电保护机制

随着科技的飞速发展&#xff0c;数据存储设备在我们的生活和工作中扮演着越来越重要的角色。然而&#xff0c;数据安全问题也随之而来&#xff0c;尤其是面对突然的电源故障或意外断电&#xff0c;我们宝贵的数据可能会面临丢失的风险。MK米客方德公司深知这一点&#xff0c;因…

【机器学习300问】129、RNN如何在情感分析任务中起作用的?

情感分析是自然语言处理&#xff08;NLP&#xff09;领域的一个重要分支&#xff0c;它的目标是自动检测和提取出非结构化文本数据中的主观信息&#xff08;比如&#xff1a;情绪、意见、评价等&#xff09; 一、情感分析任务案例 分析电商产品评论的情感倾向&#xff08;三分类…

小林图解系统-五.进程管理 5.4.怎么避免死锁?

死锁的概念 多线程编程中国&#xff0c;为了防止多线程竞争共享资源而导致数错乱&#xff0c;都会在操作共享资源之前加上互斥锁&#xff0c;只有成功获得锁的线程&#xff0c;才能操作共享资源&#xff0c;获取不到锁的线程就只能等待&#xff0c;直到锁被释放。 当两个线程…

如何使用Rekono结合多种工具自动完成渗透测试

关于Rekono Rekono是一款功能强大的自动化渗透测试工具&#xff0c;该工具能够结合其他多种网络安全工具并以自动化的形式完成整个渗透测试过程。在工具运行的过程中所收集到的数据将通过电子邮件或Telegram同时发送给用户&#xff0c;如果需要更加高级的漏洞管理功能&#xf…

移动端 UI 风格,彰显不凡

移动端 UI 风格&#xff0c;彰显不凡

PostgreSQL中 FETCH FIRST ... WITH TIES 是查询结果中限制返回的行数

在 PostgreSQL 中&#xff0c;FETCH FIRST … WITH TIES 是一个在查询结果中限制返回的行数&#xff0c;但同时确保与最后一行具有相同排序值的所有行都被包括进来的子句。这通常与 ORDER BY 子句一起使用。 当您使用 FETCH FIRST n ROWS ONLY 时&#xff0c;您只会得到前 n 个…

Flash页、扇区、块的区别

文章目录 前言玩转Flash的小知识一、页(Page)二、扇区(Sector)三、块(Block)总结存储基础知识 瑞萨芯片简介(片上资源分配)和工具链使用 前言 FLASH 存储器又称闪存,它结合了ROM和RAM的长处,不仅具备电子可擦除可编程(EEPROM)的性能,还不会断电丢失数据同时可以快速…

Web开发技术大作业(HTML\CSS\PHP\MYSQL\JS)

从6月13日到6月15日&#xff0c;经过一系列的操作&#xff0c;终于把老师布置的大作业写完了&#xff0c;虽然有很多水分&#xff0c;很多东西都是为了应付&#xff08;特别是最后做的那几个网页&#xff09;&#xff0c;真的是惨不忍睹&#xff0c;不过既然花时间写了&#xf…

WIC 图像处理初体验——读取像素的值

先放上运行结果&#xff1a; 可以发现红绿蓝是从后往前的。 必须以C方式编译代码&#xff01; // 参考资料&#xff1a;https://learn.microsoft.com/zh-cn/windows/win32/wic/-wic-lh #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <wincodec.h>…

164万年后的日期解析引发的OOM

名词解释 商家销项发票业务&#xff08;平台给商家开票&#xff09;&#xff0c;是平台提供给商家的工具产品&#xff0c;商家购买了平台的服务&#xff0c;那么平台需要开票给商家。 前言 本文所描述的问题&#xff0c;是应用的OOM引发的接口成功率下跌&#xff0c;排查过程中…

用于视觉对象跟踪的序列到序列学习

阅读完此论文后&#xff0c;对着代码过一遍思路 原文地址&#xff1a;https://arxiv.org/abs/2304.14394 本文将视觉跟踪建模为一个序列生成问题&#xff0c;以自回归的方式预测目标边界框。抛弃了设计复杂的头网络&#xff0c;采用encoder-decoder transformer architecture…

手机数据如何恢复?11 款最佳安卓手机恢复软件

媒体可能由于各种原因而从您的设备中删除&#xff0c;可能是意外或病毒攻击。 在这些情况下&#xff0c;照片恢复应用程序是唯一的解决方案。理想的照片恢复应用程序取决于各种因素&#xff0c;例如存储设备的损坏程度、删除照片后的持续时间以及应用程序使用的恢复算法的有效性…

玩玩大模型:总结归纳可以,策划创新拉垮

最近身边的人都在研究大模型。太深入的理解不了&#xff0c;有一些人会讲讲promt提示&#xff0c;学了几招。 比如&#xff1a; #角色 你是一个美食博主 #条件 我只有xxx元&#xff0c;在xxx.... #任务 找一家好吃的当地特色餐馆... 多试几次&#xff0c;有些结果很有参考价值…

前端学习-day10

文章目录 01-体验平面转换02-平移效果03-绝对定位元素居中04-案例-双开门06-转换旋转中心点07-案例-时钟-转换原点08-平面转换-多重转换09-缩放效果10-案例-按钮缩放11-倾斜效果12-渐变-线性13-案例-产品展示14-渐变-径向15-综合案例-喜马拉雅 01-体验平面转换 <!DOCTYPE h…

PCAtools|主成分分析

library(PCAtools) library(tidyverse) ls(package:PCAtools) iris <- as.data.frame(iris) iris <- iris %>% mutate(class str_c("a",1:dim(iris)[1],sep "")) rownames(iris) <- iris$class iris <- iris[,-6] head(iris) # 构建矩阵 …

国有企业数字化转型常见思考框架与路线图

一、国有企业数字化转型思考框架 在之前的十九届四中全会《关于坚持和完善中国特色社会主义制度推进国家治理体系和治理能力现代化若干重大问题的决定》中明确“推进国有经济布局优化和结构调整&#xff0c;发展混合所有制经济&#xff0c;增强国有经济竞争力、创新力、控制力…

麒麟移动运行环境(KMRE)——国内首个开源的商用移固融合“Android生态兼容环境”正式开源

近日&#xff0c;由麒麟软件研发的KMRE&#xff08;Kylin Mobile Runtime Environment&#xff0c;麒麟移动运行环境&#xff09;在openKylin&#xff08;开放麒麟&#xff09;社区正式发布&#xff0c;为Linux桌面操作系统产品提供了高效的Android运行环境解决方案。这也是国内…

【免费API推荐】:各类API资源免费获取【11】

欢迎来到各类API资源的免费获取世界&#xff01;幂简集成为您提供了一个集合了各种免费API接口的平台。无论您是开发者、数据分析师还是创业者&#xff0c;都可以通过我们的平台轻松免费获取所需的API资源。幂简精心整理了各类API接口&#xff0c;涵盖了不同领域的需求&#xf…

如何避免在React中的回调函数中使用箭头函数可能引起的内存泄漏?

在React中&#xff0c;箭头函数在回调函数中的使用确实可能引发性能问题&#xff0c;尤其是当这些函数在渲染方法或者组件内部被定义时。每次组件重新渲染时&#xff0c;都会创建这些函数的新实例&#xff0c;这可能导致不必要的计算和内存使用&#xff0c;甚至在某些情况下引发…

大模型RAG应用优化实战

之前体验OpenAI GPT-4o模型的时候&#xff0c;感觉到大语言模型进化的太快&#xff0c;基于AI应用做出的努力可能很快就被新一代模型降维打击&#xff0c;变得没有价值了&#xff0c;“人生苦短&#xff0c;终归尘土”&#xff0c;最终都化为虚无&#xff0c;还有什么意义呢&am…