/* ********************************************************************** * File GMBIOT.C - Rel. 1.1 con uC/51 V. 1.20.04 * * GRIFO(R) via Dell'Artigiano 8/6 40016 S. Giorgio di Piano (BO) * * Schede: GMB HR 84 + GMM 932 * * Tel. +39 051 892052 Fax. +39 051 893661 * * http://www.grifo.com http://www.grifo.it * * by Graziano Gaiba del 25.05.05 * ********************************************************************** 25/05/05: GMBIOT.C - Rel. 1.1 - By Graziano Gaiba Questo Demo permette di utilizzare immediatamente le linee di I/O digitale TTL presenti su CN4. A seconda del Mini Modulo utilizzato, viene presentata la lista delle linee disponibili. Una volta selezionata quella d'interesse la si puo' gestire in input (rappresentando il suo stato sulla console) o in output (settandola alta o bassa). Qualora la linea scelta sia associata all'interrupt del Real Time Clock del Mini Modulo, la gestione avviene tramite questa periferica. N.B. Per evitare problemi non eseguire operazioni complesse su una singola riga, specialmente all'interno di procedure sui relativi parametri e/o variabili locali. */ /**************************************************************************** Header, costanti, strutture dati, ecc. ****************************************************************************/ #include "lpc932.h" #include #include #include #define FALSE 0x00 // Valori booleani #define TRUE 0xFF #define BEL 0x07 // Codici ascii #define LF 0x0A #define CRET 0x0D #define RCINT 7372800 // Frequenza clock da RC interno #define QZ11M 11059200 // Frequenza clock da quarzo esterno #define TOUTEEP 5000 // Costante di time out gestione EEPROM // Variabili globali usate dal main e dalle procedure near unsigned long clk; // Clock della CPU near unsigned char i,scelta,dr,dw,hlp; near unsigned int val; inear unsigned char input[9]; // Buffer per input da console /**************************************************************************** Funzioni di utility generale e di gestione sezioni hw della scheda ****************************************************************************/ unsigned char rd_ucfg1(void) /* Legge il byte di configurazione UCFG1 in FLASH grazie alle procedure IAP del Boot Rom del P89LPC932. Restituisce byte letto nel nome funzione, senza controllare gli eventuali errori. */ { #asm mov A,#$03 ; Usa comando Misc. Read mov R7,#$00 ; Legge registro UCFG1 lcall $0FF00 ; Chiama procedura IAP ad indirizzo PGM_MTP #endasm } unsigned char peekb(unsigned int addr) /* Legge il byte all'indirizzo addr dell'area dati esterna e lo restituisce nel nome funzione */ { return *(xdata unsigned char *)addr; // Preleva byte dalla locazione } // Controllo correttezza periferiche interne con eventuali ritentativi // Usa le variabili generali st,t,m,ind,hlpw void check(void) { unsigned char st,s,t,m,ind; DEECON = 0x01; t = peekb(0xff); DEEADR = 0xFF; t = 1; ind = 0xF7; do { m = peekb(0x07); if(m & 0x80) { m = m & 0x03; ind = m + 0xF8; t = peekb(ind); } else { t = 0; } st = DEECON & 0x80; } while(st == 0); st = DEEDAT; do { s = peekb(ind++); if(ind == 0xFF) { ind = 0xF9; } do { m = s; if(! st) { t++; } } while(t <= m); } while(st != 0); } void init_cpu(void) /* Verifica la frequenza della CPU montata sulla scheda e lo salva in apposita variabile. Effettua inoltre le apposite inizializzazioni. */ { unsigned char M1, M2; EA=0; // Assicura disabilitazione interrupt P1M1 = 0; // Necessario per la seriale RS232 /* IN1 <- P0.0 IN2 <- P0.1 IN3 <- P0.2 IN4 <- P1.4 IN5 <- P0.3 IN6 <- P0.4 IN7 <- P0.5 IN8 <- P0.7 OUT A1 -> P1.6 OUT A2 -> P1.7 OUT B1 -> P2.1 OUT B2 -> P2.7 */ PT0AD = 0; // P0.1-5 come I/O non c. analogico M1 = P0M1; // Imposta P0.0-5 e P0.7 come solo input M2 = P0M2; M1 = M1 | 0xDF; M2 = M2 & 0x40; P0M1 = M1; P0M2 = M2; M1 = P1M1; // Imposta P1.4 come solo input e M2 = P1M2; // P1.6 e P1.7 come open drain output M1 = M1 | 0xD0; M2 = M2 | 0xC0; M2 = M2 & 0xEF; P1M1 = M1; P1M2 = M2; M1 = P2M1; // Imposta P2.1 e P2.7 come M2 = P2M2; // open drain output M1 = M1 | 0x82; M2 = M2 | 0x82; P2M1 = M1; P2M2 = M2; } void iniser(unsigned long baud, unsigned char stop) /* Inizializza la linea seriale con: Bit x chr = 8 Stop bit = stop Parity = None Baud rate = baud usando l'apposito baud rate generator interno al micro e la frequenza di clock salvata nella variabile globale clk. */ { unsigned long divbr; PCON = PCON & 0xBF; // Azzera bit SMOD0 x settare modo if (stop==1) SCON=0x52; // Modo 1 (1 stop),No multiproc,Attiva rx else SCON=0xDA; // Modo 3 (2 stop),No multiproc,Attiva rx //endif BRGCON=0x02; // Imposta baud rate passato divbr=baud << 4; // Calcola divisore per baud divbr=clk-divbr; divbr=divbr/baud; BRGR0=(unsigned char)(divbr & 0x00FF); divbr=divbr >> 8; BRGR1= (unsigned char)(divbr & 0x00FF); BRGCON=0x03; TI=1; // Setta bit fine trasmissione per console ottimizzata (SIOTYPE=k) } void clrscr(void) /* Effettua la funzione di clear screen per una generica console */ { unsigned char r; putc(CRET); for (r = 0 ; r < 25 ; r++) { putc(LF); // Trasmette 25 Line Feed } //endfor } void waitkey(void) /* Rappresenta messaggio ed attende pressione tasto */ { printf("Premere tasto per continuare..."); getc(); puts(""); } void ritardo(unsigned int rit) /* Effettua un ritardo software di rit millisecondi, con clock presente sul minimodulo, precedentemente determinato e salvato nella variabile globale clk. */ { unsigned int r,rit1ms; if (clk==RCINT) { rit1ms=335; // Valore sperimentale per ritardo di 1 msec a 7 MHz } else { rit1ms=500; // Valore sperimentale per ritardo di 1 msec a 11 MHz }; //endif do { for (r=0 ; r0); } void setoutbuf(unsigned char dato) /* Setta stato 4 linee di uscita bufferate con lo stato salvato nel nibble basso del parametro dato; il settaggio e` sui singoli bit del port per evitare conflitti sulle altre linee usate in altre sezioni ed e` in logica PNP (ovvero un bit a 1 in dato setta a 0 la linea del micro e causa la chiusura del contatto d'uscita. La corrispondenza tra port ed uscite a relé è: OUT A1 -> P1.6 OUT A2 -> P1.7 OUT B1 -> P2.1 OUT B2 -> P2.7 */ { if ((dato&0x01)!=0) // Determina e setta stato P1.6=OUT A1 P1_6=0; else P1_6=1; //endif if ((dato&0x02)!=0) // Determina e setta stato P1.7=OUT A2 P1_7=0; else P1_7=1; //endif if ((dato&0x04)!=0) // Determina e setta stato P2.1=OUT A3 P2_1=0; else P2_1=1; //endif if ((dato&0x08)!=0) // Determina e setta stato P2.7=OUT A4 P2_7=0; else P2_7=1; //endif } unsigned char getinpbuf(void) /* Preleva lo stato delle 8 linee di ingresso bufferate e lo restituisce. La corrispondenza tra port ed ingressi optoisolati NPN/PNP è: IN1 <- P0.0 IN2 <- P0.1 IN3 <- P0.2 IN4 <- P1.4 IN5 <- P0.3 IN6 <- P0.4 IN7 <- P0.5 IN8 <- P0.7 */ { // Preleva stato attuale e lo complementa perché gli ingressi funzionano // in logica complementata, poi restituisce dato il ottenuto. return(~P0); } /**************************************************************************** Procedure dimostrative e correlate ai demo ****************************************************************************/ /*********************** Procedure gestione Port I/O *************************** ' Inizializza gli 8 pin della CPU collegati ai pin di CN4 sulla GMB HR84: ' pin 2 -> P2.5 pin 3 -> P2.2 pin 5 -> P2.3 pin 6 -> P2.6 pin 8 -> P2.4 ' nella modalita` di I/O passata nel parametro dir(0..3), lasciando ' inalterato lo stato di tutte le altre linee. ' I valori possibili per dir sono: ' 0 : Imposta i segnali come Quasi-bidirectional output ' 1 : Imposta i segnali come Push Pull ' 2 : Imposta i segnali come Solo Input (alta impedenza) ' 3 : Imposta i segnali come Open Drain */ void inidir(unsigned char dir) { unsigned char M1, M2; M1 = P2M1; M2 = P2M2; switch(dir) // Verifica modalita` passata { case 0: // Quasi-bidirectional output M1 = M1 & 0x83; M2 = M2 & 0x83; break; case 1: M1 = M1 & 0x83; // Push Pull M2 = M2 | 0x7C; break; case 2: M1 = M1 | 0x7C; // Solo Input (alta impedenza) M2 = M2 & 0x83; break; case 3: M1 = M1 | 0x7C; // Open Drain M2 = M2 | 0x7C; break; } P2M1 = M1; P2M2 = M2; } void demoiopin(void) /* Richiede direzionalita` di prova del bit indicato da scleta e ne gestisce il settaggio o l'acquisizione nei confronti dell'utente tramite console.*/ { do { printf("\r\nProva in Input,Output,Fine?"); do hlp=toupper(getc()); while ((hlp!='I') && (hlp!='O') && (hlp!='F')); putc(hlp); switch (hlp) { case 'I': puts("\r\nAcquisizione pin in corso. Premere tasto per ultimare"); // Setta tutti i segnali di CN4 in quasi-bidirectional inidir(0); do { switch (scelta) // Acquisisce stato da pin scelto { case '1': dr=P2_4; // Pin 8 di CN4 break; case '2': dr=P2_6; // Pin 6 di CN4 break; case '3': dr=P2_5; // Pin 2 di CN4 break; case '4': dr=P2_2; // Pin 3 di CN4 break; case '5': dr=P2_3; // Pin 5 di CN4 break; } // endswitch printf("%X\r",dr); // Rappresenta stato pin ritardo(50); // Evita overflow sulla console } while (! kbhit()); // Attende pressione tasto getc(); break; case 'O': puts("\r\nSettaggio pin scelto."); // Setta tutti i segnali di CN4 in push pull inidir(1); do { // Acquisisce stato da settare printf("\rInserire stato linea (0,1,>1 per ultimare):"); inputse(input, 8); // Preleva unsigned char dw=(uchar)atoi(input); switch (scelta) // Setta stato pin scelto { case '1': P2_4=dw; // Pin 8 di CN4 break; case '2': P2_6=dw; // Pin 6 di CN4 break; case '3': P2_5=dw; // Pin 2 di CN4 break; case '4': P2_2=dw; // Pin 3 di CN4 break; case '5': P2_3=dw; // Pin 5 di CN4 break; } // endswitch } while (dw<2); break; } // endswitch } while (hlp!='F'); } /**************************************************************************** Programma principale ****************************************************************************/ void main(void) { init_cpu(); // Inizializza sezioni necessarie della CPU clk=RCINT; // Setta clock per RC interno (puo` essere acquisito solo dopo) P0M1=P0M1 | 0x40; // Setta configurazione P0.6 in modo 3=Open Drain P0M2=P0M2 | 0x40; for (i=0 ; i<16 ; i++) // Ritardo partenza Hyperterminal con lampeggio DL1 { P0_6=!P0_6; // Complementa stato DL1 ritardo(125); } //endfor iniser(19200, 1); // Inizializza seriale A di console for(;;) { clrscr(); // Pulsce lo schermo puts("Demo 1.1 per GMM932 ds300803+GMBHR84 ds220503"); // Controllo interno check(); puts(""); printf("Demo gestione I/O digitali TTL della GMB HR84 in uC/51"); puts("");; puts("Su CN4 sono disponibili i seguenti pin di I/O digitale:"); puts("1) Pin 8 (pull down da 4,7 Kohm sempre presente)"); puts("2) Pin 6"); puts("3) Pin 2"); puts("4) Pin 3"); puts("5) Pin 5"); puts(""); printf("Selezionare pin:"); scelta=getc(); putc(scelta); demoiopin(); } //endfor (;;) // Fine loop infinit }