当前位置: 首页 > article >正文

基于STM32F103C8T6标准库驱动2.4寸SPI TFT触摸屏:从零搭建嵌入式GUI交互系统

1. 项目概述与硬件准备最近在做一个智能家居控制面板的项目选用了STM32F103C8T6这块性价比超高的开发板作为主控搭配2.4寸SPI接口的TFT触摸屏作为人机交互界面。说实话刚开始接触这个组合时踩了不少坑特别是用标准库开发的时候网上的资料远不如HAL库丰富。不过经过几周的摸索总算把整套系统跑通了现在就把完整经验分享给大家。先说说为什么选择这个硬件组合。STM32F103C8T6虽然是个老将了但72MHz主频、丰富的外设接口和超低的价格让它依然是入门嵌入式开发的绝佳选择。而2.4寸SPI TFT屏更是性价比之王240x320的分辨率足够显示丰富信息SPI接口又节省IO资源。两者结合完全可以做出一个功能完善的嵌入式GUI系统。必备硬件清单STM32F103C8T6最小系统板注意要带BOOT0跳线帽2.4寸SPI TFT触摸屏型号通常是ILI9341驱动ST-Link V2下载器杜邦线若干建议用彩色线区分功能5V/3.3V电源开发板USB供电也行这里特别提醒一下市面上TFT屏的接口定义可能不同我用的这款引脚顺序是1. GND 2. VCC 3. SCK 4. SDA 5. RES 6. DC 7. CS 8. BLK接线时一定要对照屏幕背面标注接错可能烧毁屏幕。我第一次就差点把5V接到GND上幸好及时发现。2. 开发环境搭建2.1 工具链安装我习惯用Keil MDK开发STM32项目虽然现在STM32CubeIDE也很流行但标准库项目还是Keil更顺手。安装时要注意下载Keil MDK-ARM建议5.25以上版本安装STM32F1系列器件支持包安装ST-Link驱动配置工程时选择STM32F103C8设备注意不是STM32F103C8T6器件库里没有T6后缀有个坑我踩过新建工程时默认用的ARM Compiler 6但标准库用这个编译器会报错。解决方法是右键工程→Options for Target→Target→ARM Compiler选择V5。2.2 标准库获取与配置ST官方已经不再维护标准库了但GitHub上还能找到完整包。我整理了一个稳定版本// 标准库核心文件 - Libraries/CMSIS/ // 内核相关 - Libraries/STM32F10x_StdPeriph_Driver/ // 外设驱动 - Project/STM32F10x_StdPeriph_Template/ // 工程模板把这些文件放到工程目录后需要修改几个关键配置在Options for Target→C/C→Define中添加USE_STDPERIPH_DRIVER,STM32F10X_MD在Include Paths中添加\Libraries\CMSIS\CM3\CoreSupport \Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x \Libraries\STM32F10x_StdPeriph_Driver\inc3. SPI驱动TFT屏幕3.1 硬件连接SPI接口接线要特别注意电平匹配。STM32F103C8T6是3.3V器件而有些屏幕是5V tolerant的。我的接法如下STM32引脚TFT屏引脚功能说明PA4CS片选PA5SCK时钟PA7MOSI数据输出PB0DC数据/命令选择NRSTRES复位3.3VVCC电源GNDGND地PB1BLK背光控制这里PB0和PB1我用来控制DC和背光你也可以换成其他GPIO。注意CS引脚如果不接硬件SPI的NSS就需要软件控制。3.2 SPI初始化代码标准库的SPI初始化比HAL库要繁琐些但理解后其实更灵活。以下是完整配置void SPI1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; // 使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); // 配置SCK/MOSI为复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // SPI参数配置 SPI_InitStructure.SPI_Direction SPI_Direction_1Line_Tx; SPI_InitStructure.SPI_Mode SPI_Mode_Master; SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL SPI_CPOL_High; // 根据屏幕手册调整 SPI_InitStructure.SPI_CPHA SPI_CPHA_2Edge; // 根据屏幕手册调整 SPI_InitStructure.SPI_NSS SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_4; // 18MHz SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; SPI_Init(SPI1, SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); }实测发现SPI时钟相位(CPHA)和极性(CPOL)设置不对会导致花屏建议先试SPI_MODE0CPOLLow, CPHA1Edge不行再换其他模式。4. TFT屏幕驱动实现4.1 底层通信函数驱动TFT屏需要实现几个基本函数// 写命令 void TFT_WriteCmd(uint8_t cmd) { GPIO_ResetBits(GPIOB, GPIO_Pin_0); // DC0 GPIO_ResetBits(GPIOA, GPIO_Pin_4); // CS0 SPI_I2S_SendData(SPI1, cmd); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET); GPIO_SetBits(GPIOA, GPIO_Pin_4); // CS1 } // 写数据 void TFT_WriteData(uint8_t data) { GPIO_SetBits(GPIOB, GPIO_Pin_0); // DC1 GPIO_ResetBits(GPIOA, GPIO_Pin_4); // CS0 SPI_I2S_SendData(SPI1, data); while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET); GPIO_SetBits(GPIOA, GPIO_Pin_4); // CS1 }注意标准库的SPI发送函数不会自动等待传输完成必须手动检查TXE标志。我一开始没加这个等待导致数据错乱。4.2 屏幕初始化序列不同厂商的ILI9341初始化参数可能不同这里分享我调试成功的配置void TFT_Init(void) { // 硬件复位 GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 背光关闭 GPIO_ResetBits(GPIOA, GPIO_Pin_4); // CS0 GPIO_ResetBits(GPIOA, GPIO_Pin_2); // RES0 Delay_ms(100); GPIO_SetBits(GPIOA, GPIO_Pin_2); // RES1 Delay_ms(100); // 发送初始化命令 TFT_WriteCmd(0xCF); TFT_WriteData(0x00); TFT_WriteData(0xC1); TFT_WriteData(0X30); TFT_WriteCmd(0xED); TFT_WriteData(0x64); TFT_WriteData(0x03); TFT_WriteData(0X12); TFT_WriteCmd(0xE8); TFT_WriteData(0x85); TFT_WriteData(0x00); TFT_WriteData(0x78); // ... 更多初始化命令完整代码见文末链接 TFT_WriteCmd(0x29); // 开启显示 GPIO_SetBits(GPIOB, GPIO_Pin_1); // 背光开启 }有个小技巧初始化失败时可以先用逻辑分析仪抓SPI波形对照屏幕手册检查命令序列是否正确。我遇到过屏幕只亮背光不显示内容的问题最后发现是漏发了一个关键命令。5. 触摸功能实现5.1 触摸芯片驱动这款屏幕通常搭载XPT2046触摸控制器也是SPI接口。因为STM32的SPI外设有限我采用软件模拟SPI来实现uint16_t TP_Read_AD(uint8_t cmd) { uint16_t data 0; TP_CS_LOW(); TP_SPI_Write(cmd); Delay_us(6); data TP_SPI_Read() 8; data | TP_SPI_Read(); data 3; TP_CS_HIGH(); return data 0xFFF; }注意触摸芯片的SPI时序和TFT屏可能不同需要单独实现一套GPIO模拟的SPI函数。读取坐标时要多次采样取平均消除抖动void TP_Read_XY(uint16_t *x, uint16_t *y) { uint16_t xbuf[5], ybuf[5]; for(uint8_t i0; i5; i) { xbuf[i] TP_Read_AD(0xD0); // 读X ybuf[i] TP_Read_AD(0x90); // 读Y } // 排序后取中值 *x TP_Get_Median(xbuf, 5); *y TP_Get_Median(ybuf, 5); }5.2 触摸校准触摸屏必须校准才能准确反映坐标。我采用四点校准法在屏幕四个角依次显示校准点记录触摸原始值和理论值计算校准系数void TP_Calibrate(void) { uint16_t x[4], y[4]; // 触摸原始值 uint16_t xt[4] {50, 50, 230, 230}; // 理论X uint16_t yt[4] {50, 310, 50, 310}; // 理论Y // 采集四个点的触摸数据 for(uint8_t i0; i4; i) { Show_Calib_Point(xt[i], yt[i]); while(!TP_Scan()); x[i] TP_Read_X(); y[i] TP_Read_Y(); } // 计算校准参数 tp_dev.xfac (float)(xt[2]-xt[0])/(x[2]-x[0]); tp_dev.xoff xt[0] - tp_dev.xfac*x[0]; // Y轴同理... }校准参数需要保存到Flash否则每次上电都要重新校准。我选择存在STM32的最后一页Flashvoid TP_Save_Param(void) { FLASH_Unlock(); FLASH_ErasePage(0x0800FC00); FLASH_ProgramHalfWord(0x0800FC00, *(uint16_t*)tp_dev.xfac); // 保存其他参数... FLASH_Lock(); }6. 简易GUI框架搭建6.1 页面管理系统我设计了一个简单的页面管理系统通过链表管理多个页面typedef struct { void (*Load)(void); // 页面加载函数 void (*Draw)(void); // 页面绘制函数 void (*Handler)(void); // 事件处理函数 } PageType; PageType *current_page; void GUI_Run(void) { while(1) { current_page-Draw(); TP_Scan(); if(tp_dev.sta TP_PRES_DOWN) { current_page-Handler(); } } }每个页面实现自己的三个函数。比如主页面void MainPage_Load(void) { // 创建按钮等控件 Create_Button(10, 10, 100, 40, 设置, SETTING_BTN_ID); } void MainPage_Draw(void) { TFT_Clear(BLUE); Draw_All_Controls(); } void MainPage_Handler(void) { uint8_t btn_id Get_Touched_Button(); if(btn_id SETTING_BTN_ID) { current_page SettingPage; } }6.2 控件实现按钮是最基础的控件实现如下typedef struct { uint16_t x, y, width, height; char *text; uint8_t id; } ButtonType; ButtonType buttons[MAX_BUTTONS]; uint8_t btn_count 0; uint8_t Create_Button(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *text, uint8_t id) { if(btn_count MAX_BUTTONS) return 0; buttons[btn_count].x x; buttons[btn_count].y y; buttons[btn_count].width w; buttons[btn_count].height h; buttons[btn_count].text text; buttons[btn_count].id id; // 绘制按钮 TFT_DrawRectangle(x, y, xw, yh, WHITE); TFT_ShowString(x5, yh/2-8, text, WHITE, BLACK, 16); return btn_count; } uint8_t Get_Touched_Button(void) { if(!(tp_dev.sta TP_PRES_DOWN)) return 0; uint16_t x tp_dev.x[0]; uint16_t y tp_dev.y[0]; for(uint8_t i0; ibtn_count; i) { if(x buttons[i].x x buttons[i].x buttons[i].width y buttons[i].y y buttons[i].y buttons[i].height) { return buttons[i].id; } } return 0; }7. 性能优化技巧7.1 提高刷新速度SPI全速运行在18MHz时刷新整个屏幕(240x320x2153600字节)需要约85ms。通过以下优化可以提升体验局部刷新只更新变化区域void GUI_Update(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { TFT_SetWindow(x1, y1, x2, y2); // 只发送该区域数据... }使用DMA传输解放CPU资源void TFT_DMA_Send(uint8_t *data, uint16_t len) { DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)SPI1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)data; DMA_InitStructure.DMA_BufferSize len; DMA_Init(DMA1_Channel3, DMA_InitStructure); DMA_Cmd(DMA1_Channel3, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); }双缓冲机制在内存中完成绘制再一次性更新7.2 内存管理STM32F103C8T6只有20KB RAM需要精打细算使用__attribute__((section(.ccmram)))将帧缓冲区放到CCM RAM这块内存专供内核使用速度更快启用压缩字体存储比如只存ASCII 32-127的字符点阵使用位域存储控件状态节省空间typedef struct { uint16_t x : 9; // 0-319 uint16_t y : 9; // 0-239 uint16_t visible : 1; uint16_t enabled : 1; } ControlAttr;8. 项目进阶与扩展完成基础框架后可以添加更多实用功能多语言支持通过外部Flash存储不同语言的字符串资源void GUI_SetLanguage(LANG_TYPE lang) { current_lang lang; SPI_Flash_Read(lang_str_addr[lang], (uint8_t*)strings, STRING_COUNT*MAX_STR_LEN); }动画效果利用定时器实现过渡动画void GUI_Animate(uint16_t start, uint16_t end, uint16_t duration) { uint16_t step (end - start) / (duration / 10); for(uint16_t istart; i!end; istep) { // 更新位置 Delay_ms(10); } }文件系统通过SPI Flash实现图片资源存储void GUI_Show_Image(uint32_t addr) { SPI_Flash_Read(addr, buf, IMG_SIZE); TFT_DrawPicture(0, 0, 240, 320, buf); }这套系统我已经应用在几个实际项目中包括智能家居控制面板、工业HMI终端等。虽然功能比不上商用GUI库但胜在完全掌控、资源占用小特别适合对成本敏感的项目。

