笔记—代码平台化思维

代码平台化分层处理有很多好处,方便移植,减少迭代代码的更改,特别是量产后更改代码引入致命bug,代码可配置化极大方便了后期需求满足,只用多增加结构体成员变量即可,不用更改底层代码,从这种方法中获益匪浅。

在项目中遇到RingBuffer这样处理,后来自己写了关于ADC采集滤波的平台化处理。笔记如下:

需求:在项目中,peripherals Microphone/Backup battery /Antenna/Led ...涉及到14路ADC 每个外设相关的ADC 采样的buffer 深度不一样,滤波算法不一样(冒泡or取平均值)

1.文件划分

AdcFilter.C AdcFilter.h作为于底层文件后续代码移植无需更改.

AdcFilter_Cfg.c AdcFilter_Cfg.h作为配置文件根据需求更改添加或减少ADC采样滤波channel.

2.AdcFilter_Cfg.h 

2.1声明配置结构体成员变量分别如下

typedef struct sTag_TsADCFA_h_Struct_Algorithm
{
    uint16 *e_p_AdcFilterBuffer;          /**<Start address of the receiver  buffer. */
    uint16 e_w_AdcFilterSize;             /**<Size of the  buffer. */
    uint16 e_w_AdcFilterCnt;              /**<Counter of the buffer. */
    uint8 e_w_AdcFilterflag;
    uint8 e_e_AdcSource;                  /**<the adc source to padding buffer. */  
}TsADCFA_h_Struct_Algorithm;
由于项目特殊性,不是直接从芯片寄存器中取对应通道实时的ADC采样值,中间层通过Davinci 配置了ADC底层驱动,最后每个通道的ADC都实时从两个length为18的buffer中取即可。
*e_p_AdcFilterBuffer 每个参与滤波的buffer地址
e_w_AdcFilterSize buffer 深度
e_w_AdcFilterCnt buffer 采样计数值
e_w_AdcFilterflag 满buffer标记
 
2.2声明结构体
typedef struct STag_TsADCFA_h_ConfigType
{
    TsADCFA_h_Struct_Algorithm *e_p_ChannelConfigPtr;/**<The pointer e_p_ChannelConfigPtr to the structure TsADCFA_h_Struct_Algorithm . */
}TsADCFA_h_ConfigType;  

 成员变量为指向2.1配置结构体的指针.

2.3 extern声明结构体数组
extern const TsADCFA_h_ConfigType TsADCFA_h_Configuration[];

数组值为2.2结构体指针.

3.AdcFilter_Cfg.c

3.1 定义配置结构体数组并赋值
static TsADCFA_h_Struct_Algorithm TsADCFA_h_ChannelConfiguration[e_e_Max_CH] =
{
    /* index 0 */
    {
        VaADCFA_w_AntennaSwitch1,
        CeADCFA_u_BUBBLESORT_SIZE,
        0U,
        0U,
        e_e_ADCFA_Ant_lte1,
    },
    {
        VaADCFA_w_AntennaSwitch2,
        CeADCFA_u_BUBBLESORT_SIZE,
        0U,
        0U,
        e_e_ADCFA_Ant_lte2,
    },
}
3.2 定义结构体数组并赋值
const TsADCFA_h_ConfigType TsADCFA_h_Configuration[] =
{
    {
        &TsADCFA_h_ChannelConfiguration[0]
    },
    {
        &TsADCFA_h_ChannelConfiguration[1]
    },
}

后续需要更新ADC采样滤波需求直接更该 TsADCFA_h_ChannelConfiguration 和 TsADCFA_h_Configuration 成员变量即可,真是前期基础打好后面需求更新不费吹灰之力,直接配几个参数就能调接口取值。

 4.AdcFilter.c
4.1Padding adc buffer
函数调用时只需传入对应需要采样的channel
函数内部定义结构体指针指向 TsADCFA_h_Struct_Algorithm 类型的结构体,
void Filter_IF_PaddingAdcBuffer(TsADCFA_e_Channel Ls_ADCFA_e_channel)
{
    TsADCFA_h_Struct_Algorithm  *Lp_ADCFA_h_Ptr;
    uint16 Le_ADCFA_w_temp;
    
    Lp_ADCFA_h_Ptr = &(TsADCFA_h_Configuration->e_p_ChannelConfigPtr[Ls_ADCFA_e_channel]);
    if(Lp_ADCFA_h_Ptr->e_e_AdcSource < e_e_ADCFA_Max_ADSOURE)
    {
        /* Get ADC value from the ADC buffer */
        if(Lp_ADCFA_h_Ptr->e_e_AdcSource < 18U)
        {
            Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[Lp_ADCFA_h_Ptr->e_w_AdcFilterCnt]=VaADC_w_Group0_12AdTableBuff[Lp_ADCFA_h_Ptr->e_e_AdcSource];
        }
        else
        {
            Le_ADCFA_w_temp = Lp_ADCFA_h_Ptr->e_e_AdcSource ;
            Le_ADCFA_w_temp = Le_ADCFA_w_temp -18U;
            Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[Lp_ADCFA_h_Ptr->e_w_AdcFilterCnt]=VaADC_w_Group1_12AdTableBuff[Le_ADCFA_w_temp];

        }
        Lp_ADCFA_h_Ptr->e_w_AdcFilterCnt++;
        /* Time reach */
        if(Lp_ADCFA_h_Ptr->e_w_AdcFilterCnt >= Lp_ADCFA_h_Ptr->e_w_AdcFilterSize)
        {
            Lp_ADCFA_h_Ptr->e_w_AdcFilterCnt = 0U;
            Lp_ADCFA_h_Ptr ->e_w_AdcFilterflag =1U;
        }
        else
        {
            ;/*do nothing*/
        }
    }
}

