嵌入式C代码审查

嵌入式C代码审查,c,C,我需要编写一个函数,它使用一个查找表来查找温度传感器模拟输入的ADC值,并通过“插值”-线性近似来找出给定ADC值的温度。 我已经创建了一个函数并为它编写了一些测试用例,我想知道你们是否可以提出一些改进代码的建议,因为这应该是针对嵌入式uC的,可能是stm32 我张贴我的代码和附加我的C文件,它将编译和运行 如果您有任何改进意见/建议,请告知我 我还想了解一下我正在做的从uint32_t到float的转换,如果这是一种有效的编码方式的话 #include <windows.h> #i

我需要编写一个函数,它使用一个查找表来查找温度传感器模拟输入的ADC值,并通过“插值”-线性近似来找出给定ADC值的温度。 我已经创建了一个函数并为它编写了一些测试用例,我想知道你们是否可以提出一些改进代码的建议,因为这应该是针对嵌入式uC的,可能是stm32

我张贴我的代码和附加我的C文件,它将编译和运行

如果您有任何改进意见/建议,请告知我

我还想了解一下我正在做的从uint32_t到float的转换,如果这是一种有效的编码方式的话

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define TEMP_ADC_TABLE_SIZE 15

typedef struct
{
 int8_t temp;     
 uint16_t ADC;       
}Temp_ADC_t;

const Temp_ADC_t temp_ADC[TEMP_ADC_TABLE_SIZE] = 
{
    {-40,880}, {-30,750},
    {-20,680}, {-10,595},
    {0,500}, {10,450},
    {20,410}, {30,396},
    {40,390}, {50,386},
    {60,375}, {70,360},
    {80,340}, {90,325},
    {100,310}
};

// This function finds the indices between which the input reading lies.
// It uses an algorithm that doesn't need to loop through all the values in the 
// table but instead it keeps dividing the table in two half until it finds
// the indices between which the value is or the exact index.
//
// index_low, index_high, are set to the indices if a value is between sample
// points, otherwise if there is an exact match then index_mid is set.
// 
// Returns 0 on error, 1 if indices found, 2 if exact index is found.
uint8_t find_indices(uint16_t ADC_reading, 
                    const Temp_ADC_t table[],
                    int8_t dir, 
                    uint16_t* index_low, 
                    uint16_t* index_high, 
                    uint16_t* index_mid, 
                    uint16_t table_size)
{
    uint8_t found = 0;
    uint16_t mid, low, high;
    low = 0;
    high = table_size - 1;

    if((table != NULL) && (table_size > 0) && (index_low != NULL) &&
       (index_mid != NULL) && (index_high != NULL))
    {
        while(found == 0)
        {
            mid = (low + high) / 2;

            if(table[mid].ADC == ADC_reading)
            {   
                // exact match                       
                found = 2;            
            }
            else if(table[mid].ADC < ADC_reading)
            {
                if(table[mid + dir].ADC == ADC_reading)
                {
                    // exact match          
                    found = 2;
                    mid = mid + dir;                             
                }
                else if(table[mid + dir].ADC > ADC_reading)
                {
                    // found the two indices
                    found = 1;
                    low = (dir == 1)? mid : (mid + dir);
                    high = (dir == 1)? (mid + dir) : mid;                            
                }
                else if(table[mid + dir].ADC < ADC_reading)
                {                     
                    low = (dir == 1)? (mid + dir) : low;
                    high = (dir == 1) ? high : (mid + dir);
                }              
            }
            else if(table[mid].ADC > ADC_reading)
            {
                if(table[mid - dir].ADC == ADC_reading)
                {
                    // exact match          
                    found = 2;
                    mid = mid - dir;                             
                }
                else if(table[mid - dir].ADC < ADC_reading)
                {
                    // found the two indices
                    found = 1;
                    low = (dir == 1)? (mid - dir) : mid;
                    high = (dir == 1)? mid : (mid - dir);                            
                }
                else if(table[mid - dir].ADC > ADC_reading)
                {
                    low = (dir == 1)? low : (mid - dir);
                    high = (dir == 1) ? (mid - dir) : high;
                }
            } 
        }        
        *index_low = low;
        *index_high = high;
        *index_mid = mid;        
    }

    return found;  
}

