Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifdef V3_Aufgabe_1
- /*
- ES GELTEN DIE BEI "rollosteuerung_moore" AN GLEICHER STELLE VORANGESTELLTEN KOMMENTARE
- */
- // Einige Defines zum leichteren Wiederfinden
- #define BIT_POS_IST_OBEN 0
- #define BIT_POS_IST_UNTEN 1
- #define BIT_POS_NACH_OBEN 4
- #define BIT_POS_NACH_UNTEN 5
- #define BIT_POS_FAHRE_NACH_OBEN 9
- #define BIT_POS_MOTOR_AN 8
- #define BIT_POS_FAHRE_NACH_UNTEN 10
- typedef enum {hoch, runter, steht} STATE; // Datentyp für den Zustand das Automaten.
- // Vergleichbar mit "TYPE .... IS" in VHDL.
- typedef unsigned short int USHORT; // Eigener Datentyp zur Abkuerzung
- typedef struct { unsigned char hh;
- unsigned char mm;
- unsigned char ss;} UHRZEIT;
- UHRZEIT akt_zeit;
- void steuerungsfunktion ( USHORT ist_oben, USHORT ist_unten,
- USHORT nach_oben, USHORT nach_unten,
- USHORT* p_fahre_nach_oben,
- USHORT* p_fahre_nach_unten,
- STATE* p_state, USHORT nach_oben_wegen_zeit, USHORT nach_unten_wegen_zeit
- )
- {
- // 5.) switch-case-Konstrukt zur "Verwaltung" der Zustaende
- switch (*p_state) {
- // 6.) Ein CASE je Zustand
- case steht:
- // 7a.) .... Ausgabesignale bestimmen
- *p_fahre_nach_unten=0; *p_fahre_nach_oben=0;
- // 8.) Eingabesignale auswerten und Zustandswechsel herbei fuehren
- // Ein IF je Pfeil
- /*if ( (ist_unten == 0) && (nach_unten == 1) && (nach_oben == 0)) {
- *p_state = runter; // Wechsel in den Zustand "runter"
- }
- if ( (ist_oben == 0) && (nach_oben == 1)){
- *p_state = hoch; // Wechsel in den Zustand "hoch"
- }*/
- if ( (ist_unten == 0) && (nach_unten_wegen_zeit != 0)) {
- *p_state = runter; // Wechsel in den Zustand "runter"
- }
- if ( (ist_oben == 0) && (nach_oben_wegen_zeit != 0)){
- *p_state = hoch; // Wechsel in den Zustand "hoch"
- }
- // Diese if-Anweisung kann entfallen, da sie cstate nicht veraendert.
- /*if ( !( ((ist_unten == 0) && (nach_unten == 1) && (nach_oben == 0))
- || ((ist_oben == 0) && (nach_oben == 1)) ) ) {
- *p_state = steht; // Bleibe im Zustand "steht"
- }*/
- break;
- case runter:
- // 7a.) Ausgabesignale bestimmen
- *p_fahre_nach_unten=1; *p_fahre_nach_oben=0;
- // 8.) Eingabesignale auswerten und Zustandswechsel herbei fuehren
- if (ist_unten == 1) {
- *p_state = steht; // Wechsel in den Zustand "steht"
- }
- // Diese if-Anweisung kann entfallen, da sie cstate nicht veraendert.
- if (ist_unten == 0) {
- *p_state = runter; // Bleibe im Zustand "runter"
- }
- break;
- case hoch:
- // 7a.) Ausgabesignale bestimmen
- *p_fahre_nach_unten=0; *p_fahre_nach_oben=1;
- // 8.) Eingabesignale auswerten und Zustandswechsel herbei fuehren
- if (ist_oben == 1){
- *p_state = steht; // Wechsel in den Zustand "steht"
- }
- // Diese if-Anweisung kann entfallen, da sie cstate nicht veraendert.
- if (ist_oben == 0){
- *p_state = hoch; // Bleibe im Zustand "hoch"
- }
- break;
- // 9.) nicht erlaubte Zustaende "abfangen"
- default:
- *p_state = runter;
- } // end switch
- } // end steuerungsfunktion()
- void timer1_init()
- {
- /* Zur Berechnung der Werte fuer den Prescaler und den Compare-Match:
- Bei einer Frequenz von 4 Mhz zaehlt der Timer mit einem Takt von 0,25us.
- Er kann mit seinen 65536 moeglichen Zaehlstaenden eine maximale Interrupt-Periode von 65536 * 0,25us = 16384us realisieren.
- Dies ist zu schnell. => Der Zaheler muss mittels des Prescalers langsamer eingestellt werden.
- Die ideale Untersetzung waere 50000us / 16384us = 3,0517.
- Da es diese Unterssetzung (Prescaler-Wert) nicht gibt waehlen wir den naechst groesseren Wert also 8.
- Der Zaehler zaehlt jetzt mit einem Takt vom 2us. => Die Interrupts haben bei einem Compare-Match-Wert von 65535
- eine Periode von 131072 us.Der Compare-Match-Wert muss auf 50000us/131072us*65536us = 25000 eingestellt werden.
- */
- unsigned short buf = 0;
- // TCRA1
- // Clock Source auf intern/8 Prescaler
- // Timer Modus Clear-Timer-On-Compare-Match
- buf = (1 << PS11) | (1 << TM10);
- io_out16(TCRA1, buf);
- // TCRB1
- // Counter Enable
- buf = (1 <<CE1);
- io_out16(TCRB1, buf);
- // TIMR1
- // Compare Match Interrupt enable
- buf = (1 << OCIE1);
- io_out16(TIMR1, buf);
- // CMPA1
- // Compare Match Register auf ...
- buf = 5000;
- io_out16(CMPA1, buf);
- }
- // Makros damit man beim Testen nicht so lange warten muss
- // Die korrekten Werte stehen als Kommentare jeweils dahinter
- #define ZT_MAXW 2 //20 wegen 20*50ms= 1s
- #define SS_MAXW 60 //60
- #define MM_MAXW 2 //60
- #define HH_MAXW 1 //24
- // Interrupt Service Routine
- void timer1_oco1_isr()
- {
- unsigned short int buf;
- unsigned short zt;
- zt++;
- if(zt==ZT_MAXW){
- zt=0;
- akt_zeit.ss++;
- }
- if(akt_zeit.ss==SS_MAXW){
- akt_zeit.ss=0;
- akt_zeit.mm++;
- }
- if(akt_zeit.mm==MM_MAXW){
- akt_zeit.mm=0;
- akt_zeit.hh++;
- }
- if(akt_zeit.hh==HH_MAXW){
- akt_zeit.hh=0;
- }
- // Zuruecksetzen des Interrupt-Flags
- buf = io_in16(TIFR1);
- buf = buf & ~(1 << OCIF1);
- io_out16(TIFR1, buf);
- }
- void emain(void* arg)
- {
- STATE cstate; // Variable für den Zustand das Automaten.
- // Variablen für die Eingabesignale. Eine Variable fuer jedes Signal.
- USHORT nach_oben;
- USHORT nach_unten;
- USHORT ist_oben;
- USHORT ist_unten;
- // Variablen für die Ausgabesignale. Eine Variable fuer jedes Signal.
- USHORT fahre_nach_oben;
- USHORT fahre_nach_unten;
- USHORT input, output, last_output;
- //!!!
- UHRZEIT hoch_zeit, runter_zeit;
- USHORT nach_oben_wegen_zeit, nach_unten_wegen_zeit;
- USHORT buf;
- INIT_BM_WITH_REGISTER_UI; // Nur fuer Simulation
- // 1.) Hardware konfigurieren
- io_out16(DIR1, 0xFF00); // Ausgang: Bits 15 bis 8 Eingang: Bits 7 bis 0
- // 2.) Definition des Startzustandes. Entspricht dem asynchronen Reset in VHDL.
- cstate = runter;
- //!!!
- // Timer 1 initialisieren
- akt_zeit.hh=0; akt_zeit.mm=0; akt_zeit.ss=0;
- timer1_init();
- //!!! Initialisieren der Zeiten
- hoch_zeit.hh=0; hoch_zeit.mm=0; hoch_zeit.ss=0;
- runter_zeit.hh=0; runter_zeit.mm=1; runter_zeit.ss=55;
- // 3.) Unendliche Schleife. Ein Schleifendurchlauf entspricht einem Zyklus des Automaten
- while (1) {
- SYNC_SIM; // Nur fuer Simulation
- // Zur Sicherheit vor Initialisierung den Interupt des PIC generell deaktivieren
- buf = io_in16(PICC);
- buf = buf & ~(1 << PICE);
- io_out16(PICC, buf);
- // ISR registrieren
- setInterruptHandler(IVN_OC1, timer1_oco1_isr);
- // Interrupt des PIC jetzt zulassen
- buf = buf | (1 << PICE);
- io_out16(PICC, buf);
- // 4.) Einlesen der Eingabesignale einmal je Zyklus
- input = io_in16(IN1);
- // extrahieren von "ist_oben" (BIT_POS_IST_OBEN)
- ist_oben = (input >> BIT_POS_IST_OBEN) & 0x01;
- // extrahieren von "ist_unten" (BIT_POS_IST_UNTEN)
- ist_unten = (input >> BIT_POS_IST_UNTEN) & 0x01;
- // extrahieren von "nach_oben" (BIT_POS_NACH_OBEN)
- nach_oben = (input >> BIT_POS_NACH_OBEN) & 0x01;
- // extrahieren von "nach_unten" (BIT_POS_NACH_UNTEN)
- nach_unten = (input >> BIT_POS_NACH_UNTEN) & 0x01;
- //!!!!
- if((akt_zeit.hh==hoch_zeit.hh) && (akt_zeit.mm==hoch_zeit.mm) && (akt_zeit.ss==hoch_zeit.ss)) {
- nach_oben_wegen_zeit=1;
- }
- if((akt_zeit.hh==runter_zeit.hh) && (akt_zeit.mm==runter_zeit.mm) && (akt_zeit.ss==runter_zeit.ss)) {
- nach_unten_wegen_zeit=1;
- }
- // Aufruf der Steuerungsfunktion
- steuerungsfunktion ( ist_oben, ist_unten, nach_oben, nach_unten,
- &fahre_nach_oben, &fahre_nach_unten, &cstate, nach_oben_wegen_zeit, nach_unten_wegen_zeit );
- // 7b.) Ausgabesignale ausgeben
- output=fahre_nach_unten<<BIT_POS_FAHRE_NACH_UNTEN;
- output=output | (fahre_nach_oben<< BIT_POS_FAHRE_NACH_OBEN);
- // Nur wirklich ausgeben wenn notwendig
- // Optimierung mittels bedigter Portausgabe
- if (last_output != output) {
- output=output | (1<< BIT_POS_MOTOR_AN); // Nur fuer Bandmodell
- io_out16(OUT1, io_in16(OUT1) & 0x00FF);
- io_out16(OUT1, io_in16(OUT1) | output);
- last_output = output;
- }
- } // end while
- } // end main
- #endif // V3_Aufgabe_1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement