/*
Projekt: Photovoltaik-Präsentation "solar" mit MSP430
Detail: Analog-Digital-Umsetzung (ADU_Xxx),
Digital-Analog-Umsetzung (DAU_Xxx),
Relais (Rel_Xxx)
060803 erstellt
*/
#include "solar.h"
/* Hardware-Anschluss:
P6.0 = Kanal AD0: Spannung Solarzelle
P6.1 = Kanal AD1: Strom Solarzelle
P6.2 = Kanal AD2: Spannung Last
P6.3 = Kanal AD3: Strom Last
P6.4 = Kanal AD4: Spannung Akku
P6.5 = Kanal AD5: Strom Akku
P6.6 = D/A-Wandler Kanal0: Stromsenke Solarzelle (Kennlinienaufnahme)
P3.0 = Relais0 = Solarstromsteuerung - Kennlinienaufnahme
P3.1 = Relais1 = Last vom Laderegler direkt zur Solarzelle schalten
P6.7 = Relais2 = Solarzelle1 -> Solarzelle2 umschalten
ACHTUNG: Hardware-Konstruktionsfehler (falls Laderegler blöd):
Relais1 muss bei drohender Tiefentladung des Akkus anziehen!
Bei ausgeschalteter Schaltung droht dennoch Tiefentladung!
Ggf. Kontakte (Öffner und Schließer) tauschen und Software anpassen!
*/
/************************************************************************
* Analog-Digital-Konverter
************************************************************************/
static int AD_Buf[N_AVG*N_CH];
// Irgendwie hat GCC ein Problem mit zweidimensionalen Arrays!
void ADU_Init(void){
P6DIR=0x80; // REL2 = Ausgang, alles andere Eingang
P6SEL=0x3F; // 6 A/D-Wandler, 1 D/A-Wandler; REL2
P3DIR|=0x03;
ADC12CTL1=SHS0|SHP|ADC12DIV2|ADC12DIV1|ADC12DIV0|ADC12SSEL1|CONSEQ1|CONSEQ0;
ADC12CTL0=0xFF00|MSC|REF2_5V|REFON|ADC12ON;
ADC12MCTL0=0x00; // 0 = Kanal AD0: Spannung Solarzelle
ADC12MCTL1=0x01; // 1 = Kanal AD1: Strom Solarzelle
ADC12MCTL2=0x02; // 2 = Kanal AD2: Spannung Last
ADC12MCTL3=0x03; // 3 = Kanal AD3: Strom Last
ADC12MCTL4=0x04; // 4 = Kanal AD4: Spannung Akku
ADC12MCTL5=0x05; // 5 = Kanal AD5: Strom Akku
ADC12MCTL6=0x08; // 6 = Referenzspannung (Bezug für Akku-Strom)
ADC12MCTL7=0x9A; // 7 = Temperatur MSP430 und Sequenz-Ende
ADC12CTL0|=ENC/*|ADC12SC*/;
DMA0SA=(unsigned)&ADC12MEM[0]; // ADC12MEM[0]..ADC12MEM[7]
DMA0DA=(unsigned)&AD_Buf[0]; // beginnend mit erster Kopie
DMA0SZ=N_CH; // 8 Words = 1 Block
DMACTL0|=0x0006; // DMA0-Trigger ist A/D-Wandler
DMA0CTL=0x5F14; // Blocktransfer, Quelle und Ziel Auto-Inkrement,
// wortweise, DMA aktiviert, Interrupt aktiviert
}
// DMA-Interrupt: Nach 8 A/D-Wandlungen und Transfer zum Puffer
// zum nächsten Puffer weiterschalten
interrupt(DACDMA_VECTOR) DMA_Complete(void) {
int *a=(int*)DMA0DA;
a+=N_CH; // nächster Block
if (a==&AD_Buf[N_AVG*N_CH]) {
// Test-Ausgang toggeln
// P3OUT^=0x04;
a=&AD_Buf[0]; // am Ende zurück zum Anfang
}
DMA0DA=(unsigned)a;
DMA0CTL&=~DMAIFG; // muss gelöscht werden!
// Ansonsten hätte die ISR über 3 DMA-Kanäle und den D/A-Wandler
// keine Chance herauszufinden, wer der Verursacher war.
}
// Summe aus N_AVG A/D-Wandlungen beschaffen
int ADU_Get(int Kanal) {
int i,ret=0, *p;
for (i=0, p=AD_Buf+Kanal; i<N_AVG; i++,p+=N_CH) ret+=*p;
return ret;
}
/************************************************************************
* Digital-Analog-Konverter
************************************************************************/
void DAU_Init(void){
DAC12_0CTL=DAC12AMP1;
DAC12_0CTL=DAC12AMP1|DAC12CALON; // Kalibrierung starten
}
// DAU_Put ist Makro
// DAU_Get ist Makro
static volatile BYTE*const Addrs[]={&P3OUT,&P3OUT,&P6OUT};
static BYTE const Masks[]={ 0x01, 0x02, 0x80};
/************************************************************************
* Relais
* what=0: REL0 = Solarstromsteuerung - Kennlinienaufnahme
* what=1: REL1 = Last vom Laderegler direkt zur Solarzelle schalten
* what=2: REL2 = Solarzelle1 -> Solarzelle2 umschalten
************************************************************************/
void Rel_SetState(INT what, bool state){
if ((unsigned)what>=sizeof(Masks))return;
if (state) *(Addrs[what])|= Masks[what];
else *(Addrs[what])&=~Masks[what];
}
bool Rel_GetState(INT what) {
if ((unsigned)what>=sizeof(Masks))return false;
return *(Addrs[what])&Masks[what];
}
Vorgefundene Kodierung: UTF-8 | 0
|