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

2023-05-16

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

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

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

1 原理与实现步骤

(1)正余弦表格生成

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

    这里将[0,\frac{\pi}{2}]范围内的角度细分为256份,整个周期就细分了1024份。故将\sin(\frac{\pi}{2} * \frac{i}{256})\times 2^{15}保存为表格,正余弦结果表格生成程序如下

#include <stdio.h>
#include <math.h>
#define NUM  256
#define PI   3.1415926535898f

int 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是一个包含四个象限范围的值,将四个象限共细分为2^{16}=65536份,每个象限有2^{12}=4096个数。但基于存储空间考虑,在前面生成的正余弦表中,我们将一个象限细分为256份,则四个象限共细分为1024份,所以除以2^{6}=64。此时可以根据最高两位判断角度所在的象限,同时将这个数取余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        0x0100u


typedef 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 );
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 【性能优化】cpu时间抖动问题的解决修复

    问题描述 xff1a 边缘设备的cpu在低占有率时 xff0c 进程运行时间抖动较大 xff0c 在高占有率时 xff0c 运行时间抖动更稳定 低占有率运行情况图 xff1a 相同处理逻辑循环中 xff0c 两次处理的时间间隔 xff1a
  • pointRCNN 结果可视化

    由于pointRCNN源码的训练和inference很详细 xff0c 但是没有可视化的代码 xff0c 本文介绍其3d框结果的可视化方法 1 跑通pointRCNN https github com sshaoshuai PointRCN
  • C/C++学习笔记——C提高: 函数指针和递归函数

    函数指针 函数类型 通过什么来区分两个不同的函数 xff1f 一个函数在编译时被分配一个入口地址 xff0c 这个地址就称为函数的指针 xff0c 函数名代表函数的入口地址 函数三要素 xff1a 名称 参数 返回值 C语言中的函数有自己特
  • 算法基础22-最小生成树

    最小生成树 primkruskal prim 链接 acwing上一个关于prim很好的题解 prim 算法干的事情是 xff1a 给定一个无向图 xff0c 在图中选择若干条边把图的所有节点连起来 要求边长之和最小 在图论中 xff0c
  • C/C++学习笔记——C提高:预处理

    预处理的基本概念 C语言对源程序处理的四个步骤 xff1a 预处理 编译 汇编 链接 预处理是在程序源代码被编译之前 xff0c 由预处理器 xff08 Preprocessor xff09 对程序源代码进行的处理 这个过程并不对程序的源代
  • C/C++学习笔记——C提高:动态库的封装和使用

    库的基本概念 库是已经写好的 成熟的 可复用的代码 每个程序都需要依赖很多底层库 xff0c 不可能每个人的代码从零开始编写代码 xff0c 因此库的存在具有非常重要的意义 在我们的开发的应用中经常有一些公共代码是需要反复使用的 xff0c
  • FreeRTOS学习笔记——基础知识与移植(STM32F103)

    1 1 前后台系统 xff1a 早期嵌入式开发没有嵌入式操作系统的概念 xff0c 直接操作裸机 xff0c 在裸机上写程序 xff0c 比如用51单片机基本就没有操作系统的概念 通常把程序分为两部分 xff1a 前台系统和后台系统 简单的
  • STM32开源代码——MAX30100程序

    正点原子精英开发板 模块化封装 xff0c 入口函数简明 xff0c 易上手操作 展示main c代码 xff0c 完整代码请下载 xff08 数据打印到串口在MAX30100 PulseOximeter c xff09 点击下载代码 in
  • STM32开源代码——2.8寸TFTLCD屏虚拟键盘触摸程序

    正点原子精英开发板 模块化封装 xff0c 入口函数简明 xff0c 易上手操作 展示main c代码 xff0c 完整代码请下载 点击下载代码 include 34 sys h 34 include 34 delay h 34 inclu
  • STM32开源代码——光敏传感器

    正点原子精英开发板 模块化封装 xff0c 入口函数简明 xff0c 易上手操作 展示main c代码 xff0c 完整代码请下载 点击下载代码 include 34 led h 34 include 34 delay h 34 inclu
  • 个人项目——机智云开源APP基础修改教程(Android)

    之前写过一篇STM32接入机智云的教程 xff0c 最后说要有时间给大家写一篇修改机智云开源Demo APP的教程 xff0c 刚好楼主考完直流传动 xff0c 然后帮小学弟的一个32项目接入了机智云 xff0c 然后打算帮他修改一下Dem
  • FreeRTOS学习笔记——FreeRTOS任务创建和删除实验(静态方法)

    6 3 任务创建和删除实验 静态方法 6 3 1 实验程序设计 1 实验目的 上一小节我们讲了使用函数xTaskCreate 来创建任务 xff0c 本节在上一小节的基础上做简单的修改 xff0c 使用函数xTaskCreateStatic
  • FreeRTOS学习笔记——FreeRTOS 系统内核控制函数

    FreeRTOS 中有一些函数只供系统内核使用 xff0c 用户应用程序一般不允许使用 xff0c 这些API 函数就是系统内核控制函数 本章我们就来学习一下这些内核控制函数 xff0c 本章分为如下几部分 xff1a 10 1 内核控制函
  • FreeRTOS学习笔记——FreeRTOS 时间管理

    在使用FreeRTOS 的过程中我们通常会在一个任务函数中使用延时函数对这个任务延时 xff0c 当执行延时函数的时候就会进行任务切换 xff0c 并且此任务就会进入阻塞态 xff0c 直到延时完成 xff0c 任务重新进入就绪态 延时函数
  • 算法基础23-二分图

    二分图 二分图的判断二分图的最大匹配数 可以去看acwing题解 二分图的判断 span class token comment AcWing 860 染色法判定二分图 span span class token macro propert
  • Router 选择

    Connected Dominating Set Example of a Connected Dominating Set Router 必须形成一个 CDS xff08 Connected Dominating Set xff0c 连接
  • devtool: unset _PYTHON_SYSCONFIGDATA_NAME

    问题 在 Ubuntu 20 04 1 LTS 上进行编译Yocto时报错 xff0c 出现如下错误 xff1a bb data smart ExpansionError Failure expanding variable SRCPV e
  • VsCode 配置PySide6及测试

    目录 VSCode插件安装安装Python插件安装PySide6插件 PySide6安装PySide6配置VSCode创建UI文件 在这里插入图片描述 https img blog csdnimg cn cbf7cd76d7d84048ab
  • Ubuntu 14.04 Desktop的Raid1安装总结

    Ubuntu 14 04 Desktop的Raid1安装总结 安装基于Ubuntu14 04 Desktop的Raid1 由于采用UEFI GPT方式作为系统启动方式 xff0c 在安装过程中出现了很多异常情况 本文记录安装的过程 安装步骤

