HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程

HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程


✨stm32使用硬件I2C去读取角度数据,通过STM32CubeMX工具配置工程,读取角度数据,只需要调用一个函数,即可完成数据的读取。了解函数的用法以及从设备地址命令,上手十分快速和简单。

  • 📌AS5600资料:https://pan.baidu.com/s/15UMUH5_ppb2FTju7AJgFyw

📗AS5600寄存器描述

  • 📄AS5600寄存器汇总:
    在这里插入图片描述
  • 🌿ZPOS/MPOS/MANG寄存器:这些寄存器用于配置开始位置(ZPOS)和停止位置(MPOS)或最大角度(MANG)。默认范围为全0到360度,但当配置了一个较窄的范围时,输出的全分辨率将自动缩放到所配置的角度范围。角度范围必须大于18度。
  • 🌿ANGLE/RAW ANGLE 寄存器(0x0c,0x0d):RAW角度寄存器包含未缩放和未修改的角度。缩放后和过滤后的输出值在角度寄存器中可用。(原始值范围:0 - 4095)
  • 🌿ANGLE角度值(0x0e,0x0f):角度值范围:0-360
  • 🌿STATUS 状态寄存器:状态寄存器提供指示AS5600的当前状态的位。(当前磁场强度)
    在这里插入图片描述
  • 🌿AGC寄存器:AS5600在一个闭环中使用自动增益控制来补偿由于温度变化、IC和磁体之间的气隙以及磁体退化而引起的磁场强度的变化。AGC寄存器表示增益。对于最健壮的性能,增益值应该在其范围的中心。物理系统的气隙可以被调整以达到这个值。在5V操作中,AGC范围为0-255次。在3.3V模式下,AGC范围减少到0-128个计数。
  • 🌿MAGNITUDE寄存器:MAGNITUDE寄存器表示内部CORDIC的幅度值。
  • 🌿Burn_Angle命令(ZPOS,MPOS):MCU可以使用BURN_ANGLE命令执行ZPOS和MPOS的永久编程。要执行BURN_ANGLE命令,请将值0x80写入寄存器0xFF。BURN_ANGLE命令最多可以执行3次。ZMCO显示了ZPOS和MPOS被永久写入的多少次。

  • 🌿磁场Bz和典型的间隙
    在这里插入图片描述

典型的间隙在0.5 mm到3 mm之间,这取决于所选的磁铁。一个更大和更强的磁铁允许一个更大的气隙。使用AGC值作为导轨,通过调整磁体与AS5600之间的距离,使AGC值在其范围的中心,可以找到最佳的气隙。当使用直径为6mm的磁铁时,参考磁铁的旋转轴从包装中心的最大允许位移为0.25 mm。

📑功能概要

  • 🖍首先对AS5600设备地址进行扫描,并打印设备地址,然后从指定设备的指定寄存器地址读取2个字节数据。

🛠STM32CubeMX工程配置

  • 🌿勾选I2C,参数默认即可。
    在这里插入图片描述
  • 🌿使能一路串口,方便查看数据信息。

在这里插入图片描述

📙业务代码完善

  • 📄main函数内容:
int main(void)
{

  /* USER CODE BEGIN 1 */

	uint8_t Raw_num[2];
    // Read angular measurements
    uint16_t Angle = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	printf("Scanning I2C bus:\r\n");
	HAL_StatusTypeDef result;
 	uint8_t i;
 	for (i=1; i<128; i++)
 	{
 	  /*
 	   * the HAL wants a left aligned i2c address
 	   * &hi2c1 is the handle
 	   * (uint16_t)(i<<1) is the i2c address left aligned
 	   * retries 2
 	   * timeout 2
		AS5600 i2c address:(0x6c = 0x36 << 1)
 	   */
 	  result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i<<1), 2, 2);
 	  if (result != HAL_OK) // HAL_ERROR or HAL_BUSY or HAL_TIMEOUT
 	  {
 		  printf("."); // No ACK received at that address
 	  }
 	  if (result == HAL_OK)
 	  {
 		  printf("0x%X", i); // Received an ACK at that address
 	  }
 	}
 	printf("\r\n");


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while(1) {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
			HAL_I2C_Mem_Read(&hi2c1, AS5600_SLAVE_ADDRESS, addr_in, I2C_MEMADD_SIZE_8BIT, Raw_num, 2,100);
			int value = (Raw_num[0]<<8)|Raw_num[1];
			Angle = (value * 360)/4096;//换算成角度
        printf("Angle = %d degrees.\n", Angle);
        HAL_Delay(500);
    }
  /* USER CODE END 3 */
}
  • 🔖或者根据上面的寄存器,读取角度寄存器值:HAL_I2C_Mem_Read(&hi2c1, AS5600_SLAVE_ADDRESS, addr_in, I2C_MEMADD_SIZE_8BIT, 0x0e, 2,100);
  • 🌿开启串口打印,在usart.c中添加一下内容:(在调用printf的地方,包含stdio.h头文件,Keil option中勾选MicroLib选项)
#include <stdio.h>
//使用printf()发送数据,需要对printf函数进行重定向,且只能使用USART1。
// 重定向fputc函数,使用printf()发送数据
int fputc(int ch, FILE *f)
{
	// 参数1:串口句柄,参数2:要发送的数据;参数3:要发生数据的长度;参数4:超时等待时间
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100);
	return ch;
}
  • 🔖串口输出:
    -在这里插入图片描述

📚HAL_I2C_Mem_Read(阻塞方式)读取测试工程

  • 🔖基于stm32f103
链接:https://pan.baidu.com/s/1aN1n26SNdVSn6Q1CcaKrgg?pwd=48ok 
提取码:48ok

