php中文网 | cnphp.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 393|回复: 0

二维数组的查表法

[复制链接]

3138

主题

3148

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
1
威望
0
积分
7946
贡献
0
注册时间
2021-4-14
最后登录
2024-11-21
在线时间
763 小时
QQ
发表于 2022-11-22 18:39:02 | 显示全部楼层 |阅读模式
二维数组的查表法

根据输入输出的二维数组对应关系,根据输入获取输出

如根据电阻值计算温度

查表取整,补充未定义区间,获取采样点区间


[mw_shl_code=cpp,true]
#define MAX_uint32    0xFFFFFFFFU
#define Half_uint32        0x7FFFFFFFU

const uint8_T Temp_Point[13] = { 110U, 100U, 90U, 80U, 70U, 65U,60U, 50U, 40U, 30U, 20U, 10U, 0U } ;
  
const uint16_T Volt_Point[13] = { 800U, 900U, 1000U, 1200U, 1400U,1600U, 1700U, 2100U, 2600U, 3100U, 3600U, 4000U, 4400U } ;

uint8_T OutputTemp;
uint8_T LookupTableDynamic;
uint16_T Input_Volt;



void Step(void)
{
        LookUp_U8_U16_Round( &(LookupTableDynamic), Temp_Point , Input_Volt, Volt_Point, 12U);
        OutputTemp = LookupTableDynamic;
}

/*查表取整*/
/*input:uint16_T Input*/
/*Onput:uint8_T *Output*/
void LookUp_U8_U16_Round(uint8_T *Output, const uint8_T *OutPut_Point, uint16_T Input, const uint16_T *Input_Point, uint32_T Point_Num)
{
  uint32_T iLeft;
  uint32_T iRght;
  Location_Search_U16( &(iLeft), &(iRght), Input, Input_Point, Point_Num);
  Interpolate_U8_U16_Round( Output, OutPut_Point[iLeft], OutPut_Point[iRght], Point_Num, Input_Point[iLeft],Input_Point[iRght]);
}


/*查找输入值落入采样点区间*/
void Location_Search_U16(uint32_T *piLeft, uint32_T *piRght, uint16_T Input, const uint16_T *Input_Point, uint32_T Point_Num)
{
  /* Find the location of current input value in the data table. */
  *piLeft = 0U;
  *piRght = Point_Num;
  if (Input<= Input_Point[0] )
  {
    /* Less than or equal to the smallest point in the table. */
    *piRght = 0U;
  }
  else if (Input >= Input_Point[Point_Num] )
  {
    /* Greater than or equal to the largest point in the table. */
    *piLeft = Point_Num;
  }
  else
  {
      uint32_T i;

      /* Do a binary search.对半取区间,逐渐缩小区间 */
      while (( *piRght - *piLeft ) > 1U )
      {
              /* Get the average of the left and right indices using to Floor rounding. */
              i = (*piLeft + *piRght) >> 1;

              /* Move either the right index or the left index so that */
              /*  LeftDataPoint <= CurrentValue < RightDataPoint */
              if (Input< Input_Point )
              {
                *piRght = i;
              }
              else
              {
                *piLeft = i;
              }
       }
  }
}

/*值落于区间段中间时,采取y = ax+b的公式求取输出值*/
void Interpolate_U8_U16_Round(uint8_T *Output, uint8_T yL, uint8_T yR, uint16_T Input, uint16_T xL, uint16_T xR)
{
  uint32_T bigProd;
  uint8_T yDiff;
  uint16_T xNum;
  uint16_T xDen;
  *Output = yL;

  /* If x is not strictly between xR and xL
   * then an interpolation calculation is not necessary x == xL
   * or not valid.  The invalid situation is expected when the input
   * is beyond the left or right end of the table.  The design is
   * that yL holds the correct value for *pY
   * in invalid situations.
   * x---input
   * y---output
   */
  if ((xR > xL) && (Input> xL) ) {
    xDen = xR;
    xDen = (uint16_T)((uint32_T)xDen - (uint32_T)xL);
    xNum = Input;
    xNum = (uint16_T)((uint32_T)xNum - (uint32_T)xL);
    if (yR >= yL ) {
      yDiff = yR;
      yDiff = (uint8_T)((uint32_T)yDiff - (uint32_T)yL);
    } else {
      yDiff = yL;
      yDiff = (uint8_T)((uint32_T)yDiff - (uint32_T)yR);
    }

    bigProd = (uint32_T)yDiff * (uint32_T)xNum;  //
    yDiff = (uint8_T)div_u32_round(bigProd, (uint32_T)xDen);
    if (yR >= yL ) {
      *Output = (uint8_T)((uint32_T)*Output + (uint32_T)yDiff);
    } else {
      *Output = (uint8_T)((uint32_T)*Output - (uint32_T)yDiff);
    }
  }
}

/*四舍五入取整*/
uint32_T div_u32_round(uint32_T numerator, uint32_T denominator)
{
  uint32_T quotient;
  if (denominator == 0U) {
    quotient = MAX_uint32;

    /* Divide by zero handler */
  }
  else
  {
      quotient = numerator / denominator;               //商= 分子/分母
      numerator %= denominator;                           //求余
      if (numerator > Half_uint32) {
        quotient++;
      }
      else
     {
        numerator <<= 1U;                                       //余数左移1位,即乘以2
        if (numerator >= denominator)
       {
          quotient++;
        }
      }
  }

  return quotient;
}
[/mw_shl_code]

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|php中文网 | cnphp.com ( 赣ICP备2021002321号-2 )

GMT+8, 2024-11-22 03:06 , Processed in 1.139849 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

申明:本站所有资源皆搜集自网络,相关版权归版权持有人所有,如有侵权,请电邮(fiorkn@foxmail.com)告之,本站会尽快删除。

快速回复 返回顶部 返回列表