资讯详情

STM32_iC-MHM磁编码器使用

直接看代码到最后第六章,前面是流水账笔记

1、前言

讲道理,iC-MHM这是一个模型,我误以为硬件组的同事很懒,因为这个模型没有任何数字,看起来不像芯片模型。 结果我用这个型号搜索,真的搜索到了。iC-Haus Homepage - product: iC-MHM (ichaus.de)

拿到老规矩datasheet,先看功能介绍,特点等。然后拉通

根据原理图, STM32主芯片与iC-MHM芯片通信采用 SPI因此,主要关注通信接口SPI接口。

看这样的目录挺吓人的。其实还好。让我们先看看。SPI接口相关内容

和iC-MHM用SPI其他人写得很清楚通信操作的规则。

前黄色OP7 - OP0,就是OPcode意思,操作码。蓝色背面ADR7 - ADR0.我不知道这个缩写是什么,但是上表 下图显然意味着你(STM32主芯片 Master)不仅要先发一个操作码,还要再发一个 数据码(我暂时称之为数据码)。

正如前一篇文章所说,每个需要配置的寄存器都必须不可避免地再次阅读和配置。现在,事实上,我们必须阅读每个操作代码。

2、iC-MHM SPI通信操作码 详解

以下是对每个操作码的总结简要描述

0xB0 Activate,激活

那这两个位 (RACTIVE和PACTIVE)数据字节在哪里? 也给出了数据手册,如下图所示

我暂时可以理解, 我可以这样做

我发送 0xB0 0x先关闭激活两个字节。

我再发送0xB0 0x打开激活两个字节。 这样呢,能够实现一次类似于软复位的功能。

或者不操作, 默认情况活状态

或直接发送0xB0 0x03字节,我管你默认是什么状态,反正我激活一次。

另一个值得注意的地方

大意是:这两个位置,不能读,只能写。

0xA6 Position Read 位置读取命令

最短3个字节,最常见的7个字节。 这个多圈意味着它会帮你记录你转了多少圈,但是对于我们使用的场景,我们不会转一圈以上, 所以我们用singleturn Position数据应该是可以的。但既然都看了,就可以了解了。

上面是多圈, 以下是单圈配置

单圈位置(角度)总是用两个字节传输。 如果由参数 RESO_ST 插值器的分辨率小于 16 位置,单圈位置值在单圈位置字段中左对齐,未使用 LSB 设置为零。

例如,如果 RESO_ST= 6.单圈位置(角度)为 16 位字段中的 10 位值。 在这种情况下,位 15:6 包括单圈位置和位置 5:0 为零。 有关 RESO_ST 更多信息请参考第一条 21 页的 INTERPOLATOR。

一开始就看到这个编码器的分辨率是14位。 所以它Note里面不推荐 > 14。 然后>12需要使用到

AVGFILT,是平均滤波器。 AVGFILT不能为0。

啥意思? 鱼和熊掌不能兼得, 不可能分辨率高,反应快。 我觉得拿个中间值吧。RESO_ST 设置为 2,即14位, AVGFILT设置为1,1.2us延迟。 如果没有,则设置为2,2.3us延迟,其实是可以接受的。

刚刚发散,现在收回,继续我们Position Read,解释这个命令。 分析了多圈圈数和单圈角度,还有一个error位 warning位

说白了,如果这两个位置是0,说明这个芯片有问题, 假如都是1,那就没问题了。 暂时不跳30页和21页, 感觉指针满天飞

Register Access

不推荐用 Register Read(Single)和Register Write(Single)。 目前,我认为我们应该关注它 0x70后地址。

0x8A Register Read (Continuous) 寄存器读取(连续)

第一段:寄存器读取(连续)命令 (0x8A) 从指定地址开始的一个或多个 RAM 连续块读取地址的数据。

