Files
Gamble/MPU6050/APP/AS5600.c
2023-12-18 14:36:22 +08:00

170 lines
4.7 KiB
C
Raw Permalink Blame History

#include "as5600.h"
#include "math.h"
#define cpr 4096
float full_rotation_offset;
long angle_data_prev;
unsigned long velocity_calc_timestamp;
float angle_prev;
/******************************************************************************/
void I2C_Init_(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//GPIOB
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0; //I2C_OAR1
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000; //400KHz
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
}
/******************************************************************************/
/******************************************************************************/
#define AS5600_Address 0x36
#define RAW_Angle_Hi 0x0C
/******************************************************************************/
unsigned short I2C_getRawCount(I2C_TypeDef* I2Cx)
{
uint32_t Timeout;
unsigned short temp;
unsigned char dh,dl;
Timeout = 0xFFFF;
I2Cx->CR1 |= 0x0100;//CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)return 0;
}
/* Send the slave address, Reset the address bit0 for write*/
I2Cx->DR = AS5600_Address<<1;
Timeout = 0xFFFF;
/* Wait until ADDR is set: EV6 */
while ((I2Cx->SR1 &0x0002) != 0x0002)
{
if (Timeout-- == 0)return 0;
}
/* Clear ADDR flag by reading SR2 register */
temp = I2Cx->SR2;
/* Write the first data in DR register (EV8_1) */
I2Cx->DR = RAW_Angle_Hi;
/* EV8_2: Wait until BTF is set before programming the STOP */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/////////////////////////////////////////////////////////////////////////
/* Set POS bit */
I2Cx->CR1 |= 0x0800;//CR1_POS_Set;
Timeout = 0xFFFF;
/* Send START condition */
I2Cx->CR1 |= 0x0100;//CR1_START_Set;
/* Wait until SB flag is set: EV5 */
while ((I2Cx->SR1&0x0001) != 0x0001)
{
if (Timeout-- == 0)return 0;
}
Timeout = 0xFFFF;
/* Send slave address */
I2Cx->DR = (AS5600_Address<<1)+1;
/* Wait until ADDR is set: EV6 */
while ((I2Cx->SR1&0x0002) != 0x0002)
{
if (Timeout-- == 0)return 0;
}
/* EV6_1: The acknowledge disable should be done just after EV6,
that is after ADDR is cleared, so disable all active IRQs around ADDR clearing and
ACK clearing */
__disable_irq();
/* Clear ADDR by reading SR2 register */
temp = I2Cx->SR2;
/* Clear ACK */
I2Cx->CR1 &= 0xFBFF;//CR1_ACK_Reset;
/*Re-enable IRQs */
__enable_irq();
/* Wait until BTF is set */
while ((I2Cx->SR1 & 0x00004) != 0x000004);
/* Disable IRQs around STOP programming and data reading because of the limitation ?*/
__disable_irq();
/* Program the STOP */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* Read first data */
dh = I2Cx->DR;
/* Re-enable IRQs */
__enable_irq();
/**/
/* Read second data */
dl = I2Cx->DR;
/* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
while ((I2Cx->CR1&0x200) == 0x200);
/* Enable Acknowledgement to be ready for another reception */
I2Cx->CR1 |= 0x0400;//CR1_ACK_Set;
/* Clear POS bit */
I2Cx->CR1 &= 0xF7FF;//CR1_POS_Reset;
temp++; //useless,otherwise warning
return ((dh<<8)+dl);
}
/******************************************************************************/
void MagneticSensor_Init(void)
{
// angle_data_prev = I2C_getRawCount(I2C1);
full_rotation_offset = 0;
velocity_calc_timestamp=0;
}
//<2F><>
float getAngle(void)
{
float angle_data,d_angle;
angle_data = I2C_getRawCount(I2C1);
d_angle = angle_data - angle_data_prev;
if(fabs(d_angle) > (0.8*cpr) ) full_rotation_offset += d_angle > 0 ? -_2PI : _2PI;
angle_data_prev = angle_data;
return (full_rotation_offset + ( angle_data / (float)cpr) * _2PI) ;
}
/******************************************************************************/
float getVelocity(void)
{
unsigned long now_us;
float Ts, angle_c, vel;
now_us = SysTick->VAL;
if(now_us<velocity_calc_timestamp)Ts = (float)(velocity_calc_timestamp - now_us)/9*1e-6;
else
Ts = (float)(0xFFFFFF - now_us + velocity_calc_timestamp)/9*1e-6;
if(Ts == 0 || Ts > 0.5) Ts = 1e-3;
angle_c = getAngle();
vel = (angle_c - angle_prev)/Ts;
angle_prev = angle_c;
velocity_calc_timestamp = now_us;
return vel;
}
/******************************************************************************/