代码平台化分层处理有很多好处,方便移植,减少迭代代码的更改,特别是量产后更改代码引入致命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;
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配置结构体的指针.
extern const TsADCFA_h_ConfigType TsADCFA_h_Configuration[];
数组值为2.2结构体指针.
3.AdcFilter_Cfg.c
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, }, }
const TsADCFA_h_ConfigType TsADCFA_h_Configuration[] = { { &TsADCFA_h_ChannelConfiguration[0] }, { &TsADCFA_h_ChannelConfiguration[1] }, }
后续需要更新ADC采样滤波需求直接更该 TsADCFA_h_ChannelConfiguration 和 TsADCFA_h_Configuration 成员变量即可,真是前期基础打好后面需求更新不费吹灰之力,直接配几个参数就能调接口取值。
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; }
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 ~撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★*