{ **************************************************************** * File: gmbda.ppas - Ver. 1.1 * * Compilatore: mikroPascal for PIC by mikroElektronica * * IDE: mikroPascal for PIC by mikroElektronica * * Versione Compilatore: 2.1.6.0 * * Schede: GMM 4620 + GMB HR168 * * GRIFO(R) via Dell'Artigiano 8/6 * * 40016 S. Giorgio di Piano (BO) * * Tel. +39 051 892052 Fax. +39 051 893661 * * http://www.grifo.com http://www.grifo.it * * by Graziano Gaiba 09.03.05 * **************************************************************** Il demo utilizza la sezione CCP1 Mini Modulo per generare, su CN7, 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. Rel 1.1 - by Graziano Gaiba Demo per generazione segnali PWM usando una GMB HR168 pilotata da un Mini Modulo GMM 4620 } { ***************** Definizioni del compilatore ****************** } program gmbda; { *************** Dichiarazione delle contanti ******************* } const RTCSLA: byte = $A0; { ******************* Dichiarazione delle Variabili ******************** } // Variabili di uso generico var chr_in: byte; // Usata nella gestione del demo PWM duty_cycle: word; { ******************* Definizione delle procedure ********************* } // Inizializzazione direzione segnali della CPU procedure Init_cpu; begin ADCON1 :=$0f; // Imposta come I/O digitale i pin AN0..12 CMCON :=$07; // Imposta come I/O digitale RA0..4 { Gli ingressi optoisolati di CN1 sono: IN1-1 <-> RA0 IN2-1 <-> RA1 IN3-1 <-> RB0 IN4-1 <-> RB1 IN5-1 <-> RA4 IN6-1 <-> RC0 IN7-1 <-> RC1 IN8-1 <-> RC5 } trisa := trisa or $13; trisb := trisb or $03; trisc := trisc or $23; { Gli ingressi optoisolati di CN2 sono: IN1-2 <-> RD0 IN2-2 <-> RD1 IN3-2 <-> RD2 IN4-2 <-> RD3 IN5-2 <-> RD4 IN6-2 <-> RD5 IN7-2 <-> RD6 IN8-2 <-> RD7 } trisd := $ff; { Le uscite relays di CN3 sono: OUT A1 <-> RB4 OUT A2 <-> RB5 OUT B1 <-> RB6 OUT B2 <-> RB7 OUT C1 <-> RB3 OUT C2 <-> RB2 } trisb := trisb and $03; { Le uscite relays di CN4 sono: OUT D1 <-> RA3 OUT D2 <-> RC2 (J10 in posizione 3-4) } trisa := trisa and $f7; trisc := trisc and $fb; // Inizialzza modulo USART (8 bit, 19200 baud rate, // no parity) Usart_init(19200); end; // Invia una stringa di caratteri alla porta seriale procedure print_USART(var txt: string[100]); var temp1, temp2: byte; begin temp1 := txt[0]; for temp2 := 1 to temp1 do begin USART_Write(txt[temp2]); end; end; // Invia CR + LF procedure print_CRLF; begin USART_Write(10); USART_Write(13); end; // Pulisce lo schermo, inviando 25 volte CR + LF. procedure clrscr; var temp: byte; begin for temp := 0 to 24 do begin print_CRLF; end; end; // Chiede la pressione di un tasto procedure wait_key; var temp: byte; begin print_usart('Premere un tasto...'); repeat begin nop; end; until USART_Data_Ready = 1; temp := USART_Read; end; { Procedura per impostare lo stato dei relays sui connettori CN3 e CN4. A seconda del valore dei bits di port_val, ogni relay viene attivato (contatto chiuso) o disattivato (contatto aperto). I bit di port_val hanno il seguente significato: -- CN3 port_val.0 pilota il relay OUT A1 port_val.1 pilota il relay OUT A2 port_val.2 pilota il relay OUT B1 port_val.3 pilota il relay OUT B2 port_val.4 pilota il relay OUT C1 port_val.5 pilota il relay OUT C2 -- CN4 port_val.6 pilota il relay OUT D1 port_val.7 pilota il relay OUT D2 Ogni bit ha il seguente significato: bit Significato 0 Relay disattivato (contatto aperto) 1 Relay attivato (contatto chiuso) } procedure set_relays(port_val: byte); begin // I relays sono pilotati in logica complementata , quindi anche port_val // deve essere complementato port_val:=port_val xor $ff; if TestBit(port_val, 0) = 0 then begin ClearBit(portb, 4); end else begin SetBit(portb, 4); end; if TestBit(port_val, 1) = 0 then begin ClearBit(portb, 5); end else begin SetBit(portb, 5); end; if TestBit(port_val, 2) = 0 then begin ClearBit(portb, 6); end else begin SetBit(portb, 6); end; if TestBit(port_val, 3) = 0 then begin ClearBit(portb, 7); end else begin SetBit(portb, 7); end; if TestBit(port_val, 4) = 0 then begin ClearBit(portb, 3); end else begin SetBit(portb, 3); end; if TestBit(port_val, 5) = 0 then begin ClearBit(portb, 2); end else begin SetBit(portb, 2); end; if TestBit(port_val, 6) = 0 then begin ClearBit(porta, 3); end else begin SetBit(porta, 3); end; if TestBit(port_val, 7) = 0 then begin ClearBit(portc, 2); end else begin SetBit(portc, 2); end; end; // Verifica che il parametro in ingresso sia una cifra esadecimale function is_HEX_digit(valore: byte): byte; var flag: byte; begin flag := 0; if (valore >=48) and (valore <= 57) then begin flag := 1; end; if (valore >= 65) and (valore <= 70) then begin flag := 1; end; if (valore >= 97) and (valore <= 102) then begin flag := 1; end; Result := flag; end; // Restituisce il valore di una singola cifra esadecimale ASCII. // NON verifica che il parametro in ingresso sia una cifra esadecimale function HEX_val(valore: byte): byte; begin valore := valore - 48; if valore > 9 then begin valore := valore - 17; if valore > 5 then begin valore := valore - 32; end; valore := valore + 10; end; Result := valore; end; {Inserimento di un valore esadecimale fino a quattro cifre. Il parametro in ingresso e' il numero di cifre, restituisce una word contenente il valore immesso. Gestisce il backspace (ASCII 08) ed accetta cifre in input da '0' a '9', da 'a' a 'f' e da 'A' a 'F'. Iniva un carattere di bell (ASCII 07) quando riceve un dato non accettabile per l'input, o si tenta un inserimento o una cancellazione fuori dal range ammesso. } function inputHEX(n_char: byte): word; var str_input: array[6] of byte; idx, chr_input: byte; pow_of_16: array[5] of word; valore: word; begin pow_of_16[1] := 1; pow_of_16[2] := 16; pow_of_16[3] := 256; pow_of_16[4] := 4096; // Indice deve partire da 1 idx := 1; Inc(n_char); // Nessun carattere in input chr_input := 0; // Valore iniziale valore := 0; // Continua finche' non riceve un carattere CR while chr_input <> 13 do begin // Se un dato e' pronto if usart_data_ready = 1 then begin // Leggilo chr_input := USART_Read; // Se e' backspace (ASCII BS) if chr_input = 8 then begin // e il buffer non e' vuoto if idx > 1 then begin // Invia dato letto USART_Write(chr_input); // Cancella carattere USART_Write(32); USART_Write(chr_input); // Elimina ultimo dato letto Dec(idx); end else begin // Carattere bell per indicare un errore USART_Write(7); end; end; // Se CR ricevuto, elabora il valore e restituiscilo if chr_input = 13 then begin n_char := 0; while idx > 1 do begin Dec(idx); Inc(n_char); valore := valore + word(HEX_val(str_input[n_char])) * pow_of_16[idx]; end; end else begin // Se il carattere puo' essere inserito if idx < n_char then begin // Se il dato ricevuto e' valido: // 0..9 o 'a'..'f' o 'A'..'F' if is_HEX_digit(chr_input) = 1 then begin // Invia il dato letto USART_Write(chr_input); // Memorizzalo nel buffer di ingresso str_input[idx] := chr_input; // Punta alla posizione successiva Inc(idx); end; end else begin // Carattere bell per indicare un errore USART_Write(7); end; end; end; end; print_CRLF; Result := valore; end; { ********************** Programma principale *************************** } begin Init_cpu; // Spegne i relays set_relays(0); // Pulisce lo schermo clrscr; print_USART('Demo PWM Rel 1.1 per GMM 4620 rel 120304 e GMB HR168 rel 110104'); print_CRLF; print_CRLF; print_USART('Questo demo genera un segnale PWM a circa 10 kHz sul pin 6 di CN7.'); print_CRLF; print_USART('Per un corretto funzionamento, il pin 6 di CN7 NON deve essere connesso al'); print_CRLF; print_USART('relay OUT D2 alla sezione RS 485 per cui J10 va connesso in 1-2 e 4-5.'); print_CRLF; wait_key; print_CRLF; print_CRLF; // Prescaler di Timer 2 impostato 1 t2con := 0; // Pin CCP1 impostato come uscita ClearBit(trisc, 2); // Modulo CCP1 in CCP standard PWM mode ccp1con := $0f; // Circa 10 KHz di frequenza per il segnale PWM pr2 := $ff; // Attiva timer 2, timer 2 viene usato come base dei tempi per PWM dei CCP SetBit(t2con, 2); repeat begin print_USART('Duty cycle (esadecimale da 0 a 03FF): '); duty_cycle := inputHEX(4); chr_in := Lo(duty_cycle); //ccp1con.4 = duty_cycle.0 //ccp1con.5 = duty_cycle.1 if TestBit(chr_in, 0) = 0 then begin ClearBit(ccp1con, 4); end else begin SetBit(ccp1con, 4); end; if TestBit(chr_in, 1) = 0 then begin ClearBit(ccp1con, 5); end else begin SetBit(ccp1con, 5); end; // ccpr1l = lo(duty_cycle) >> 2 ccpr1l := chr_in shr 2; chr_in := Hi(duty_cycle); // ccpr1l.6 = chr_in.0 // ccpr1l.7 = chr_in.1 if TestBit(chr_in, 0) = 0 then begin ClearBit(ccpr1l, 6); end else begin SetBit(ccpr1l, 6); end; if TestBit(chr_in, 1) = 0 then begin ClearBit(ccpr1l, 7); end else begin SetBit(ccpr1l, 7); end; end; until False; end.