相关文章:

基于STM32F103C8T6标准库驱动2.4寸SPI TFT触摸屏:从零搭建嵌入式GUI交互系统

1. 项目概述与硬件准备 最近在做一个智能家居控制面板的项目,选用了STM32F103C8T6这块性价比超高的开发板作为主控,搭配2.4寸SPI接口的TFT触摸屏作为人机交互界面。说实话,刚开始接触这个组合时踩了不少坑,特别是用标准库开发的时…...

RJ45连接器工程实战:从PoE热故障到户外防水的12个设计禁区

一句话核心:RJ45连接器选型失败,往往不是速率不达标,而是热、水、地、工艺四个字中的一个出了问题。本文从电源供电发热、户外环境腐蚀、屏蔽接地错误、现场压接失控四个维度,梳理12个容易被忽视的设计禁区,并提供可复…...

Guava Ratelimiter实现单机接口限流

废话不多说直接上代码&#xff1a;1.依赖&#xff1a;<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version></dependency>2.配置类注册bean&#xff1a;package com.h…...

通过 Taotoken CLI 工具一键配置开发环境中的多工具 API 端点

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过 Taotoken CLI 工具一键配置开发环境中的多工具 API 端点 在接入多个大模型服务时&#xff0c;开发者常常需要为不同的工具和 …...

