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

STM32和STM32CubeMX实现遥控器控制, 保姆级教程

【背景】各位现在无人车和机器人大发展但是大家也都看到了在无人车和机器人能够自动控制之前都是用遥控器来控制的。那么实现一个遥控器的控制就变得非常有必要。然而实际情况是业内的人都觉得用遥控器控制是基本的和理所当然的业外的人都知道遥控器控制要做遥控器的设计又觉得无从下手。那么今天我就来写一写用STM32和STM32CubeMX实现遥控器控制的保姆级教程让大家都能实现遥控器控制自由。【遥控器控制的方式】市面上的遥控器有很多甚至于游戏手柄也是遥控器的一种。那现在比较流行的遥控器都是用SBUS的协议来控制的。我这里就来实现SBUS协议的遥控器控制。这协议应该是能适用90%的遥控器了。如果不明白什么是SBUS协议可以自行去网上学习。【硬件设计】我这是用的STM32的uart3来作为遥控器的接收电路。实际上只用了接收端RXD3, TXD3空着没用。H3是个3端子插头接遥控器的接收端。 SBUS信号是个反的所以要用上面的电路反一下。【STM32CubeMX的设置】stm32cubemx的配置就这么多要注意的是波特率是100kbps跟一般的串口不一样。照着我上面配就行了。【软件编写】sbus.h#ifndef _RC_SBUS_H_ #define _RC_SBUS_H_ #include main.h // RC遥控器相关 开始 #define SBUS_NUM_CHANNELS 16 #define SBUS_PACKET_SIZE 25 #define SBUS_HEADER 0x0F #define SBUS_END 0x00 #define SBUS_BUFFER_SIZE 25 #define SBUS_OPT_C17 0x01 #define SBUS_OPT_C18 0x02 #define SBUS_OPT_FS 0x08 #define SBUS_OPT_FL 0x04 typedef struct { uint16_t channels[SBUS_NUM_CHANNELS]; uint8_t ch17, ch18; uint8_t failsafe; uint8_t frameLost; uint8_t sbus_flag; // 1: valid, 0: invalid } sbus_packet_t; enum sbus_err_t { SBUS_OK 0, SBUS_FAIL -1, }; typedef struct { sbus_packet_t sbus_packet; uint8_t sbus_Buffer[SBUS_BUFFER_SIZE]; /// flag for RC transimtter is existing or not /// 0: not exist, 1: exist but not using, 2: exist and using uint8_t isExist; /// counter for RC transmitter existing judgement uint8_t exist_cnt1; uint8_t exist_cnt2; } sbus_handle_t; extern sbus_handle_t sbusHandle; // SBUS handle extern UART_HandleTypeDef huart3; void RC_init(sbus_handle_t sbusHandle); void RC_run(sbus_handle_t sbusHandle); // RC遥控器相关 结束 #endif /* _RC_SBUS_H_ */sbus.c#include rc_sbus.h #include uart.h // RC遥控器相关 开始 void RC_init(sbus_handle_t sbusHandle) { // Initialize SBUS packet structure for (int i 0; i SBUS_NUM_CHANNELS; i) { sbusHandle.sbus_packet.channels[i] 0; } sbusHandle.sbus_packet.ch17 0; sbusHandle.sbus_packet.ch18 0; sbusHandle.sbus_packet.failsafe 0; sbusHandle.sbus_packet.frameLost 0; sbusHandle.sbus_packet.sbus_flag 0; // Initially invalid // Initialize SBUS buffer for (int i 0; i SBUS_BUFFER_SIZE; i) { sbusHandle.sbus_Buffer[i] 0; } sbusHandle.isExist1; sbusHandle.exist_cnt10; sbusHandle.exist_cnt20; // Start receiving data HAL_UARTEx_ReceiveToIdle_IT(huart3, sbusHandle.sbus_Buffer, SBUS_BUFFER_SIZE); // sbusHandle.isExist1; printf(RC Initialized\r\n); // HAL_Delay(5); // Delay for stability }可以看到遥控器是用的uart3的空闲中断25bytes。每个中断会接收25bytes数据然后进行解码。解码是在uart3的中断里进行的。代码如下uart.cvoid HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { // Handle idle line detection for sbus if(huart-Instance USART3) { if(Size25) // Expected packet size is 25bytes { if(sbusHandle.sbus_Buffer[0]SBUS_HEADER sbusHandle.sbus_Buffer[SBUS_BUFFER_SIZE-1]SBUS_END) { sbusHandle.sbus_packet.channels[0] (uint16_t)((sbusHandle.sbus_Buffer[1] 0 | sbusHandle.sbus_Buffer[2] 8) 0x07FF); sbusHandle.sbus_packet.channels[1] (uint16_t)((sbusHandle.sbus_Buffer[2] 3 | sbusHandle.sbus_Buffer[3] 5) 0x07FF); sbusHandle.sbus_packet.channels[2] (uint16_t)((sbusHandle.sbus_Buffer[3] 6 | sbusHandle.sbus_Buffer[4] 2 | sbusHandle.sbus_Buffer[5] 10) 0x07FF); sbusHandle.sbus_packet.channels[3] (uint16_t)((sbusHandle.sbus_Buffer[5] 1 | sbusHandle.sbus_Buffer[6] 7) 0x07FF); sbusHandle.sbus_packet.channels[4] (uint16_t)((sbusHandle.sbus_Buffer[6] 4 | sbusHandle.sbus_Buffer[7] 4) 0x07FF); sbusHandle.sbus_packet.channels[5] (uint16_t)((sbusHandle.sbus_Buffer[7] 7 | sbusHandle.sbus_Buffer[8] 1 | sbusHandle.sbus_Buffer[9] 9) 0x07FF); sbusHandle.sbus_packet.channels[6] (uint16_t)((sbusHandle.sbus_Buffer[9] 2 | sbusHandle.sbus_Buffer[10] 6) 0x07FF); sbusHandle.sbus_packet.channels[7] (uint16_t)((sbusHandle.sbus_Buffer[10] 5 | sbusHandle.sbus_Buffer[11] 3) 0x07FF); sbusHandle.sbus_packet.channels[8] (uint16_t)((sbusHandle.sbus_Buffer[12] 0 | sbusHandle.sbus_Buffer[13] 8) 0x07FF); sbusHandle.sbus_packet.channels[9] (uint16_t)((sbusHandle.sbus_Buffer[13] 3 | sbusHandle.sbus_Buffer[14] 5) 0x07FF); sbusHandle.sbus_packet.channels[10] (uint16_t)((sbusHandle.sbus_Buffer[14] 6 | sbusHandle.sbus_Buffer[15] 2 | sbusHandle.sbus_Buffer[16] 10) 0x07FF); sbusHandle.sbus_packet.channels[11] (uint16_t)((sbusHandle.sbus_Buffer[16] 1 | sbusHandle.sbus_Buffer[17] 7) 0x07FF); sbusHandle.sbus_packet.channels[12] (uint16_t)((sbusHandle.sbus_Buffer[17] 4 | sbusHandle.sbus_Buffer[18] 4) 0x07FF); sbusHandle.sbus_packet.channels[13] (uint16_t)((sbusHandle.sbus_Buffer[18] 7 | sbusHandle.sbus_Buffer[19] 1 | sbusHandle.sbus_Buffer[20] 9) 0x07FF); sbusHandle.sbus_packet.channels[14] (uint16_t)((sbusHandle.sbus_Buffer[20] 2 | sbusHandle.sbus_Buffer[21] 6) 0x07FF); sbusHandle.sbus_packet.channels[15] (uint16_t)((sbusHandle.sbus_Buffer[21] 5 | sbusHandle.sbus_Buffer[22] 3) 0x07FF); sbusHandle.sbus_packet.ch17 (sbusHandle.sbus_Buffer[23] 0x0f) SBUS_OPT_C17; sbusHandle.sbus_packet.ch18 (sbusHandle.sbus_Buffer[23] 0x0f) SBUS_OPT_C18; sbusHandle.sbus_packet.failsafe (sbusHandle.sbus_Buffer[23] 0x0f) SBUS_OPT_FS; sbusHandle.sbus_packet.frameLost (sbusHandle.sbus_Buffer[23] 0x0f) SBUS_OPT_FL; sbusHandle.sbus_packet.sbus_flag 1; } else { sbusHandle.sbus_packet.sbus_flag 0; } // printf(sbus has been received successfully! sbus_flag %d\n, sbusHandle.sbus_packet.sbus_flag); } else { sbusHandle.sbus_packet.sbus_flag 0; printf(sbus received invalid length: %d\n, Size); } HAL_UARTEx_ReceiveToIdle_IT(huart3, sbusHandle.sbus_Buffer, SBUS_BUFFER_SIZE); // Restart receiving data } }看到没有在uart中断里面解码之后会置一个sbusHandle.sbus_packet.sbus_flag1; 那么在应用程序里面进行查询看到了sbusHandle.sbus_packet.sbus_flag1就可以对各个channels的数据进行处理了。这里做一个简单的例子就是将数据打印出来。void RC_run(sbus_handle_t sbusHandle) { if (sbusHandle.sbus_packet.sbus_flag 1) { sbusHandle.sbus_packet.sbus_flag 0; // Reset flag after processing // usb_printf(RC Data Received: ); printf(RC Data Received: ); for (int i 0; i SBUS_NUM_CHANNELS; i) { printf(Channel %d: %d , i 1, sbusHandle.sbus_packet.channels[i]); } printf(Ch17: %d, Ch18: %d, Failsafe: %d, Frame Lost: %d\r\n, sbusHandle.sbus_packet.ch17, sbusHandle.sbus_packet.ch18, sbusHandle.sbus_packet.failsafe, sbusHandle.sbus_packet.frameLost); } }需要说明的是遥控器的数据来得很快每帧25bytes间隔是14ms。应用程序进行处理的时候要在14ms里面处理完一帧并接着处理下一帧。通常来说放在一个while(1)大循环里是来不及的。需要用另外一个并发的任务来处理。这就牵涉到RTOS了这是另外一个话题这里就不展开了。在系统上还要能够检测到遥控器开和关进行plugplay, 这是跟每个具体的遥控器和接收机相关的这里也不展开了。各位自己去探索吧。【结果检验】这套代码用在了我实际的无人车的控制中已经经过长时间的检验没有问题。【好了大功告成亲个嘴儿。】