📗HAL_I2C_Mem_Read_DMA和HAL_I2C_Mem_Read_IT方式读取数据

  • 🔧在STM32CubeMX中,配置I2C时,在DMA选项中,添加RX配置:
    在这里插入图片描述
  • 🌿勾选事件中断
    在这里插入图片描述
  • 🔖完成以上参数内容配置后,在工程代码中可以使用HAL_I2C_Mem_Read_DMAHAL_I2C_Mem_Read_IT函数都可以读取角度原始数据值。
  • 🌿添加读I2C设备是否在线函数。(可以省略,默认只查询一次。)
HAL_StatusTypeDef I2C_WaitUntilDeviceReady(I2C_HandleTypeDef *hi2c,uint16_t DevAddress,uint32_t Timeout){
    uint32_t tickstart = HAL_GetTick();                 //获取当前时间
    while(HAL_GetTick()-tickstart <= Timeout){          //如果没有超时就一直尝试
        if(HAL_I2C_IsDeviceReady(&hi2c1, DevAddress,1, Timeout) == HAL_OK){   //如果准备好了就return
            return HAL_OK;
        }
    }
    return HAL_TIMEOUT;                                 //否则return一个错误
}
  • 🌾main函数内容
int main(void)
{

  /* USER CODE BEGIN 1 */

	uint8_t Raw_num[2];
    // Read angular measurements
    uint16_t Angle = 0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	printf("Scanning I2C bus:\r\n");
	HAL_StatusTypeDef result;
 	uint8_t i;
 	for (i=1; i<128; i++)
 	{
 	  /*
 	   * the HAL wants a left aligned i2c address
 	   * &hi2c1 is the handle
 	   * (uint16_t)(i<<1) is the i2c address left aligned
 	   * retries 2
 	   * timeout 2
		AS5600 i2c address:(0x6c = 0x36 << 1)
 	   */
 	  result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i<<1), 2, 2);
 	  if (result != HAL_OK) // HAL_ERROR or HAL_BUSY or HAL_TIMEOUT
 	  {
 		  printf("."); // No ACK received at that address
 	  }
 	  if (result == HAL_OK)
 	  {
 		  printf("0x%X", i); // Received an ACK at that address
 	  }
 	}
 	printf("\r\n");


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while(1) {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
			if(I2C_WaitUntilDeviceReady(&hi2c1,AS5600_SLAVE_ADDRESS, 5)==HAL_OK)//检测设备是否在线,设置5ms超时
			HAL_I2C_Mem_Read_DMA(&hi2c1, AS5600_SLAVE_ADDRESS, addr_in, I2C_MEMADD_SIZE_8BIT, Raw_num, 2);
			int value = (Raw_num[0]<<8)|Raw_num[1];
			Angle = (value * 360)/4096;//换算成角度
        printf("Angle = %d degrees.\n", Angle);
        HAL_Delay(500);
    }
  /* USER CODE END 3 */
}
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: hal库是一种硬件抽象层,用于在嵌入式系统中简化与硬件的交互。I2C是一种串行通信协议,用于连接微控制器与外部设备。AS5600是一款角度传感器,可以测量角度信息。 在使用hal读取AS5600的过程中,首先需要初始化I2C总线,设置好通信的速率和地址。然后通过hal库提供的函数,发送读取命令给AS5600设备,请求读取角度AS5600设备会通过I2C总线传输角度数据给微控制器。 读取过程中可能还需要检查传输的状态,例如检查设备是否回应,或者确保传输数据的完整性。可以使用hal库提供的函数来执行这些操作。 读取到的角度数据可以按照需求进行处理和利用。可以将角度信息用于控制系统,或者用于监测和记录物体的运动状态。 总的来说,使用hal读取AS5600需要进行I2C总线的初始化,发送读取命令,接收并处理传输的数据。通过这种方式,可以方便地获取AS5600设备的角度信息,并进行相应的处理和应用。 ### 回答2: 使用HAL读取AS5600传感器的I2C数据需要以下步骤: 1. 配置I2C总线:首先,需要调用HAL库的I2C初始化函数,设置I2C总线的时钟速率、I2C地址模式和GPIO引脚配置等。例如: ```c I2C_HandleTypeDef hi2c; hi2c.Instance = I2C1; hi2c.Init.Timing = 0x00303D5B; hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c.Init.OwnAddress1 = 0; hi2c.Init.OwnAddress2 = 0; hi2c.Init.OwnAddress2Masks = I2C_OA2_NOMASK; hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; ... HAL_I2C_Init(&hi2c); ``` 2. 发送I2C开始信号并选择从设备地址:调用HAL库的函数发送I2C开始信号,并选择AS5600传感器的从设备地址。例如,如果AS5600的地址是0x36: ```c uint8_t devAddr = 0x36; HAL_I2C_Master_Transmit(&hi2c, devAddr << 1, NULL, 0, 1000); ``` 3. 发送寄存器地址:根据AS5600的寄存器地址,调用HAL库的函数发送寄存器地址。例如,如果要读取寄存器0x03的值: ```c uint8_t regAddr = 0x03; HAL_I2C_Master_Transmit(&hi2c, devAddr << 1, &regAddr, 1, 1000); ``` 4. 读取数据:使用HAL库的函数读取AS5600传感器返回的数据。例如,读取一个字节的数据: ```c uint8_t data; HAL_I2C_Master_Receive(&hi2c, devAddr << 1, &data, 1, 1000); ``` 以上就是使用HAL读取AS5600传感器的I2C数据的基本步骤。根据实际需要,还可以添加错误处理、超时控制等。请根据具体项目和硬件环境进行适当的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值