大模型产品经理进阶指南:从零基础到行业精英的完整学习路线图!

随着人工智能技术的发展&#xff0c;尤其是大模型&#xff08;Large Model&#xff09;的兴起&#xff0c;越来越多的企业开始重视这一领域的投入。作为大模型产品经理&#xff0c;你需要具备一系列跨学科的知识和技能&#xff0c;以便有效地推动产品的开发、优化和市场化。以下…...

八大网盘直链解析工具:告别限速,实现高速下载自由

八大网盘直链解析工具&#xff1a;告别限速&#xff0c;实现高速下载自由 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘…...

AI产品经理的进阶路线图

本文深入探讨了AI产品经理的核心特质&#xff0c;强调AI思维的重要性远超单纯的技术知识。文章解析了AI产品设计以极度简单为标准背后的复杂系统&#xff0c;以及AI产业链的三大结构层——基础层、技术层与应用层。此外&#xff0c;文章还详细阐述了AI产品经理的四象限分类&…...

大模型“开源”到底开了什么?不同协议有什么区别?

大模型发布常以“开源”为噱头&#xff0c;但与传统软件开源不同&#xff0c;大模型开源可能仅开放代码、权重、训练方法或数据说明&#xff0c;且协议复杂多样。企业需关注开放深度&#xff0c;区分开放权重、开放代码、开放训练过程三个层次&#xff0c;警惕GPL、AGPL、CC-BY…...