第二段:主机在 MOSI 发送读取寄存器操作码 (0x8A),跟随要读取的地址块 (ADR) 起始地址。 iC-MHM 立即输出 MISO 操作的操作码和地址,然后是地址 ADR (DATA1) 寄存器中的数据。只要 NCS 从下一个寄存器(地址)保持有效(低) ADR 1)数据将被输出(DATA2)。 只要 NCS 保持低电平,后续寄存器的数据将继续输出。

第三段:简而言之,第一个命令讲的,要激活“寄存器通道”,否则会报错。

0xCF Register Write(Continuous) 寄存器写入(连续)

和连续读取一样, 只要你的电影选择没有被提升,你就可以根据你指定的地址将字节连续写入寄存器。

0x9C Read Status 读取状态寄存器 指令

这个指令跟 【寄存器读取(连续)】指令非常相似,只要你的电影选线没有降低,你就会一直阅读。 您不需要指定状态寄存器的地址。如果你直接使用这个命令,他就会知道你在读状态寄存器。 但他最多应该读4个地址的数据,0x70-0x73。 另外,最后一段还是说要激活寄存器操作的通道。

0xD9 Write Instruction 写入命令寄存器 指令

这个指令跟 【寄存器写入(连续)】指令非常相似,只要你的选线没有拉低,就会一直写。 您不需要指定命令寄存器的地址。如果你直接使用这个命令,他就会知道你在写命令寄存器。 地址是从0x74开始的, 同样,最后一段还是说要激活寄存器操作的通道。 注意:你不需要写0的起始地址x74哦,你发送的第一个数据是0x74数据,第二个数据是0x75的数据。这很关键。

0x97 Register Read(Single) 寄存器读取(单次)

意思是第一个字节发送 0x97,第二个字节发送 指定地址,第三个字节发送0x00,

接收第一个字节 0x97 第二个字节接收 指定地址,第三个字节接收您想要的相应地址的数据。

看一下MAP吧,

0xD2 Register Write(Single) 寄存器写入(单次)

意思是第一个字节发送 0xD二、发送第二个字节 指定地址,第三个字节发送您想要写入地址的数据,

接收第一个字节 0xD2 第二个字节接收 指定地址,第三个字节接收您刚刚写入的数据。

0xAD Read Register Status/Data 读取寄存器状态/数据

这个指令有点迷人。

其实大概意思是: 你在最后一个操作 例如,寄存器的单读或单写命令 如果你跟着这个命令,你就会得到上一个命令执行的状态, 比如你的操作码错了, 你操作的地址错了啊,这些都可以给你爆出来。 它返回的第二个字节。 第三个字节是你读或写的字节,完全一样。 主要作用还是用于判断上一个命令执行状态。

3.如何写代码?

如何编写代码,或者根据第二步整理的操作码,整理

0xB0 Activate:

SPI 发送0xB0 0x03或0x83两个字节,我管你默认是什么状态,反正我激活了两个通道。

0CF Register Write(Continuous):

CS 拉低

SPI发送 0xCF + 0x00 + 字节1 + 字节2,四个字节

SPI接收 0xCF + 0x00 + 字节1 + 字节2(无用的)

CS拉高

字节1 对应RAM 地址是 0x00

字节2 对应RAM 地址是0x01

根据第二章的总结理解,总结关注三个配置点

 

 

RESO_MT = 0 多圈就算了,因为我们不转圈。

RESO_ST = 2 单圈位置14位 配套的 AVGFILT设置成1(1.2us延迟) 或者 设置成2(2.3us延迟)

地址:0x01的数据配置成什么已经可以确定了。

0 010 0 000 即 0x20

2 0

地址: 0x00的还不确定,应该还有HYS DIR TLF这些东西我都不知道是什么? 需要去看看。

 

 

  HYS 磁滞(磁铁旋转角度), 这个东西到底是啥意思,我还在真不懂,先设置成0吧,// TODO

DIR是方向意思, 0是逆时针,1是顺时针。 这个也设置成0吧,这个问题不大。  

我们的AVGFILT ≠ 0,所以TLF 得≥ 3。 那就设置成3吧。 暂时不纠这么细了。

