前言
在BLDC控制算法中需要频繁进行三角函数运算,通常的做法是查表法,但是查表法精度受限于表格大小,表格越大颗粒度越小精度越小,但是需要存储越多,所以精度一般。
ACM32F40正是应BLDC控制而生,具备硬件算数加速,支持24 位 CORDIC 旋转引擎,支持 sin/cos/atan2 函数,非常适合这类应用。
代码
HAL_FAU_20210325.lib
HAL_FAU.h
HAL_CORDIC_CosSin_1~HAL_CORDIC_CosSin_8
其中输入参数:以弧度为单位的角度值(除以p ,Q31 格式)
输出参数:cos和sin的值(范围[-1,1],Q31 格式)
HAL_CORDIC_AtanSqrt_1~HAL_CORDIC_AtanSqrt_8
输入参数x 方向坐标值(如果|x|>1,那么必须对其进行缩放以使其范围在[-1,1],Q31 格式)
输入参数y 方向坐标值(如果|y|>1,那么必须对其进行缩放以使其范围在[-1,1],Q31 格式)
输出参数xy 代表向量的长度(Q31 格式)
输出参数xy 代表向量的角度(Q31 格式)
8个函数分别对应1~8级精度
Q31 格式中,数字由1 个符号位和31 个二进制小数位表示,因此数字范围是- 1(0x80000000)到1-2 ^31(0x7FFFFFFF) 。
例如0.5 转换成Q31 格式为:0.5* 2^31=1073741824=0x40000000
简单理解就是左移31位放大2^31。
测试
以最高精度函数
HAL_CORDIC_CosSin_8
和ARM DSP的库
void arm_sin_cos_q31(
q31_t theta,
q31_t * pSinVal,
q31_t * pCosVal);
函数进行对比。
进行4组测试数据测试,没组测试数据测试10000000万次。
测试
基于\ModulesDemo\FAU\demo工程
代码如下
/***********************************************************************
* All rights reserved.
* Filename : app.c
* Description : function demo
* Author(s) : eric
* version : 1.0
* Modify date : 2015-02-02
***********************************************************************/
#include "app.h"
#include "stdlib.h"
#include "math.h"
#include "arm_math.h"
extern unsigned int gu32_SystemCount;
void armdsp_cossin_test(unsigned int num)
{
int i;
int cos_value,sin_value;
const int angle_test_data[4] = {0x85b05b00,0xc05b05c0,0xf05b05b0,0x405b0580};
const int cossin8_expect[8]={0x813ee530,0xee2f9460,0x011df430,0x80013f40,0x76adf5a0,0xd00ce370,0xfee20de0,0x7ffec0b0};
int flag=0;
unsigned int t0 = gu32_SystemCount;
unsigned int t1;
for(i=0;i<10000000;i++)
{
arm_sin_cos_q31(angle_test_data[num], &sin_value,&cos_value);
//if(cos_value!=cossin8_expect[i<<1])
//{
// printf("cos error 8: %d cos_value is 0x%.08x\r\n",i,cos_value);
// flag=1;
//}
//if(sin_value!=cossin8_expect[(i<<1)+1])
//{
// printf("sin error 8: %d sin_value is 0x%.08x\r\n",i,sin_value);
// flag=1;
//}
}
t1 = gu32_SystemCount;
//if(flag)
//{
// flag = 0;
// printf("cos/sin test error\n");
//}
//else
//{
// printf("cos/sin test success\n");
//}
printf("armdsp:\t%8d mS %#-8x,%#-8x,%#-8x,\r\n",t1-t0,angle_test_data[num],cos_value,sin_value);
}
void cordic_cossin_test(unsigned int num)
{
int i;
int cos_value,sin_value;
const int angle_test_data[4] = {0x85b05b00,0xc05b05c0,0xf05b05b0,0x405b0580};
const int cossin8_expect[8]={0x813ee530,0xee2f9460,0x011df430,0x80013f40,0x76adf5a0,0xd00ce370,0xfee20de0,0x7ffec0b0};
int flag=0;
unsigned int t0 = gu32_SystemCount;
unsigned int t1;
for(i=0;i<10000000;i++)
{
HAL_CORDIC_CosSin_8(angle_test_data[num],&cos_value, &sin_value);
//if(cos_value!=cossin8_expect[i<<1])
//{
// printf("cos error 8: %d cos_value is 0x%.08x\r\n",i,cos_value);
// flag=1;
//}
//if(sin_value!=cossin8_expect[(i<<1)+1])
//{
// printf("sin error 8: %d sin_value is 0x%.08x\r\n",i,sin_value);
// flag=1;
//}
}
t1 = gu32_SystemCount;
//if(flag)
//{
// flag = 0;
// printf("cos/sin test error\n");
//}
//else
//{
// printf("cos/sin test success\n");
//}
printf("fau:\t%8d mS %#-8x,%#-8x,%#-8x,\r\n",t1-t0,angle_test_data[num],cos_value,sin_value);
}
void cordic_test(void)
{
for(int i=0;i<4;i++)
{
printf("\r\n\r\ntest case %d\r\n",i+1);
cordic_cossin_test(i);
armdsp_cossin_test(i);
}
}
测试结果如下
可以看到两者有一点差异待确认
从计算时间来看硬件加速只有armdsp库运算时间的1/4左右,所以提升非常明显。
总结
FAU 硬件加速算法库为BLDC控制算法而生,速度提升非常明显,非常适合BLDC控制等需要频繁三角运算的场景。