2017年8月9日 星期三

ADC平均方式

一般在MCU進行ADC時,通常會因為雜訊等問題而需要做濾波,最常見的軟體濾波方式就是平均,在此將介紹幾種平均方式:
(1)算術平均,原理可以參考WIKI : 算術平均數(Arithmetic mean)是表征數據集中趨勢的一個統計指標。它是一組數據之和,除以這組數據個數/項數。算術平均數在統計學上的優點,就是它較中位數、眾數更少受到隨機因素影響,缺點是它更容易受到極端值影響。計算公式為:
在MCU的使用當中,由於程式的設計攸關效能及所佔記憶體空間大小,因此通常會將平均方式調整為2^n,假設要做八次的平均,則為(X[0]+X[1]+X[2]+X[3]+...X[7]) / 8, 除8有必要提出來說明一下,因為很多MCU沒有除法這樣的硬體,因此通常都會將除以8(8 = 2^3)改為右移3bit來達到同樣的功能!
(2)簡單的移動平均(節省data memory的做法) : 簡單來說就是將前8筆資料加總為Sum, 然後Avg = Sum / 8; 就得到第一次8筆資料的算術平均結果為Result, 下一次做平均時則先進行Sum -= Sum / 8; 然後再將新的資料加進來Sum += New; 再將結果Sum /= 8; 得到新的平均Avg
Example code : 
for(Samples = 0; Samples < 32; Samples++) // Over sampling 32 times
{
        __delay_us(20);
        ADGO = 1;
        while(!ADIF);
        ADIF = 0;
        ADC_Result.Byte[0] = ADRESL;
        ADC_Result.Byte[1] = ADRESH;
        ADC_SUM += ADC_Result.Word;
}
ADC_SUM >>= 5; // ADC_SUM / 32
if(!FLAGbits.ADCMovAvgOk)
{
        ADCMovAvgSUM += ADC_SUM;
        ADCMovAvgIndex++;
        AdcMovAvg = (ADCMovAvgSUM / ADCMovAvgIndex);
        if(ADCMovAvgIndex == 8)
{
ADCMovAvgIndex = 0;
FLAGbits.ADCMovAvgOk = 1;
}
}
else
{
ADCMovAvgSUM -= (ADCMovAvgSUM >> 3);
ADCMovAvgSUM += ADC_SUM;
AdcMovAvg = (ADCMovAvgSUM >> 3);
}
(3)複雜移動平均(耗費data memory空間) : 假設做8筆的移動平均,則需先開一個陣列Buf可存放8筆數據的大小,並宣告一個陣列的索引Index且設定初值為0, 每次存放一筆資料於Buf[Index]則將Index加1,等Index等於8時,陣列為放滿的階段,Index歸零,並執行第一次加總平均得到結果Sum = (X[0]+X[1]+...+X[7] / 8); Result = Sum / 8; 下一次新的資料進來時,此時Index會指向Buf最舊的那筆數據的空間,並將新的數據存入Buf[Index]一筆數據的位置,然後Index加1,再重新做加總平均得到新的平均值,以此類推重複循環!



STM32於IAR 9.3以後的版本將uart導向至printf

首先,請先參考如以下IAR提供的"在IAR Embedded Workbench中实现打印输出技術資料" https://www.iar.com/cn/knowledge/support/technical-notes/general/implementing-printf-ou...