You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言在无浮点无数学库MCU上实现int8_t坐标0.2°精度绕原点旋转

无浮点无数学库的MCU坐标旋转实现方案

核心思路

因为要求0.2°的角度增量精度,全程用定点运算+预生成三角函数表实现,完全避免浮点运算和数学库调用,仅使用int32_t作为运算中间类型,符合MCU的资源限制。

前置准备

  • 角度量化:把0~360°按0.2°为步长拆分,总共有360/0.2=1800个步长,任意输入角度先转成对应步长,对1800取模后即可覆盖所有旋转场景
  • 预生成定点三角函数表:使用Q15格式(1位符号位+15位小数位)存储sin值,即把sin(步长*0.2°)乘以32768后四舍五入取整,预生成1800个int16_t类型的数值存入代码常量区,占用Flash仅3.6KB,对MCU资源压力极低。cos值可通过cosθ = sin(θ+90°)的关系直接从sin表取数,无需单独存cos表

运算逻辑

坐标旋转的整数定点版公式如下:

x' = (x * cosθ_q15 - y * sinθ_q15 + 16384) >> 15
y' = (x * sinθ_q15 + y * cosθ_q15 + 16384) >> 15
其中cosθ_q15、sinθ_q15是Q15格式的三角函数值,加16384是做四舍五入,右移15位是还原Q15的缩放比例,得到最终整数坐标。
由于输入x、y是int8_t类型,最大绝对值为128,单步乘法结果最大为128*32767=4194176,远小于int32_t的取值范围,中间运算不会出现溢出。

代码实现示例

#include <stdint.h>

// 0.2°为步长,覆盖0~359.8°总共有1800个步长
#define ROT_STEP_COUNT 1800
// Q15格式sin表,预生成规则:sin_table[i] = round(sin(i * 0.2° * π / 180) * 32767)
// 以下为示例表片段,完整表可在PC端提前计算后直接填入
static const int16_t sin_table[ROT_STEP_COUNT] = {
    0, 114, 228, 343, 457, 571, 686, 800, 914, 1028,
    // 剩余1790个值省略
    32767, 32756, 32745, // 对应90°、89.8°、89.6°...
};

// 从sin表获取Q15格式cos值,90°对应步长为450
static int16_t get_cos_q15(int32_t step) {
    return sin_table[(step + 450) % ROT_STEP_COUNT];
}

/**
 * 坐标绕原点旋转函数
 * @param x 输入x坐标,int8_t类型
 * @param y 输入y坐标,int8_t类型
 * @param angle_deci 输入旋转角度,单位为0.1°,比如40.8°传408,0.2°传2,避免浮点传参
 * @param out_x 输出旋转后x坐标
 * @param out_y 输出旋转后y坐标
 */
void rotate_point(int8_t x, int8_t y, int32_t angle_deci, int8_t *out_x, int8_t *out_y) {
    // 角度转步长,+1做四舍五入保证0.2°精度
    int32_t step = (angle_deci + 1) / 2;
    // 步长取模到合法范围
    step = step % ROT_STEP_COUNT;
    if (step < 0) step += ROT_STEP_COUNT;
    
    int32_t cos_q15 = get_cos_q15(step);
    int32_t sin_q15 = sin_table[step];
    
    // 用int32_t存中间结果避免溢出
    int32_t x_res = (int32_t)x * cos_q15 - (int32_t)y * sin_q15;
    int32_t y_res = (int32_t)x * sin_q15 + (int32_t)y * cos_q15;
    
    // 四舍五入后还原Q15缩放,转成int8_t输出
    *out_x = (int8_t)((x_res + 16384) >> 15);
    *out_y = (int8_t)((y_res + 16384) >> 15);
}

验证示例

输入坐标(32, -64),旋转90°,对应angle_deci=900,计算步长为(900+1)/2=450,sin_q15=32767,cos_q15=0:

  • x_res = 32*0 - (-64)*32767 = 2097088,(2097088+16384)>>15 = 2113472>>15 = 64
  • y_res = 32*32767 + (-64)*0 = 1048544,(1048544+16384)>>15 = 1064928>>15 =32
    输出结果为(64,32),和要求完全一致。

资源优化方案

如果MCU Flash空间不足,可仅存储0~90°对应的450个步长的sin表,其余象限的sin、cos值通过符号翻转和索引对称计算得到,仅需900字节Flash即可实现完整功能。

内容的提问来源于stack exchange,提问作者NessDan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 18:48:02