调了半天终于调通了,贴出来给有需要的朋友参考下,给stm32写的,硬件SPI:
c文件:
/**
******************************************************************************
* @file AS5048A.c
* @author Lei Liu
* @version V1.0
* @date 2018.03.16
* @brief
******************************************************************************
* @attention
* SCK -- PB13
* MISO -- PB14
* MOSI -- PB15
* CS -- PB12
******************************************************************************
*/
#include "AS5048.h"
#include "stm32f10x.h"
uint8_t error_flag;
//SPI2
void AS5048A_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //Set CS pin high to disable device
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
SPI_Cmd(SPI2, DISABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
DelayUs(500);
}
uint16_t SPI_WriteByte(uint16_t TxData)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
DelayUs(1);
SPI_I2S_SendData(SPI2, TxData);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
DelayUs(1);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
DelayUs(1);
return SPI_I2S_ReceiveData(SPI2);
}
// Calculates even parity of 16it value, returns 1 (odd) or 0 (even)
uint8_t parity_even(uint16_t v)
{
if(v == 0) return 0;
v ^= v >> 8;
v ^= v >> 4;
v ^= v >> 2;
v ^= v >> 1;
return v & 1;
}
uint16_t Read_As5048A_Reg(uint16_t cmd)
{
uint16_t data = 0;
uint16_t res;
uint16_t command = 0x4000;// PAR=0 R/W=R
command = command | cmd;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
SPI_WriteByte(command);
command = 0x4000;// PAR=0 R/W=R
command = command | CMD_NOP;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
res = SPI_WriteByte(command);
error_flag = 1;
if ((res & (1 << 14)) == 0)//判断第14位是否为0,0为正确值
{
data = (res & 0x3FFF);
error_flag = (parity_even(data) ^ (res >> 15));
}
else//读数据错误,发送清错误命令
{
command = 0x4000;
command = command | CMD_CLEAR_ERROR;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
SPI_WriteByte(command);
}
return data;
}
//写寄存器
void Write_As5048A_Reg(uint16_t cmd,uint16_t value)
{
uint16_t data = 0;
uint16_t res;
uint16_t command = 0x0000; // PAR=0 R/W=W
command = command | cmd;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
SPI_WriteByte(command);
command = 0x0000; // PAR=0 R/W=W
command = command | value;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
SPI_WriteByte(command);
command = 0x4000;// PAR=0 R/W=R
command = command | CMD_NOP;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
res = SPI_WriteByte(command);
error_flag = 1;
if ((res & (1 << 14)) == 0)//判断第14位是否为0,0为正确值
{
data = (res & 0x3FFF);
error_flag = (parity_even(data) ^ (res >> 15));
}
else//读数据错误,发送清错误命令
{
command = 0x4000;
command = command | CMD_CLEAR_ERROR;
command |= ((uint16_t)parity_even(command)<<15);//Add a parity bit on the the MSB
SPI_WriteByte(command);
}
}
uint16_t Read_As5048A_Value(uint16_t cmd)
{
uint16_t val;
val = Read_As5048A_Reg(cmd);
if(error_flag)//奇偶校验错误
{
val = 0;
}
return val;
}
/************************************
OTP Write Zero Position: 0 for No error
1. Read angle information
2. Set the Programming Enable bit in the OTP control register
3. Write previous read angle position into OTP zero position register
4. Read back for verification the zero position register data
5. Set the Burn bit to start the automatic programming procedure
6. Read angle information (equals to 0)
7. Set the Verify bit to load the OTP data again into the internal registers with modified threshold comparator levels
8. Read angle information (equals to 0)
******************************************/
uint8_t Write_As5048A_ZeroPosition()
{
uint16_t Angle_val;
uint8_t Angle_High,Angle_Low;
uint16_t cmd;
Angle_val = Read_As5048A_Value(CMD_ANGLE);
cmd=Read_As5048A_Value(CMD_ProgramControl);
Write_As5048A_Reg(CMD_ProgramControl,0x01);
DelayUs(10);
cmd=Read_As5048A_Value(CMD_ProgramControl);
DelayUs(10);
Write_As5048A_Reg(CMD_OTPHigh,Angle_val>>8);
DelayUs(10);
Write_As5048A_Reg(CMD_OTPLow,Angle_val&0xFF);
DelayUs(10);
Angle_High=Read_As5048A_Value(CMD_OTPHigh);
DelayUs(10);
Angle_Low=Read_As5048A_Value(CMD_OTPLow);
DelayUs(10);
if(Angle_High != (uint8_t)(Angle_val>>8))
return 1;
if(Angle_Low != (uint8_t)(Angle_val&0xFF))
return 2;
Write_As5048A_Reg(CMD_ProgramControl,0x09);
DelayUs(10);
cmd=Read_As5048A_Value(CMD_ProgramControl);
DelayUs(10);
Angle_val = Read_As5048A_Value(CMD_ANGLE);
DelayUs(10);
if(Angle_val != 0 )
return 3;
Write_As5048A_Reg(CMD_ProgramControl,0x49);
DelayUs(10);
cmd=Read_As5048A_Value(CMD_ProgramControl);
DelayUs(10);
Angle_val = Read_As5048A_Value(CMD_ANGLE);
DelayUs(10);
if(Angle_val != 0 )
return 4;
return 0;
}
#ifndef __AS5048A_H
#define __AS5048A_H
#include "sys.h"
h文件:
#define CMD_ANGLE 0x3FFF //((1<<15) | (1<<14) | 0x3FFF)//角度信息
#define CMD_READ_MAG 0x3FFE//磁信息
#define CMD_READ_DIAG 0x3FFD //诊断信息
#define CMD_NOP 0x0000 //No operation dummy information
#define CMD_CLEAR_ERROR 0x0001 //错误状态寄存器
#define CMD_ProgramControl 0x0003
#define CMD_OTPHigh 0x0016
#define CMD_OTPLow 0x0017
void AS5048A_Init(void);
uint16_t SPI_WriteByte(uint16_t TxData);
void Write_As5048A_Reg(uint16_t cmd,uint16_t value);
uint8_t parity_even(uint16_t v);
uint16_t Read_As5048A_Reg(uint16_t cmd);
uint16_t Read_As5048A_Value(uint16_t cmd);
uint8_t Write_As5048A_ZeroPosition();//OTP Abandoned
#endif