4.2 BubbleSort get average value alogorithm

void Filter_IF_BubbleSortFunc(TsADCFA_e_Channel Ls_ADCFA_e_channel,uint16* Ls_ADCFA_e_Value)
{
    uint16  LeADCFA_u_Big = 0U;                                          /*Bubble sort max value position*/
    uint16  LeADCFA_u_Small = 0U;                                        /*Bubble sort min value position*/
    uint16  LeADCFA_u_Temp = 0U;                                         /*Bubble sort middle value*/
    uint16  LeADCFA_u_TempValue1 = 0U;                                   /*size1 of Bubble sort array*/
    uint16  LeADCFA_u_TempValue2 = 0U;                                   /*size2 of Bubble sort array*/
    uint16  LeADCFA_w_Buffersize = 0U;
    TsADCFA_h_Struct_Algorithm  *Lp_ADCFA_h_Ptr;

    Lp_ADCFA_h_Ptr = &(TsADCFA_h_Configuration->e_p_ChannelConfigPtr[Ls_ADCFA_e_channel]);
    if (Lp_ADCFA_h_Ptr->e_w_AdcFilterflag == 1U)
    {
        LeADCFA_w_Buffersize = Lp_ADCFA_h_Ptr->e_w_AdcFilterSize;
    }
    else
    {
        LeADCFA_w_Buffersize = Lp_ADCFA_h_Ptr->e_w_AdcFilterCnt +1U;
    }       
    if(LeADCFA_w_Buffersize < 2)
    {
      LeADCFA_u_Temp = Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_w_Buffersize];
    }
    else
    {
        LeADCFA_u_TempValue1 = LeADCFA_w_Buffersize -1U;
        for(LeADCFA_u_Big = 0U; LeADCFA_u_Big < LeADCFA_u_TempValue1; LeADCFA_u_Big++)
        {
            LeADCFA_u_TempValue2 = LeADCFA_u_Big + 1U;
            for(LeADCFA_u_Small = LeADCFA_u_TempValue2; LeADCFA_u_Small <= LeADCFA_u_TempValue1; LeADCFA_u_Small++)
            {
                if(Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_u_Big] > Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_u_Small])
                {
                    LeADCFA_u_Temp = Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_u_Big];
                    Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_u_Big] = Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_u_Small];
                    Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_u_Small] = LeADCFA_u_Temp;
                }
            }
        }
        LeADCFA_u_TempValue1 = LeADCFA_w_Buffersize & 0x01U;     /*Judge parity*/
        if(0U != LeADCFA_u_TempValue1)                           /*odd number: take the median*/
        {
            LeADCFA_u_Temp = Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_w_Buffersize / 2U];
        }
        else                                                                     /*even number: take the average*/zh
        {
            LeADCFA_u_Temp = (Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[(LeADCFA_w_Buffersize / 2U) - 1U] + Lp_ADCFA_h_Ptr->e_p_AdcFilterBuffer[LeADCFA_w_Buffersize / 2U]) / 2U;
        }
    }
    *Ls_ADCFA_e_Value = LeADCFA_u_Temp;
}
 
总结:代码分层处理
1.定义一个结构体StructA 成员为底层函数需要调用的可变参数;
typedef struct
{
    uint16 *e_p_AdcFilterBuffer;         
    uint16 e_w_AdcFilterSize;            
    uint16 e_w_AdcFilterCnt;              
    uint8 e_w_AdcFilterflag;
    uint8 e_e_AdcSource;                  
}StructA;

2.再定义一个数组TableA 数组中元素为类型为StructA 的结构体;

static TableA[2] =
{
    /* index 0 */
    {
        VaADCFA_w_AntennaSwitch1,
        CeADCFA_u_BUBBLESORT_SIZE,
        0U,
        0U,
        e_e_ADCFA_Ant_lte1,
    },
    {
        VaADCFA_w_AntennaSwitch2,
        CeADCFA_u_BUBBLESORT_SIZE,
        0U,
        0U,
        e_e_ADCFA_Ant_lte2,
    },
}

3.定义一个结构体StructB 成员为指向StructA类型结构体的指针;

typedef struct
{
    StructA *Ptr2A;
}SructB;

4.再定义一个数组TableB 存放StructB 类型的结构体,初始化TableB 元素值为TableA 每个元素的首地址,即TableB元素为指向StructA类型结构体的指针;

const StructB TableB[] =
{
    {
        &TableA[0]
    },
    {
        &TableA[1]
    }
}

5.如何在底层函数调用配置的可变参的结构体呢?

  5.1在函数内毒定义一个指针变量*Ptr,该指针变量指向SructA 类型的结构体

    StructA  *Ptr;

  5.2通过传入channel,该channel 对应的就是TableB 每一个数值的位置,channel = 0 代表取Table[0]的值

    Ptr = &(TableB ->Ptr2A[channel]);

    将TableA中元素对应首地址赋值给Ptr

  5.3 Ptr->e_w_AdcFilterSize 便能直接访问可变参数。

End ~撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★* 

原文地址:https://www.cnblogs.com/smy87/p/14303606.html