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

MT6835 21位 磁编码器 SPI 平台无关通用驱动框架 STM32

MT6835 21位 磁编码器 SPI 平台无关通用驱动框架 STM32

      • 1. 获取代码:
      • 2. 加入你的项目
        • 2.1 以 STM32 为例:
        • 2.2 以 ESP-IDF 为例:
      • 3. 对接 API
        • 3.1 以 STM32 为例:
      • 4. 更多函数说明
      • 5. 写入 EEPROM 示例

MT6835 Framework

纯C语言实现,跨平台(stm32、ESP32),移植灵活,低耦合高内聚的
MT6835(21位磁编) 驱动框架

1. 获取代码:

请为你的Git账户配置好SSH,然后在你喜欢的项目目录下使用以下命令
或去 项目地址页面 下载

git clone git@github.com:Hotakus/mt6835.git

2. 加入你的项目

2.1 以 STM32 为例:

该项目为标准 CMake 项目,可以很方便的加入你的项目中。
例如,STM32CubeMX 可以自动生成 STM32 的 CMake 工程文件,请在你的根目录的CMakeLists.txt中(不是该项目)加入以下内容:

add_subdirectory(mt6835) # 添加子目录,在 add_executable() 之前# 找到这句话,在上下加入代码
add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})# 假设你的项目名为 “your_project”,则添加依赖⬇
# target_link_libraries 一般放在 add_executable() 之后
target_link_libraries(your_project mt6835) 
2.2 以 ESP-IDF 为例:

若你使用其他平台,请跳过该小节
若你使用 ESP-IDF 框架进行 ESP32 开发,首先,你的ESP-IDF项目根目录应该会有一个components文件夹,
若没有,请自己创建一个,这个目录用于添加额外组件(拉取的本项目同样要放在这个目录下)。
接下来,进入mt6835项目根目录,注意到CMakeLists_esp_idf.txt文件,
然后将CMakeLists.txt与该文件名进行交换即可。ESP-IDF 会自动检测


3. 对接 API

程序预留硬件抽象层 API 给用户对接,对于 MT6835,采用 SPI 全双工通信,可以读出21位的角度原始数据,请确保以下:

  • 提前配置好 SPI 全双工通信(例如 STM32 可以使用 STM32CubeMX 配置 SPI1 )
  • SPI 时钟理论不超过 16MHz,
  • CPOL(1), CPHA(1),8bit 数据模式,
  • 软 CS,提前配置好一根 CS 引脚,默认拉高

在该项目的 example 目录,你可以看到预先实现的对应平台的移植文件,可以直接放到你的项目中使用。若你想要自己实现,可以参考下面的示例:

