AVR SDR
My project on mega 644 ...
#include <math.h>
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define Ntap 31
#define DCgain 32768
#define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (0<<ADLAR)) // Внутренне опорное напряжение 2,56 Вольта
#define LED_PORT PORTC
#define Led_I 1
#define Led_Q 2
#define Led_Run 0
// Глобальные переменные
int OutSample,I,Q,N,X1,X2,X3,Y1,Y2,Y3;
float count=0;
int led_flag=0;
int cos_N[4]={1,0,-1,0};
int sin_N[4]={0,1,0,-1};
int sin_N_m[4]={0,-1,0,1};
// Читаем ADC
int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | ADC_VREF_TYPE;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
// Wait for the AD conversion to complete
while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW-512; // Убираем постоянную составляющую (преобразуем однополярный сигнал в двухполярный)
}
// Инициализация ADC
void adc_init(void)
{
DIDR0=(0<<ADC7D) | (0<<ADC6D) | (0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D);
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
}
// Настройка генератора
void clk_init(void)
{
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
}
// Инициализация портов
void port_init(void)
{
// Порт А на ввод ADC (подтягивающие резисторы не включены)
PORTA=0x00;
DDRA=0x00;
// Порт С на вывод
PORTC=0x00;
DDRC=0xFF;
// Порт D на вывод
PORTD=0x00;
DDRD=0xFF;
}
// Настройки таймера 1 (Срабатывание по совпадению)
void timer_init(void)
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 312,500 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 0,20972 s
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x01;
OCR1AL=0x77;
OCR1BH=0x00;
OCR1BL=0x00;
// Включение прерываний по таймеру
TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (1<<OCIE1A) | (0<<TOIE1);
}
// Фильтр канала I
int fir_I(int NewSample) {
int FIRCoef[Ntap] = {
-406,
-207,
529,
240,
-698,
-274,
942,
308,
-1317,
-338,
1972,
363,
-3441,
-379,
10572,
17042,
10572,
-379,
-3441,
363,
1972,
-338,
-1317,
308,
942,
-274,
-698,
240,
529,
-207,
-406
};
static int x[Ntap]; //input samples
long int y=0; //output sample
int n;
//shift the old samples
for(n=Ntap-1; n>0; n--)
x[n] = x[n-1];
//Calculate the new output
x[0] = NewSample;
for(n=0; n<Ntap; n++)
y += FIRCoef[n] * x[n];
return y / DCgain;
}
// Фильтр канала Q
int fir_Q(int NewSample) {
int FIRCoef[Ntap] = {
-406,
-207,
529,
240,
-698,
-274,
942,
308,
-1317,
-338,
1972,
363,
-3441,
-379,
10572,
17042,
10572,
-379,
-3441,
363,
1972,
-338,
-1317,
308,
942,
-274,
-698,
240,
529,
-207,
-406
};
static int x[Ntap]; //input samples
long int y=0; //output sample
int n;
//shift the old samples
for(n=Ntap-1; n>0; n--)
x[n] = x[n-1];
//Calculate the new output
x[0] = NewSample;
for(n=0; n<Ntap; n++)
y += FIRCoef[n] * x[n];
return y / DCgain;
}
// Обработчик прерывания по таймеру 1200 Гц
ISR (TIMER1_COMPA_vect)
{
if (N==3)
{
N=0;
}
else N++;
I=read_adc(0);
Q=read_adc(1);
X1=I*cos_N[N]+Q*sin_N[N];
X2=fir_I(X1);
X3=X2*cos_N[N];
Y1=I*sin_N_m[N]+Q*cos_N[N];
Y2=fir_Q(Y1);
Y3=Y2*sin_N_m[N];
OutSample=X3+Y3;
PORTD=OutSample+512;// восстанавливаем однополярный сигнал
}
int main (void)
{
//Инициализация ADC
adc_init();
//Инициализация генератора
clk_init();
// Инициализация портов
port_init();
// Инициализация таймера
timer_init();
// Разрешение прерываний
sei();
while(1)
{
// Led_Run индикатор просчета фильтров
if (count==1000)
{
led_flag=1;
}
else
{
count++;
}
if (led_flag==1)
{
LED_PORT |= 1 << Led_Run; //зажечь
led_flag=0;
count=0;
}
else
{
LED_PORT &= ~(1 << Led_I);// Гасим
}
if (I==0)
{
// Зажигаем диод I
LED_PORT |= 1 << Led_I; //зажечь
}
else
{
// Гасим диод I
LED_PORT &= ~(1 << Led_I);// Гасим
}
if (Q==0)
{
// Зажигаем диод Q
LED_PORT |= 1 << Led_Q; //зажечь
}
else
{
// Гасим диод Q
LED_PORT &= ~(1 << Led_I);// Гасим
}
}
}