如果用数学库中的sin和cos函数计算,可能涉及浮点、乘法、除法运算,运行速率较低。这里介绍一种正余弦查表算法。

  • 参考代码:SMT32 FOC电机库的mc_math.c

首先我们知道正弦和余弦的函数值差了90°,所以查表数据只需要保存正弦或者余弦的结果即可。待计算的角度范围为[0,2π],我们只需要保存的角度,其它象限的角度通过三角函数公式变换一下即可。

1 原理与实现步骤

(1)正余弦表格生成

第一步当然是保存范围内正余弦函数的值,保存的越多计算结果越精确,但又消耗更多的存储空间。在STM32电机库中采用int16类型表示角度,其中(0,32767]表示(0°,180°],[-32768,0]表示(180°,360°],同时为了避免浮点运算,这里采用Q15格式表示角度。之所以是Q15是因为保存的是 范围内正余弦函数的值,后续转换到别的象限还有正负号,故最后求出来的正余弦值也可以用int16范围变量表示。

这里将范围内的角度细分为256份,整个周期就细分了1024份。故将保存为表格,正余弦结果表格生成程序如下

#include <stdio.h>
#include <math.h>
#define NUM  256
#define PI   3.1415926535898fint main()
{int i;for(i = 0; i < NUM; i++){printf("0x%04X,", (unsigned short)((sin(PI/2*i/NUM)) * 32768));if((i+1) % 8==0){putchar('\n');}}return 0;
}

(2)索引获取

输入的角度为int16范围的hAngle,作如下处理,求对应角度的索引:

int32_t shindex;
uint16_t uhindex;
shindex = ( ( int32_t )32768 + ( int32_t )hAngle );
uhindex = ( uint16_t )shindex;
uhindex /= ( uint16_t )64;

shindex是一个包含四个象限范围的值,将四个象限共细分为=65536份,每个象限有=4096个数。但基于存储空间考虑,在前面生成的正余弦表中,我们将一个象限细分为256份,则四个象限共细分为1024份,所以除以。此时可以根据最高两位判断角度所在的象限,同时将这个数取余256,就是该角度所对应在正余弦表中的索引。

(3)判断角度范围

前面代码中,将int16的角度转为正数,此时[0,32768)表示(180°,360°],(32768,65535]表示[0,180°) ,前面又除以了一个64,故十进制数范围和其对应的角度范围如下表所示:

十进制数范围 角度范围
(0,256) (180°,270°)
(256,512) (270°,360°)
(512,768) (0°,90°)
(768,1024) (90°,180°)

故角度和SIN_MASK相与,判断最高两位就可以知道输入角度的范围。

#define SIN_MASK        0x0300u
#define U0_90           0x0200u
#define U90_180         0x0300u
#define U180_270        0x0000u
#define U270_360        0x0100u

(4)查表求角度

这里的索引将uint16类型的变量uhindex强制转化为uint8范围,实际上就是对256取余,等价于uhindex % 256。然后就是直接查表了,由于前面建立的表中角度是(0°,90°)范围内的,所以根据三角函数公式转换其它象限的角度到这个范围内即可求出。

switch ( ( uint16_t )( uhindex ) & SIN_MASK ){case U0_90:Local_Components.hSin = hSin_Cos_Table[( uint8_t )( uhindex )];Local_Components.hCos = hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];break;case U90_180:Local_Components.hSin = hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];Local_Components.hCos = -hSin_Cos_Table[( uint8_t )( uhindex )];break;case U180_270:Local_Components.hSin = -hSin_Cos_Table[( uint8_t )( uhindex )];Local_Components.hCos = -hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];break;case U270_360:Local_Components.hSin =  -hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];Local_Components.hCos =  hSin_Cos_Table[( uint8_t )( uhindex )];break;default:break;}

2 完整代码