// This function uses the lookup table provided as an input argument to find the
// temperature for a ADC value using linear approximation. 
// 
// Temperature value is set using the temp pointer.  
// 
// Return 0 if an error occured, 1 if an approximate result is calculate, 2
// if the sample value match is found.

uint8_t lookup_temp(uint16_t ADC_reading, const Temp_ADC_t table[], 
                    uint16_t table_size ,int8_t* temp)
{
    uint16_t mid, low, high;
    int8_t dir;
    uint8_t return_code = 1;
    float gradient, offset;

    low = 0;
    high = table_size - 1;

    if((table != NULL) && (temp != NULL) && (table_size > 0))
    {
        // Check if ADC_reading is out of bound and find if values are
        // increasing or decreasing along the table.
        if(table[low].ADC < table[high].ADC)
        {
            if(table[low].ADC > ADC_reading)
            {
                return_code = 0;                                    
            }
            else if(table[high].ADC < ADC_reading)
            {
                return_code = 0;
            }
            dir = 1;
        }    
        else
        {
            if(table[low].ADC < ADC_reading)
            {
                return_code = 0;                                    
            }
            else if(table[high].ADC > ADC_reading)
            {
                return_code = 0;
            }
            dir = -1; 
        }
    }
    else
    {
        return_code = 0;    
    } 

    // determine the temperature by interpolating
    if(return_code > 0)
    {
        return_code = find_indices(ADC_reading, table, dir, &low, &high, &mid, 
                                   table_size);

        if(return_code == 2)
        {
            *temp = table[mid].temp;
        }
        else if(return_code == 1)
        {
            gradient = ((float)(table[high].temp - table[low].temp)) / 
                       ((float)(table[high].ADC - table[low].ADC));
            offset = (float)table[low].temp - gradient * table[low].ADC;
            *temp = (int8_t)(gradient * ADC_reading + offset);
        }
    }  

    return return_code;   
}