相关文章:

STM32和STM32CubeMX实现遥控器控制, 保姆级教程

【背景】各位,现在无人车和机器人大发展,但是,大家也都看到了,在无人车和机器人能够自动控制之前,都是用遥控器来控制的。那么,实现一个遥控器的控制,就变得非常有必要。然而,实际情…...

VSCode 2026合规校验不是插件——是嵌入式医疗合规沙箱(含ISO 13485:2025附录D映射表),首批白名单机构仅开放127个License

更多请点击: https://intelliparadigm.com 第一章:VSCode 2026医疗代码合规校验的核心定位与演进逻辑 VSCode 2026 将医疗软件开发中的法规遵从性(如 HIPAA、GDPR、NMPA《人工智能医疗器械注册审查指导原则》)深度内嵌为编辑器原…...

ComfyUI Impact Pack V8终极指南:解锁AI图像细节增强的完整能力

ComfyUI Impact Pack V8终极指南:解锁AI图像细节增强的完整能力 【免费下载链接】ComfyUI-Impact-Pack Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more. 项目地址:…...

Hermes Agent 自定义提供商配置指向 Taotoken 聚合端点的教程

Hermes Agent 自定义提供商配置指向 Taotoken 聚合端点的教程 1. 准备工作 在开始配置之前,请确保您已经完成以下准备工作: 拥有有效的 Taotoken API Key(可在 Taotoken 控制台创建)已安装 Hermes Agent 框架并具备基本运行环境…...