#define int16_t short
#define uint8_t unsigned char
#define uint16_t unsigned short
#define int32_t unsigned int#define SIN_COS_TABLE {\0x0000,0x00C9,0x0192,0x025B,0x0324,0x03ED,0x04B6,0x057F,\0x0648,0x0711,0x07D9,0x08A2,0x096A,0x0A33,0x0AFB,0x0BC4,\0x0C8C,0x0D54,0x0E1C,0x0EE3,0x0FAB,0x1072,0x113A,0x1201,\0x12C8,0x138F,0x1455,0x151C,0x15E2,0x16A8,0x176E,0x1833,\0x18F9,0x19BE,0x1A82,0x1B47,0x1C0B,0x1CCF,0x1D93,0x1E57,\0x1F1A,0x1FDD,0x209F,0x2161,0x2223,0x22E5,0x23A6,0x2467,\0x2528,0x25E8,0x26A8,0x2767,0x2826,0x28E5,0x29A3,0x2A61,\0x2B1F,0x2BDC,0x2C99,0x2D55,0x2E11,0x2ECC,0x2F87,0x3041,\0x30FB,0x31B5,0x326E,0x3326,0x33DF,0x3496,0x354D,0x3604,\0x36BA,0x376F,0x3824,0x38D9,0x398C,0x3A40,0x3AF2,0x3BA5,\0x3C56,0x3D07,0x3DB8,0x3E68,0x3F17,0x3FC5,0x4073,0x4121,\0x41CE,0x427A,0x4325,0x43D0,0x447A,0x4524,0x45CD,0x4675,\0x471C,0x47C3,0x4869,0x490F,0x49B4,0x4A58,0x4AFB,0x4B9D,\0x4C3F,0x4CE0,0x4D81,0x4E20,0x4EBF,0x4F5D,0x4FFB,0x5097,\0x5133,0x51CE,0x5268,0x5302,0x539B,0x5432,0x54C9,0x5560,\0x55F5,0x568A,0x571D,0x57B0,0x5842,0x58D3,0x5964,0x59F3,\0x5A82,0x5B0F,0x5B9C,0x5C28,0x5CB3,0x5D3E,0x5DC7,0x5E4F,\0x5ED7,0x5F5D,0x5FE3,0x6068,0x60EB,0x616E,0x61F0,0x6271,\0x62F1,0x6370,0x63EE,0x646C,0x64E8,0x6563,0x65DD,0x6656,\0x66CF,0x6746,0x67BC,0x6832,0x68A6,0x6919,0x698B,0x69FD,\0x6A6D,0x6ADC,0x6B4A,0x6BB7,0x6C23,0x6C8E,0x6CF8,0x6D61,\0x6DC9,0x6E30,0x6E96,0x6EFB,0x6F5E,0x6FC1,0x7022,0x7083,\0x70E2,0x7140,0x719D,0x71F9,0x7254,0x72AE,0x7307,0x735E,\0x73B5,0x740A,0x745F,0x74B2,0x7504,0x7555,0x75A5,0x75F3,\0x7641,0x768D,0x76D8,0x7722,0x776B,0x77B3,0x77FA,0x783F,\0x7884,0x78C7,0x7909,0x794A,0x7989,0x79C8,0x7A05,0x7A41,\0x7A7C,0x7AB6,0x7AEE,0x7B26,0x7B5C,0x7B91,0x7BC5,0x7BF8,\0x7C29,0x7C59,0x7C88,0x7CB6,0x7CE3,0x7D0E,0x7D39,0x7D62,\0x7D89,0x7DB0,0x7DD5,0x7DFA,0x7E1D,0x7E3E,0x7E5F,0x7E7E,\0x7E9C,0x7EB9,0x7ED5,0x7EEF,0x7F09,0x7F21,0x7F37,0x7F4D,\0x7F61,0x7F74,0x7F86,0x7F97,0x7FA6,0x7FB4,0x7FC1,0x7FCD,\0x7FD8,0x7FE1,0x7FE9,0x7FF0,0x7FF5,0x7FF9,0x7FFD,0x7FFE}
const int16_t hSin_Cos_Table[256] = SIN_COS_TABLE;#define SIN_MASK        0x0300u
#define U0_90           0x0200u
#define U90_180         0x0300u
#define U180_270        0x0000u
#define U270_360        0x0100utypedef struct
{int16_t hCos;int16_t hSin;
} Trig_Components;Trig_Components MCM_Trig_Functions( int16_t hAngle )
{int32_t shindex;uint16_t uhindex;Trig_Components Local_Components;/* 10 bit index computation  */shindex = ( ( int32_t )32768 + ( int32_t )hAngle );uhindex = ( uint16_t )shindex;uhindex /= ( uint16_t )64;switch ( ( uint16_t )( uhindex ) & SIN_MASK ){case U0_90:Local_Components.hSin = hSin_Cos_Table[( uint8_t )( uhindex )];Local_Components.hCos = hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];break;case U90_180:Local_Components.hSin = hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];Local_Components.hCos = -hSin_Cos_Table[( uint8_t )( uhindex )];break;case U180_270:Local_Components.hSin = -hSin_Cos_Table[( uint8_t )( uhindex )];Local_Components.hCos = -hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];break;case U270_360:Local_Components.hSin =  -hSin_Cos_Table[( uint8_t )( 0xFFu - ( uint8_t )( uhindex ) )];Local_Components.hCos =  hSin_Cos_Table[( uint8_t )( uhindex )];break;default:break;}return ( Local_Components );
}