总结一下 HYS 0 DIR 0 TLF 3 AVGFILT 2

1 0 0 0 1 1 1 0 即 0x8E

8 E

也就是说地址: 0x00的字节是0x8E

最终总结

CS 拉低

SPI发送 0xCF + 0x00 + 字节1 + 字节2,四个字节

SPI接收 0xCF + 0x00 + 字节1 + 字节2(无用的)

CS拉高

字节1 对应RAM 地址是 0x00 :0x8E

字节2 对应RAM 地址是0x01 :0x20

0xA6 Position Read

SPI直接发送0xA6 + 0x00 + 0x00 + 0x00 四个字节

SPI接收到 0xA6 + Multiturn Position(0字节) + singleturn Position(2字节) + (Err and warning) 一个字节

先就这三个命令就可以了,其它的暂时先不管。

4、STM32CubeMx开始配置

 

 

4.1 NSS Signal Type

SPI需要配置的东西,已经框出来了。 NSS是片选的选项,我们的原理图的是用一个GPIO引脚来做片选的(3线SPI),而不是用指定的那个NSS引脚之间直接连的(4线SPI)。 所以这里应该选择Software,即我们在发送消息的时候,需要自己去把片选线电平拉低。 下面看看其它的配置

4.2 Data Size & First Bit

芯片的Datasheet上讲了,SPI 支持Mode 0和Mode 3, 后面还有两个信息,byte by byte 即 Data Size 选 8Bits。

MSB first,即 First Bit 选 MSB first。

4.3 Clock Polarity(CPOL) & Clock Phase(CPHA)

上面谈到了芯片SPI通信支持Mode 0和Mode 3, 那看看 SPI的4中Mode分别是长什么样的。

 

 

也就是说,配置的时候配成: (CPOL = LOW && CPHA = 1 Edge) || (CPOL = High && CPHA = 2Edge)

我暂时选后者。

4.4 Prescaler(for Baud Rate)

另外,只剩时钟频率了,时钟频率这个东西,建议在芯片手册上搜索 System Clock这个关键字

最小 11.5Mhz 典型 14MHz 最大16MHz

所以我最终配置成 4分频, 10.5MBits/s

 

 测试 :基于上面的配置

#define iCMHM_spi_cs_A_Enable	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET)
#define iCMHM_spi_cs_A_Disable	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET)		

		iCMHM_spi_cs_A_Enable;		
		Tx[0] = 0xB0;
		Tx[1] = 0x83;
		
		Rx[0] = 0x00;
		Rx[1] = 0x00;

		HAL_SPI_TransmitReceive(&hspi2,Tx,Rx,2,100);	
		iCMHM_spi_cs_A_Disable;

向芯片发送 B0 83,接收到 B0 20。 这个配置是没有问题的。

但是,如果把分频设置2, 21MBits/s , 接收的数据就是错误的。 也就是你的分频器Prescaler只能 >= 4

5、测试配置按照第3章所诉的配置是否能够成功

实验发现,激活 + 只配置00和01地址的方式,无法正常的读取传感器数据,

还是需要从0x00 - 0x13地址,把所有的寄存器都配置一遍。

Two thousand years later!

这件事情告诉我们,一定要把买芯片的时候,最好选那种软件支持做得好的,最好有参考配置例程的。

Two thousand years later!

6、不倔强了,参考前辈的代码,给出最终结果

我只能说这个芯片比那个3轴陀螺+3轴加速度计的芯片还难搞。这件事情告诉我们买东西的时候一定要拿参考程序,正经看datasheet配置出来,我感觉没有十天半个月搞不定,这回拉长开发周期。

摆结果吧,不多说了。

#define icMHM_cs_A_enable		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET)
#define icMHM_cs_A_disable	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET)

#define icMHM_OP_Active 0xB0
#define icMHM_OP_Register_Write_Continuous 0xCF
#define icMHM_OP_Register_Read_Continuous 0x8A
#define icMHM_OP_Write_Instruction 0xD9
#define icMHM_OP_Position_Read 0xA6