VSCode 2026容器化调试增强:内置Podman Rootless模式原生支持+OCI Image Manifest智能符号映射,仅限Insiders通道第127版起可用

更多请点击: https://intelliparadigm.com 第一章:VSCode 2026 容器化调试增强概述 VSCode 2026 引入了深度集成的容器化调试架构,原生支持 OCI 兼容运行时(如 containerd、Podman)与 Kubernetes DevSpace 的双向调试…...

如何免费下载喜马拉雅VIP音频?跨平台下载工具完整指南

如何免费下载喜马拉雅VIP音频?跨平台下载工具完整指南 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 你是否曾为喜马拉…...

3步高效掌握TVBoxOSC:让你的电视盒子实现智能升级终极指南

3步高效掌握TVBoxOSC:让你的电视盒子实现智能升级终极指南 【免费下载链接】TVBoxOSC TVBoxOSC - 一个基于第三方项目的代码库,用于电视盒子的控制和管理。 项目地址: https://gitcode.com/GitHub_Trending/tv/TVBoxOSC TVBoxOSC是一款基于第三方…...

独立开发者如何借助 Taotoken 模型广场快速选型与对比测试

独立开发者如何借助 Taotoken 模型广场快速选型与对比测试 1. 模型选型的核心挑战 独立开发者在项目初期常面临模型选型难题。不同功能模块对语言模型的需求各异,例如对话系统需要强上下文理解,而数据清洗可能更看重结构化输出能力。传统方式需要逐一注…...

