• 笔记—代码平台化思维


    代码平台化分层处理有很多好处,方便移植,减少迭代代码的更改,特别是量产后更改代码引入致命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 ~撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★* 

  • 相关阅读:
    linux磁盘管理
    yarn一直在跑一个用户为dr.who的application
    HBASE强制删除表
    Centos安装git2.2.1
    MySQL类型float double decimal的区别
    PHP的extension_dir设置问题
    opencart安装和使用PHPMailer
    在路上
    修改win10中linux子系统的root密码
    关于js for循环click事件
  • 原文地址:https://www.cnblogs.com/smy87/p/14303606.html
Copyright © 2020-2023  润新知