Other Parts Discussed in Thread: LF353, TINA-TI
Hello everyone,
I need to obtain a radiation spectrometer using the ADC of the C2000 launchpad. The ADC configuration has been set to sample at the fastest rate possible. I confirmed from the oscilloscope that I can sample at intervals of 600 ns when controlled with the ISR. The signal from a CZT-type semiconductor detector is amplified with a Cremat preamplifier. The signal output seen on the oscilloscope varies between 300-600 mV depending on the radiation source. The rise time of the signal at the preamplifier output is approximately 2 microseconds. I believe that sampling at 600 ns intervals should be sufficient. I'm sure the ADC is working correctly because I can sample sine and square waves at 1 MHz from a signal generator and capture the peak points. However, for some reason, when I connect the preamplifier output to the ADC input, I can read zero or near-zero values. Could this be due to impedance mismatch? If not, what recommendations do you suggest for troubleshooting? The code attached below.
#include "F28x_Project.h" // Cihaz Başlık Dosyası ve Örnekler Dahil Dosyası
#define DATA_SIZE 128
float input_data[DATA_SIZE] = {0}; // ADC'den gelen veri dizisi
float filtered_data[DATA_SIZE] = {0}; // Filtrelenmiş veri dizisi
float Result = 0;
float peak_value;
// ADC verilerini okuyan ve filtreleyen fonksiyon
void ReadAndFilterADCData() {
int i;
// ADC'den veri oku ve input_data dizisine kaydet
for(i = 0; i < DATA_SIZE; i++) {
input_data[i] = AdcaResultRegs.ADCRESULT0;
// Örneğin AdcaResultRegs.ADCRESULT0, ADC'nin sonuç kaydı
// Bu, gerçek donanımınıza göre değişebilir
}
// Trapezoidal filtreleme işlemi
for(i = 0; i < DATA_SIZE; i++) {
// İlk iki ve son iki örneği doğrudan kopyala
if(i < 2 || i >= DATA_SIZE - 2) {
filtered_data[i] = input_data[i];
} else {
// Trapezoidal filtreleme
filtered_data[i] = (input_data[i - 2] + 2 * input_data[i - 1] + 2 * input_data[i] + 2 * input_data[i + 1] + input_data[i + 2]) / 8.0;
}
}
}
// Tepe noktasını bulan fonksiyon
float FindPeak(float filtered_data[], int data_size) {
float peak_value = filtered_data[0]; // Tepe noktasının başlangıç değeri, dizinin ilk elemanı olarak belirlenir
// Tüm diziyi tarayarak tepe noktasını bul
int i;
for (i = 1; i < data_size; i++) {
// Eğer mevcut eleman tepe değerinden büyükse, tepe değeri güncellenir
if (filtered_data[i] > peak_value) {
peak_value = filtered_data[i];
}
}
// Bulunan tepe değeri döndürülür
return peak_value;
}
interrupt void adcint1_isr(void) {
Result = AdcaResultRegs.ADCRESULT0;
//GpioDataRegs.GPBTOGGLE.bit.GPIO32 = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Kesme bayrağını temizle
}
void main(void) {
// Sistem Kontrolünü Başlat:
// PLL, WatchDog, Periferik Saatleri etkinleştir
InitSysCtrl();
// Tüm kesmeleri temizleyin ve PIE vektör tablosunu başlatın:
// CPU kesmelerini devre dışı bırak
DINT;
// PIE kontrol kayıtlarını varsayılan durumlarına başlatın.
// Varsayılan durum, tüm PIE kesmelerinin devre dışı bırakılması ve bayrakların temizlenmesidir.
InitPieCtrl();
// CPU kesmelerini devre dışı bırakın ve tüm CPU kesme bayraklarını temizleyin:
IER = 0x0000;
IFR = 0x0000;
// PIE vektör tablosunu kabuk Kesme Servis Rutinlerine (ISR) işaretçilerle başlatın.
// Bu, kesme kullanılmıyor olsa bile tüm tabloyu doldurur.
// Bu, hata ayıklama amaçları için yararlıdır.
// Kabuk ISR rutinleri, F2837xD_DefaultIsr.c dosyasında bulunur.
InitPieVectTable();
// Global Kesmeleri ve daha yüksek öncelikli gerçek zamanlı hata ayıklama olaylarını etkinleştirin:
//EINT; // Global kesmeyi etkinleştir INTM
//ERTM; // Global gerçek zamanlı kesmeyi etkinleştir DBGM
EALLOW;
// GPIO34'ü Başlat:
GpioCtrlRegs.GPBGMUX1.bit.GPIO32 = 0;
GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 0; // Pini GPIO olarak yapılandır
GpioCtrlRegs.GPBDIR.bit.GPIO32 = 1; // GPIO34'ü çıkış olarak tanımla
GpioDataRegs.GPBDAT.bit.GPIO32 = 1; // Çıkış kilitlenmesine 1 girin
// Timer0 kesmesi için dönem değerini yükle
CpuTimer0Regs.PRD.all = 30 - 1; // Varsayılan 2000
CpuTimer0Regs.TPR.bit.TDDR = 0; // Zamanlayıcı için öncül değeri 1 olarak ayarla
CpuTimer0Regs.TCR.bit.TSS = 1; // Zamanlayıcıyı durdur
CpuTimer0Regs.TCR.bit.TRB = 1; // Zamanlayıcıyı yeniden yükle
CpuTimer0Regs.TCR.bit.TIE = 1; // Zamanlayıcı0 kesmesini periferik seviyede etkinleştir
CpuTimer0Regs.TCR.bit.TSS = 0; // Zamanlayıcıyı başlat
// ADC için ayarları yap
AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // ADCCLK bölenini /4 olarak ayarla
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // ADC'yi etkinleştir
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // Kesme darbesi pozisyonlarını geç ayarlara ayarla
AdcaRegs.ADCCTL2.bit.RESOLUTION = 0; // 12-bit çözünürlük
AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0; // Tek bitişik (sadece 12-bit modu)
// ADC kullanmadan önce en az 500 mikrosaniye gecikme olmalı
DELAY_US(1000);
// ADC'nin dönüştürme yapacağı pini belirle
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 1; // SOC0 pini ADCINA0'ı dönüştürecek
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15 - 1; // Örnekleme penceresi 8000 SYSCLK döngüsü
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0x01; // CPU Timer 0 ile tetikle
// ADCINT1'in EOC0 bayrağını ayarla
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // EOC0 INT1 bayrağını ayarlar
AdcaRegs.ADCINTSEL1N2.bit.INT1CONT = 1; // Kesmeler oluşturulacak
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // INT1 bayrağını etkinleştir
// ISR adresini yeniden yönlendir:
PieVectTable.ADCA1_INT = &adcint1_isr;
// PIE bloğunu etkinleştir
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
// PIE Grup 1 INT1 ADCA1'i etkinleştir
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
// CPU INT1'i etkinleştir (Xint1 dahil)
IER |= M_INT1;
// Global kesme maskesini etkinleştir (INTM)
EINT;
// Gerçek zamanlı kesme maskesini etkinleştir (DBGM)
ERTM;
EDIS;
// Ana döngü
while(1) {
ReadAndFilterADCData();
peak_value = FindPeak(filtered_data, DATA_SIZE);
}
}