基于Node.js与gRPC的实时文本转语音驱动数字人面部动画实践

1. 项目概述与核心价值最近在折腾一个挺有意思的玩意儿,叫text-to-audio2face。简单来说,这是一个用 Node.js 搭起来的“桥梁”应用,它能把你输入的文字,或者让 ChatGPT 帮你生成的文字,先变成语音,然后实时…...

固件安全:为什么你的联网设备正在成为黑客的攻击入口?

固件:被忽视的“最后一道防线”与严峻的数据现实当企业将主要安全预算集中在防火墙、端点防护和员工培训时,一个深埋于硬件中的关键环节正被普遍忽略——​固件​。固件是嵌入在路由器、摄像头、工业控制器等所有联网设备中的底层软件,它直接…...

ComfyUI-Manager:终极AI绘画插件管理神器,让创作更简单

ComfyUI-Manager:终极AI绘画插件管理神器,让创作更简单 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable v…...

WordPress 4.6老漏洞复现:用Docker+BurpSuite一步步拿Shell(附绕过字符限制技巧)

WordPress 4.6命令执行漏洞实战:从Docker环境搭建到Shell获取全解析 在网络安全领域,漏洞复现是提升实战能力的重要途径。今天我们将深入探讨WordPress 4.6版本中一个经典的命令执行漏洞(PwnScriptum),通过完整的实验流…...

从修补Boot到反编译锁屏:一个安卓ROM修改新手的完整避坑日记

从修补Boot到反编译锁屏:一个安卓ROM修改新手的完整避坑日记 第一次接触安卓ROM修改时,我像大多数新手一样充满热情却屡屡碰壁。那些看似简单的解包、修改、打包操作背后,隐藏着无数让设备变砖的陷阱。这篇日记记录了我从零开始学习安卓ROM修…...

开源社区荣誉提名系统:从量化到质化的贡献认可实践

1. 项目概述:一个开源社区的荣誉提名系统如果你参与过开源项目,尤其是那些有活跃社区的项目,你可能会注意到一个现象:总有一些贡献者,他们提交的代码可能不是最多的,解决的议题也不是最复杂的,但…...

手把手教你用MounRiver Studio给WCH CH582 BLE项目添加TMOS多任务(附完整代码)

基于WCH CH582的TMOS多任务开发实战指南 在嵌入式BLE开发领域,南京沁恒微电子推出的RISC-V架构CH582系列芯片凭借其出色的低功耗表现和内置TMOS任务管理系统,正成为物联网终端设备的理想选择。本文将带您从零开始,在MounRiver Studio环境中构…...

一个开发者的AI工具链优化实录:从三个会员到一站搞定

4月29号晚上,技术群里被一条消息刷屏了——Gemini 3.1 Pro 上线了创意漫画功能。 我随手敲了句“画一个后端排查死锁的心路历程”,几秒钟弹出一套四格漫画,分镜利落,对白清晰,最后一格里那个趴在键盘上的小人&#xf…...

告别调参烦恼!手把手教你用ESO实现永磁同步电机无模型预测控制(附Simulink仿真)

永磁同步电机无模型预测控制实战:从理论到Simulink仿真全解析 电机控制领域正在经历一场从依赖精确模型到数据驱动的范式转变。传统PI调节器虽然结构简单,但面对非线性、强耦合的永磁同步电机系统时,调试过程往往令人抓狂——比例系数和积分…...

ClawDesk:基于YAML与心跳机制的AI Agent自动化编排平台

1. 项目概述:ClawDesk,一个为AI Agent团队设计的“指挥中心” 如果你正在使用OpenClaw,并且手头管理着不止一个AI Agent,那你可能已经体会过那种“甜蜜的烦恼”:每个Agent都在各自的终端里跑着,任务进度得靠…...

2026年晋城文化墙设计大揭秘,独特创意究竟藏着什么奥秘?

