Other Parts Discussed in Thread: CONTROLSUITE
Tool/software: Code Composer Studio
Hello,
I am trying to convert a 2.5V DC voltage without essential noise via the channels ADCDIN2 and ADCDIN3 (voltage is applicated on both channels and was measured via a multimeter directly at the ADC channel pins) of the ADCD module on my microcontroller. The control of the AdcdRegsiters is given to CPU2 and the triggering of the two SOCs is done by CPU2 too. Both projects (one project per core) are projects with Operating System. The two SOCs are triggered by the clock module of the OS every 10 milliseconds. The expected value is 2.5/3.3*4096=3103, since I am operating in 12-bit resolution.
The problem presents itself as follows: AdcdResultRegister shows values round about 2300 instead of the expected round about 3100.
What I have observed: I have also ADCA module working as expected without errors in my application which I initialize and trigger (I will post my code later at the end of my text) the exact same way as ADCD module.
What I have observed by accident: When I load the .out file of CPU1 on CPU2, let it run, don't reset the device, after that load the correct .out file of CPU2 on CPU2 and let this program run, the ADCD module works as expected and shows values round about 3000-3100 in the AdcdResultRegister! When I reset the device I must run CPU1 .out file on CPU2 first before the ADCD works as expected again. Seems to me, that something in the .out file of CPU1 initializes something in the microcontroller, that is required for ADCD module to work properly (but apparently not necessary for ADCA module, since this works fine with normal load and running of the cores), that is deleted when the device is reset.
I hope you have some advice for me and I say thanks in advance.
Code of CPU1:
main_1.c:
Int main() { System_printf("enter main()\n"); InitGpio(); InitDrehzahlsensoren(); InitSF_DC_Test(); #ifdef _STANDALONE IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH); #endif BIOS_start(); return(0); }
Drehzahlsensoren_1.c:
#include <Drehzahlsensoren_1.h> //Initialisiert die ECap1 Peripherie, die die Flanken des Drehzahlsensors 1 erkennt void InitDrehzahlerkennung_1() { EALLOW; InputXbarRegs.INPUTSELECTLOCK.bit.INPUT7SELECT = 0; //INPUTXBAR7 Einstellungen werden freigeschaltet InputXbarRegs.INPUT7SELECT = 94; //GPIO 94 wird mit INPUTXBAR7 verbunden InputXbarRegs.INPUTSELECTLOCK.bit.INPUT7SELECT = 1; //INPUTXBAR7 Einstellungen werden verriegelt DevCfgRegs.CPUSEL1.bit.ECAP1 = 1; //ECap1 Register werden mit CPU2 verbunden EDIS; } //Initialisiert die ECap2 Peripherie, die die Flanken des Drehzahlsensors 2 erkennt void InitDrehzahlerkennung_2() { EALLOW; InputXbarRegs.INPUTSELECTLOCK.bit.INPUT8SELECT = 0; //INPUTXBAR8 Einstellungen werden freigeschaltet InputXbarRegs.INPUT8SELECT = 90; //GPIO 94 wird mit INPUTXBAR8 verbunden InputXbarRegs.INPUTSELECTLOCK.bit.INPUT8SELECT = 1; //INPUTXBAR8 Einstellungen werden verriegelt DevCfgRegs.CPUSEL1.bit.ECAP2 = 1; //ECap2 Register werden mit CPU2 verbunden EDIS; } void InitDS_DC_Test() { EALLOW; DevCfgRegs.CPUSEL11.bit.ADC_D = 1; //ADCD Register werden mit CPU2 verbunden EDIS; } //Initialisiert die ECap3 Peripherie, die das PWM Signal für den ersten ADC erzeugt void InitADC1MCLK() { GPIO_SetupPinMux(3, GPIO_MUX_CPU1, 2); //GPIO3 wird von CPU1 gesteuert und mit OUTPUTXBAR2 verbunden GPIO_SetupPinOptions(3, GPIO_OUTPUT, GPIO_PUSHPULL); //GPIO3 wird als Output konfiguriert EALLOW; OutputXbarRegs.OUTPUT2MUX0TO15CFG.bit.MUX4 = 3; //Der ECap3 Output wird mit MUX4 der OUTPUTXBAR2 verbunden OutputXbarRegs.OUTPUT2MUXENABLE.bit.MUX4 = 1; //Der Slot MUX4 der OUTPUTXBAR2 wird aktiviert DevCfgRegs.CPUSEL1.bit.ECAP3 = 1; //ECap3 Register werden mit CPU2 verbunden EDIS; } //Initialisiert die ECap4 Peripherie, die das PWM Signal für den zweiten ADC erzeugt void InitADC2MCLK() { GPIO_SetupPinMux(2, GPIO_MUX_CPU2, 5); //GPIO2 wird von CPU2 gesteuert und mit OUTPUTXBAR1 verbunden GPIO_SetupPinOptions(2, GPIO_OUTPUT, GPIO_PUSHPULL); //GPIO2 wird als Output konfiguriert EALLOW; OutputXbarRegs.OUTPUT1MUX0TO15CFG.bit.MUX6 = 3; //Der ECap3 Output wird mit MUX4 der OUTPUTXBAR1 verbunden OutputXbarRegs.OUTPUT1MUXENABLE.bit.MUX6 = 1; //Der Slot MUX4 der OUTPUTXBAR1 wird aktiviert DevCfgRegs.CPUSEL1.bit.ECAP4 = 1; //ECap4 Register werden mit CPU2 verbunden EDIS; } void InitDrehzahlsensoren() { InitDrehzahlerkennung_1(); InitDrehzahlerkennung_2(); InitADC1MCLK(); InitADC2MCLK(); InitDS_DC_Test(); }
Schwingungsfuehler_1.c:
#include "Schwingungsfuehler_1.h" void InitSF_DC_Test() { EALLOW; DevCfgRegs.CPUSEL11.bit.ADC_A = 1; //ADCA Register werden mit CPU2 verbunden EDIS; }
Code of CPU2:
main_2.c:
#include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> #include "main_2.h" Int main() { System_printf("enter main()\n"); InitDrehzahlsensoren(); InitSF_DC_Test(); BIOS_start(); return(0); }
Drehzahlsensoren_2.c:
#include <Drehzahlsensoren_2.h>
//Initialisiert die ECap1 Peripherie, die die Flanken des Drehzahlsensors 1 erkennt
void InitDrehzahlerkennung_1()
{
EALLOW;
CpuSysRegs.PCLKCR3.bit.ECAP1 = 1; //ECap1 bekommt den Betriebstakt
ECap1Regs.ECCTL1.bit.CAP1POL = 0; //CEVT1 wird bei steigender Flanke gefeuert
ECap1Regs.ECCTL1.bit.CAP2POL = 0; //CEVT2 wird bei steigender Flanke gefeuert
ECap1Regs.ECCTL1.bit.CAP3POL = 0; //CEVT3 wird bei steigender Flanke gefeuert
ECap1Regs.ECCTL1.bit.CAP4POL = 0; //CEVT4 wird bei steigender Flanke gefeuert
ECap1Regs.ECCTL1.bit.CTRRST1 = 1; //Zähler wird nach CEVT1 zurückgesetzt
ECap1Regs.ECCTL1.bit.CTRRST2 = 1; //Zähler wird nach CEVT2 zurückgesetzt
ECap1Regs.ECCTL1.bit.CTRRST3 = 1; //Zähler wird nach CEVT3 zurückgesetzt
ECap1Regs.ECCTL1.bit.CTRRST4 = 1; //Zähler wird nach CEVT4 zurückgesetzt
ECap1Regs.ECCTL1.bit.CAPLDEN = 1; //CAP Register werden mit Time-Stamps der jeweiligen CEVTs geladen
ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; //Zähler des ECAP1 wird gestartet
ECap1Regs.ECEINT.bit.CEVT1 = 1; //CEVT1 feuert einen ECap1-Interrupt in Richtung CPU
EDIS;
}
//Initialisiert die ECap2 Peripherie, die die Flanken des Drehzahlsensors 2 erkennt
void InitDrehzahlerkennung_2()
{
EALLOW;
CpuSysRegs.PCLKCR3.bit.ECAP2 = 1; //ECap2 bekommt den Betriebstakt
ECap2Regs.ECCTL1.bit.CAP1POL = 0; //CEVT1 wird bei steigender Flanke gefeuert
ECap2Regs.ECCTL1.bit.CAP2POL = 0; //CEVT2 wird bei steigender Flanke gefeuert
ECap2Regs.ECCTL1.bit.CAP3POL = 0; //CEVT3 wird bei steigender Flanke gefeuert
ECap2Regs.ECCTL1.bit.CAP4POL = 0; //CEVT4 wird bei steigender Flanke gefeuert
ECap2Regs.ECCTL1.bit.CTRRST1 = 1; //Zähler wird nach CEVT1 zurückgesetzt
ECap2Regs.ECCTL1.bit.CTRRST2 = 1; //Zähler wird nach CEVT2 zurückgesetzt
ECap2Regs.ECCTL1.bit.CTRRST3 = 1; //Zähler wird nach CEVT3 zurückgesetzt
ECap2Regs.ECCTL1.bit.CTRRST4 = 1; //Zähler wird nach CEVT4 zurückgesetzt
ECap2Regs.ECCTL1.bit.CAPLDEN = 1; //CAP Register werden mit Time-Stamps der jeweiligen CEVTs geladen
ECap2Regs.ECCTL2.bit.TSCTRSTOP = 1; //Zähler des ECAP2 wird gestartet
ECap2Regs.ECEINT.bit.CEVT1 = 1; //CEVT1 feuert einen ECap2-Interrupt in Richtung CPU
EDIS;
}
void InitDS_DC_Test()
{
EALLOW;
CpuSysRegs.PCLKCR13.bit.ADC_D = 1; //ADCD bekommt den Betriebstakt
AdcdRegs.ADCCTL2.bit.PRESCALE = 6; //ADCLK = SYSCLK/4
AdcSetMode(ADC_ADCD, ADC_RESOLUTION_12BIT //ADCD auf 12 bit Auflösung und Singlemode eingestellt
, ADC_SIGNALMODE_SINGLE);
AdcdRegs.ADCCTL1.bit.ADCPWDNZ = 1; //ADCD wird eingeschaltet
DELAY_US(1000); //1 ms Wartezeit um ADCD komplett hochfahren zu lassen
AdcdRegs.ADCSOC0CTL.bit.CHSEL = 2; //SOC0 konvertiert Kanal 2
AdcdRegs.ADCSOC0CTL.bit.ACQPS = 15; //SOC0 S&H Window wird auf 16 SYSCLKs eingestellt
AdcdRegs.ADCSOC0CTL.bit.TRIGSEL = 0; //SOC0 wird mittels Software getriggert
AdcdRegs.ADCSOC1CTL.bit.CHSEL = 3; //SOC1 konvertiert Kanal 3
AdcdRegs.ADCSOC1CTL.bit.ACQPS = 15; //SOC1 S&H Window wird auf 16 SYSCLKs eingestellt
AdcdRegs.ADCSOC1CTL.bit.TRIGSEL = 0; //SOC1 wird mittels Software getriggert
EDIS;
}
void starteADCWandlungDS_DC() //alle 10ms
{
AdcdRegs.ADCSOCFRC1.bit.SOC0 = 1; //SOC0 wird getriggert; Abtastung Kanal 2
AdcdRegs.ADCSOCFRC1.bit.SOC1 = 1; //SOC1 wird getriggert; Abtastung Kanal 3
}
//Initialisiert die ECap3 Peripherie, die das PWM Signal für den ersten ADC erzeugt
void InitADC1MCLK()
{
CpuSysRegs.PCLKCR3.bit.ECAP3 = 1; //ECap3 bekommt den Betriebstakt
ECap3Regs.ECCTL2.bit.CAP_APWM = 1; //ECap3 arbeitet im AWPM Modus
ECap3Regs.CAP1 = 20000000; //Die Periodendauer der PWM beträgt 100ms
ECap3Regs.CAP2 = 5000000; //Die On Time der PWM beträgt 25 ms
ECap3Regs.ECCTL2.bit.TSCTRSTOP = 1; //Der Zähler des ECap3 wird gestartet
EDIS;
}
//Initialisiert die ECap4 Peripherie, die das PWM Signal für den zweiten ADC erzeugt
void InitADC2MCLK()
{
EALLOW;
CpuSysRegs.PCLKCR3.bit.ECAP4 = 1; //ECap4 bekommt den Betriebstakt
ECap4Regs.ECCTL2.bit.CAP_APWM = 1; //ECap4 arbeitet im AWPM Modus
ECap4Regs.CAP1 = 20000000; //Die Periodendauer der PWM beträgt 100ms
ECap4Regs.CAP2 = 5000000; //Die On Time der PWM beträgt 25 ms
ECap4Regs.ECCTL2.bit.TSCTRSTOP = 1; //Der Zähler des ECap4 wird gestartet
EDIS;
}
//Interrupt-Routine zum Verarbeiten der Time Stamps des ECap1-Moduls für die Berechnung
//von Drehzahl und Periodendauer
void hole_TimeStamps_1()
{
rpm_1 = (1.0/(ECap1Regs.CAP1*(1.0/CPU_FREQ)))*60.0; //Berechnung der Drehzahl
periode_1 = ECap1Regs.CAP1*(1.0/CPU_FREQ); //Berechnung der Periodendauer
ECap1Regs.ECCLR.bit.CEVT1 = 1; //CEVT1 Interrupt-Flag löschen
ECap1Regs.ECCLR.bit.INT = 1; //ECap1-Interrupt-Flag löschen
}
//Interrupt-Routine zum Verarbeiten der Time Stamps des ECap2-Moduls für die Berechnung
//von Drehzahl und Periodendauer
void hole_TimeStamps_2()
{
rpm_2 = (1.0/(ECap2Regs.CAP1*(1.0/CPU_FREQ)))*60.0; //Berechnung der Drehzahl
periode_2 = ECap2Regs.CAP1*(1.0/CPU_FREQ); //Berechnung der Periodendauer
ECap2Regs.ECCLR.bit.CEVT1 = 1; //CEVT1 Interrupt-Flag löschen
ECap2Regs.ECCLR.bit.INT = 1; //ECap2-Interrupt-Flag löschen
}
void DS_DC_Test_1()
{
power_ds1 = AdcdResultRegs.ADCRESULT0;
}
void DS_DC_Test_2()
{
power_ds2 = AdcdResultRegs.ADCRESULT1;
}
void InitDrehzahlsensoren()
{
InitDrehzahlerkennung_1();
InitDrehzahlerkennung_2();
InitADC1MCLK();
InitADC2MCLK();
InitDS_DC_Test();
}
Schwingungsfuehler_2.c:
#include "Schwingungsfuehler_2.h" void InitSF_DC_Test() { EALLOW; CpuSysRegs.PCLKCR13.bit.ADC_A = 1; //ADCA bekommt den Betriebstakt AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //ADCLK = SYSCLK/4 AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT //ADCA auf 12 bit Auflösung und Singlemode eingestellt , ADC_SIGNALMODE_SINGLE); AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; //ADCA wird eingeschaltet DELAY_US(1000); //1 ms Wartezeit um ADCA komplett hochfahren zu lassen AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; //SOC0 konvertiert Kanal 0 AdcaRegs.ADCSOC0CTL.bit.ACQPS = 15; //SOC0 S&H Window wird auf 16 SYSCLKs eingestellt AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0; //SOC0 wird mittels Software getriggert AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1; //SOC1 konvertiert Kanal 1 AdcaRegs.ADCSOC1CTL.bit.ACQPS = 15; //SOC1 S&H Window wird auf 16 SYSCLKs eingestellt AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0; //SOC1 wird mittels Software getriggert EDIS; } void starteADCWandlungSF_DC() //alle 10ms { AdcaRegs.ADCSOCFRC1.bit.SOC0 = 1; //SOC0 wird getriggert; Abtastung Kanal 0 AdcaRegs.ADCSOCFRC1.bit.SOC1 = 1; //SOC1 wird getriggert; Abtastung Kanal 1 } void SF_DC_Test_1() //alle 10ms { if(periode_1 > 0.1) //wenn Unwuchtsignal unter 10Hz (600 U/min) { static Uint16 counter = 0; //Zählervariable für bereits abgetastete Werte static Uint32 mittelwert_summe = 0; //Variable für das Aufsummieren der Abtastwerte mittelwert_summe += AdcaResultRegs.ADCRESULT0; //Aufsummieren des aktuellen Abtastwertes counter++; //Erhöhen der Zählervariable if(counter >= periode_1/0.01) //wenn eine Periode abgetastet wurde { mittelwert_summe /= counter; //Division der Summe der Abtastwerte durch Anzahl der Abtastwerte dc_sf_signal_1 = mittelwert_summe; //Gleichspannung des ersten SFs beträgt ermittelten Mittelwert mittelwert_summe = 0; //Summenvariable zurücksetzen für neue Berechnung counter = 0; //Zählervariable zurücksetzen für neue Berechnung } }else //wenn Unwuchtsignal über 10Hz (600 U/min) { dc_sf_signal_1 = AdcaResultRegs.ADCRESULT0; //Gleichspannung des ersten SFs ist der aktuelle Abtastwert } } void SF_DC_Test_2() //alle 10ms { if(periode_2 > 0.1) //wenn Unwuchtsignal unter 10Hz (600 U/min) { static Uint16 counter = 0; //Zählervariable für bereits abgetastete Werte static Uint32 mittelwert_summe = 0; //Variable für das Aufsummieren der Abtastwerte mittelwert_summe += AdcaResultRegs.ADCRESULT1; //Aufsummieren des aktuellen Abtastwertes counter++; //Erhöhen der Zählervariable if(counter >= periode_2/0.01) //wenn eine Periode abgetastet wurde { mittelwert_summe /= counter; //Division der Summe der Abtastwerte durch Anzahl der Abtastwerte dc_sf_signal_2 = mittelwert_summe; //Gleichspannung des zweiten SFs beträgt ermittelten Mittelwert mittelwert_summe = 0; //Summenvariable zurücksetzen für neue Berechnung counter = 0; //Zählervariable zurücksetzen für neue Berechnung } }else //wenn Unwuchtsignal über 10Hz (600 U/min) { dc_sf_signal_2 = AdcaResultRegs.ADCRESULT1; //Gleichspannung des zweiten SFs ist der aktuelle Abtastwert } }