AS5048的硬件SPI操作源码

17 篇文章 0 订阅
14 篇文章 3 订阅

调了半天终于调通了,贴出来给有需要的朋友参考下,给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










 

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值