主题中讨论的其他器件:LF353、 TINA-TI
大家好!
我需要使用 C2000 Launchpad 的 ADC 获得辐射光谱仪。 ADC 配置已设置为以尽可能最快的速率采样。 我从示波器中确认、当使用 ISR 进行控制时、可以以600ns 的间隔进行采样。 来自 CZT 型半导体探测器的信号通过 Cremat 前置放大器放大。 示波器上的信号输出在300-600mV 之间变化、具体取决于辐射源。 前置放大器输出端信号的上升时间约为2微秒。 我认为以600ns 的间隔进行采样就足够了。 我确信 ADC 工作正常、因为我可以在1 MHz 处从信号发生器对正弦波和方波进行采样并捕获峰值点。 但是、出于某种原因、当我将前置放大器输出连接到 ADC 输入时、我可以读取零或接近零的值。 这可能是由于阻抗不匹配造成的? 如果不是、您建议哪些故障排除建议? 下面随附的代码。
#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); } }