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); } }