/* ********************************************************************** ** Programma: gmbser.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: GMBSER.C - Rel. 1.1 - By Graziano Gaiba Il demo e' un semplice esempio di comunicazione in grado di operare con tutti i protocolli elettrici disponibili su CN2 (RS 232, RS 422, RS 485, current loop o TTL). In dettaglio, tramite funzioni a basso livello, e' possibile programmare il baud rate da console, poi ogni carattere ricevuto dalla seriale viene ritrasmesso sulla stessa; la ricezione del carattere 'r' o 'R' determina la gestione della direzione (segnale DIR) per RS 422 e RS 485. !!!!!!!!!!!!!!!!!!!!!!!!!!! IMPORTANTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Nel menu Project | Options | Target, impostare: Soft Stack Size: almeno 64 */ #include #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; } int get_num (void) // Preleva valore numerico di max 6 cifre dalla console restituendolo nel // nome funzione. { char num[7]; char x; char ch; x=0; do { ch=getchar(); // attendo un carattere if (ch==13) // se "CR" chiudo la stringa con "0" num[x]=0; else num[x]=ch; // memorizzo il carattere putchar(ch); // visualizzo "echo" x=x+1; // incremento il puntatore al vettore } while (!(ch==13 || x==6)); // esco se ho ricevuto 6 caratteri o "CR" putchar(13); putchar(13); return (atoi(num)); // Restituisce valore numerico } /**************************************************************************** ** 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); } /**************************************************************************** ** Funzioni di gestione a basso livello dell'UART ****************************************************************************/ void uart_low_level_init(unsigned long int baud) { UCSRB = 0x00; //disabilita la periferica mentre imposta il baud rate UCSRA = 0x00; UCSRC = 0x86; UBRRL = (7372800 / (16 * baud)) - 1; UBRRH = 0x00; //imposta baud rate hi UCSRB = 0x18; } /**************************************************************************** Programma principale ****************************************************************************/ void main(void) { unsigned char dir; unsigned long int baud_rate; 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 della USART a basso livello."); puts(""); puts("Per RS 232: settare ON gli switch 1 e 2 e OFF gli switch 3 e 4 di DSW1."); puts("La Gestione Software e' Bascom,Vedere Documentazione Per piu' informazioni"); puts("Settando OFF gli switch 1 e 2 e ON gli switch 3 e 4,sullo zoccolo"); puts("vanno i segnali TTL dell'UART."); puts(""); puts("Premere un tasto per continuare..."); getchar(); puts("Collegare J7 in 2-3."); printf("Baud Rate: "); baud_rate=get_num(); uart_low_level_init(baud_rate); puts("Testare in RS232,poi configurare GMB per altro protocollo:"); puts("togliere alimentazione,settare DSW1:"); puts("1=2=OFF,3=4=ON,poi:"); puts(""); puts("RS422:"); puts("-montare SN75176 o MAX483 su IC1 e IC2"); puts("-J2=1-2 J3=1-2 J4=1-2 J5=2-3"); puts(""); puts("RS485:"); puts("-montare SN75176 o MAX483 su IC1"); puts("-J2=1-2 J3=1-2 J4=1-2 J5=1-2"); puts(""); puts("Scheda a un capo rete->J1 chiuso"); puts("R commuta trasmettitore"); // Il segnale dir e' PB.1 (connettere J7 in 2-3!), viene configurato come // uscita e inizializzato a livello basso DDRB|=0x02; PORTB&=0xFD; // Ripete all'infinito while(1) { // Riceve il carattere e ne fa l'echo putchar(dir=getchar()); // Se e' la lettera 'r', complementa lo stato del segnale dir if(toupper(dir)=='R') { if(PINB & 0x02) { PORTB&=0xFD; } else { PORTB|=0x02; } } } } //endfor (;;) // Fine loop infinito }