最近在学习AS5600的使用,在STM32F4上,便记录一下。如有问题欢迎指出。
AS5600是一个易于编程的磁性旋转位置传感器,具有高分辨率的12位模拟或PWM输出。这种非接触式系统测量一个直径磁化的轴上磁铁的绝对角度。该AS5600是为非接触式电位计的应用而设计的,其稳健的设计消除了任何均匀的外部杂散磁场的影响。
行业标准的I²C接口支持简单的非易失性参数的用户编程。
默认情况下,输出表示从0到360度的范围。还可以通过编程零角度(起始位置)和最大角度(停止位置)来定义更小的输出范围。
AS5600还配备了智能低功耗模式功能,以自动降低功耗。
输入引脚(DIR)根据旋转方向选择输出的极性。如果DIR连接到地面,则输出值随顺时针旋转而增加。如果DIR连接到VDD,则输出值随逆时针旋转而增加。
Functional Blocks of AS5600
![](https://i-blog.csdnimg.cn/blog_migrate/ad25775c7eb0657d31ce082d97b24ad1.png)
SOIC-8 Pin-Out
![](https://i-blog.csdnimg.cn/blog_migrate/08f39bed6a973002675ca8b9be639934.png)
#define AS5600_Address 0x36
#define RAW_Angle_Hi 0x0C
uint16_t ReadAS5600(void)
{
unsigned char dh,dl;
IIC_Start(IIC1);
IIC_Send_Byte(IIC1,AS5600_Address<<1);
IIC_Wait_Ack(IIC1);
IIC_Send_Byte(IIC1,RAW_Angle_Hi);
IIC_Wait_Ack(IIC1);
IIC_Start(IIC1);
IIC_Send_Byte(IIC1,(AS5600_Address<<1)+1);
IIC_Wait_Ack(IIC1);
dh=IIC_Read_Byte(IIC1,1);
dl=IIC_Read_Byte(IIC1,0);
IIC_Stop(IIC1);
return ((dh<<8)+dl);
}
value = ReadAS5600() & 0x0FFF;//打印即可
#define SDA0_IN() \
{ \
GPIOC->MODER &= ~(3 << (6 * 2)); \
GPIOC->MODER |= 0 << (6 * 2); \
}
#define READ_SDA0 (GPIOC->IDR & (1 << 6))
void IIC_Start(uint8_t iic_num)
{
if (iic_num == IIC0){
SDA0_OUT();
IIC0_SDA_H;
IIC0_SCL_H;
delay_s(IIC_DELAY_CNT); //延时8
IIC0_SDA_L;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_L;
}else if (iic_num == IIC1){
SDA1_OUT();
IIC1_SDA_H;
IIC1_SCL_H;
delay_s(IIC_DELAY_CNT); //延时8
IIC1_SDA_L;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_L;
}
}
void IIC_Stop(uint8_t iic_num)
{
if (iic_num == IIC0){
SDA0_OUT();
IIC0_SCL_L;
IIC0_SDA_L;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_H;
IIC0_SDA_H;
delay_s(IIC_DELAY_CNT);
}else if (iic_num == IIC1){
SDA1_OUT();
IIC1_SCL_L;
IIC1_SDA_L;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_H;
IIC1_SDA_H;
delay_s(IIC_DELAY_CNT);
}
}
unsigned char IIC_Wait_Ack(uint8_t iic_num)
{
unsigned char ucErrTime = 0;
if (iic_num == IIC0){
IIC0_SDA_H;
delay_s(1);
SDA0_IN();
IIC0_SCL_H;
delay_s(IIC_DELAY_CNT >> 1);
while (READ_SDA0 != 0){
if (++ucErrTime > 250){
IIC_Stop(iic_num);
return 1;
}
}
IIC0_SCL_L;
}else if (iic_num == IIC1){
IIC1_SDA_H;
delay_s(1);
SDA1_IN();
IIC1_SCL_H;
delay_s(IIC_DELAY_CNT >> 1);
while (READ_SDA1 != 0){
if (++ucErrTime > 250){
IIC_Stop(iic_num);
return 1;
}
}
IIC1_SCL_L;
}
return 0;
}
void IIC_Ack(uint8_t iic_num)
{
if (iic_num == IIC0){
IIC0_SCL_L;
SDA0_OUT();
IIC0_SDA_L;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_H;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_L;
}else if (iic_num == IIC1){
IIC1_SCL_L;
SDA1_OUT();
IIC1_SDA_L;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_H;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_L;
}
}
void IIC_NAck(uint8_t iic_num)
{
if (iic_num == IIC0){
IIC0_SCL_L;
SDA0_OUT();
IIC0_SDA_H;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_H;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_L;
}else if (iic_num == IIC1){
IIC1_SCL_L;
SDA1_OUT();
IIC1_SDA_H;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_H;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_L;
}
}
void IIC_Send_Byte(uint8_t iic_num, unsigned char txd)
{
unsigned long i;
if (iic_num == IIC0){
SDA0_OUT();
IIC0_SCL_L;
for (i = 0; i < 8; i++){
if ((txd & 0x80) != 0)
IIC0_SDA_H;
else
IIC0_SDA_L;
txd <<= 1;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_H;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_L;
delay_s(IIC_DELAY_CNT);
}
}else if (iic_num == IIC1){
SDA1_OUT();
IIC1_SCL_L;
for (i = 0; i < 8; i++){
if ((txd & 0x80) != 0)
IIC1_SDA_H;
else
IIC1_SDA_L;
txd <<= 1;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_H;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_L;
delay_s(IIC_DELAY_CNT);
}
}
}
unsigned char IIC_Read_Byte(uint8_t iic_num, unsigned char ack)
{
unsigned char i, rcv = 0;
if (iic_num == IIC0){
SDA0_IN();
for (i = 0; i < 8; i++){
IIC0_SCL_L;
delay_s(IIC_DELAY_CNT);
IIC0_SCL_H;
rcv <<= 1;
if (READ_SDA0 != 0)
rcv++;
delay_s(IIC_DELAY_CNT >> 1);
}
}else if (iic_num == IIC1){
SDA1_IN();
for (i = 0; i < 8; i++){
IIC1_SCL_L;
delay_s(IIC_DELAY_CNT);
IIC1_SCL_H;
rcv <<= 1;
if (READ_SDA1 != 0)
rcv++;
delay_s(IIC_DELAY_CNT >> 1);
}
}
if (!ack)
IIC_NAck(iic_num);
else
IIC_Ack(iic_num);
return rcv;
}