一、 关于AS5600
1.1 芯片内部框图和引脚功能介绍
具体的内容大家可以查看数据手册:AS5600数据手册,在这里只是对一下重要的地方进行说明。
系统框图如下:
电源设计选项,我在设计时选择的是第二种电源方案,但是采用此方案,一定要将VDD5V和VDD3V3接在一起。
下图是引脚的说明,AS5600可以将测得的角度信息通过IIC或者OUT口读取:
后续会有对PGO口和OUT口的介绍。
1.2 IIC总线
上图是IIC的时序图以及各时序的时间,其中关于的时序的时间一定要保证符合要求,否则将导致无法读写数据,所以为了保证能正常使用IIC,建议还是使用IO口模拟的IIC。
AS5600有两个地址,一个是从地址(0x36);另一个是寄存器地址,在读写事件中确定往哪里读写。地址这个东西也很好理解,你给某个人家送快递,你得知道这户人家在哪栋楼(从地址),住在这栋楼的第几层(寄存器地址),这样清楚知道后才会把东西交到正确的人手上;找到错误的地址,你就无法把东西交给正确的人。关于IIC的地址会在STM32系列博客中进行细致的讲解,大家可以订阅我的专栏,不久就能更新到IIC的知识了。
有一些特殊的寄存器: ANGLE, RAW ANGLE 和MAGNITUDE 寄存器,它们在读取时禁止地址指针的自动增加,因此重新读取这些寄存器不需要I²C写命令来重新加载地址指针。注意:对指针的这种特殊处理仅在地址指针设置为寄存器的高字节时有效。
只有当总线不忙时(因为有时候一个IIC上不光挂一个器件,可能并联多个IIC器件,所以在某一时刻可能存在某个器件正在读写数据,即总线忙;当某个器件结束读写,总线不忙了,才可以读写这个器件),才可以开始数据传输。在数据传输过程中,当SCL高时,数据线必须保持稳定(这也是为什么IIC必须要加上拉电阻的原因)。当SCL高时,数据线的变化被解释为START或STOP条件。
下面就是一些总线空闲、起始、停止、数据传输、应答的介绍,这些算是IIC的基础内容,在这就不再进行详细介绍了。
1.3 AS5600从模式
1.3.1 写模式
在起始条件之后,主机发送从地址(0x36),再接一个读写指令(0–写;1–读);AS5600确认是从地址正确,会返回一个应答(A)。紧接着主机再发送寄存器地址,如果AS5600确认寄存器地址正确,则返回应答(A);之后主机开始发送要写入的数据,AS5600从寄存器地址开始,地址指针会自动增加,将数据写入对应的寄存器中。注意:无论寄存器地址是否正确,在每传输一个字节之后都会自增。
1.3.2 读模式
和写模式差不多,从地址+1(读),AS5600返回一个应答(A),然后,AS5600开始从地址指针指向的寄存器地址开始传输数据。如果在开始读事务之前没有写地址指针,那么读到的第一个地址就是存储在地址指针中的最后一个地址。AS5600必须收到一个不确认(NACK)来结束读事假。
这个地方很奇怪,数据手册的格式里面没有说在哪写寄存器地址,但是这又是必须的,我没太看明白这个地方。
1.3.2 用地址指针重新加载读取数据
这个才是正确的读操作的格式,后面的读取数据都是使用这个模式。
1.4 寄存器
1.4.1 配置寄存器
ZMOC:表示了ZPOS和MPOS被永久写入的次数
ZPOS、MPOS、MANG :这些寄存器用于配置起始位置(ZPOS)和停止位置(MPOS)或更窄角度范围的最大角度(MANG)。角度范围必须大于18度。在角范围变窄的情况下,分辨率不会缩放到变窄的范围。
CONF:
1.4.2 输出寄存器
RAW ANGLE寄存器包含未缩放和未修改的角度。缩放后的输出值在ANGLE寄存器中可用。
1.4.3 状态寄存器
STATUS:
AGC:AS5600在闭环中使用自动增益控制来补偿由于温度变化,IC和磁铁之间的气隙以及磁铁退化而引起的磁场强度变化。AGC寄存器表示增益。为了获得最稳健的性能,增益值应该位于其范围的中心。物理系统的气隙可通过调节来达到此值。
MAGNITUDE:表示内部CORDIC的幅度值
1.4.4 Burn指令
Burn_Angle Command (ZPOS, MPOS):主控制器可以用BURN_ANGLE命令对ZPOS和MPOS进行永久编程。要执行BURN_ANGLE命令,请将值0x80写入寄存器0xFF。BURN_ANGLE命令最多可以执行3次。ZMCO显示了ZPOS和MPOS被永久写入的次数。该命令只能在检测到磁铁存在的情况下执行(MD = 1)。
Burn_Setting Command (MANG, CONFIG):主控制器可以使用BURN_SETTING命令执行MANG和CONFIG的永久写入。要执行BURN_SETTING命令,将值0x40写入寄存器0xFF。只有当ZPOS和MPOS从未被永久写入(ZMCO = 00)时,才可以写入MANG。BURN_ SETTING命令只能执行一次。
二、 代码实现
目前使用的IIC读取寄存器的值,来获取角度等信息,所以对OUT口读取数据不再介绍,后续如果使用到的话会再次更新该博客。
目前使用的是模拟IIC读取数据,下面是有关模拟IIC实现读取角度的代码:
IIC读命令:
uint8_t I2C_Read8(uint8_t moni_dev_addr, uint8_t moni_reg_addr, uint8_t moni_i2c_len, uint8_t *moni_i2c_data_buf)
{I2C1_START();I2C1_SendByte(moni_dev_addr << 1 | I2C1_Direction_Transmitter);I2C1_Wait_Ack();I2C1_SendByte(moni_reg_addr);I2C1_Wait_Ack();//Sim_I2C1_STOP();I2C1_START();I2C1_SendByte(moni_dev_addr << 1 | I2C1_Direction_Receiver);I2C1_Wait_Ack();while (moni_i2c_len){if (moni_i2c_len==1) *moni_i2c_data_buf =I2C1_ReceiveByte();else *moni_i2c_data_buf =I2C1_ReceiveByte_WithACK();moni_i2c_data_buf++;moni_i2c_len--;}I2C1_STOP();return 0x00;
}
IIC写命令:
int8_t I2C1_Write8(uint8_t moni_dev_addr, uint8_t moni_reg_addr, uint8_t moni_i2c_len, uint8_t *moni_i2c_data_buf)
{uint8_t i;I2C1_START();I2C1_SendByte(moni_dev_addr << 1 | I2C1_Direction_Transmitter);I2C1_Wait_Ack();I2C1_SendByte(moni_reg_addr);I2C1_Wait_Ack();//Sim_I2C1_START();for (i=0; i<moni_i2c_len; i++){I2C1_SendByte(moni_i2c_data_buf[i]);I2C1_Wait_Ack();}I2C1_STOP(); return 0;
}
读取两个字节:
uint16_t readTwoBytes(uint8_t in_adr_hi, uint8_t in_adr_lo)
{uint16_t retVal = -1;uint8_t low=0,high=0;/* Read Low Byte */low = readOneByte(in_adr_lo);/* Read High Byte */ high = readOneByte(in_adr_hi);//printf("high:%d,low:%d ",high,low);retVal = high << 8;retVal = retVal | low;//printf("retVal:%d\r\n",retVal);return retVal;
}
读取单个字节:
uint8_t readOneByte(uint8_t in_adr)
{uint8_t retVal = -1;I2C_Read8(AS5600_Address,in_adr,1,&retVal);I2C1_NOP;return retVal;
}
IIC获取原始角度:
int16_t getRawAngle(void)
{return readTwoBytes(_raw_ang_hi, _raw_ang_lo);
}
原始角度信息转换为真实角度:
float convertRawAngleToDegrees(int16_t newAngle)
{/* Raw data reports 0 - 4095 segments, which is 0.087 of a degree */ float retVal = newAngle * 0.087;return retVal;
}
效果展示:
原理图和PCB:
二、往期回顾
FOC系列(一)----DRV8301芯片的学习
FOC系列(二)----继续学习DRV8301芯片