Other Parts Discussed in Thread: LF353, TINA-TI
主题中讨论的其他器件: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);
}
}


