1.44寸ST7735 LCD液晶屏STM32硬件SPI中文显示实战项目
一块小小的屏幕,背后凝聚的是软硬件协同设计的智慧。从ST7735的寄存器配置,到SPI时序的精准把控,再到中文显示的优雅实现,每一步都在考验工程师的耐心与理解力。希望这篇文章不仅帮你点亮了屏幕,更能点燃你对嵌入式开发的热情 🔥。下次当你看到设备上的文字缓缓滑过时,你会知道——那是你亲手写下的诗。本文还有配套的精品资源,点击获取简介:本项目围绕1.44寸LCD液晶串口模块(驱动芯片为ST7735)
简介:本项目围绕1.44寸LCD液晶串口模块(驱动芯片为ST7735)与STM32单片机的硬件SPI通信展开,重点实现中文字符在小型彩色显示屏上的正确显示。项目提供完整测试源码,涵盖SPI接口初始化、ST7735驱动配置、汉字编码处理及字库调用等关键环节。适用于嵌入式系统开发中对低功耗、小尺寸屏幕中文显示需求的应用场景,帮助开发者掌握LCD驱动原理与实际编程技巧。
ST7735液晶驱动芯片与STM32的深度整合:从时序控制到中文显示全链路解析
在嵌入式系统设计中,图形化人机交互界面正逐渐成为标配。一块小小的1.44寸TFT彩屏,不仅能提升产品档次,还能极大增强用户体验。而在这背后,ST7735作为一款经典且广泛应用的LCD驱动控制器,配合性能强劲又成本低廉的STM32微控制器,构成了无数智能设备的“眼睛”。
你有没有遇到过这样的情况:明明代码写得一丝不苟,引脚也接得清清楚楚,可屏幕就是不亮?或者显示乱码、花屏、闪屏……这些问题往往不是硬件坏了,而是我们对底层时序和协议的理解还不够深入。今天,咱们就来一次彻底的“解剖”,把ST7735+STM32这套组合拳从里到外讲明白—— 不只是告诉你怎么做,更要让你知道为什么必须这么做 。
芯片内核剖析:ST7735到底是个啥?
别看它只有指甲盖大小,里面可是藏着不少门道。ST7735本质上是一个 高度集成的TFT面板驱动IC ,它的核心任务是将MCU送来的数字信号转换成能点亮像素的模拟电压。听起来简单?其实不然。
这个小家伙内部集成了 132×162 bit 的 GRAM(图形显示内存) ,虽然比不上手机动辄几MB的显存,但对于一个128×128的小屏来说已经绰绰有余了。它支持 16位RGB565色彩格式 ,也就是红5位、绿6位、蓝5位,总共可以显示 65,536 种颜色 🎨。这个选择非常巧妙——视觉效果足够好,数据量又不会太大,完美适配资源有限的MCU平台。
通信方面,它通过标准的 SPI接口 接收命令和数据。没错,就是那个你在传感器、Flash、EEPROM上经常用的SPI。但别小瞧它,这里的每一个字节都有其特定含义,而且顺序不能错!比如发送 0x11 是唤醒屏幕, 0x3A 是设置颜色模式, 0x29 是开启显示。这些命令必须按照严格的时序依次下发,否则轻则黑屏,重则死机。
⚠️ 小贴士:很多初学者以为只要初始化函数写了就能工作,结果忘了关键的一点—— 复位后必须等待足够长时间让内部振荡器稳定 。如果你发现每次上电都要按几次复位键才正常,很可能就是这里没加延时!
更有趣的是,ST7735还支持多种低功耗模式:
- Sleep In/Out :睡眠进出模式,关闭大部分电路;
- Standby Mode :待机模式,连主振荡器都停了;
- Display Off :仅关显示,GRAM仍保留数据;
这些特性让它特别适合电池供电的应用场景,比如智能手环、环境监测仪等。合理利用这些模式,可以让整机电流从几十mA降到μA级别 💡。
硬件连接的艺术:每一根线都不能马虎
再强大的软件也离不开扎实的硬件基础。要想让STM32和ST7735愉快地合作,首先要搞清楚它们之间的“对话语言”是怎么建立的。
屏幕参数知多少?
先来看看这块常见的1.44寸LCD模块的基本参数:
| 参数 | 数值 |
|---|---|
| 尺寸 | 1.44英寸(对角线约36mm) |
| 分辨率 | 128 × 128 像素 |
| 色彩深度 | 16位 RGB565,65K色 |
| 显示类型 | TFT LCD,有源矩阵 |
| 视角范围 | 水平/垂直 ≥ ±80° |
| 面板技术 | IPS 或 TN(依具体模块而定) |
看到没?这可不是什么“马赛克屏”,IPS面板带来的宽视角表现,在不同角度下也能保持色彩一致性。不过要注意,并非所有标称“1.44寸”的模块都是128×128的。有些厂商为了省成本,会使用128×160的驱动逻辑,但只点亮中间128×128区域。这时候如果不正确配置MADCTL寄存器,就会出现偏移或裁剪问题 😵。
背光设计:亮度自由掌控的秘密
说到背光,很多人直接把它接到3.3V就完事了。但这有个大问题: 太费电!
实测数据显示,整个模块在全亮状态下电流可能超过 100mA ,其中背光电流占了50~90mA!对于靠纽扣电池运行的设备来说,这简直是“电量杀手”。
聪明的做法是什么?当然是 PWM调光 啦!用STM32的一个定时器输出PWM信号去控制BLK引脚,既能实现多级亮度调节,又能大幅降低平均功耗。
// 使用TIM3_CH1 输出PWM 控制背光
void MX_TIM3_PWM_Init(void) {
__HAL_RCC_TIM3_CLK_ENABLE();
htim3.Instance = TIM3;
htim3.Init.Prescaler = 83; // 84MHz APB1 -> 1MHz计数频率
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 99; // 10kHz PWM 频率
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}
void Set_Backlight_Level(uint8_t level) {
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, level); // level: 0~100
}
这样,你可以轻松实现三档亮度切换:
Set_Backlight_Level(25); // 低亮,节能模式
Set_Backlight_Level(50); // 中等,日常使用
Set_Backlight_Level(100); // 全亮,阳光下可视
💡 经验之谈:PWM频率建议设在 10kHz以上 ,避免人耳听到“滋滋”声。低于1kHz时会有明显可闻噪声,影响体验。
引脚详解:谁是谁的“翻译官”
来看这张经典的接线表:
| LCD引脚 | STM32引脚 | 功能备注 |
|---|---|---|
| VCC | 3.3V | 不可接5V!会烧毁模块 ❌ |
| GND | GND | 必须共地 ✅ |
| SCK | PA5 | SPI1_SCK |
| MOSI | PA7 | SPI1_MOSI |
| CS | PB0 | 软件控制片选 |
| DC | PB1 | 数据/命令标志 |
| RST | PC13 | 可选硬件复位 |
| BLK | PA6 | 连接TIM3_CH1用于PWM调光 |
注意几个易错点:
- VCC只能接3.3V ,绝对不要图方便接开发板的5V输出,否则分分钟变“冒烟实验”;
- CS、DC、RST都是普通GPIO ,不需要复用功能,但要确保初始化时拉高,防止误触发;
- BLK是否需要外部驱动 取决于模块设计,有的内部已上拉,默认常亮;有的则需外部驱动才能点亮。
下面这张mermaid流程图清晰展示了连接关系:
graph TD
A[STM32F103] -->|SPI1_SCK| B(SCK)
A -->|SPI1_MOSI| C(MOSI)
A -->|PB0| D(CS)
A -->|PB1| E(DC)
A -->|PC13| F(RST)
A -->|PA6/PWM| G(BLK)
H[VCC 3.3V] --> A
I[GND] --> A
B --> J[ST7735]
C --> J
D --> J
E --> J
F --> J
G --> J
style J fill:#f9f,stroke:#333
是不是一目了然?这种结构化的表达方式比纯文字描述直观多了 👍。
对应的GPIO初始化代码如下:
void LCD_GPIO_Init(void) {
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef gpio = {0};
// SCK & MOSI: AF_PP, 复用推挽
gpio.Pin = GPIO_PIN_5 | GPIO_PIN_7;
gpio.Mode = GPIO_MODE_AF_PP;
gpio.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &gpio);
// CS, DC: Output PP
gpio.Pin = GPIO_PIN_0;
gpio.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOB, &gpio);
gpio.Pin = GPIO_PIN_1;
HAL_GPIO_Init(GPIOB, &gpio);
// RST: PC13
gpio.Pin = GPIO_PIN_13;
HAL_GPIO_Init(GPIOC, &gpio);
// 默认状态
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // CS=H
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // DC=H
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); // RST=H
}
重点来了: PA5和PA7必须配置为AF_PP(复用推挽输出) ,这样才能启用SPI1的硬件功能;而其他控制线用普通推挽即可。顺序也不能颠倒——一定要先开时钟,再配引脚!
SPI通信的灵魂:模式匹配与时序精准度
你以为SPI就是随便发几个字节那么简单?Too young too simple!
SPI有四种工作模式,由 CPOL(Clock Polarity) 和 CPHA(Clock Phase) 决定:
| 模式 | CPOL | CPHA | 描述 |
|---|---|---|---|
| Mode 0 | 0 | 0 | 空闲低电平,上升沿采样 ✅ |
| Mode 1 | 0 | 1 | 空闲低电平,下降沿采样 |
| Mode 2 | 1 | 0 | 空闲高电平,下降沿采样 |
| Mode 3 | 1 | 1 | 空闲高电平,上升沿采样 ⚠️ |
查ST7735手册可知,它默认支持 Mode 0 和 Mode 3 ,大多数模块出厂设定为 Mode 0 。也就是说:
- SCK空闲时为 低电平 ;
- 数据在 上升沿被采样 ;
- MOSI应在下降沿改变数据以保证建立时间。
所以你的SPI配置必须这么写:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL = 0
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA = 0 → Mode 0
hspi1.Init.NSS = SPI_NSS_SOFT; // 软件控制CS
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
其中最关键的是:
- CLKPolarity = LOW :SCK空闲为低;
- CLKPhase = 1EDGE :第一个边沿(上升沿)采样;
- NSS = SOFT :禁用硬件NSS,由软件控制CS;
- FirstBit = MSB :高位先行,符合协议要求。
如果通信失败,别急着换线,先试试改成Mode 3看看能不能通。有时候个别模块确实有点“个性” 😂。
波特率怎么选?速度与稳定的博弈
SPI速率也不是越快越好。ST7735官方文档写着最大支持 15MHz (部分版本可达27MHz),但我们得留足裕量。
假设STM32主频72MHz,APB2总线也是72MHz(SPI1挂载于此),那么预分频后的实际SCK频率如下:
| 预分频值 | 实际SCK频率 | 是否推荐 |
|---|---|---|
| 2 | 36 MHz | ❌ 超限,绝对不行 |
| 4 | 18 MHz | ⚠️ 边缘试探,风险高 |
| 8 | 9 MHz | ✅ 安全稳妥 |
| 16 | 4.5 MHz | ✅ 低速可靠 |
我强烈建议使用 SPI_BAUDRATEPRESCALER_8 ,即9MHz。既快又稳,兼顾效率与兼容性。
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; // 72MHz / 8 = 9MHz
除非你在极端恶劣的电磁环境下工作(比如电机旁边),否则没必要降到16甚至32。那样刷新率会严重受限,动画卡顿感明显。
系统启动的“交响乐”:时钟→GPIO→SPI的执行序曲
嵌入式系统的初始化就像一场精密的交响乐演奏,每个乐器(外设)何时登场都有严格规定。一旦节奏乱了,整首曲子就废了。
第一步:敲响时钟的钟声
一切始于RCC(复位和时钟控制)。没有正确的时钟,CPU都无法运行,更别说外设了。
通常我们会先启用HSI(8MHz内部RC振荡器),然后通过PLL倍频到72MHz系统主频。这是F1系列的经典操作:
RCC_OscInitTypeDef oscConfig = {0};
RCC_ClkInitTypeDef clkConfig = {0};
oscConfig.OscillatorType = RCC_OSCILLATORTYPE_HSI;
oscConfig.HSIState = RCC_HSI_ON;
oscConfig.PLL.PLLState = RCC_PLL_ON;
oscConfig.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; // HSI/2 = 4MHz
oscConfig.PLL.PLLMUL = RCC_PLL_MUL16; // 4MHz * 16 = 64MHz ← 注意这里是64MHz!
if (HAL_RCC_OscConfig(&oscConfig) != HAL_OK) {
Error_Handler();
}
clkConfig.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
clkConfig.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
clkConfig.AHBCLKDivider = RCC_SYSCLK_DIV1;
clkConfig.APB1CLKDivider = RCC_HCLK_DIV2;
clkConfig.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&clkConfig, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
⚠️ 注意一个常见误区:有人想当然地认为 HSI_DIV2 * MUL9 = 72MHz ,但实际上HSI是8MHz,除以2是4MHz,乘以9才36MHz!想要接近72MHz,得用 MUL16 得到64MHz,或者改用HSE晶振。
下面是完整的初始化流程图:
graph TD
A[上电复位] --> B{是否启用外部晶振?}
B -->|否| C[启动HSI 8MHz]
B -->|是| D[启动HSE 8MHz]
C --> E[配置PLL: HSI/2 * MUL]
D --> F[配置PLL: HSE * MUL]
E --> G[切换SYSCLK至PLLCLK]
F --> G
G --> H[设置AHB/APB分频器]
H --> I[Flash等待周期配置]
I --> J[系统主频就绪]
第二步:铺好GPIO的道路
时钟准备好之后,赶紧把要用的GPIO配置好。记住一句话: 外设初始化前,相关引脚必须完成配置 。
特别是SPI引脚,必须提前设为复用推挽输出模式:
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpioInit = {0};
gpioInit.Pin = GPIO_PIN_5 | GPIO_PIN_7;
gpioInit.Mode = GPIO_MODE_AF_PP; // 复用推挽
gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; // 高速
HAL_GPIO_Init(GPIOA, &gpioInit);
其他控制线如CS、DC、RST则设为普通输出即可:
gpioInit.Pin = GPIO_PIN_0 | GPIO_PIN_1;
gpioInit.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOB, &gpioInit);
千万别忘了使能对应端口的时钟!否则配置无效。可以用这张表快速对照:
| 外设 | 对应使能宏 | 所属总线 |
|---|---|---|
| GPIOA~G | __HAL_RCC_GPIOX_CLK_ENABLE() |
AHB |
| SPI1 | __HAL_RCC_SPI1_CLK_ENABLE() |
APB2 |
| USART1 | __HAL_RCC_USART1_CLK_ENABLE() |
APB2 |
| I2C1 | __HAL_RCC_I2C1_CLK_ENABLE() |
APB1 |
第三步:激活SPI外设
最后才是调用 HAL_SPI_Init() :
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
整个顺序必须是:
SystemClock_Config(); // 1. 配置系统主频
MX_GPIO_Init(); // 2. 配置引脚
MX_SPI1_Init(); // 3. 初始化SPI
LCD_ST7735_Init(); // 4. 发送LCD初始化命令
任何颠倒都会导致失败。比如你先初始化SPI,但此时GPIO还没设成复用模式,那SPI根本驱动不了物理引脚!
时序的生命线:每一个ns都至关重要
别以为现在就能开始画图了?NO!真正的挑战才刚刚开始。
ST7735对时序的要求极为苛刻。哪怕只是差了几百纳秒,也可能导致命令丢失或数据错位。让我们来看几个关键参数:
| 参数 | 含义 | 最小值 |
|---|---|---|
| Tcss | 片选有效前建立时间 | 100 ns |
| Tcsh | 片选无效后保持时间 | 100 ns |
| Tdsu | 数据建立时间(相对SCK上升沿) | 10 ns |
| Tdhd | 数据保持时间 | 55 ns |
什么意思呢?举个例子:当你拉低CS准备通信时,必须确保至少提前100ns就把DC和其他信号准备好;传输结束后,CS拉高后还得维持100ns以上的高电平才算结束。
下面是命令写入的完整时序图:
sequenceDiagram
participant MCU
participant ST7735
Note over MCU,ST7735: SPI Command Write Timing
MCU->>ST7735: CS↓ (Tcss ≥ 100ns)
MCU->>ST7735: DC=0 (提前设置)
loop SCK Clock Cycle
MCU->>ST7735: SCK↑ → MOSI valid (Tdsu≥10ns)
MCU->>ST7735: SCK↓ → hold data (Tdhd≥55ns)
end
MCU->>ST7735: CS↑ (Tcsh≥100ns)
虽然HAL库做了封装,但在高频下仍可能出现竞争条件。因此建议在调试阶段加入超时保护:
HAL_StatusTypeDef SPI_WriteByte(uint8_t byte) {
uint32_t tickstart = HAL_GetTick();
while (!(__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE))) {
if ((HAL_GetTick() - tickstart) > 100) {
return HAL_TIMEOUT;
}
}
hspi1.Instance->DR = byte;
tickstart = HAL_GetTick();
while (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_BSY)) {
if ((HAL_GetTick() - tickstart) > 100) {
return HAL_TIMEOUT;
}
}
return HAL_OK;
}
监控这些标志位能有效防止程序卡死,尤其是在电源不稳定或干扰较强的环境中。
中文显示的魔法:如何让汉字跃然屏上?
终于到了最激动人心的部分——让我们的屏幕不再只是英文和数字的天下,而是真正支持中文!
编码体系的选择
首先得搞清楚你要处理的是哪种编码:
- GB2312 :双字节,简体中文常用,适合固定文本;
- GBK :扩展版,包含繁体字;
- UTF-8 :国际化首选,汉字一般3字节。
判断一个字符是不是汉字也很简单:
uint8_t is_chinese(uint8_t high_byte, uint8_t low_byte) {
return (high_byte >= 0xB0 && high_byte <= 0xF7) &&
(low_byte >= 0xA1 && low_byte <= 0xFE);
}
效率极高,遍历字符串时一秒几千次没问题。
字库生成与存储策略
汉字无法像ASCII那样枚举,必须依赖字模。工具推荐 PCtoLCD2002 ,可以导出16×16、24×24等格式的横向取模数组。
例如“中”字的16×16点阵:
const unsigned char chinese_zhong_16x16[] = {
0x00,0x00,0x3F,0xFC,0x20,0x08,0x20,0x08,...
};
所有字模组织成结构体数组:
typedef struct {
uint16_t code;
const uint8_t *matrix;
} chinese_font_t;
const chinese_font_t font_table[] = {
{0xB0A1, chinese_zhong_16x16},
{0xB0A2, chinese_guo_16x16},
// ...
};
根据需求选择存储方式:
| 存储方式 | 容量上限 | 访问速度 | 成本 | 适用场景 |
|---|---|---|---|---|
| 内部Flash数组 | ~100–300字 | 极快 | 低 | 固定提示文本 |
| 外部SPI Flash | 数千至上万字 | 中等 | 较高 | 多语言UI、电子书 |
| 动态加载 | 无限 | 慢 | 高 | OTA更新、网络终端 |
高效绘制技巧
单个像素点逐个画太慢!我们应该按行批量写入:
void ShowChinese(uint16_t x, uint16_t y, uint16_t unicode) {
const uint8_t *p = get_font_data(unicode);
if (!p) return;
for (int row = 0; row < 16; row++) {
LCD_SetWindow(x, y + row, x + 15, y + row);
for (int col = 0; col < 16; col++) {
uint8_t byte = p[row * 2 + (col / 8)];
uint8_t bit = (byte >> (7 - (col % 8))) & 0x01;
LCD_FillColor(bit ? RED : BLACK);
}
}
}
更进一步,引入DMA传输和帧缓冲机制,实现滚动文本:
#define FB_WIDTH 128
#define FB_HEIGHT 16
uint16_t frame_buffer[FB_WIDTH * FB_HEIGHT];
void ScrollText(const char *text) {
static int offset = 0;
memset(frame_buffer, 0, sizeof(frame_buffer));
PrintToBuffer(frame_buffer, text + offset);
LCD_WriteFrameDMA(frame_buffer);
offset = (offset + 1) % strlen(text);
}
搭配定时器中断,每100ms滚动一像素,CPU占用率从90%降至不到10%,简直不要太爽 😎。
数据流路径如下:
graph TD
A[文本字符串] --> B{是否汉字?}
B -->|是| C[查字模表]
B -->|否| D[ASCII字体渲染]
C --> E[生成点阵]
D --> F[写入帧缓冲]
E --> F
F --> G[DMA+SPI传输]
G --> H[LCD显示]
最终验证:点亮属于你的第一行中文
万事俱备,只欠东风。main函数就这么写:
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
LCD_Init();
LCD_Clear(BLACK);
ShowChinese(10, 10, 0x4E2D); // “中”
ScrollText("欢迎使用嵌入式中文显示系统");
while (1) {
HAL_Delay(100);
}
}
编译烧录步骤:
1. 使用 Keil MDK 或 STM32CubeIDE;
2. 包含 st7735.c 和字库头文件;
3. 设置 Flash 下载算法;
4. 编译并烧录;
5. 上电观察效果!
🎉 成功那一刻,你会觉得之前所有的调试和等待都值得。
结语:从像素到体验的跨越
一块小小的屏幕,背后凝聚的是软硬件协同设计的智慧。从ST7735的寄存器配置,到SPI时序的精准把控,再到中文显示的优雅实现,每一步都在考验工程师的耐心与理解力。
希望这篇文章不仅帮你点亮了屏幕,更能点燃你对嵌入式开发的热情 🔥。下次当你看到设备上的文字缓缓滑过时,你会知道——那是你亲手写下的诗。
简介:本项目围绕1.44寸LCD液晶串口模块(驱动芯片为ST7735)与STM32单片机的硬件SPI通信展开,重点实现中文字符在小型彩色显示屏上的正确显示。项目提供完整测试源码,涵盖SPI接口初始化、ST7735驱动配置、汉字编码处理及字库调用等关键环节。适用于嵌入式系统开发中对低功耗、小尺寸屏幕中文显示需求的应用场景,帮助开发者掌握LCD驱动原理与实际编程技巧。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)