一、DMA的应用
有关更多DMA的应用,详见【STM32+HAL】DMA应用
二、HAL库配置
1、开启I2C
开启对应DMA及中断
2、开启串口通信
至此,HAL库配置完毕
三、DMA版(高效但不稳定)
1、as5600.c
#include "AS5600.h"
#include "math.h"float angle_prev=0;
int full_rotations=0; // full rotation tracking;
uint8_t data[2]={0};float x1;
float x2;//发送单字节时序
void AS5600_Write_Reg(uint16_t reg, unsigned char value)
{HAL_I2C_Mem_Write(&hi2c1, AS5600_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, &value, 1, 50);
}//发送多字节时序
void AS5600_Write_Regs(uint16_t reg, unsigned char *value, unsigned char len)
{HAL_I2C_Mem_Write(&hi2c1, AS5600_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, value, len, 50);
}//IIC读多字节
void AS5600_Read_DMA(uint8_t regAddress, uint8_t* pData, uint16_t Size) {// 启动I2C DMA接收if (HAL_I2C_Mem_Read_DMA(&hi2c1, AS5600_ADDRESS, regAddress, I2C_MEMADD_SIZE_8BIT, pData, Size) != HAL_OK) {// 错误处理,例如打印错误信息printf("I2C DMA read failed\r\n");}
}//得到弧度制的角度,范围在0-6.28
float GetAngle_Without_Track(void)
{float angle_d;int16_t in_angle;
// AS5600_Read_DMA( Angle_Hight_Register_Addr, data, DATA_SIZE);in_angle = ((int16_t)data[0] <<8) | (data[1]);angle_d = (float)in_angle * (2.0f*PI) / 4096;return angle_d;//angle_d为弧度制,范围在0-6.28
}//得到弧度制的带圈数角度
float GetAngle(void)
{float val = GetAngle_Without_Track();float d_angle = val - angle_prev;//计算旋转的总圈数//通过判断角度变化是否大于80%的一圈(0.8f*6.28318530718f)来判断是否发生了溢出//如果发生了,则将full_rotations增加1(如果d_angle小于0)或减少1(如果d_angle大于0)。if(fabs(d_angle) > (0.8f*2.0f*PI) ) full_rotations += ( d_angle > 0 ) ? -1 : 1;angle_prev = val;return (float)full_rotations * 2.0f * PI + angle_prev;
}// DMA传输完成回调函数
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {if (hi2c->Instance == I2C1) {x1=GetAngle_Without_Track();x2=GetAngle();// 重新启动DMA接收以实现连续读取AS5600_Read_DMA( Angle_Hight_Register_Addr, data, DATA_SIZE);}
}
2、main.c
/* USER CODE BEGIN Includes */
#include "AS5600.h"
#include "stdio.h"
/* USER CODE END Includes *//* USER CODE BEGIN PV */
extern uint8_t data[2];extern float x1;
extern float x2;
/* USER CODE END PV *//* USER CODE BEGIN 2 */printf("Hello World\r\n");HAL_Delay(500);AS5600_Read_DMA(Angle_Hight_Register_Addr, data, DATA_SIZE); // 启动I2C DMA接收/* USER CODE END 2 *//* USER CODE BEGIN WHILE */while (1){printf("degree:%.4f\r\n",x1);printf("circle:%.4f\r\n",x2);HAL_Delay(50);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
四、不用DMA版(低效率但稳定)
1、AS5600.c
#include "AS5600.h"
#include "math.h"float angle_prev=0;
int full_rotations=0; // full rotation tracking;
float angle_d; //GetAngle_Without_Track()的返回值
float angle_cd; //GetAngle()的返回值//发送单字节时序
void AS5600_Write_Reg(uint16_t reg, uint8_t *value)
{HAL_I2C_Mem_Write(&hi2c1, AS5600_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, value, 1, 50);
}//发送多字节时序
void AS5600_Write_Regs(uint16_t reg, uint8_t *value, uint8_t len)
{HAL_I2C_Mem_Write(&hi2c1, AS5600_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, value, len, 50);
}//IIC读多字节
void AS5600_Read_Reg(uint16_t reg, uint8_t* buf, uint8_t len)
{HAL_I2C_Mem_Read(&hi2c1, AS5600_ADDRESS, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 50);
}//得到弧度制的角度,范围在0-6.28
float GetAngle_Without_Track(void)
{ int16_t in_angle;uint8_t temp[DATA_SIZE]={0};AS5600_Read_Reg( Angle_Hight_Register_Addr, temp, DATA_SIZE);in_angle = ((int16_t)temp[0] <<8) | (temp[1]);angle_d = (float)in_angle * (2.0f*PI) / 4096;
//angle_d为弧度制,范围在0-6.28 return angle_d;
}//得到弧度制的带圈数角度
float GetAngle(void)
{float val = angle_d;float d_angle = val - angle_prev;//计算旋转的总圈数//通过判断角度变化是否大于80%的一圈(0.8f*6.28318530718f)来判断是否发生了溢出,如果发生了,则将full_rotations增加1(如果d_angle小于0)或减少1(如果d_angle大于0)。if(fabs(d_angle) > (0.8f*2.0f*PI) ) full_rotations += ( d_angle > 0 ) ? -1 : 1; angle_prev = val;angle_cd = full_rotations * (2.0f*PI) + angle_prev;return angle_cd;
// return (float)full_rotations * 6.28318530718f + angle_prev;
}void Track(void)
{GetAngle_Without_Track();GetAngle();
}
2、main.c
/* USER CODE BEGIN PV */
extern uint8_t data[2];extern float angle_d; //GetAngle_Without_Track()的返回值
extern float angle_cd; //GetAngle()的返回值
/* USER CODE END PV *//* USER CODE BEGIN WHILE */while (1){Track();printf("%.3f %.3f\r\n",angle_d,angle_cd);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}
五、巨人之肩
STM32 HAL库 AS5600编码器程序
六、源码提供
资源【STM32+HAL】I2C+DMA读取AS5600编码器
【STM32+HAL】I2C读取AS5600编码器【不加DMA版本】