1.代码思路

给AS5047D发指令,AS5047D回传数据。但是发指令需要注意是16位数据(校验位+读写位+寄存器地址),接收的 数据也是16位数据(校验位+错误位+14绝对位置编码值0~16384)。

硬件连接:

PC8 -> CSN

PC7 -> SCK

PC6 -> MISO

PC0 -> MOSI

2.SPI时序图

3.寄存器地址

4.写指令读数据框架图

5.代码

main.c

#include "main.h"


uint8_t mg_data=0;
uint16_t angle_data=0;
float angle=0;
uint32_t data1=0;

/**
  * @brief  上电初始化
  */
void setup(void)
{
    NVIC_Conflg();
    OLED_Init();
    Key_Init();
    Beep_Init();
    AS5047D_Init();
    
    OLED_ShowString(1,1,"all init");
}


/**
  * @brief  while(1)
  */
void loap(void)
{
    for(;;)
    {
        angle_data = AS5047D_GetAngleComData(); // 0~16384
        angle = (float)angle_data / 16384.0f * 360.0f;
        
        OLED_ShowBinNum(2, 1, angle_data, 16);
        OLED_ShowNum(3, 1, angle_data, 6);
        OLED_ShowFloat(4, 1, angle, 3, 2);
    }
}

AS5047D.h

#ifndef __AS504D_H_
#define __AS5047D_H_

/**** 头文件 ****/
#include "main.h"


/**** 宏定义 ****/



/**** 函数 ****/
void AS5047D_Init(void);
uint16_t AS5047D_GetAngleUncData(void);
uint16_t AS5047D_GetAngleComData(void);


#endif // __AS5047D_H_

AS5047D.c

#include "AS5047D.h"



#define AS5047D_Enable()         GPIOC->BRR  |= GPIO_PIN_8
#define AS5047D_Disable()        GPIOC->BSRR |= GPIO_PIN_8


static void AS5047D_W_SCK(uint8_t bit)
{
	if(bit)
        GPIOC->BSRR |= GPIO_PIN_7;
    else
        GPIOC->BRR |= GPIO_PIN_7;
}

static uint8_t AS5047D_R_MISO(void)
{
	return HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_6);
}

static void AS5047D_W_MOSI(uint8_t bit)
{
	if(bit)
        GPIOC->BSRR |= GPIO_PIN_0;
    else
        GPIOC->BRR |= GPIO_PIN_0;
}

/**
  * @brief  AS5047D 软件SPI 初始化
  */
void AS5047D_Init(void)
{
    __HAL_RCC_GPIOC_CLK_ENABLE();
    
    GPIO_InitTypeDef  GPIO_InitStruct={0};
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_7 | GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
	AS5047D_Disable();
	AS5047D_W_SCK(0);
}

/***********************************************************
*@fuction	: AS5047D_GetAngleUncData
*@brief		: AS5047D 读取无动态补偿角度的原始数据 0~16384
*@param		: None
*@return	: 角度数据 0~16384
*@author	: HongScholar
*@date		: 2025.09.08
***********************************************************/
uint16_t AS5047D_GetAngleUncData(void)
{
    uint16_t tx_data=0; // 校验位 + 读写位 + 寄存器地址
    uint16_t rx_data=0; // 校验位 + 错误位 + 数据
    
    AS5047D_Enable();
    
    /**** 校验位 + 读写位 + 寄存器地址 ****/
    tx_data = (1 << 15) | (1 << 14) | (0x3FFE);
    
    /**** 发命令 ****/
    for (uint8_t i=0; i<16; i++)
	{
		AS5047D_W_MOSI(tx_data & (0x8000 >> i));
		AS5047D_W_SCK(1);
		if(AS5047D_R_MISO() == 1)
        {
            rx_data |= (0x8000 >> i);
        }
		AS5047D_W_SCK(0);
	}
    
    /**** 获取角度信息 ****/
	for (uint8_t j=0; j<16; j++)
	{
        AS5047D_W_MOSI(1);   // 无效数据位
		AS5047D_W_SCK(1);
		if(AS5047D_R_MISO() == 1)
        {
            rx_data |= (0x8000 >> j);
        }
		AS5047D_W_SCK(0);
	}
	
    rx_data &= 0x3fff;    // 高二位不要
    AS5047D_Disable();
    
    return rx_data;
}

/***********************************************************
*@fuction	: AS5047D_GetAngleComData
*@brief		: AS5047D 读取动态补偿角度的原始数据 0~16384
*@param		: None
*@return	: 角度数据 0~16384
*@author	: HongScholar
*@date		: 2025.09.08
***********************************************************/
uint16_t AS5047D_GetAngleComData(void)
{
    uint16_t tx_data=0; // 校验位 + 读写位 + 寄存器地址
    uint16_t rx_data=0; // 校验位 + 错误位 + 数据
    
    AS5047D_Enable();
    
    /**** 校验位 + 读写位 + 寄存器地址 ****/
    tx_data = (0 << 15) | (1 << 14) | (0x3FFF);
    
    /**** 发命令 ****/
    for (uint8_t i=0; i<16; i++)
	{
		AS5047D_W_MOSI(tx_data & (0x8000 >> i));
		AS5047D_W_SCK(1);
		if(AS5047D_R_MISO() == 1)
        {
            rx_data |= (0x8000 >> i);
        }
		AS5047D_W_SCK(0);
	}
    
    /**** 获取角度信息 ****/
	for (uint8_t j=0; j<16; j++)
	{
        AS5047D_W_MOSI(1);   // 无效数据位
		AS5047D_W_SCK(1);
		if(AS5047D_R_MISO() == 1)
        {
            rx_data |= (0x8000 >> j);
        }
		AS5047D_W_SCK(0);
	}
	
    rx_data &= 0x3fff;    // 高二位不要
    AS5047D_Disable();
    
    return rx_data;
}

6.演示视频

软件SPI读取AS5047D的演示视频


路还很长,感谢陪伴...

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