This code shows an IIR 2nd order section.
The numerator coefficients are b=[1 0 -1];
The Denominator Coeffs are a=[1 -2rcos(\theta) r^2]; r=.8; th=pi/3;
For implementation in integer arithmetic in the PIC thte coeffs become:
b=[127 0 -128]; a=[ 127 -110 104];
The code is given followed by output from the WATCH table, which shows the response to an impulse input magnitude 50.
Then a MATLAB simulation is presented which gives the exact same integer values for the example.
Code:
// // Example C code for 2nd order IIR filter // // RGH 2012 richard.hayes@dit.ie #include <p18f4620.h> void main(void) { int yint; // temp variable for 16 bit multiply result char b0=127, b1=0, b2=-128, a1=-111, a2=82; char x=50, x1=0, x2=0, y=0, y1=0, y2=0; int bit_shift = 7; int dc_shift = 128; int voltage; char datain[13]={128+50,128,128,128,128,128,128,128,128,128,128,128,128}; char dataout[13]; int i=0; // Operating Loop //x=50; //i=0; while (i<12) { x=datain[i]-dc_shift; // Remove DC level from a/d i/p //Implement the filter and crudely update the 'past' input and output x and y values yint = (int)b0*x+(int)b1*x1+(int)b2*x2-(int)a1*y1-(int)a2*y2; y=(char)(yint>>bit_shift); // 8- bit result from filter. Note type casting y2 = y1; y1 = y; x2 = x1; x1 = x; dataout[i]=y; // Save output; this will be output to D/A x=0; i=i+1; } }
WATCH TABLE variable dataout
Update Symbol Name Hex Decimal Binary
dataout
[0] 0x31 49 00110001
[1] 0x2A 42 00101010
[2] 0xD3 -45 11010011
[3] 0xBE -66 10111110
[4] 0xE3 -29 11100011
[5] 0x11 17 00010001
[6] 0x21 33 00100001
[7] 0x11 17 00010001
[8] 0xF9 -7 11111001
[9] 0xEF -17 11101111
[10] 0xF5 -11 11110101
[11] 0x01 1 00000001
[12] 0x00 0 00000000
b0 0x7F 127 01111111
Now compare these results with the output from the following MATLAB programme:
% Simulation of integer operation of IIR filter % The filter is implemented in 'C' for the PIC18 % The aim is to 'exactly match the integer behaviour % of the microcontroller clear all b0=127; b1=0; b2=-127; a1=-111; a2=82; x1=0; x2=0; y1=0; y2=0; x=50; i=0; for i=0:20 yint(i+1) = b0*x + b1*x1 + b2*x2 - a1*y1 - a2*y2 ; y(i+1)=floor(yint(i+1)/(128)); y2 = y1;y1 = y(i+1); x2 = x1;x1 = x; x=0; i=i+1; %pause end i=0:20; subplot(2,1,1);stem(i,y) subplot(2,1,2);stem(i,yint)
MATLAB Output:
49,42,-45,-66,-29,17,33,17,-7,-17,-11,1,7,5,-1,-5,-4,-1,1,1,0,…
Filed under: Digital Filters, example c code