一、AS5047P介绍
AS5047P是14 位同轴磁性旋转位置传感器,集成动态角度误差补偿 (DAEC™)延时极低,同时拥有SPI ABZ PWM UVW多种数据输出方式。
内部寄存器地址及含义:
/*内容随外界变化的寄存器 可读不可写*/
#define NOP_ADDR 0x0000 //启动读取过程寄存器地址
#define ERRFL_ADDR 0x0001 //错误寄存器地址
#define PROG_ADDR 0x0003 //编程寄存器地址
#define DIAAGC_ADDR 0x3FFC //诊断和AGC寄存器地址
#define MAG_ADDR 0x3FFD //CORDIC寄存器地址
#define ANGLEUNC_ADDR 0x3FFE //无动态角度误差补偿的测量角度寄存器地址
#define ANGLECOM_ADDR 0x3FFF //带动态角度误差补偿的测量角度寄存器地址
/*配置选项寄存器 可读可写*/
#define ZPOSM 0x0016
#define ZPOSL 0x0017
#define SETTINGS1 0x0018
#define SETTINGS2 0x0019
二、AS5047P的SPI时序及读写帧格式
1.SPI时序
AS5047P的SPI工作在模式1 ( CPOL=0 CPHA=1 ),即空闲状态下时钟CLK为低电平,在CLK的第二个边沿进行数据采样,片选信号为低电平选中,数据高位先发送 ( MSB ),数据宽度16位,最高可支持10MHz时钟。我们需要严格设置主机配置与其相同
2.偶校验
偶校验就是保证一个数中的位1个数为偶数,AS5047P采用偶校验来保证数据传输的正确性,具体来说其返回的数据最高位15位是偶校验位,当位14-0有偶数个位1那么最高位为0 否则为1,这里有很多方法可以进行判断数据到底有多少位1
unsigned int even_check(unsigned int x)
{
unsigned int count = 0;
//1.计算位1个数
while(x)
{
x = x & (x-1);
count++;
}
//2.奇数个1 返回1 偶数个1 返回0
return (count % 2) == 0 ? 0 : 1;
}
unsigned int even_check(unsigned int v)
{
if(v == 0) return 0;
v ^= v >> 8;
v ^= v >> 4;
v ^= v >> 2;
v ^= v >> 1;
return v & 1;
}
3.读写帧格式
AS50047P拥有三种帧格式,分别为命令帧、读取帧、写入帧
命令帧格式:bit15偶校验位 bit14 R(1)W(0) bit13-0为寄存器地址 该帧由主机发送给AS5047P
读取帧格式:bit15偶校验位 bit14 前一次指令错误(1) bit13-0为读取的数据 该帧由AS5047P返回给主机
写入帧格式:bit15偶校验位 bit14 固定为0 bit13-0为写入的数据 该帧由主机发送给AS5047P
这里我们需要注意SPI为同步通信,主机写入数据同时也会返回数据,但是返回的数据是上一次指令所获取的数据!所以实际的读写操作往往包括连续的两次写入!
读取数据:发送一帧读命令 接着发送一帧读取NOP命令 从而得到我们想要的数据
写入数据:发送一帧写命令,后再发一个数据帧,数据帧发送后得到一个该地址上次的值
三、常用寄存器及错误处理
我们常用的寄存器为ANGLECOM (0x3FFF) 带动态角度误差补偿的测量角度寄存器,ERRFL (0x0001) 错误寄存器,NOP (0x0000)
读取ANGLECOM可以获得角度数据,读取ERRFL会清除错误标记,读取NOP相当于一次空操作,当返回的读数据帧中第高14位为1时说明出现错误,我们需要发送读取ERRFL的帧清除错误
由寄存器地址和读可以生成常用的读取指令:
/*读取数据命令*/
#define READ_ANGLECOM 0xFFFF
#define READ_NOP 0xC000
#define READ_ERRFL 0x4001
四、读取角度及错误处理函数
unsigned int Read_Form_AS5047P(unsigned int cmd)
{
unsigned int data = 0;
(void)send_and_receive_16(cmd);//发送指令
data = send_and_receive_16(READ_NOP);//返回的是上一次命令返回的数据 也就是获取的数据
//3.检查错误及校验
if(data & (1<<14))
{
//有错误 发送清除错误指令
(void)send_and_receive_16(READ_ERRFL);
//获取错误原因
spi_error = send_and_receive_16(READ_NOP);
spi_error = spi_error & 0x0003;
return 0;
}
else//无错误
{
//偶校验最高位 通过则读取数据
if((data>>15) == even_check(data & 0x7FFF))
{
return (data & 0x3FFF);
}
else{return 0;}
}
}
五、实际读取AS5407P角度数据
for(;;)
{
run_flag++;
delay_ms(200);
//读取AS5047的返回值
val = Read_Form_AS5047P(READ_ANGLECOM);
angle = (double)val*360.0/16384.0;
//通过UART打印
(void)printf("AS5047P = %u %.2f\n",val,angle);
}
需要注意没有放置好磁铁与IC上方时,其角度数据是随机值!好了,SPI读取AS5047P数据基本实现了,使用其他类型MCU都是一样的,后面将实现ABZ脉冲的读取