#include "../h/pmc.h"
#include "../h/tc.h"
#include "../h/pio.h"
#include "../h/aic.h"
#include "./config.cfg"
// fuer die Initialisierung der Zaehler
#define TC_INIT TC_CLKS_MCK2 | TC_LDBSTOP | TC_CAPT | TC_LDRA_RISING_EDGE | TC_LDRB_RISING_EDGE
void init_Timer3(void);
int MessungderMasse(void);
void init_Waage(void);
void init_keys(void);
void init_leds(void);
void itos(int, char *);
void taste_irq_handler (void) __attribute__ ((interrupt));
volatile int key;
int main(void)
{
/* ################ Structs definieren ##################### */
StructPMC* pmcbase = PMC_BASE; // Basisadresse des PMC
StructPIO* piobaseA = PIOA_BASE; // Basisadresse PIO A
StructPIO* piobaseB = PIOB_BASE; // Basisadresse PIO B
StructAIC* aicbase = AIC_BASE;
pmcbase->PMC_PCER = 0x6200; // Peripheral Clocks einschalten für PIOB, PIOA, Timer3
/* ################ Ende Structs ########################### */
/* ################### initalisierung ###################### */
init_Timer3(); // init Pumpe
init_ser();
init_Waage();
init_keys();
/*########### Interrupt Service Routine ausführbar machen ################*/
aicbase->AIC_IDCR = 1 << 14;
aicbase->AIC_ICCR = 1 << 14;
aicbase->AIC_SVR[PIOB_ID] = (unsigned int)taste_irq_handler;
aicbase->AIC_SMR[PIOB_ID] = 0x7;
aicbase->AIC_IECR = 1 << 14;
piobaseB->PIO_IER = KEY1 | KEY2;
/* ################## ende initalisierung ################## */
while(1)
{
key = 0;
/* ################## Aufgabe 3 ################## */
int MasseBecher;
int Masse;
Masse = 0;
MasseBecher = 0;
do{
aicbase->AIC_IECR = 1 << 14; // Interrupt einschalten
while(key!=1)
{
pmcbase->PMC_SCDR = 1; // Prozessor ausgeschaltet zum Stomsparen
}
aicbase->AIC_IDCR = 1 << 14; // INterrupt ausschalten
MasseBecher = MessungderMasse();
if(MasseBecher > 1) // Wenn Becher dasteht, Gewicht ausgeben
{
char arr[11];
itos(MasseBecher, arr);
}
}while(MasseBecher<2);
/* ################## Aufgabe 4 ################## */
aicbase->AIC_IECR = 1 << 14; // Interrupt einschalten
while(key!=2)
{
pmcbase->PMC_SCDR = 1; // Prozessor ausgeschaltet zum Stomsparen
}
aicbase->AIC_IDCR = 1 << 14; // Interrupt ausschalten
MasseBecher = MessungderMasse();
if(MasseBecher > 1) // Wenn der Becher noch dasteht
{
piobaseA->PIO_PDR = (1<<PIOTIOA3) ; // Pumpen
while((Masse - MasseBecher) < Einfuellmenge)
{
int MasseAlt;
MasseAlt=Masse;
Masse = MessungderMasse();
if(MasseAlt != Masse) // Wenn die Masse sich geändert hat
{
char arr[12];
itos(Masse-MasseBecher, arr);
}
if(Masse+10 < MasseAlt) // wenn der Becher weggenommen wird
{
piobaseA->PIO_PER = (1<<PIOTIOA3); // auf jeden Fall das Pumpen aufhören!
break;
}
}
piobaseA->PIO_PER = (1<<PIOTIOA3); // Pumpen aufhören!
}
if((Masse-MasseBecher) < 49) // Wenn der Becher zu früh weggenommen wurde
{
}
else
{
char arr[12];
itos(Masse-MasseBecher, arr);
}
while(Masse!=0){
Masse = MessungderMasse();
}
}
}
void taste_irq_handler (void)
{
StructPIO* piobaseA = PIOA_BASE;
StructPIO* piobaseB = PIOB_BASE; // Basisadresse PIO B
StructAIC* aicbase = AIC_BASE; // Basisadresse des Advanced interrupt controllers
if(!(piobaseB->PIO_PDSR & KEY1))
{
key = 1;
}
if(!(piobaseB->PIO_PDSR & KEY2))
{
key = 2;
}
aicbase->AIC_EOICR = piobaseB->PIO_ISR; //Ende der Interruptserviceroutine
}
void init_PIO(void)
{
StructPMC* pmcbase = PMC_BASE;
StructPIO* piobaseA = PIOA_BASE;
StructPIO* piobaseB = PIOB_BASE;
pmcbase->PMC_PCER = 0x6000; // PIOA, PIOB
piobaseA->PIO_PDR = 0x090; // p4 p7
}
void init_leds(void)
{
StructPMC* pmcbase = PMC_BASE;
// Basisadresse des PMC
StructPIO* piobaseB = PIOB_BASE;
// Basisadresse PIO B
piobaseB->PIO_PER = ALL_LEDS;
piobaseB->PIO_OER = ALL_LEDS;
}
void init_keys(void)
{
StructPMC* pmcbase = PMC_BASE;
// Basisadresse des PMC
StructPIO* piobaseB = PIOB_BASE;
// Basisadresse PIO B
pmcbase->PMC_PCER = 0x4000; // Peripheral Clocks aktiv für PIOB
piobaseB->PIO_PER = KEY1 | KEY2; // Key1 und 2 einschalten.
}
void init_Waage(void)
{
StructPMC* pmcbase = PMC_BASE;
StructTC* tcbase4 = TCB4_BASE;
StructTC* tcbase5 = TCB5_BASE;
StructPIO* piobaseA = PIOA_BASE; // Basisadresse PIO A
piobaseA->PIO_PDR = 0x090; // p4 p7
pmcbase->PMC_PCER = 0x00f00; // Clock Timer5, Timer4 einschalten
// Timer4:
tcbase4->TC_CCR = TC_CLKDIS; // CCR= CounterControlRegister; TC_CLKDIS=0x2
tcbase4->TC_CMR = TC_INIT; // Timer Counter Mode Register
tcbase4->TC_CCR = TC_CLKEN; // 0x1
tcbase4->TC_CCR = TC_SWTRG; // 0x4
// Timer5:
tcbase5->TC_CCR = TC_CLKDIS; // CCR= CounterControlRegister; TC_CLKDIS=0x2
tcbase5->TC_CMR = TC_INIT; // Timer Counter Mode Register
tcbase5->TC_CCR = TC_CLKEN; // 0x1
tcbase5->TC_CCR = TC_SWTRG; // 0x4
}
void init_Timer3( void ) // Pumpe
{
StructTC* timerbase3 = TCB3_BASE; // Basisadressse TC Block 1
StructPIO* piobaseA = PIOA_BASE; // Basisadresse PIO A
StructPMC* pmcbase = PMC_BASE; // Basisadresse des PMC
pmcbase->PMC_PCER = 0x200; // Peripheral Clocks einschalten für Timer3
timerbase3->TC_CCR = TC_CLKDIS; // Disable Clock
// Initialize the mode of the timer 3
timerbase3->TC_CMR =
TC_ACPC_CLEAR_OUTPUT | //ACPC : Register C clear TIOA
TC_ACPA_SET_OUTPUT | //ACPA : Register A set TIOA
TC_WAVE | //WAVE : Waveform mode
TC_CPCTRG | //CPCTRG : Register C compare trigger enable
TC_CLKS_MCK8; //TCCLKS : MCKI / 8
// Initialize the counter:
timerbase3->TC_RA = 31250; //50% High
timerbase3->TC_RC = 62500; //
// Start the timer :
timerbase3->TC_CCR = TC_CLKEN ; // Timer Enable
timerbase3->TC_CCR = TC_SWTRG ; // Softwaretrigger
piobaseA->PIO_PER = (1<<PIOTIOA3) ; // Pinport A3 enable
piobaseA->PIO_OER = (1<<PIOTIOA3) ; // Outputenable
piobaseA->PIO_CODR = (1<<PIOTIOA3) ; // Clear output data register -> kein anderes signal liegt an
}
int MessungderMasse(void){
StructPMC* pmcbase = PMC_BASE;
StructPIO* piobaseA = PIOA_BASE;
StructPIO* piobaseB = PIOB_BASE;
StructTC* tcbase4 = TCB4_BASE;
StructTC* tcbase5 = TCB5_BASE;
volatile int captureRA1;
volatile int captureRB1;
volatile int capturediff1;
volatile float Periodendauer1;
volatile int captureRA2;
volatile int captureRB2;
volatile int capturediff2;
volatile float Periodendauer2;
volatile int ave = 0;
// Periodendauer der Waagensignale messen
// Signal an TIOA4 ca. 16kHz entspricht ca. einer Periodendauer von 62,5us
// durch den Teiler von 32 ergeben sich ca. 2ms
// Zähler mit positiver Flanke starten
int i = 0;
for(i=0;i<4;i++){
tcbase4->TC_CCR = TC_SWTRG;
tcbase5->TC_CCR = TC_SWTRG;
while (!( tcbase4->TC_SR & 0x40)); // Capture Register B wurde geladen (RB Loading Status) Messung abgeschlossen
captureRA1 = tcbase4->TC_RA; // Speichert TC_RA (1. Gemesser wert) in Variable
captureRB1 = tcbase4->TC_RB;
while (!( tcbase5->TC_SR & 0x40)); // Capture Register B wurde geladen (Messung abgeschlossen
captureRA2 = tcbase5->TC_RA;
captureRB2 = tcbase5->TC_RB;
capturediff2 = captureRB2 - captureRA2;
Periodendauer2 = capturediff2; // Zeit in us
capturediff1 = captureRB1 - captureRA1;
Periodendauer1 = capturediff1; // Zeit in us
volatile int C1 = c1;
volatile int C2 = c2;
ave += (C1 * ((Periodendauer1/Periodendauer2)-1))-C2;
}
return (ave/4)+2;
}
void itos(int i, char * arr)
{
if(i==0)
{
arr[0]='0';
arr[1]= 0 ;
return;
}
int count;
int tmpi;
tmpi = i;
count = 0;
char cache;
int negative;
negative = 0;
if(i < 0 ) // Ist die Zahl negativ?
{
negative = 1;
tmpi = tmpi * -1;
i = i * -1;
}
while(tmpi > 0) // wie viele Stellen hat unsere Zahl?
{
tmpi = tmpi / 10;
count++;
}
if(negative == 1) // Wenn sie negativ ist, eine Stelle mehr, an Stelle 0 kommt das -
{
count++;
//chr[0] = '-';
}
int tmpcount;
tmpcount = count + 1;
char chr[tmpcount]; // Array erstellen (+1 für 0 an die ende)
chr[count] = 0;
if(negative == 1) // Wenn sie negativ ist, eine Stelle mehr, an Stelle 0 kommt das -
{
chr[0] = '-';
}
int j;
j= count - 1;
for(j;j-negative>=0;j--) // Achtung Achtung bei negativen Zahlen hier eine Veränderung! oder so...
{
cache = i%10; // Das hinterste Zeichen isolieren
i = i/10; // Die Nächste Stelle nach ganz rechts
chr[j] = cache + '0'; // und an die letzte Stelle des Arrays schreiben
}
j=0;
for(j;j<11;j++)
{
arr[j] = chr[j];
}
}