在晋城,文化墙不仅是城市的一道风景线,更是文化传承与创新的重要载体。2026年,晋城飞达广告有限公司设计的文化墙展现出了独特的魅力,让我们一起揭开其背后的奥秘。一、深度融合文化理念数据支撑据不完全统计,晋城飞达…...

3分钟极速上手:八大网盘下载加速神器LinkSwift终极指南

3分钟极速上手:八大网盘下载加速神器LinkSwift终极指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼…...

LuatOS+Air8101引擎主机开发钉钉机器人APP

本文以Air8101引擎主机为硬件平台,基于LuatOS系统和AirUI轻量化图形框架,开发一款钉钉机器人消息发送APP。文章详细记录了从软硬件环境准备、代码仓库拉取、PC模拟器配置,到使用DeepSeek生成UI界面及资源文件,最终利用Trae AI工具…...

好用的石墨消解仪哪家技术强

在分析检测领域,石墨消解仪是重要的样品前处理设备。那么,哪家的石墨消解仪技术强呢?下面为您详细分析。石墨消解仪的重要性石墨消解仪在环境监测、食品安全、农产品检测等众多领域发挥着关键作用。它能对样品进行有效的消解处理,…...

想搞懂国产大飞机C919的‘准生证’?一文拆解民航局适航审定的18种证件与办理流程

国产大飞机C919适航取证全流程解析:18种关键证件与实战指南 当一架国产大飞机从设计图纸到翱翔蓝天,背后是数以万计的零部件协同工作和长达数年的适航审定历程。C919作为中国首款按照国际适航标准研制的大型客机,其取证过程堪称航空工业的&qu…...

2026年小程序开发公司怎么选?这份避坑指南+标杆企业推荐请收好

随着小程序市场规模突破476亿元、年增速达37%,越来越多的企业面临开发公司选择难题。如何在百家争鸣的市场中精准匹配需求?本文将从行业现状、选型标准到标杆企业横向对比,为你提供一份实用决策指南。一、2026年小程序开发市场三大关键趋势定…...

对比直接使用原厂 API 体验 Taotoken 在接入便捷性上的优势

Taotoken 统一接入体验:多模型密钥管理与分钟级配置 1. 多模型密钥的统一管理 在实际开发过程中,管理多个大模型提供商的 API 密钥往往成为一项繁琐的工作。每个厂商通常有独立的控制台、不同的密钥生成机制以及各自的安全策略。通过 Taotoken 平台&am…...

GitHub下载加速终极指南:如何让GitHub下载速度提升10倍

GitHub下载加速终极指南:如何让GitHub下载速度提升10倍 【免费下载链接】Fast-GitHub 国内Github下载很慢,用上了这个插件后,下载速度嗖嗖嗖的~! 项目地址: https://gitcode.com/gh_mirrors/fa/Fast-GitHub 还在为GitHub的…...

实测 Taotoken 多模型路由的稳定性与低延迟体感

实测 Taotoken 多模型路由的稳定性与低延迟体感 1. 测试环境与调用场景 本次测试基于实际开发需求展开,调用频率模拟中小型应用的生产负载。测试周期为连续7天,每日调用量约500-800次,覆盖文本生成、代码补全和对话交互三类典型场景。测试使…...

【Swoole+LLM长连接生产落地白皮书】:20年架构师亲授高并发、低延迟、零断连的5大核心部署法则

更多请点击: https://intelliparadigm.com 第一章:SwooleLLM长连接架构全景与生产价值定位 Swoole 作为高性能 PHP 协程引擎,结合大语言模型(LLM)的流式推理能力,可构建低延迟、高并发、全双工的智能会话服…...

观测Taotoken平台用量与成本的实际体感与账单透明度

观测Taotoken平台用量与成本的实际体感与账单透明度 1. 用量看板的实时可视化呈现 登录Taotoken控制台后,用量看板默认展示最近7天的调用趋势。顶部卡片区以三组核心指标开场:总消耗Token数、成功请求次数和平均响应延迟。这种布局让开发者能快速把握近…...

Windows系统优化神器:5分钟掌握Chris Titus Tech WinUtil完整指南

Windows系统优化神器:5分钟掌握Chris Titus Tech WinUtil完整指南 【免费下载链接】winutil Chris Titus Techs Windows Utility - Install Programs, Tweaks, Fixes, and Updates 项目地址: https://gitcode.com/GitHub_Trending/wi/winutil 还在为Windows系…...