/* ********************************************************************** ** Programma: gmbda.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: GMBDA.C - Rel. 1.1 - By Graziano Gaiba Il demo utilizza il timer 2 del Mini Modulo per generare, su CN4, un segnale PWM di frequenza prestabilita, con duty cycle programmabile in percentuale da console. Tale segnale, collegato ad una opportuna circuiteria integratrice (rete RC, amplificatore operazionale con capacita' su ramo di retroazione, ecc.) permette di ottenere un segnale analogico analogo a quello di un D/A. L'esecuzione del demo e' subordinata al Mini Modulo utilizzato e alla configurazione della linea seriale. !!!!!!!!!!!!!!!!!!!!!!!!!!! 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; } //Inizializza il Timer 2 per funzionare come PWM void init_pwm(void) { DDRB|=0x08; // Imposta portb.3 come uscita OCR2=0x80; // Duty Cycle 50% // Modalita' Fast PWM, Nessun Prescaler, Pone ad 1 il pin 8 dello zoccolo ad // ogni corrispondenza tra i registri OCR2 e contatore del timer TCCR2=0x79; TCNT2=0; // Azzera il timer } 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 duty_cycle; 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("Timer 2 (8 bit) configurato come PWM (pin 3 di CN4)."); puts(""); init_pwm(); // Inizializza il Timer 2 come PWM do { printf("Duty cycle in decimale (da 0 a 255, 0 per resettare): "); duty_cycle=get_num(); puts(""); OCR2 = duty_cycle; // Reimposta il duty cycle }while(duty_cycle); TCCR2=0x48; // Ferma Timer 2 } //endfor (;;) // Fine loop infinito }