Umschalten des PSoC 4 ADC-SAR Compare-Mode zur Laufzeit

Umgang mit PSoC Logikkomponenten
Antworten
Reiner W.
Beiträge: 112
Registriert: Di 7. Apr 2015, 11:43

Umschalten des PSoC 4 ADC-SAR Compare-Mode zur Laufzeit

Beitrag von Reiner W. » Di 13. Okt 2015, 14:40

Der ADC hat die Möglichkeit, Interrrupts bei folgender Eingangsspannung zu generieren:

Code: Alles auswählen

< Low_Limit
<= Low_Limit und < High_Limit (inner window)
>= High_Limit
< Low_Limit oder >= High_limit (outer window)
Überwacht man ein Spannungsfenster (inner/outer) bekommt man zwar einen IR, kann aber nicht
erkennen, ob nun Low_Limit oder High_Limit zugeschlagen hat.
Natürlich kann man die Spannung auslesen, dann weis man woran man ist. Aber das müßte man
dann bei jedem IR machen, auch wenn man die Spannung gar nicht benötigt, weil man z.B. nur
die Limits überwachen will.
Im konkreten Fall soll ein Programm so nebenher meckern, wenn die Versorgungsspannung den
Wert ADC_LOW_LIMIT unterschreitet(Led an) und wenn ADC_HIGH_LIMIT erreicht ist, soll er nicht
mehr meckern(Led aus).

Vorgangsweise: (Pseudocode)

Code: Alles auswählen

Compare Mode = Low_Limit (Default) 
adcHasLowLimit = 0       (Default) 


ISR generiert Limit Detect:
ist der Compare Mode Low_Limit
     Konfiguriere den ADC um: Compare Mode = High_Limit
     Compare Mode = High_Limit
     adcHasLowLimit = 1
 
sonst muss der Compare High_Limit sein
     Konfiguriere den ADC um: Compare Mode = Low_Limit
     Compare Mode = Low_Limit
     adcHasLowLimit = 0

ist  adcHasLowLimit = 1 -> Led ein sonst Led aus
Code-Schnipsel für die Umschaltung des Compare Mode
c code
#define LOW_LIMIT 0     //adc compare mode
#define HIGH_LIMIT 2    //adc compare mode

volatile uint8  adcLimitDetect = 0u;   //adc isr Flag for limit violation 
volatile uint8  adcDataReady = 0u;     //adc isr flag for end of scan
uint8 adcHasLowLimit = 0u;              //global Flag for LOW_LIMIT


//actual adc compare_mode (initial mode)
//            ADC_DEFAULT_COMPARE_MODE 0 -> Low_Limit
//                                     1 -> inner boundarys
//                                     2 -> High Limit
//                                     3 -> Outer Boundary
uint8 adcCompareMode = ADC_DEFAULT_COMPARE_MODE;      

...
if (adcLimitDetect) { 
           
	ADC_IRQ_Disable();    
     	if (adcCompareMode == LOW_LIMIT) {  
         	ADC_SAR_RANGE_COND_REG  = (uint32)((uint32)(HIGH_LIMIT) << ADC_CMP_OFFSET); //set to High_Limit
                adcCompareMode = HIGH_LIMIT;
                adcHasLowLimit = 1u;  
	} else {  //adcCompareMode == HIGH_LIMIT            
                ADC_SAR_RANGE_COND_REG  = (uint32)((uint32)(LOW_LIMIT) << ADC_CMP_OFFSET); //set to High_Limit
                adcCompareMode = LOW_LIMIT;
                adcHasLowLimit = 0u;  
        }
        ADC_IRQ_Enable();
                        
        //Test LowLimit
        Pin_AdcLow_Write(adcHasLowLimit);

} //end adcLimitDetect
Das Beispielprojekt zeigt eine entsprechene Limitüberwachung
Unteres und oberes Limit können in den Konstanten:
c code
#define ADC_LOW_LIMIT  (0x7FF * 0.5 / 1.024)  //Low Warning at 0.5V
#define ADC_HIGH_LIMIT (0x7FF * 0.7 / 1.024)  //End of Low Warning at 0.7V
hinterlegt werden. Im Beispiel wird der aktuelle Spannungspegel noch auf dem Display gezeigt.
Nötig ist das nicht.
ADC_switch_compare_mode.cyprj.Archive.zip
Beispiel zur ADC CompareMode Umschaltung
(353.62 KiB) 546-mal heruntergeladen
Reiner W.

Antworten