ESP32-S3物联网开发实战:从ADC采样到MQTT云端通信

1. 项目概述&#xff1a;从传感器到云端的数据之旅在物联网项目的开发中&#xff0c;我们常常需要解决一个核心问题&#xff1a;如何让物理世界的信息被数字系统感知、处理&#xff0c;并最终在云端呈现或接受远程控制&#xff1f;这背后涉及三个关键环节&#xff1a;感知、处理…...

柔性构建板原理与实战:从材料科学到3D打印取模难题的工程解法

1. 项目概述&#xff1a;为什么你需要一块柔性构建板&#xff1f;如果你玩3D打印有一段时间了&#xff0c;大概率经历过这样的抓狂时刻&#xff1a;打印完成&#xff0c;模型牢牢地“焊”在玻璃板或者美纹纸胶带上&#xff0c;你用铲刀、刮片又撬又掰&#xff0c;结果要么是模型…...

2230固态硬盘延长安装技巧指南!

2230规格的M.2固态硬盘因体积小巧&#xff0c;广泛应用于掌机、轻薄笔记本和微型PC&#xff0c;但许多主板的M.2插槽默认为2280规格&#xff0c;导致2230硬盘“装不稳”。本文详细讲解2230与2280的尺寸差异、延长安装的核心方法&#xff08;转接支架、螺丝柱调整、散热适配&…...