随机推荐

  • sem_wait sem_post信号量操作进本函数

    sem wait sem post 信号量的数据类型为结构sem t xff0c 它本质上是一个长整型的数 函数sem init xff08 xff09 用来初始化一个信号量 它的原型为 xff1a extern int sem init
  • 常见gcc编译警告整理(开始)

    1 warning no newline at end of file 在文件最后一行加上回车键 解释 xff1a 在 Rationale for the C99 standard 一文中 xff0c 有C99的相关信息 xff1a A b
  • 对于结构体变量赋值的误区

    以前在使用结构体时没有在结构体变量之间直接赋值 xff0c 今天同事在查看别人的代码时 xff0c 发现有两个结构体变量直接赋值的语句当时感觉这个语句不对 xff0c 认为在一个结构体里边 xff0c 既有一般的无符号整形与数组 xff0c
  • 线程同步(互斥锁与信号量的作用与区别)

    信号量用在多线程多任务同步的 xff0c 一个线程完成了某一个动作就通过信号量告诉别的线程 xff0c 别的线程再进行某些动作 xff08 大家都在semtake的时候 xff0c 就阻塞在 哪里 xff09 而互斥锁是用在多线程多任务互斥
  • 误解程序运行(从单片机到开始)

    误解程序运行 从单片机到开始 关于程序的执行 xff0c 以前想的不多 xff0c 没有意识到一个程序在运行时 xff0c 从哪里读指令 xff0c 数据又写在哪里 最近在看CSAPP时这个念头经常在脑袋中晃荡 从单片机上知道 xff0c
  • Out-of-Bounds Memory References and Buffer Overflow

    callee pushl edp save edp on stack movl esp edp pushl ebx save ebx subl 20 esp popl ebx restore ebx popl edp restore
  • 嘉立创专业板stm32拓展板十分钟快速入门

    本文是为不想深入学PCB但是迫不得已需要用PCB的人或者想要做一个32的拓展版的童鞋们的快速入门并做出板子的博客 xff0c 因此 xff0c 本文内容不会深入讨论元件 xff0c 只会教授基础流程 xff0c 并且没有画芯片 本文内容 x
  • 电子信息工程四年学习之思

    毕业后 xff0c 回顾四年学习历程发现 xff0c 当时以为的明白 xff0c 到现在都是那时的不明白 或许是自己的经历 xff08 参加比赛比较多 xff09 导致了现在的反思 但是 xff0c 回顾那个时候的课程设置 xff0c 却都
  • 将要到来的三大技术革命与联系

    http www csdn net article 2013 02 14 2814128 2013大数据 http www csdn net article 2013 02 15 2814135 bigdata is coming 大数据
  • Keil的常见编译警告

    1 warning 767 D conversion from pointer to smaller integer 解释 xff1a 将指针转换为较小的整数 影响 xff1a 可能造成的影响 xff1a 容易引起数据截断 xff0c 造成
  • 《大数据时代》之后

    现在想想也不记得当时是怎么找到 大数据时代 这本书的 xff0c 好像是在查找数据库方面的书 xff0c 看到亚马逊推荐的书里有这本 xff0c 发现最近才出版的就买一本回来看看 然而这个过程中 xff0c 其实自己已经得到了大数据带来的影
  • 《代码大全》笔记

    最近将去年毕业时 xff0c 大神推荐的 代码大全 看完了 xff08 已经过去一年了 xff0c 要十分感谢推荐 xff0c 还有凤林兄的 深入理解计算机系统 xff09 零零碎碎的时间 xff0c 发现很多东西虽然在书中标记了 xff0
  • 《编程精粹》思之代码与产品

    之前眼中有代码无产品 xff0c 现在眼中有产品有代码 xff0c 什么时候能做到有产品无代码 xff1f 还需要努力 刚开始实习的时候 xff0c 总喜欢在程序中使用 p 43 1 61 而不是p 1 来给入参 xff0c 甚至于用来给定
  • 树莓派4B+Intel神经计算棒(Stick2)+YoloV5可行性考察报告

    1 神经棒只能作为协处理器 在执行脚本时 xff0c 通过在命令后面加上 d 设备名 就可以指定硬件设备来加速推理 例如 命令行指定神经棒运行 demo squeezenet download convert run span class
  • 在Vue中获取v-for的index值

    lt el submenu index 61 34 item id 43 39 39 34 v for 61 34 item index in menuList 34 key 61 34 item id 34 gt lt template
  • 死区时间的分析与设置

    出现死区的主要原因是因为MOS管的源极和栅极之间的结电容 现在在栅极加上一个门电路 当门电路输出的信号跳变的瞬间 xff0c 电流是非常大的 xff0c 会导致MOS管发热 xff0c 所以需要在门电路后面再串联一个电阻 xff0c 这个电
  • MOS管特性和导通过程

    三极管是流控流器件 xff0c 它不能驱动功率太大的器件 xff0c 因为此时C极电流大 xff0c 而CE压降为0 3V左右 xff0c 在三极管上面消耗的功率就很大 xff0c 还容易发热 所以压控压型的MOS管就诞生了 特性 一开始给
  • 2014欢聚时代(YY)软件研发笔试题

    本文转载自 xff1a http blog csdn net arcsinsin article details 12714027
  • FOC 单电阻采样 位置环控制伺服电机

    最近在做微型伺服电机的控制 xff0c 需要平滑地将电机定位到某个位置 伺服电机 编码器 PCB都是自制的 这里我把整个的流程和遇到的问题记录一下 目录 硬件设计 STM32CubeMX配置 程序设计 测试遇到的问题 演示视频 硬件设计 这
  • C语言正余弦函数定点查表算法原理及实现

    如果用数学库中的sin和cos函数计算 xff0c 可能涉及浮点 乘法 除法运算 xff0c 运行速率较低 这里介绍一种正余弦查表算法 参考代码 xff1a SMT32 FOC电机库的mc math c 首先我们知道正弦和余弦的函数值差了9