调了半天终于调通了,贴出来给有需要的朋友参考下,给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
上一篇:SCA100T STM32代码
下一篇:STM32F0系列Hal库SPI库BUG
推荐阅读最新更新时间:2024-11-17 00:21
设计资源 培训 开发板 精华推荐
- 用于 MCU 系统负载感应的 NCP300LSN44T1 4.4V 电压检测器的典型应用
- PCF8574APWR 接口 - I/O 扩展器方案验证板
- LT1634CCZ-5 微功率电压和电流基准的典型应用
- LTC2150CUJ-12 单通道、12 位、170Msps ADC 的典型应用电路
- 基于 LTC4410 的 USB 兼容充电器充分利用 USB 输入的可用功率
- AD9788-DPG2-EBZ,使用 AD9788 双通道、16 位、800 MSPS DAC 和低功耗 32 位复杂 NCO 的评估板
- LTC3624IDD-23.3 3.3V 输出电压、2A 同步降压稳压器、同步至 500kHz、强制连续模式的典型应用
- 使用 Analog Devices 的 LTC3126IFE 的参考设计
- DC2001A,使用 LTC3787EUFD、4 相大电流同步升压转换器的演示板
- AL9910EV12,基于 AL9910 85VAC-277VAC 不可调光 LED 驱动器的评估板