使用STM32F103C8T6驱动磁编码器AS5600

老小孩
原创
发布时间: 2025-07-26 15:20:53 | 阅读数 0收藏数 0评论数 0
封面
最近在网上又发现一个好玩的模块-磁编码器AS5600。以前一直是用旋转编码器来读取一些需要标记的旋转角度,偶然间发现了这个模块,买了2个,今天趁着兴趣的热度,实验一把。接下来我们用 STM32F103C8T6 驱动磁编码器 AS5600,并且从串口观察它的变化。
1

材料

从网上下单的2套模块,手里又STM32C8T6单片机,还需要USB串口线,拿一个圆柱体的小棍,在顶部用胶水贴上模块的配套磁铁,一会测试用(这样旋转磁铁方便一些),OK,家伙什齐全,开整。

2

硬件连接

商家没有给数据手册,只有一个原理图的截图,又搜了下网络。它是用IIC驱动的,用IIC写和读

硬件连接:

VDD GND 不用说之间对联即可,SCK SDA 和单片机的 SCK SDA 引脚直连,我用的是硬件IIC口,PB6 PB7,然后就是用串口线连接电脑和单片机。在电脑上打开STC-ISP的烧录软件,它上面自带一个串口助手。

3

软件

用KEIL5新建工程,然后新建 as5600.c 和 as5600.h 文件,串口的代码就不再多讲了,我用的是正点原子的串口代码。开始写代码。先写IIC的部分,再写AS5600编码器部分。

IIC代码:

/**

* @brief I2C 外设配置

*/

void I2C_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

I2C_InitTypeDef I2C_InitStructure;

// 1. 开启时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

// 2. 配置I2C引脚为开漏输出

GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(I2C_PORT, &GPIO_InitStructure);

// 3. I2C参数配置

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // I2C模式

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 占空比50%

I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 主机地址(任意)

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // 使能ACK

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7位地址

I2C_InitStructure.I2C_ClockSpeed = I2C_CLK_SPEED; // 时钟速度

I2C_Init(I2Cx, &I2C_InitStructure);

I2C_Cmd(I2Cx, ENABLE); // 使能I2C

}



编码器代码:

/**

* @brief 从AS5600读取角度值

* @retval 12位角度数据(0-4095)

*/

uint16_t AS5600_ReadAngle(void)

{

uint8_t reg_addr = AS5600_ANGLE_REG_H; // 起始寄存器地址

uint8_t buffer[2] = {0}; // 存储读取数据

uint16_t angle = 0;

// 1. 发送起始条件

I2C_GenerateSTART(I2Cx, ENABLE);

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

// 2. 发送设备地址(写操作)

I2C_Send7bitAddress(I2Cx, AS5600_ADDRESS << 1, I2C_Direction_Transmitter);

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

// 3. 发送要读取的寄存器地址

I2C_SendData(I2Cx, reg_addr);

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

// 4. 发送重复起始条件(重启)

I2C_GenerateSTART(I2Cx, ENABLE);

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

// 5. 发送设备地址(读操作)

I2C_Send7bitAddress(I2Cx, AS5600_ADDRESS << 1, I2C_Direction_Receiver);

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

// 6. 读取高字节(带ACK)

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));

buffer[0] = I2C_ReceiveData(I2Cx);

// 7. 读取低字节(带NACK)

I2C_AcknowledgeConfig(I2Cx, DISABLE); // 发送NACK

I2C_GenerateSTOP(I2Cx, ENABLE); // 准备停止条件

while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));

buffer[1] = I2C_ReceiveData(I2Cx);

// 8. 重新使能ACK

I2C_AcknowledgeConfig(I2Cx, ENABLE);

// 9. 组合12位角度数据

angle = ((uint16_t)buffer[0] << 8) | buffer[1]; // 合并高低字节

angle = angle & 0x0FFF; // 屏蔽高4位

return angle; // 返回0-4095的角度值

}


然后在main.c 中轮询检测IIC读到的角度值,用一个变量存个BUFF,然后检测它和备份的有没有改变,如果有就用串口发送到电脑端。用串口助手观看结果。

main.c代码:

#include "sys.h"

#include "led.h"

#include "key.h"

#include "usart.h"

#include "delay.h"

#include "as5600.h"




int main(void)

{

u16 angle = 0;

u16 angleBuff = 0;



LED_Init();

delay_init();

KEY_Init();

I2C_Configuration();

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断分组

uart_init(9600);



while(1)

{

angle = AS5600_ReadAngle(); // 读取角度值

if(angleBuff != angle)

{

// 例如: 通过串口输出角度值或控制电机

printf("角度值是:%d", angle);

// USART1->DR = angle>>4;

// USART1->DR = angle&0x0F;




while((USART1->SR&0X40)==0); //等待发送结束

angleBuff = angle;

}




LED_Flashing(300); //闪烁 LED,提示系统正在运行.

// delay_ms(100);



}

}




4

烧录上机测试

编译代码没有错误的话,就可以上机了。

打开电脑端的STC-ISP软件,打开串口调试助手,然后拿刚才自制的测试手棒开始测试。可以看到它返回的数据在0---4096之间,对应360度封闭圆环的角度。实验顺利通过。

因为这个模块芯片里有一个磁场产生器和一个霍尔磁场检测器,所以对机械贴合度,要求精确。咱们是手拿着精度差的太远,所以看到的值飘忽不定。属于正常现象。只要范围在0---4096之间,表示驱动时没有问题的。

阅读记录0
点赞0
收藏0
禁止 本文未经作者允许授权,禁止转载
猜你喜欢
评论/提问(已发布 0 条)
评论 评论
收藏 收藏
分享 分享
pdf下载 下载