ESERCIZI IN C E BASIC Per il linguaggio C faccio riferimento all’IDE MPLAB C18, perciò ai processori PIC18Fxx. Per il linguaggio Basic faccio riferimento ai PIC16F876. Per la verifica delle proprie soluzioni in C degli esercizi si può usare il file eserC18_0.C. E’ consigliabile, per chiarezza, negli esercizi un po’ complessi realizzare la soluzione come una subroutine lanciata dal programma principale. Esercizi di selezione CS1 (ris.) Considerando i numeri contenuti nelle locazioni scritti in binario senza segno implementare il seguente diagramma di flusso F V (num1)<= 10 (num2) 42H CS2 (ris.) Considerando i numeri contenuti nelle locazioni scritti in binario senza segno implementare il seguente diagramma di flusso T F (num1) > (num2) (RB) 41H CS3 (ris.) Considerando i numeri contenuti nelle locazioni scritti in binario senza segno implementare il seguente diagramma di flusso T F (num1)<> 20 (num2) 41H (num3) 44H CS4 (ris.) Considerando i numeri contenuti nelle locazioni scritti in binario senza segno implementare il seguente diagramma di flusso T F (num1) = 50 (num2) 40H T F (num1) > 60 (num2) 41H (num2) 42H CS5 (ris.) Leggere i 3 pin meno significativi di RA e emettere sui pin di RB e RC i valori indicati dal diagramma di flusso (per poterlo simulare bisogna disattivare ADC e comparatore: vedi file eserC18_0.C) CS6 Leggere i 3 pin meno significativi di RA e copiarne il valore sui corrispondenti pin di RB lasciando inalterati gli altri. CS7 Estrarre il valore assoluto del numero ‘num1s’ di tipo short (Integer in Basic di SourceBoost) e copiarlo nel numero di tipo unsigned short ‘num1us’ (Word in Basic di SourceBoost), inoltre, se il ‘num1s’ è negativo scrivere l’ASCII di ‘-‘ nella variabile unsigned char ‘sign’ (Byte in Basic) Programmazione di diagrammi di flusso FCC1 (ris.) Esempio di controllo di temperatura ambiente mediante un climatizzatore. Scrivere il codice in linguaggio C o Basic corrispondente al seguente diagramma di flusso, quindi assemblarlo e simularlo. Aggiungere le etichette che si ritiene opportuno. ‘STATO’ e ‘val’ sono bytes della RAM, ‘BON’ è il bit mieiflag.7, PORT1 è PORTB FCC2 Scrivere il codice in linguaggio C corrispondente al seguente diagramma di flusso, quindi assemblarlo e simularlo in ambiente MPLAB C18. Aggiungere le etichette che si ritiene opportuno. ‘STATO’ e ‘val’ sono bytes della RAM, ‘BON’ è il bit mieiflag.1, PORT1 è PORTB FCC3 Scrivere il codice in linguaggio C corrispondente al seguente diagramma di flusso, quindi assemblarlo e simularlo in ambiente MPLAB C18. Aggiungere le etichette che si ritiene opportuno. ‘STATO’ e ‘val’ sono bytes della RAM, ‘BON’ è il bit mieiflag.0, PORT1 è PORTB TAB1 (ris.) In un ciclo che si ripete 8 volte usare le variabili di tipo char (o byte) ‘inp’ e ‘stato’ come indici di colonna e di riga, rispettivamente, per prelevare da una tabella in flash , organizzata come in figura, il byte puntato dagli indici e copiarlo in ‘statofut’ 0 2 4 6 1 3 5 7 TAB2 (ris.) Preliminare per gli automi. In una routine usare delle variabili variabili di tipo char (o byte) ‘inp’, ‘statt’ e ‘outrb’ per la gestione di un sistema di controllo che gestisce delle tabelle nel seguente modo. In un ciclo infinito legge l’input sul bit 0 di PORTA e lo copia nel byte ‘inp’. Usa le variabili ‘inp’ e ‘statt’ come indici di colonna e di riga, rispettivamente, per prelevare da una tabella (3x2) in flash , organizzata come in figura, il byte puntato dagli indici e lo copia in ‘statt’. Una volta aggiornato il valore di ‘statt’ lo usa come indice di colonna per copiare il ‘outrb’ il contenuto di una locazione di una tabella (1x3). Copia sui pin di PORTB il contenuto di ‘outrb’. Ritorna all’inizio. 1 2 2 1 0 1 %00100000 %10000000 %01000000 Esercizi sulle iterazioni IT1 (ris.) 1)Preimpostare RB in out, RA in input digitale 2) leggere l'input su RA e accendere e poi spegnere il LED di RB3 tante volte quante indicate dal numero dei pin RA0, 1, 2 3) Usando una funzione di libreria come la waitms in BaSic o la Delay1KTCYx(x) in C (vedi libreria delays.h) che dà un ritardo di 1000*x*(4Tck), dare una durata di 250 ms a ogni tempo di accensione e di spegnimento. Considerare un quarzo di 4MHz 4)tornare al punto 2 IT2 1)impostare RB in out, RA in input digitale 2) leggere l'input su RA e mettere a 1 tanti pin di RB quanto indicato dal numero composto dai pin RA0, 1, 2 3) In Basic dare un ritardo di 10ms. Solo in C: usando l’istruzione Delay1KTCYx(x) (vedi libreria delays.h) che dà un ritardo di 1000*x*(4Tck), dare una pausa di 10 ms. Considerare un quarzo di 4MHz 4) tornare al punto 2 IT3 (ris.) Data una tabella in RAM di 8 numeri short (Integer in Basic) calcolarne la media aritmetica usando l’istruzione di rotazione (>> in C e shiftright in Basic) (metodo molto più rapido dell’uso dell’istruzione / ) IT4 Data una tabella in RAM di 8 numeri di un byte in binario senza segno, trovarne il massimo e il minimo SOLUZIONI Soluzione degli esercizi di confronto e salto CS1)Non si può fare un ‘if’ senza il ramo ‘then’, volendo fare la routine a tutti i costi si può mettere un’istruzione fasulla nel ramo del ‘vero’, ma la cosa più logica sarebbe mettere il segno ‘>’ nella ‘if’ e l’istruzione num2=0x42; nel ramo del ‘vero’ -------------- C -----------------if (num1<=10) {_asm nop //N.B. istruzione in assembler ma manca il ‘;’ e il commento è con // _endasm } else {num2=0x42; } ------------BASIC ---------Dim num1 As Byte Dim num2 As Byte If num1 > 10 Then num2 = 0x42 Endif ++++++++++++++++ CS2 --------------- C ----------------if (num1>num2) {PORTB= 0B01000001; //numero 41H in binario } ------------------- BASIC ------------------ Dim num1 As Byte Dim num2 As Byte If num1 > num2 Then PORTB = 0x41 Endif +++++++++++++++++ CS3 --------------- C ----------------if (num1!=10) num2='A'; //41H è l’ASCII della lettera A else num3=0x44; ------------------- BASIC -----------------If num1 <> 20 Then num2 = 0x41 Else num3 = 0x44 Endif CS4 --------------- C ----------------if (num1==50) num2=64; //passo il valore 40h in decimale else if (num1>60) num2= 0x41; else num2= 0x42; ------------------- BASIC -----------------If num1 = 50 Then num2 = 64 Else If num1 > 60 Then num2 = 0x41 Else num2 = %01000010 Endif Endif +++++++++++++++++++++++++ CS5 etic:; inp=PORTA; inp = inp & 0b00000111; //si può usare anche la forma inp &= 0b00000111; switch (inp) {case 1: PORTB=0x01; break; /*il break serve ad impedire il confronto di ‘inp’ con i valori successivi */ case 2: {PORTB=0x02; } break; case 4: {PORTB=0x04; } break; default: {PORTB=0; PORTCbits.RC0=1; //imposto a 1 un solo bit } break; //se non ha trovato nessun valore uguale a Num1 //esegue questa istruzione } goto etic; ------------------- BASIC (per PIC16F876) -----------------PORTA = 0 PORTB = 0 PORTC = 0 TRISA = 0xff 'RA input TRISB = 0 'RB output TRISC = 0 ADCON0 = 0x00 'LSb=0 -> disabilito ADC ADCON1 = 00000110b 'nessun pin usato in analogico OPTION.7 = 0 'attivo pull-up di RB etic: inp = PORTA inp = inp And %00000111 Select Case inp Case 1 PORTB = 0x01 Case 2 PORTB = 0x02 Case 4 PORTB = 0x04 Case Else PORTB = 0 PORTC.0 = 1 EndSelect Goto etic End --------------------------------Soluzione degli esercizi di programmazione di diagrammi di flusso //+++++++++++++++++ soluzione dell'esercizio FCC1 +++++++++++++++++++ -------------C-----------void soleserFCC1(void) {//variabili locali (formali) unsigned char val; unsigned char STATO; //bit della RAM con nome simbolico union { struct {unsigned BON:1; //1° bit (LSb) del byte MIEIFLAG } Bit; unsigned char Byte; }MIEIFLAG; inizio:; PORTB=0; waitcom:; if (MIEIFLAG.Bit.BON==1) {if (STATO==1) {if (val>30) {PORTB=1; } else {if (val<20) {PORTB=2; } else {PORTB=0; } } goto waitcom; } } goto inizio; } --------------------- BASIC ------------------Dim val As Byte Dim stato As Byte Dim mieiflag As Byte Symbol bon = mieiflag.7 PORTB = 0 TRISB = 0 'RB output OPTION.7 = 0 'attivo pull-up di RB inizio: PORTB = 0 waitcom: If bon = 1 Then If stato = 1 Then If val > 30 Then PORTB = 1 Else If val < 20 Then PORTB = 2 Else PORTB = 0 Endif Endif Goto waitcom Endif Endif Goto inizio End //+++++++++++++++++ fine esercizio FCC1 +++++++++++++++++++ //+++++++++++++++++ soluzione dell'esercizio TAB1 +++++++++++++++++++ //--------- prelevo dalla tabella i valori puntati dagli indici 'stato' e 'inp' (OK) //----------- parte dichiarativa --------------char inp; //indice di colonna unsigned char stato; //indice di riga unsigned char statofut; near rom char *near_rom_ptr; //puntatore alla Flash a numeri di un byte rom char tsf0[2] = {0,1}; rom char tsf1[2] = {2,3}; rom char tsf2[2] = {4,5}; rom char tsf3[2] = {6,7}; //------------------- codice --------------for (inp=0; inp<2; inp++) //gestisco il prelievo da entrambe le colonne {for (stato=0; stato<4; stato++) //gestisco il prelievo da tutte 4 le righe {switch (stato) {case 0:{near_rom_ptr=&tsf0[0]; //puntatore <- indirizzo del 1° byte della 1° riga near_rom_ptr+=inp; //sommo l'indice di colonna statofut=*near_rom_ptr; //carico in 'stato' il valore puntato }break; case 1:{near_rom_ptr=&tsf1[0]; //puntatore <- indirizzo del 1° byte della 2° riga near_rom_ptr+=inp; //sommo l'indice di colonna statofut=*near_rom_ptr; //carico in 'stato' il valore puntato }break; case 2:{near_rom_ptr=&tsf2[0]; //puntatore <- indirizzo del 1° byte della 3° riga near_rom_ptr+=inp; //sommo l'indice di colonna statofut=*near_rom_ptr; //carico in 'stato' il valore puntato }break; case 3:{near_rom_ptr=&tsf3[0]; //puntatore <- indirizzo del 1° byte della 4° riga near_rom_ptr+=inp; //sommo l'indice di colonna statofut=*near_rom_ptr; //carico in 'stato' il valore puntato }break; } } } - - - - - - - - - - - BASIC - - - - - - - - Dim stato As Byte Dim statofut As Byte 'ci metto lo stato attuale in RAM Dim inp As Byte PORTA = 0 PORTB = 0 TRISA = 0xff 'porta in input TRISB = 0 'portb in output OPTION_REG.7 = 0 'attivo resistenze di pull-up su RB For inp = 0 To 1 'inp conta 2 cicli esterni (è l'indice di colonna) For stato = 0 To 3 'stato conta 4 cicli interni Select Case stato 'stato è l'indice di riga Case 0 statofut = LookUp(0, 1), inp 'inp è l'indice di colonna Case 1 statofut = LookUp(2, 3), inp Case 2 statofut = LookUp(4, 5), inp Case 3 statofut = LookUp(6, 7), inp EndSelect Next stato Next inp fine: Goto fine End //+++++++++++++++++ fine esercizio TAB1 +++++++++++++++++++ //+++++++++++++++++ soluzione dell'esercizio TAB2 +++++++++++++++++++ Dim statt As Byte Dim inp As Byte Dim outrb As Byte PORTA = 0 PORTB = 0 TRISA = 0xff TRISB = 0 ANSEL = 0 statt = 0 ciclo: inp = PORTA inp = inp And 0x01 Select Case statt Case 0 statt = LookUp(1, 2), inp Case 1 statt = LookUp(2, 1), inp Case 2 statt = LookUp(0, 1), inp EndSelect outrb = LookUp(%00100000, %10000000, %01000000), statt PORTB = outrb WaitMs 1 Goto ciclo //+++++++++++++++++ fine esercizio TAB2 +++++++++++++++++++ Soluzioni degli esercizi sulle iterazioni //+++++++++++++ esercizio IT1 (OK) +++++++++++++++++++ ----------C------punto2:; num1=PORTA; //leggo i pin num1&=0x07; //azzero bit superflui while (num1>0) {PORTBbits.RB3=1; Delay1KTCYx(250); /*ritardo di 250000 cicli (vedi menù View->Simulator Trace- > ->Cycles) ogni ciclo è 4Tck che corrisponde a 1s */ PORTBbits.RB3=0; Delay1KTCYx(250); num1--; //decremento unitario del contatore } goto punto2; - - - - - - - - BASIC - - - - - - Dim cont As Byte Dim inp As Byte PORTA = 0 PORTB = 0 TRISA = 0xff 'porta in input TRISB = 0 'portb in output OPTION_REG.7 = 0 'attivo resistenze di pull-up su RB ADCON0 = 0x00 'LSb=0 -> disabilito ADC ADCON1 = 00000110b 'nessun pin usato in analogico inizio: inp = PORTA inp = inp And %00000111 For cont = 1 To inp High PORTB.3 WaitMs 250 Low PORTB.3 WaitMs 250 Next cont Goto inizio End //+++++++++++++ fine esercizio IT1 (OK) +++++++++++++++++++ //++++++++++++++ esercizio IT3 (OK) +++++++++++++ //precarico la tabella con valori estremi per i collaudi for (num1=0;num1<8;num1++) //8 cicli con num1 che fa da indice per la tabella //tabin[num1]=-32768; //valori tutti uguali a 1000H (minimo) tabin[num1]=+32767; //valori tutti uguali a 7FFFH (massimo) //-------- sommo i valori numsL1=0; // ci metto il totale (ci vogliono tre bytes) for (num1=0;num1<8;num1++) //8 cicli per calcolare il totale numsL1=numsL1+tabin[num1]; //avrò un totale di FC0000H (num. negativi) o 3FFF8 (num. positivi //-------- divido per 8 il totale nums0=numsL1>>3; //ogni rotazione a destra divide per 2 un numero binario - - - - - - - - BASIC - - - - - - - - Il linguaggio Basic della Oshon non gestisce numeri di 2 bytes con segno ma solo positivi (vedi help per il tipo di variabili WORD) per cui il metodo non è applicabile. //++++++++++++++ fine esercizio IT3 +++++++++++++++++ {}