3.1 以 STM32 为例:
#include <math.h>
#include "mt6835.h" // MT6835 驱动头文件
#include "spi.h"    // STM32CubeMX 生成的 SPI 头文件#define SPI_INSTANCE hspi1             // STM32CubeMX 生成的 SPI 句柄
#define SPI_CS       SPI1_CS_Pin       // STM32CubeMX 生成的 CS 引脚
#define SPI_CS_PORT  SPI1_CS_GPIO_Port // STM32CubeMX 生成的 CS 端口// 示例 CS 操作函数,可以根据需要进行修改
static void mt6835_cs_control(mt6835_cs_state_enum_t state) {if (state == MT6835_CS_HIGH) {  // 高电平HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS, GPIO_PIN_SET);} else {// 低电平HAL_GPIO_WritePin(SPI_CS_PORT, SPI_CS, GPIO_PIN_RESET);}
}// 示例收发函数,可以根据需要进行修改
static void mt6835_spi_send_recv(uint8_t *tx_buf, uint8_t *rx_buf, uint8_t len) {HAL_StatusTypeDef status = HAL_OK;status = HAL_SPI_TransmitReceive_IT(&SPI_INSTANCE, tx_buf, rx_buf, len);if (status != HAL_OK) {printf("spi send_recv failed %d\n\r", status);return;}// wait ITuint32_t tickstart = HAL_GetTick();while (HAL_SPI_GetState(&SPI_INSTANCE) != HAL_SPI_STATE_READY) {if (HAL_GetTick() - tickstart > 1) {printf("spi send_recv timeout\n\r");return;}}
}int main(void) { /* STM32CubeMX 生成的初始化 */HAL_Init();......MX_SPI1_Init();/* 创建 MT6835 对象 */mt6835_t *mt6835 = mt6835_create();/* 链接 SPI 的 CS 操作函数 */mt6835_link_spi_cs_control(mt6835, mt6835_cs_control);/* 链接 SPI 收发函数 */mt6835_link_spi_send_recv(mt6835, mt6835_spi_send_recv);/* 可选 */// mt6835_link_spi_send(mt6835, mt6835_spi_send);// mt6835_link_spi_recv(mt6835, mt6835_spi_recv);/* 是否开启 CRC 校验,使用查表法,通常不会有性能影响* 若开启,则会使用 mt6835_t 结构体中的 crc_res 位存储该次角度读取正确性,* 用户可以根据 crc_res 的值进行判断,*/mt6835_enable_crc_check(mt6835);// mt6835_disable_crc_check(mt6835);    // 禁用 CRC 校验/* 开始读取角度 */uint32_t raw_angle = 0;float radian_angle = 0.0f;while(1) {/* * 读取原始角度数据* 第二个参数为读取方式, MT6835_READ_ANGLE_METHOD_NORMAL 或 MT6835_READ_ANGLE_METHOD_BURST * MT6835_READ_ANGLE_METHOD_BURST 会更快*/raw_angle = mt6835_get_raw_angle(mt6835, MT6835_READ_ANGLE_METHOD_BURST);radian_angle = raw_angle * (M_PI * 2.0f) / MT6835_ANGLE_RESOLUTION;// radian_angle = mt6835_get_angle(motor1_mt6835, MT6835_READ_ANGLE_METHOD_BURST);if (!mt6835->crc_res) {printf("crc error\n\r");}printf("raw_angle: %d, radian_angle: %f\n\r", raw_angle, radian_angle);HAL_Delay(500);}
}

若不想自己实现,则直接将example/stm32/mt6835_stm32_spi_port.h文件中宏定义MT6835_STM32_SPI_PORT_ENABLE改为1即可:
然后按照如下调用:

int main() {uint32_t raw_angle = 0;float radian_angle = 0.0f;mt6835_t * mt6835 = mt6835_stm32_spi_port_init();while(1) {raw_angle = mt6835_get_raw_angle(mt6835, MT6835_READ_ANGLE_METHOD_BURST);radian_angle = raw_angle * (M_PI * 2.0f) / MT6835_ANGLE_RESOLUTION;// radian_angle = mt6835_get_angle(motor1_mt6835, MT6835_READ_ANGLE_METHOD_BURST);printf("raw_angle: %d, radian_angle: %f\n\r", raw_angle, radian_angle);HAL_Delay(500);}
}

4. 更多函数说明

  • 创建销毁函数:

    • mt6835_create() 创建一个 mt6835 对象
    • mt6835_destroy() 销毁一个 mt6835 对象
  • 链接函数:

    • mt6835_link_spi_send() 链接 SPI 发送函数
    • mt6835_link_spi_recv() 链接 SPI 接收函数
    • mt6835_link_spi_send_recv() 链接 SPI 收发函数
    • mt6835_link_spi_cs_control() 链接 CS 引脚操作函数
  • CRC:

    • mt6835_enable_crc_check() 使能 CRC 校验(查表法)
    • mt6835_disable_crc_check() 失能 CRC 校验
  • GET 和 SET 函数

    • mt6835_get_id() 读取 MT6835 ID 寄存器
    • mt6835_set_id() 暂时写入 MT6835 ID 寄存器(配合 mt6835_write_eeprom() 函数)
    • mt6835_get_raw_angle() 读取原始角度数据(21位)
    • mt6835_get_angle() 读取原始角度数据并换算为弧度值(0 ~ 2*PI)
    • mt6835_get_raw_zero_angle() 读取原始零位值(12位)(零位值在 FOC 中很重要,最好是将正确零位固化在EEPROM中)
    • mt6835_get_zero_angle() 读取零位值,并换算成弧度值
    • mt6835_set_zero_angle() 暂时写入零位值(以弧度)到寄存器,(配合 mt6835_write_eeprom() 函数)
  • 底层函数:

    • mt6835_read_reg() 单字节读取寄存器
    • mt6835_write_reg() 单字节暂时写入寄存器(配合 mt6835_write_eeprom() 函数)
    • mt6835_write_eeprom() 将当前所有的可固化寄存器值写入(固化)到 EEPROM,所有写入操作最后都要额外调用这个函数

5. 写入 EEPROM 示例

存在寄存器的值断电消失,所以只是写入寄存器并不等于固化到 EEPROM

int main() {/* 写入 ID */mt6835_set_id(mt6835, 0xDA); // 写入 ID 0xDA 到寄存器,只在寄存器,断电消失HAL_Delay(1);uint8_t id = mt6835_get_id(mt6835); // 读取 IDprintf("id: 0x%x\r\n", id);/* 写入特定零位值,零位值需要你自己校准并读取角度 */// 2.0943951024f 是 120 度,假设 120 度是零位mt6835_set_zero_angle(mt6835, 2.0943951024f); //写入到零位寄存器,断电消失HAL_Delay(1);float zero_angle = mt6835_get_zero_angle(mt6835); // 读取零位值printf("zero_angle: %f rad\r\n", zero_angle);/*下面进行统一固化,为保证断电后 MT6835 数据不丢失,需要固化到 EEPROM *//** 直接调用 mt6835_write_eeprom 发送固化命令,* 命令成功发送则返回 0x55, 若正确收到 0x55,* 则程序 respond 为 true,错误则 false*/bool respond = mt6835_write_eeprom(mt6835);if (!respond) {printf("write eeprom failed\r\n");} else {printf("write eeprom success\r\n");}HAL_Delay(6000);    // 写入后至少 6 秒钟不能断电/* * 将上面的所有写入和固化操作注释掉,重新烧录程序,* 并重新给编码器上电,进行读取验证 */ id = mt6835_get_id(mt6835); // 读取 IDprintf("id: 0x%x\r\n", id);zero_angle = mt6835_get_zero_angle(mt6835); // 读取零位值printf("zero_angle: %f rad\r\n", zero_angle);// 若任何环节失败,请优先检测你的 SPI 初始化代码是否有问题,// 因为所有代码均经过正确验证
}

最后附上简单的 STM32CubeMX配置图片:
注意另配 CS 引脚,任意引脚设置为 OUTPUT 即可
在这里插入图片描述

相关文章:

MT6835 21位 磁编码器 SPI 平台无关通用驱动框架 STM32

MT6835 21位 磁编码器 SPI 平台无关通用驱动框架 STM32 1. 获取代码&#xff1a;2. 加入你的项目2.1 以 STM32 为例:2.2 以 ESP-IDF 为例: 3. 对接 API3.1 以 STM32 为例&#xff1a; 4. 更多函数说明5. 写入 EEPROM 示例 MT6835 Framework 纯C语言实现&#xff0c;跨平台&…...

python视频爬虫

文章目录 爬虫的基本步骤一些工具模拟浏览器并监听文件视频爬取易错点一个代码示例参考 爬虫的基本步骤 1.抓包分析&#xff0c;利用浏览器的开发者工具 2.发送请求 3.获取数据 4.解析数据 5.保存数据 一些工具 requests, 用于发送请求&#xff0c;可以通过get&#xff0c;p…...

嵌入式WebRTC压缩至670K,目标将so动态库压缩至500K,.a静态库还可以更小

最近把EasyRTC的效果发布出去给各大IPC厂商体验了一下&#xff0c;直接就用EasyRTC与各个厂商的负责人进行的通话&#xff0c;在通话中&#xff0c;用户就反馈效果确实不错&#xff01; 这两天有用户要在海思hi3516cv610上使用EasyRTC&#xff0c;工具链是&#xff1a;gcc-2024…...

Rhel Centos环境开关机自动脚本

Rhel Centos环境开关机自动脚本 1. 业务需求2. 解决方法2.1 rc.local2.2 rc.d2.3 systemd2.4 systemd附着的方法2.5 tuned 3. 测试 1. 业务需求 一台较老的服务器上面业务比较简单,提供一个简单的网站,但已经没有业务的运维人员. 想达到的效果: 由于是非标准的apache或者nginx…...

phpipam1.7安装部署

0软件说明 phpipam是一个开源Web IP地址管理应用程序&#xff08;IPAM&#xff09; phpipam官网&#xff1a;https://www.phpipam.net/ 1安装环境 操作系统&#xff1a;Rocky Linux9.5x86_64 phpipam版本&#xff1a;1.7 php版本&#xff1a;8.0.30 数据库版本&#xff1a…...

深入理解org.springframework.web.context.request.RequestContextHolder

在Spring Web应用中&#xff0c;RequestContextHolder是一个非常有用的工具类&#xff0c;用于在任何地方访问当前请求的上下文信息。它解决了非Controller层或非过滤器层需要访问请求上下文的问题&#xff0c;如在Service层或DAO层。以下是对 RequestContextHolder的详细解析。…...

Django中select_related 的作用

Django中这句代码Dynamic.objects.select_related(song)是什么意思&#xff1f; 在 Django 中&#xff0c;这句代码&#xff1a; Dynamic.objects.select_related(song) 的作用是 在查询 Dynamic 模型的同时&#xff0c;预加载 song 关联的外键对象&#xff0c;从而减少数据…...

正泰中间电磁继电器【8脚10A】DC24V 待机功率

需求&#xff1a;继电器能耗测试。 1.连接24V2A的电源&#xff0c; 2. 稳定功率为 1.4W 3. 正泰中间电磁继电器【8脚10A】直流DC24V 注&#xff1a;联通时电磁继电器会轻微发热 4.电磁继电器的工作原理基于电流的磁效应 电磁激励&#xff1a;电磁继电器主要由线圈、铁芯、衔…...

C++ 中的 Const 关键字(1)

C 中的 Const 关键字 最后更新&#xff1a; 2024 年 8 月 6 日 本文讨论了C中const 关键字的各种功能。只要将const 关键字附加到任何方法 ()、变量、指针变量以及类的对象上&#xff0c;它就会阻止特定对象/方法 ()/变量修改其数据项的值。 常量变量&#xff1a; 常量变量的声…...

Mac上搭建宝塔环境并部署PHP项目

安装Docker Desktop》搭建Centos版本的宝塔环境》部署PHP项目 1. 下载Docker for mac 软件&#xff1a;https://www.docker.com/ 或使用终端命令&#xff1a;brew install --cask --appdir/Applications docker 2. 使用命令安装宝塔环境的centos7系统&#xff1a; docker pul…...

哈希表-两个数的交集

代码随想录-刷题笔记 349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 内容: 集合的使用 , 重复的数剔除掉&#xff0c;剩下的即为交集&#xff0c;最后加入数组即可。 class Solution {public int[] intersection(int[] nums1, int[] nums2) {Set<Integer…...

win11 终端乱码导致IDE 各种输出也乱码

因为 win11 终端乱码导致IDE 各种输出也乱码导致作者对此十分头大。所以研究了各种方法。 单独设置终端编码对 HKEY_CURRENT_USER\Console 注册表进行修改对 HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processo 注册表进行修改使用命令[Console]::OutputEncoding [Syst…...

LabVIEW用户界面(UI)和用户体验(UX)设计

作为一名 LabVIEW 开发者&#xff0c;满足功能需求、保障使用便捷与灵活只是基础要求。在如今这个用户体验至上的时代&#xff0c;为 LabVIEW 应用程序设计直观且具有美学感的界面&#xff0c;同样是不容忽视的关键任务。一个优秀的界面设计&#xff0c;不仅能提升用户对程序的…...

23、深度学习-自学之路-激活函数relu、tanh、sigmoid、softmax函数的正向传播和反向梯度。

在使用这个非线性激活函数的时候&#xff0c;其实我们重点还是学习的是他们的正向怎么传播&#xff0c;以及反向怎么传递的。 如下图所示&#xff1a; 第一&#xff1a;relu函数的正向传播函数是&#xff1a;当输入值&#xff08;隐藏层&#xff09;值大于了&#xff0c;就输出…...

【matlab优化算法-16期】基于遗传算法的电热气及储能综合优化项目实践

电热气及储能综合优化项目实践 一、前言 随着能源转型和可持续发展的推进&#xff0c;综合能源系统的优化逐渐成为研究热点。本文介绍了一个电热气及储能综合优化项目&#xff0c;旨在通过优化算法实现多能源系统的协同运行&#xff0c;提高能源利用效率&#xff0c;降低运行…...

单例模式和单例Bean

单例模式 定义&#xff1a;单例模式是一种软件设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问这个实例。 实现方式 饿汉式&#xff1a;在类加载时就立即创建单例实例&#xff0c;线程安全&#xff0c;调用效率高&#xff0c;但可能会造成…...

springboot239-springboot在线医疗问答平台(源码+论文+PPT+部署讲解等)

&#x1f495;&#x1f495;作者&#xff1a; 爱笑学姐 &#x1f495;&#x1f495;个人简介&#xff1a;十年Java&#xff0c;Python美女程序员一枚&#xff0c;精通计算机专业前后端各类框架。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xf…...

DeepSeek系统崩溃 | 极验服务如何为爆火应用筑起安全防线?

引言 极验服务让您的产品站在风口之时&#xff0c;不必担心爆红是灾难的开始&#xff0c;而是期待其成为驱动持续创新的全新起点。 01现象级狂欢背后&#xff0c;你的业务安全防线抗得住吗&#xff1f; “近期DeepSeek线上服务受到大规模恶意攻击&#xff0c;注册可能繁忙&am…...

vcredist_x64.exe 是 Microsoft Visual C++ Redistributable 的 64 位版本

vcredist_x64.exe 是 Microsoft Visual C++ Redistributable 的 64 位版本,它提供了运行基于 Visual C++ 编写的应用程序所需的库文件。许多 Windows 应用程序都依赖这些库来正常运行,特别是使用 Visual Studio 编译的程序。 用途和重要性: 运行时库:vcredist_x64.exe 安装…...

Spring:Spring实现AOP的通俗理解(有源码跟踪)

目录标题 AOP定义SpringAOP和AspectJ联系Spring如何实现AOPAOP的代理对象AOP的代理对象生成过程 AOP定义 AOP &#xff08;Aspect Orient Programming&#xff09;&#xff1a;直译过来就是 面向切面编程。AOP 是一种编程思想用途&#xff1a;Transactions &#xff08;事务调…...

kotlin-kapt

kotlin-kapt kotlin-kapt 是 Kotlin 的一个插件&#xff0c;专门用于处理注解处理器&#xff08;Annotation Processor&#xff09;。以下是对该插件的详细解释和指南&#xff1a; kotlin-kapt 是什么&#xff1f; kotlin-kapt 是 Kotlin 官方提供的一个插件&#xff0c;用于在…...

Linux中getifaddrs函数

文章目录 **函数原型****参数****返回值****释放资源****`struct ifaddrs` 结构****示例代码****输出示例****相关函数****总结**getifaddrs 是 Linux(以及其他 Unix-like 系统)中用于获取本机网络接口信息的系统调用。它提供了一种简单的方法来获取所有网络接口的地址信息,…...

java后端开发day15--字符串(一)

&#xff08;以下内容全部来自上述课程&#xff09; 1.API &#xff08;Application Programming Interface 应用程序编程接口&#xff09; 1.简单理解 简单理解&#xff1a;API就是别人已经写好的东西&#xff0c;我们不需要自己编写&#xff0c;直接使用即可。 Java API&…...

vue项目 Axios创建拦截器

Axios 1. Axios 和 Ajax 简介2. Axios 和 Ajax 的区别3. 从 按钮 到 Axios请求后端接口的 大致顺序 1. Axios 和 Ajax 简介 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09; 不是一种技术&#xff0c;而是一个编程技术概念&#xff0c;核心是通过 XMLHttpReques…...

NLP面试之-激活函数

一、动机篇 1.1 为什么要有激活函数&#xff1f; 数据角度&#xff1a;由于数据是线性不可分的&#xff0c;如果采用线性化&#xff0c;那么需要复杂的线性组合去逼近问题&#xff0c;因此需要非线性变换对数据分布进行重新映射;线性模型的表达力问题&#xff1a;由于线性模型…...

深入探究 Go 语言中的 Fx 框架:依赖注入的强大工具

在软件开发中&#xff0c;依赖注入&#xff08;Dependency Injection&#xff0c;简称 DI&#xff09;是一种重要的设计模式&#xff0c;它可以帮助我们降低代码的耦合度&#xff0c;提高代码的可测试性和可维护性。Go 语言作为一门高效、简洁的编程语言&#xff0c;拥有许多优…...

Notepad++ 中删除所有以 “pdf“ 结尾的行

Notepad 中删除所有以 “pdf” 结尾的行 操作步骤 1.打开文件&#xff1a; 在 Notepad 中打开你需要处理的文本文件。 2.打开查找和替换对话框&#xff1a; 按快捷键 Ctrl F&#xff0c;打开“查找和替换”对话框。 3.启用正则表达式模式&#xff1a; 在对话框的底部&#xf…...

b站——《【强化学习】一小时完全入门》学习笔记及代码(1-3 多臂老虎机)

问题陈述 我们有两个多臂老虎机&#xff08;Multi-Armed Bandit&#xff09;&#xff0c;分别称为左边的老虎机和右边的老虎机。每个老虎机的奖励服从不同的正态分布&#xff1a; 左边的老虎机&#xff1a;奖励服从均值为 500&#xff0c;标准差为 50 的正态分布&#xff0c;即…...

数据结构与算法之排序算法-插入排序

排序算法是数据结构与算法中最基本的算法之一&#xff0c;其作用就是将一些可以比较大小的数据进行有规律的排序&#xff0c;而想要实现这种排序就拥有很多种方法~ 那么我将通过几篇文章&#xff0c;将排序算法中各种算法细化的&#xff0c;详尽的为大家呈现出来&#xff1a; &…...

基于YoloV11和驱动级鼠标模拟实现Ai自瞄

本文将围绕基于 YoloV11 和驱动级鼠标实现 FPS 游戏 AI 自瞄展开阐述。 需要着重强调的是&#xff0c;本文内容仅用于学术研究和技术学习目的。严禁任何个人或组织将文中所提及的技术、方法及思路应用于违法行为&#xff0c;包括但不限于在各类游戏中实施作弊等违规操作。若因违…...