void iCMHM_config(void){
		unsigned char ActivateOpcodeTx[2]					= {icMHM_OP_Active,0x03};
		unsigned char WriteContinuousOpcodeTx[2]	= {icMHM_OP_Register_Write_Continuous,0x00};
		unsigned char ReadContinuousOpcodeTx[2]		= {icMHM_OP_Register_Read_Continuous,0x00};
		unsigned char WriteInstructionOpcodeTx[4] = {icMHM_OP_Write_Instruction,0x01,0x07,0xC0};	// Reset			
		unsigned char configTx[20]	= {0x8E, 0x20, 0x00, 0x28, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C};
		unsigned char Rxtemp[24]		= {0x00};
		
		int iCRCPoly = 0x11D; // CRC-Polynomial 100011101
		uint8_t ucDataStream = 0;
		uint8_t ucCRC;
		
// A
		icMHM_cs_A_enable;
		HAL_SPI_TransmitReceive(&hspi3,ActivateOpcodeTx,Rxtemp,2,3);
		icMHM_cs_A_disable;
		HAL_Delay(4);
				
		// Calculate Config-CRC //
		ucCRC = 2; // startvalue !!!
		for (int iReg = 0 ; iReg<12; iReg ++) {
		ucDataStream = configTx[iReg];
		for (int i =0; i <=7; i ++) {
			if ( (ucCRC & 0x80) != (ucDataStream & 0x80))
				ucCRC = (ucCRC << 1 ) ^ iCRCPoly ;
			else
				ucCRC = (ucCRC << 1 ) ;
			ucDataStream = ucDataStream << 1 ;
		}
		}	
		configTx[12] = ucCRC;
		// Calculate Offset-CRC //
		ucCRC = 2; // startvalue !!!
		for (int iReg = 13 ; iReg<19; iReg ++) {
			ucDataStream = configTx[iReg];
			for (int i =0; i <=7; i ++) {
				if ( (ucCRC & 0x80) != (ucDataStream & 0x80))
					ucCRC = (ucCRC << 1 ) ^ iCRCPoly ;
				else
					ucCRC = (ucCRC << 1 ) ;
				ucDataStream = ucDataStream << 1 ;
			}
		}
		configTx[19] = ucCRC;	
	
		
		icMHM_cs_A_enable;
		HAL_SPI_TransmitReceive(&hspi3,WriteContinuousOpcodeTx,Rxtemp,2,3);
		HAL_SPI_TransmitReceive(&hspi3,configTx,Rxtemp,20,3);
		icMHM_cs_A_disable;	
		HAL_Delay(4);
			
		icMHM_cs_A_enable;		
		HAL_SPI_TransmitReceive(&hspi3,ReadContinuousOpcodeTx,Rxtemp,2,3);
		HAL_SPI_Receive(&hspi3,Rxtemp,20,10);		
		icMHM_cs_A_disable;
		HAL_Delay(4);
		
		icMHM_cs_A_enable;		
		HAL_SPI_TransmitReceive(&hspi3,WriteInstructionOpcodeTx,Rxtemp,2,3);
		icMHM_cs_A_disable;
		HAL_Delay(4);
}



void iCMHM_position_read(void){
		unsigned char positionTx[4] = {icMHM_OP_Position_Read,0x00,0x00,0x00};
		unsigned char Rxtemp[4] ={0x00};
		unsigned short HighByte, LowByte, u14_position; 
		
		icMHM_cs_A_enable;
		HAL_SPI_TransmitReceive(&hspi3,positionTx,Rxtemp,4,10);
		icMHM_cs_A_disable;
		LowByte =  Rxtemp[2];
		HighByte = Rxtemp[1];		
		u14_position = HighByte << 6 | LowByte >> 2;
		fAencoder = (float)u14_position * 0.02197265625f; //  360 / 16384 = 0.02197265625
}

标签: 传感器的磁环4k7单圈电位器ksp102

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台