int main(int argc, char *argv[])
{
  int8_t temp = 0;
  uint8_t x = 0;  
  uint16_t u = 0;
  uint8_t return_code = 0; 
  uint8_t i;

  //Print Table
  printf("Lookup Table:\n");
  for(i = 0; i < TEMP_ADC_TABLE_SIZE; i++)
  {
      printf("%d,%d\n", temp_ADC[i].temp, temp_ADC[i].ADC);                
  }

  // Test case 1
  printf("Test case 1: Find the temperature for ADC Reading of 317\n");
  printf("Temperature should be 95 Return Code should be 1\n");
  return_code = lookup_temp(317, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Temperature: %d C\n", temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 2  
  printf("Test case 2: Find the temperature for ADC Reading of 595 (sample value)\n");
  printf("Temperature should be -10, Return Code should be 2\n");
  return_code = lookup_temp(595, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Temperature: %d C\n", temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 3  
  printf("Test case 3: Find the temperature for ADC Reading of 900 (out of bound - lower)\n");
  printf("Return Code should be 0\n");
  return_code = lookup_temp(900, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 4 
  printf("Test case 4: Find the temperature for ADC Reading of 300 (out of bound - Upper)\n");
  printf("Return Code should be 0\n");
  return_code = lookup_temp(300, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 5
  printf("Test case 5: NULL pointer (Table pointer) handling\n");
  printf("Return Code should be 0\n");
  return_code = lookup_temp(595, NULL, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 6
  printf("Test case 6: NULL pointer (temperature result pointer) handling\n");
  printf("Return Code should be 0\n");
  return_code = lookup_temp(595, temp_ADC, TEMP_ADC_TABLE_SIZE, NULL);
  printf("Return code: %d\n", return_code);

  // Test case 7
  printf("Test case 7: Find the temperature for ADC Reading of 620\n");
  printf("Temperature should be -14 Return Code should be 1\n");
  return_code = lookup_temp(630, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Temperature: %d C\n", temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 8
  printf("Test case 8: Find the temperature for ADC Reading of 880 (First table element test)\n");
  printf("Temperature should be -40 Return Code should be 2\n");
  return_code = lookup_temp(880, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Temperature: %d C\n", temp);
  printf("Return code: %d\n\n", return_code);

  // Test case 9
  printf("Test case 9: Find the temperature for ADC Reading of 310 (Last table element test)\n");
  printf("Temperature should be 100 Return Code should be 2\n");
  return_code = lookup_temp(310, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);
  printf("Temperature: %d C\n", temp);
  printf("Return code: %d\n\n", return_code);  

  printf("Press ENTER to continue...\n");  
  getchar();
  return 0;
}
#包括
#包括
#包括
#包括
#定义温度ADC表尺寸15
类型定义结构
{
内部温度;
uint16_t ADC;
}温度ADC;
常数温度ADC温度ADC[温度ADC表大小]=
{
{-40,880}, {-30,750},
{-20,680}, {-10,595},
{0,500}, {10,450},
{20,410}, {30,396},
{40,390}, {50,386},
{60,375}, {70,360},
{80,340}, {90,325},
{100,310}
};
//此函数用于查找输入读数所在的索引。
//它使用的算法不需要遍历
//表,但它一直将表一分为二,直到找到
//值所在的索引或精确索引。
//
//如果某个值介于两个样本之间,则将索引设置为低,索引设置为高
//点,否则,如果存在精确匹配,则设置索引。
// 
//错误时返回0,找到索引时返回1,找到精确索引时返回2。
uint8查找索引(uint16 ADC读取,
常数温度ADC t表[],
国际事务主任,
uint16指数低,
uint16指数高,
uint16指数,
uint16(表尺寸)
{
uint8_t found=0;
uint16_t中、低、高;
低=0;
高=表_尺寸-1;
如果((表!=NULL)&&(表大小>0)&&(索引低!=NULL)&&
(索引中!=NULL)和&(索引高!=NULL))
{
while(找到==0)
{
中等=(低+高)/2;
if(表[mid].ADC==ADC\U读数)
{   
//精确匹配
发现=2;
}
else if(表[mid].ADCADC\U读数)
{
//找到了两个索引
发现=1;
低=(方向==1)?中:(中+方向);
高=(直接==1)?(中间+直接):中间;
}
else if(表[mid+dir].ADCADC\U读数)
{
if(表[mid-dir].ADC==ADC\U读数)
{
//精确匹配
发现=2;
mid=mid-dir;
}
else if(表[mid-dir].ADCADC\u读数)
{
low=(dir==1)?low:(mid-dir);
高=(直接==1)?(中间直接):高;
}
} 
}        
*指数低=低;
*指数高=高;
*指数_mid=mid;
}
发现退货;
}
//此函数使用作为输入参数提供的查找表查找
//使用线性近似的ADC值的温度。
// 
//使用温度指针设置温度值。
// 
//如果发生错误,则返回0;如果近似结果为calculate,则返回1;2
//如果发现样本值匹配。
uint8查找温度(uint16 ADC读数,常数温度ADC表[],
uint16表格大小,int8*temp)
{
uint16_t中、低、高;
国际电讯局长;
uint8返回代码=1;
浮动梯度,偏移量;
低=0;
高=表_尺寸-1;
如果((表!=NULL)&&(温度!=NULL)&&(表大小>0))
{
//检查ADC_读数是否超出范围,并查找值是否超出范围
//沿着桌子增加或减少。
中频(表[low].ADC<表[high].ADC)
{
中频(表[low].ADC>ADC\U读数)
{
返回_码=0;
}
else if(表[高]。ADCADC\U读数)
{
返回_码=0;
}
dir=-1;
}
}
其他的
{
返回_码=0;
} 
//通过插值确定温度
如果(返回\u代码>0)
{
return\u code=查找索引(ADC\u读数、表格、目录、低位、高位和中位数、,
表(尺寸);
if(返回_代码==2)
{
*临时工=
if condition 
{
   if another_condition
   {
        if third condition
        {
if not condition 
    return false;

// Here the condition IS true, thus no reason to indent
 low = (dir == 1)? mid : (mid + dir);
 high = (dir == 1)? (mid + dir) : mid;  
int sum = mid+dir;
if dir == 1
{
low = mid;
high = sum;
}
else
{
low=sum;
high=mid;
}
enum Match { MATCH_ERROR, MATCH_EXACT, MATCH_INTERPOLATE, MATCH_UNDERFLOW, MATCH_OVERFLOW };

enum Match find_indices (uint16_t ADC_reading, 
                    const Temp_ADC_t table[],
                    uint16_t* index_low, 
                    uint16_t* index_high )
{
    uint16_t low = *index_low;
    uint16_t high = *index_high;

    if ( low >= high ) return MATCH_ERROR;
    if ( ADC_reading < table [ low ].ADC ) return MATCH_UNDERFLOW;
    if ( ADC_reading > table [ high ].ADC ) return MATCH_OVERFLOW;  

    while ( low < high - 1 )
    {
        uint16_t mid = ( low + high ) / 2;
        uint16_t val = table [ mid ].ADC;

        if ( ADC_reading > val)
        {
            low = mid; 
            continue;
        }

        if ( ADC_reading < val )
        {
            high = mid;
            continue;
        }

        low = high = mid;
        break;
    }

    *index_low = low;
    *index_high = high;

    if ( low == high )
        return MATCH_EXACT;
    else
        return MATCH_INTERPOLATE;
}
enum Match lookup_temp ( uint16_t ADC_reading, const Temp_ADC_t table[], 
                uint16_t table_size, int8_t* temp)
{
    uint16_t low = 0;
    uint16_t high = table_size - 1;

    enum Match match = find_indices ( ADC_reading, table, &low, &high );

    switch ( match ) {
        case MATCH_INTERPOLATE:
            {
                float gradient = ((float)(table[high].temp - table[low].temp)) / 
                                 ((float)(table[high].ADC - table[low].ADC));
                float offset = (float)table[low].temp - gradient * table[low].ADC;

                *temp = (int8_t)(gradient * ADC_reading + offset);

                break;
            }  

        case MATCH_EXACT:
            *temp = table[low].temp;
            break;
    }

    return match;   
}
*temp = temp_low + uint16_t ( ( uint32_t ( ADC_reading - adc_low ) * uint32_t (  temp_high - temp_low ) ) / uint32_t ( adc_high - adc_low ) );
temp = table[dac_value]; //TODO add special case for max dac_value and max dac_value-1 or make the table 129 entries deep if(dac_value&1) { temp=(table[(dac_value>>1)+0]+table[(dac_value>>1)+1])>>1; } else { temp=table[dac_value>>1]; }
static const struct test_case
{
    int  inval;   /* Test reading */
    int  rcode;   /* Expected return code */
    int  rtemp;   /* Expected temperature */
} test[] =
{
    { 317, 1,  95 },
    { 595, 1, -10 },
    { 900, 0,   0 },  // Out of bound - lower
    { 300, 0,   0 },  // Out of bound - upper
    { 620, 1, -14 }, 
    { 880, 2, -40 },  // First table element
    { 310, 2, 100 },  // Last table element
};
static int test_one(int testnum, const struct test_case *test)
{
    int result = 0;
    int temp;
    int code = lookup_temp(test->inval, temp_ADC, TEMP_ADC_TABLE_SIZE, &temp);

    if (temp == test->rtemp && code == test->rcode)
        printf("PASS %d: reading %d, code %d, temperature %d\n",
               testnum, test->inval, code, temp);
    else
    {
        printf("FAIL %d: reading %d, code (got %d, wanted %d), "
               "temperature (got %d, wanted %d)\n",
               testnum, test->inval, code, test->rcode, temp, test->rtemp);
        result = 1;
    }
}
#define DIM(x) (sizeof(x)/sizeof(*(x)))

int failures = 0;
int i;

for (i = 0; i < DIM(test); i++)
    failures += test_one(i + 1, &test[i]);

if (failures != 0)
    printf("!! FAIL !! (%d of %d tests failed)\n", failures, (int)DIM(test));
else
    printf("== PASS == (%d tests passed)\n", (int)DIM(test));