1、测试平台
单片机:CH32V303;使用SPI与AS5047P通讯;磁铁使用径向磁铁。
2、问题现象
使用0X3FFF命令,读取AS5047P数据。其中14bit为0,即数据没有错误。但是得到的数据为从8000多到16000多。在数据16000多后,继续旋转磁铁,数据会跳变到8000多。此时应该是0。
3、问题分析
(1)测试其他芯片
使用ESP32编写程序
#include <Arduino.h>
#include <SPI.h>
#define AS5047P_ANGLECOM 0x3FFF
#define MY_CS 15
#define MY_SCK 14
#define MY_MOSI 13
#define MY_MISO 12 //自定义spi引脚
SPIClass my_spi(HSPI); //创建SPIClass对象my_spi
void spiInit()
{
my_spi.begin(MY_SCK, MY_MISO, MY_MOSI, MY_CS); //初始化,并绑定引脚
spiAttachSS(my_spi.bus(), 0, MY_CS); //绑定cs引脚
my_spi.setFrequency(1000000); //设置频率,1MHz
my_spi.setBitOrder(SPI_MSBFIRST); //设置高位bit先传输
my_spi.setDataMode(SPI_MODE2); //设置spi模式
}
uint16_t readAngleData()
{
// 构造命令帧
// uint16_t cmd = AS5047P_ANGLECOM | (1 << 14); // 设置读命令
// cmd = cmd ^ (0x1 << 15); // 计算偶校验位
uint16_t cmd = 0xffff;
uint16_t uwData;
my_spi.transfer16(cmd);
uwData = my_spi.transfer16(0xc000);
return uwData & 0x3FFF; // 返回有效数据
}
void setup() {
Serial.begin(115200);
spiInit(); // 初始化SPI
// 设置磁编码器参数
// 等待设备稳定
delay(100);
}
void loop() {
uint16_t angleData = readAngleData();
// 将读取的数据转换为角度值
float angle = (angleData * 360.0) / 0x4000;
Serial.print("AngleBin: ");
Serial.println(angleData);
Serial.print("Angle: ");
Serial.println(angle);
delay(1000); // 每秒读取一次
}
烧录至ESP32进行测试,数据仍然错误。
(2)分析AS5047P自身数据
8000~16000,正好是13bit的数据,有点巧,怀疑是不是这个芯片是不是烧过非出厂代码?
调查SETTINGS1寄存器,地址0x0018:
读取SETTINGS1寄存器数据:
printf("SETTINGS1=%d\r\n",AS5047_Read2Byte(0x18|(0x3<<14)));
根据AS5047P的命令格式,计算15bit的偶校验位,为1;14bit的操作位为1(读取)。
读取得
解读:
0bit:工厂设置;预编程为1;
当前值为0;
1bit:未被使用标志;预编程为0,且不可被复写;
当前值为1;
分析:该芯片可能非全新,被烧写过其他程序。
3、验证与解决
在返回AS5047P的数据时,只保留后13bit,即与0x1FFF进行与运算,获取角度信息时:
角度 = 采样值 * 360.f / (float) 0x2000;
即可计算13bit的角度数据。
烧写验证:
旋转一圈;可看出数据正常。
4、最后
本文只针对手上的这一片AS5047P。
若分析有误,欢迎大佬在评论区指正与交流。