威望0
积分7946
贡献0
在线时间763 小时
UID1
注册时间2021-4-14
最后登录2024-11-21
管理员
- UID
- 1
- 威望
- 0
- 积分
- 7946
- 贡献
- 0
- 注册时间
- 2021-4-14
- 最后登录
- 2024-11-21
- 在线时间
- 763 小时
|
二维数组的查表法
根据输入输出的二维数组对应关系,根据输入获取输出
如根据电阻值计算温度
查表取整,补充未定义区间,获取采样点区间
[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] |
|