【ITIL4】32服务实践 - 问题管理(Problem Management)

【ITIL4】32服务实践 - 问题管理&#xff08;Problem Management&#xff09; 文章目录【ITIL4】32服务实践 - 问题管理&#xff08;Problem Management&#xff09;一、核心定义1. 问题&#xff08;Problem&#xff09;2. 已知错误&#xff08;Known Error&#xff09;3. 变通…...

别再死记硬背MPNN公式了!用“邻居传纸条”的比喻彻底搞懂消息传递神经网络

用"班级传纸条"游戏理解消息传递神经网络 想象一下&#xff0c;你正坐在教室里&#xff0c;老师突然宣布要进行一个特殊的游戏——每个同学可以给任意一位朋友传递一张写有秘密信息的纸条。这个看似简单的游戏&#xff0c;恰恰揭示了人工智能领域最前沿的图神经网络(…...

深度学习优化算法(二)—— SGD + Momentum + Nesterov(三十四)

1. 定位导航 第 33 篇讲了为什么训练困难(病态、鞍点、梯度爆炸)。本篇正式介绍解决方案的第一波——三个经典优化算法: 算法 关键思想 年代 SGD 随机梯度估计 + 学习率衰减 1951(Robbins-Monro) Momentum 累积梯度方向加速 1964(Polyak) Nesterov 先"前瞻"再…...

深度学习优化算法(一)—— 学习 vs 纯优化 + 优化挑战(三十三)

