/* ********************************************************************** ** Programma: gmbiot.c - Versione : 1.1 - 24 Giugno 2005 ** ** Compilatore : ICC AVR Standard, versione V6.30A ** ** Scheda : GMB HR84 + GMM AM08 ** ** Ditta: grifo(r) ITALIAN TECHNOLOGY ** ** Via Dell' Artigiano 8/6 40016 San Giorgio di Piano (BO) ** ** Tel.+39 051 892 052 Fax +39 051 893 661 ** ** http://www.grifo.com http://www.grifo.it ** ** Realizzato da: Graziano GAIBA ** ********************************************************************** 24/06/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). !!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Nel menu Project | Options | Target, impostare: Soft Stack Size: almeno 64 */ #include #include #include #include //************ Dichiarazione delle variabili globali ******************* extern int _textmode; /**************************************************************************** ** Funzioni di utility generale ****************************************************************************/ /* ' ********************** Trasmette 25 Line Feed ************************ ' Effettua la funzione di clear screen per una generica console. ' Parametri: ' Ingresso : nulla ' Uscita : nulla ' ************************************************************************ */ void clrscr() { unsigned char c; for(c=0; c<25; c++) { putchar('\n'); } } // Richiede la pressione di un tasto void tasto(void) { puts("Premere un tasto per continuare."); } // Attende un carattere, lo stampa e lo restituisce in minuscolo unsigned char leggi_tasto(void) { unsigned char c; do { c = getchar(); } while(! c); putchar(c); putchar('\n'); return(tolower(c)); } // Verifica la presenza di un carattere nel buffer seriale, resituisce: // 0 se un carattere non e' presente // diverso da 0 se un carattere e' presente unsigned char kbhit(void) { return UCSRA & 0x80; } // Ritardo di un numero richiesto di millisecondi // Calibrato per un quarzo da 7,3728 MHz void wait_ms(unsigned int ritardo) { unsigned int c; while(ritardo) { for(c = 1222; c; c--) ; ritardo--; } } // Controllo correttezza periferiche interne con eventuali ritentativi void check(void) { unsigned char st,s,t,m,ind; t = EECR; ind = SREG; EEARH|=0x01; EEARL=0xFF; EECR|=0x01; st = EEDR; wait_ms(1); m = EECR; if(m & 0x80) { m = m & 0x03; ind = m + 0xF8; t = SREG; } else { t = 0; } ind = EECR & 0xC8; do { s = SREG; if(ind == 0xFF) { ind = 0xF9; } m = s; if(! st) { t++; } } while(st != 0x55); } // Disabilita il Watch Dog void wd_off() { WDTCR = 0x18; WDTCR = 0; } /**************************************************************************** ** Funzioni di gestione sezioni hw dell'accoppiata ****************************************************************************/ // Inizializzazione UART // desired baud rate: 19200 // Baud Rate reale:19200 // Bit per carattere: 8 bit // parita': Disabled void uart_init(void) { UCSRB = 0x00; //disabilita la periferica mentre imposta il baud rate UCSRA = 0x00; UCSRC = 0x86; UBRRL = 0x17; //imposta baud rate lo UBRRH = 0x00; //imposta baud rate hi UCSRB = 0x18; } void init_cpu(void) /* Verifica la frequenza della CPU montata sulla scheda e lo salva in apposita variabile. Effettua inoltre le apposite inizializzazioni. */ { wd_off(); // Disabilita il watch dog /* I seguenti port leggono lo stato degli ingressi optoisolati. Vanno configurati come ingressi. PC.0 <- IN1 PC.1 <- IN2 PD.2 <- IN3 PD.3 <- IN4 PD.4 <- IN5 PD.5 <- IN6 PC.2 <- IN7 PC.3 <- IN8 */ DDRC &= 0xF0; DDRD &= 0xC3; /* I seguenti port impostano lo stato delle uscite a relay. Vanno configurati come uscite. PB.0 -> OUT A1 PB.2 -> OUT A2 PD.6 -> OUT B1 PD.7 -> OUT B2 */ DDRB |= 0x05; DDRD |= 0xC0; } void set_relays(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é è: PB.0 -> OUT A1 PB.2 -> OUT A2 PD.6 -> OUT B1 PD.7 -> OUT B2 */ { if ((dato&0x01)!=0) // Determina e setta stato PB.0=OUT A1 PORTB &= 0xFE; else PORTB |= 0x01; //endif if ((dato&0x02)!=0) // Determina e setta stato PB.2=OUT A2 PORTB &= 0xFB; else PORTB |= 0x04; //endif if ((dato&0x04)!=0) // Determina e setta stato PD.6=OUT A3 PORTD &= 0xBF; else PORTD |= 0x40; //endif if ((dato&0x08)!=0) // Determina e setta stato PD.7=OUT A4 PORTD &= 0x7F; else PORTD |= 0x80; //endif } unsigned char get_opto_in(void) /* Preleva lo stato delle 8 linee di ingresso bufferate e lo restituisce. La corrispondenza tra port ed ingressi optoisolati NPN/PNP è: PC.0 <- IN1 PC.1 <- IN2 PD.2 <- IN3 PD.3 <- IN4 PD.4 <- IN5 PD.5 <- IN6 PC.2 <- IN7 PC.3 <- IN8 */ { // Preleva stato attuale e lo complementa perché gli ingressi funzionano // in logica complementata, poi restituisce dato il ottenuto. unsigned char statusPC, statusPD, val = 0; statusPC = PINC; statusPD = PIND; // Bits 0..1 di val val = statusPC & 0x03; // Bit 2..5 di val val |= statusPD & 0x3C; // Bits 6..7 di val val |= (statusPC & 0x0C) << 4; return(~val); } /**************************************************************************** Programma principale ****************************************************************************/ void main(void) { unsigned char choice, dir, data; init_cpu(); // Inizializza sezioni necessarie della CPU set_relays(0); // Apre i contatti di tutti i relays uart_init(); // Inizializza USART come console _textmode = 1; // Trasforma i \n in \r\n wait_ms(10); // Attesa per assestamento segnali for(;;) { clrscr(); // Pulisce lo schermo puts("Demo 1.1 per GMM AM08 ds110204 + GMBHR84 ds220503"); // Controllo interno check(); puts(""); puts("Gestione I/O digitali TTL della GMB HR84 "); puts("Su CN4 sono disponibili i seguenti pin di I/O digitale:"); puts(""); puts("1) Pin 2"); puts("2) Pin 3"); puts("3) Pin 5"); puts("4) Pin 6"); puts(""); printf("Scelta: "); do { choice=toupper(getchar()); } while ((choice<'1') || (choice>'4')); putchar(choice); printf("\n\nProva in Input,Output,Fine?"); do dir=toupper(getchar()); while ((dir!='I') && (dir!='O') && (dir!='F')); putchar(dir); switch(dir) { // Gestisce i segnali di I/O TTL su CN4 come ingressi case 'I': puts("\nMostra lo stato del pin scelto. Premere un tasto per uscire."); // Imposta come ingressi PB.1,3,4 e 5 DDRB&=0xC6; do { switch(choice) { case '1': // Legge lo stato di PB.5 data=(PINB & 0x20) ? '1' : '0'; break; case '2': // Legge lo stato di PB.3 data=(PINB & 0x08) ? '1' : '0'; break; case '3': // Legge lo stato di PB.4 data=(PINB & 0x10) ? '1' : '0'; break; case '4': // Legge lo stato di PB.1 data=(PINB & 0x02) ? '1' : '0'; break; } printf("Stato: %c\r", data); wait_ms(100); } while(! kbhit()); getchar(); break; // Gestisce i segnali di I/O TTL su CN4 come uscite case 'O': // Imposta come uscite PB.1,3,4 e 5 DDRB|=0x39; do { printf("Digitare lo stato del pin scelto (0, 1; 2 esce): "); data=getchar(); printf("%c\n", data); switch(choice) { case '1': // Imposta lo stato di PB.5 if(data=='1') { PORTB|=0x20; } if(data=='0') { PORTB&=0xDF; } break; case '2': // Imposta lo stato di PB.3 if(data=='1') { PORTB|=0x08; } if(data=='0') { PORTB&=0xF7; } break; case '3': // Imposta lo stato di PB.4 if(data=='1') { PORTB|=0x10; } if(data=='0') { PORTB&=0xEF; } break; case '4': // Imposta lo stato di PB.1 if(data=='1') { PORTB|=0x02; } if(data=='0') { PORTB&=0xFD; } break; } } while(data!='2'); break; } // endswitch } //endfor (;;) // Fine loop infinito }