Soluzione degli esercizi di confronto e salto

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 1s */
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 +++++++++++++++++
{}