1. 定位导航 第 7 章我们解决了"怎么防过拟合"。第 8 章正式进入深度学习的另一个核心——怎么训练得快、稳、好。 第 8 章规划(5 篇): 篇号 主题 33(本篇) 学习 vs 纯优化 + 优化挑战 34 基本优化算法(SGD + Momentum + Nesterov) 35 自适应学习率(AdaGra…...

新手入门,用外卖系统吃透Tomcat与Java Web全流程

对于刚接触Java Web的小伙伴来说&#xff0c;Tomcat、Servlet、端口号、网络请求这些概念&#xff0c;很容易越学越懵。今天全程用外卖系统做统一比喻&#xff0c;把复杂技术名词全部转化为生活场景&#xff0c;从零梳理Java Web核心流程&#xff0c;看完彻底理清浏览器、服务器…...

【CLIP论文阅读】:基于自然语言监督的通用视觉预训练范式

论文信息 标题&#xff1a;Learning Transferable Visual Models From Natural Language Supervision会议&#xff1a;ICML 2021单位&#xff1a;OpenAI代码&#xff1a;https://github.com/OpenAI/CLIP论文&#xff1a;https://arxiv.org/pdf/2103.00020.pdf 一、引言&#x…...

Python Django REST Framework实战:构建RESTful API

Python Django REST Framework实战&#xff1a;构建RESTful API 引言 在Python Web开发中&#xff0c;Django REST Framework&#xff08;DRF&#xff09;是构建RESTful API的首选框架。作为一名从Rust转向Python的后端开发者&#xff0c;我深刻体会到DRF在快速构建高质量API方…...

上位机知识篇---提高Linux下载速度

提升 wget、pip 和 conda 的下载速度&#xff0c;核心方法可以归结为两类&#xff1a;一是使用更快的下载工具&#xff0c;二是连接到更近的镜像站点。下面的表格总结了几种主流的加速方案&#xff0c;方便你快速查阅&#xff1a;提速方法wgetpipconda&#x1f680; 换用更快的…...

观察使用Taotoken Token Plan后月度API成本的变化趋势

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 观察使用Taotoken Token Plan后月度API成本的变化趋势 对于依赖大模型API进行开发的中小型团队而言&#xff0c;月度API成本的可预…...

供水泵恒压变频控制系统:备用泵自动投切,保障供水不间断

供水泵恒压变频控制系统是一套融合变频调速、PID闭环控制与智能多泵管理的自动化节能供水解决方案&#xff0c;核心是按需供水、稳压节能、无人值守。 一、核心原理压力采集&#xff1a;管网压力传感器实时采集水压(0~1.6MPa)。偏差计算&#xff1a;PLC/专用控制器将实测值与设…...

终极窗口尺寸调整工具:WindowResizer完整使用指南

终极窗口尺寸调整工具&#xff1a;WindowResizer完整使用指南 【免费下载链接】WindowResizer 一个可以强制调整应用程序窗口大小的工具 项目地址: https://gitcode.com/gh_mirrors/wi/WindowResizer 还在为那些无法拖拽大小的顽固应用程序窗口而烦恼吗&#xff1f;Wind…...

Nrfr终极指南:5步轻松修改SIM卡国家码,免Root突破区域限制

Nrfr终极指南&#xff1a;5步轻松修改SIM卡国家码&#xff0c;免Root突破区域限制 【免费下载链接】Nrfr &#x1f30d; 免 Root 的 SIM 卡国家码修改工具 | 解决国际漫游时的兼容性问题&#xff0c;帮助使用海外 SIM 卡获得更好的本地化体验&#xff0c;解锁运营商限制&#x…...

为什么需要图像篡改检测?5个简单步骤守护数字世界的真实性

为什么需要图像篡改检测&#xff1f;5个简单步骤守护数字世界的真实性 【免费下载链接】image_tampering_detection_references A list of papers, codes and other interesting collections pertaining to image tampering detection and localization. 项目地址: https://g…...

别再只会轮询了!STM32CubeMX配置USART中断,从原理到调试一条龙指南

STM32串口中断实战&#xff1a;从轮询到事件驱动的效率跃迁 在嵌入式开发中&#xff0c;串口通信就像系统的神经末梢&#xff0c;负责与外界交换关键信息。传统轮询方式如同不断拨打电话确认消息&#xff0c;而中断机制则像设置来电提醒——只有当数据真正到达时才会唤醒CPU。这…...

ETS2LA:让《欧洲卡车模拟2》自动驾驶的终极解决方案

ETS2LA&#xff1a;让《欧洲卡车模拟2》自动驾驶的终极解决方案 【免费下载链接】Euro-Truck-Simulator-2-Lane-Assist Plugin based interface program for ETS2/ATS. 项目地址: https://gitcode.com/gh_mirrors/eur/Euro-Truck-Simulator-2-Lane-Assist 你是否曾梦想在…...

Photoshop图层批量导出效率革命:10倍速免费脚本完全指南

Photoshop图层批量导出效率革命&#xff1a;10倍速免费脚本完全指南 【免费下载链接】Photoshop-Export-Layers-to-Files-Fast This script allows you to export your layers as individual files at a speed much faster than the built-in script from Adobe. 项目地址: h…...

用STM32F103和RC522模块DIY一个智能门禁,附完整代码和PCB文件

用STM32F103和RC522模块打造高性价比智能门禁系统 在创客圈子里&#xff0c;智能门禁系统一直是极受欢迎的DIY项目。它不仅融合了嵌入式开发、射频识别和物联网技术&#xff0c;还能解决生活中的实际问题。相比动辄上千元的商业门禁设备&#xff0c;用STM32F103C8T6&#xff0…...

OpenCV颜色操作避坑指南:cv::Scalar里BGR和RGB顺序别再搞混了

OpenCV颜色操作避坑指南&#xff1a;cv::Scalar里BGR和RGB顺序别再搞混了 第一次用OpenCV画红色矩形时&#xff0c;我信心满满地写下cv::Scalar(255, 0, 0)&#xff0c;结果屏幕上却出现了一个蓝色方块——这个场景恐怕每个OpenCV初学者都遇到过。颜色通道顺序这个看似简单的细…...

Acepe:下一代AI驱动的开发者环境,实现多代理协同与可控编程

1. 项目概述&#xff1a;下一代AI驱动的开发者环境如果你和我一样&#xff0c;在过去一年里尝试过各种AI编程助手&#xff0c;从Copilot的代码补全到Cursor的聊天式编程&#xff0c;再到Claude Code的深度分析&#xff0c;你可能会发现一个共同的痛点&#xff1a;这些工具虽然强…...