C语言正余弦函数定点查表算法原理及实现相关推荐

  1. python反三角函数arctan_arctan()函数的查表算法

    目标:实现反正切函数的查表算法,精度0.5°. 分析: f(x) = arctan(x)函数单调但非线性,越接近原点处,斜率越大. 90°比较特殊,其值为正无穷大,只要得到的正切值tana大于114. ...

  2. FOC 位置环S曲线之定点查表算法

    在位置环中,若直接让电机到指定位置刚开始加速度过大,会对电机造成损坏,所以一般不会直接将实际位置误差进行PID计算,而是逐步地增加位置.本篇文章介绍一种简单的定点数查表实现S曲线的方法. 一.原理 实 ...

  3. C语言五子棋评分函数,五子棋评分表算法

    最近学了一点QT的绘图,因而乎照着学长的代码绘制了五子棋的小游戏.算法 最基础的东西这里就不说了,本身的知识也仅仅比会用多那么一点,下面咱们来讲说这里貌似高大上的人机AI吧.编程 评分表算法数组 通常 ...

  4. 正余弦函数的matlab仿真,实现正余弦信号的算法比较

    实现正余弦函数的几种算法记录 1.几种算法的理论推导与matlab仿真 (1)Taylor级数逼近正余弦函数的推导 精度要求为20bit,其对应误差为9.536e-7,所以泰勒函数逼近的误差值要小于9 ...

  5. CRC(循环冗余校验)查表算法的代码实现

    CRC(循环冗余校验)查表算法的代码实现 前言 准备工作 查表算法的由来 查表算法的基本原理 模二减法(异或运算)的性质 对直接计算法进行分析 基本原理的推广 查表算法的代码实现 测试用例 正式编码 ...

  6. ML之MIC:利用有无噪音的正余弦函数理解相关性指标的不同(多图绘制Pearson系数、最大信息系数MIC)

    ML之MIC:利用有无噪音的正余弦函数理解相关性指标的不同(多图绘制Pearson系数.最大信息系数MIC) 目录 利用有无噪音的正余弦函数理解相关性指标的不同(多图绘制Pearson系数.最大信息系 ...

  7. Matplotlib 绘制折线图 - 正余弦函数图像

    运行环境 : python 3.6.0 用 Matplotlib 的 scatter 方法绘制散点图 核心代码 : # -*- encoding: utf-8 -*- # @Version : Pyt ...

  8. 编程示例:以人名为输入判断性别的函数 以查表的方式实现

    编程示例:以人名为输入判断性别的函数 以查表的方式实现 需求分析:功能是根据输入的人名,来判断人名的男女的可能性.限定条件是中国的汉族的人名. 格式如下: 输入是"孙 机    苏东海   ...

  9. 正余弦函数及其反函数导数推导

    正余弦函数及其反函数导数推导 背景 三角函数的求导涉及到重要极限 limx→0sinxx\lim_{x\to0}\frac{sin x}{x} 的使用. 其反三角函数涉及复合函数求导.此文主要是对这两 ...

最新文章

  1. OpenStack 镜像密码修改办法
  2. Boost:std ::bind与Boost的_1绑定的测试程序
  3. window环境下mysql配置参数_Window下mysql环境配置问题整理
  4. 2021年广西高考成绩查询方法,2021年广西高考成绩查询网站查分网址:https://www.gxeea.cn/...
  5. C++ 与Qt开发人机象棋(第一部分)
  6. 解决APKIDE(APK改之理)运行出现ApkIDE Exception:…报错的问题
  7. Layabox2初学(一)javascript
  8. ps 计算机 性能设置,电脑运行PS软件太卡?6大设置提高你的PS运行速度
  9. 《计算机世界》封面报道:互联网10年孤独[z]
  10. 人工智能管家机器人应当具备哪些功能?拥有家电控制能力是优势
  11. 植物大战僵尸存档关卡和金币修改
  12. 腾讯云服务器安装win10
  13. 日渐临近的苹果秋季发布会,iOS 11 GM 固件到底提前泄露了哪些秘密?
  14. 自媒体视频素材|短视频标题文字动画PR模板素材
  15. OpenCV路在何方
  16. 2K和XP的CMD命令教程(命令篇.要求置顶)
  17. java的OpenGL学习资料
  18. 如何选择合适的统计学方法
  19. windows重建linux引导,Linux引导修复 利用Linux重建Windows引导
  20. excel下拉菜单vba_Excel 2007的经典菜单

热门文章

  1. 软件测试就业前景怎么样?
  2. 如何轻松搞定各种图形化展现
  3. GD32 f130G8U6 RS485发送数据
  4. GPU呈现模式分析中颜色的意义
  5. 河南高校计算机好的是排名,河南高校的计算机科学与技术专业排名如何?
  6. BZOJ 2448: 挖油-区间DP+单调队列
  7. IIS 支持 flv文件播放 (浏览器中可打开一flv文件)
  8. Python查询12306车票和使用selenium进行买票
  9. Python中的虚拟变量(dummy variables)
  10. 用毕安格将投影坐标的3dmax模型转换为3dtiles