IC-MU128磁编码器芯片通信验证
最近公司在关节模组上面使用的一款磁编码器IC-MU128和IC-MU200。该芯片是使用BISS或者SPI去通信的。由于我使用的是STM32作为MCU,所以只能使用SPI去通信。
由于目前我还不是很熟悉这款芯片,等后面供应商过来校准后,开发更详细的资料后,后续我还会再写一篇文档补充,目前只是记录一下如何验证该款芯片的通信。
目前和供应商那边沟通的情况是,SPI通信波特率小于10Mbit即可,具体多少手册上面也没有写。

从手册上面了解到的是该款芯片是只支持SPI0和SPI3模式。目前的话我使用的是软件SPI去验证通信的,没有使用硬件SPI的原因很简单,硬件工程师那边画错了。
(1)软件SPI验证IC-MU磁编码器:

下面是bsp_spi.h的内容:
#ifndef __BSP_SPI_H
#define __BSP_SPI_H
#include "main.h"
#include "bsp_delay.h"
#define SPI_SCK_PIN GPIO_PIN_4
#define SPI_SCK_GPIO_PORT GPIOB
#define SPI_MOSI_PIN GPIO_PIN_5
#define SPI_MOSI_GPIO_PORT GPIOB
#define SPI_MISO_PIN GPIO_PIN_2
#define SPI_MISO_GPIO_PORT GPIOB
#define SPI_NSS_PIN GPIO_PIN_3
#define SPI_NSS_GPIO_PORT GPIOB
#define MOSI_H HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET)
#define MOSI_L HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_RESET)
#define SCK_H HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET)
#define SCK_L HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_RESET)
#define MISO HAL_GPIO_ReadPin(SPI_MISO_GPIO_PORT, SPI_MISO_PIN)
#define NSS_H HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET)
#define NSS_L HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_RESET)
uint8_t SOFT_SPI_RW_MODE0(uint8_t write_dat);
#endif
下面是bsp_spi.c的内容:
#include "bsp_spi.h"
uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat )
{
uint8_t i, read_dat;
for( i = 0; i < 8; i++ )
{
if( write_dat & 0x80 )
MOSI_H;
else
MOSI_L;
write_dat <<= 1;
SCK_H;
read_dat <<= 1;
if( MISO )
read_dat++;
SCK_L;
__nop();
}
return read_dat;
}

直接找个地方调用接口函数去发送0xA6即可,不需要发送0xB0去ACTIVATE也能通信。

目前的话IC-MU200/IC-MU128磁编码器的位数都是14位的,有效数据的大小和磁盘也有关系。比如我使用的磁盘是32对极的(2^5)。那么就代表这磁编码器的有效数据是14+5 = 19位。发现字节去获取数据的时候,返回的24bit的数据需要右移5位才是真实的数据。
(2)硬件SPI验证IC-MU编码器


#include "ic_mu.h"
#include "mc_type.h"
#include "mc_config.h"
#include "PIC32SPIDriver.h"
#include "abs_encoder_pos_fdbk.h"
#include "pmsm_motor_parameters.h"
typedef ENCODER_Handle_t IC_MU128_Handle;
typedef SpeednPosFdbk_Handle_t IC_MU200_Handle;
void IC_MU_H( void * pHdl, IC_MU_TYPE_t SensorType );
void IC_MU_L( void * pHdl, IC_MU_TYPE_t SensorType );
uint8_t wdata[4] = {0xA6,0xFF,0xFF,0xFF};
uint8_t rHdata[4] = {0};
uint8_t rLdata[4] = {0};
uint32_t SPI_Send( void * pHdl ,IC_MU_TYPE_t SensorType )
{
uint32_t rtdata;
ENCODER_Handle_t * pHandle = (ENCODER_Handle_t *)pHdl;
if( SensorType == IC_MU_128 )
{
IC_MU128_Handle * Handle = pHandle;
if(Handle->hspi != MC_NULL)
{
HAL_SPI_TransmitReceive_IT(Handle->hspi,wdata,rLdata,4);
rtdata = Handle->wRawAngleData;
}
}
else if (SensorType == IC_MU_200 )
{
IC_MU200_Handle * Handle = &pHandle->_Super;
if(Handle->hspi != MC_NULL)
{
HAL_SPI_TransmitReceive_IT(Handle->hspi,(uint8_t *)&wdata,rHdata,4);
rtdata = Handle->hRawAngleData;
}
}
return rtdata;
}
void IC_MU_H( void * pHdl, IC_MU_TYPE_t SensorType )
{
ENCODER_Handle_t * pHandle = (ENCODER_Handle_t *)pHdl;
if( SensorType == IC_MU_128 )
{
IC_MU128_Handle * Handle = pHandle;
if(Handle->hspi != MC_NULL) SPI1_CS_H;
}
else if(SensorType == IC_MU_200)
{
IC_MU200_Handle * Handle = &pHandle->_Super;
if(Handle->hspi != MC_NULL) SPI2_CS_H;
}
}
void IC_MU_L( void * pHdl, IC_MU_TYPE_t SensorType)
{
ENCODER_Handle_t * pHandle = (ENCODER_Handle_t *)pHdl;
if( SensorType == IC_MU_128 )
{
IC_MU128_Handle * Handle = pHandle;
if(Handle->hspi != MC_NULL) SPI1_CS_L;
}
else if(SensorType == IC_MU_200)
{
IC_MU200_Handle * Handle = &pHandle->_Super;
if(Handle->hspi != MC_NULL) SPI2_CS_L;
}
}
uint32_t SPI_IC_MU128(void * pHandle)
{
uint32_t theta;
IC_MU_L(pHandle,IC_MU_128);
theta = SPI_Send(pHandle,IC_MU_128);
return theta;
}
uint32_t SPI_IC_MU200(void * pHandle)
{
uint32_t theta;
IC_MU_L(pHandle,IC_MU_200);
theta = SPI_Send(pHandle,IC_MU_200);
return theta;
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if(hspi->Instance == SPI1)
{
SPI1_CS_H;
Encoder_M1.wRawAngleData = (( rLdata[1] << 16 | rLdata[2] << 8 | rLdata[3] << 0 ) & 0xFFFFFF ) >> 5;
}
if(hspi->Instance == SPI2)
{
SPI2_CS_H;
Encoder_M1._Super.hRawAngleData = (( rHdata[1] << 16 | rHdata[2] << 8 | rHdata[3] << 0 ) & 0xFFFFFF ) >> 5;
}
if(hspi->Instance == SPI3)
{
}
}
在进行通信之前将SPI_CS片选引脚拉低,使用SPI中断相关的中断中断函数HAL_SPI_TransmitReceive_IT(Handle->hspi,wdata,rLdata,4);进行数据发送,在中断回调函数里面将SPI_CS片选引脚拉高即可。
可以写一个数据 uint8_t wdata[4] = {0xA6,0xFF,0xFF,0xFF}; 一次性发送四个字节,这样字节和字节间的通信间隔不会太长。
还有就是片选引脚问题,通信之前片选引脚一定要是高片选,通信前要拉低,通过测试发现可能芯片IC-MU可能需要识别片选引脚来判断触发通信。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)