Un esempio di semaforo a LED con PIC16F84A.
Schema elettrico:
Il circuito è molto semplice, abbiamo tre led di colore verde, giallo e rosso sulle uscite RB0, RB1 e RB2 rispettivamente.
Il codice è scritto in C ed il compilatore usato è XC8 della Microchip. Viene usato il Timer0 per ottenere un interrupt ogni secondo. Con le costanti TEMPO_DI_ON_VERDE,TEMPO_DI_ON_GIALLO,TEMPO_DI_ON_ROSSO è possibile fissare il tempo di accensione dei led verde, giallo e rosso modificando i valori. Nel codice sono impostate a 15 sec per i led verde e rosso e 3 sec per quello giallo.
Il codice è ampiamente commentato ma in caso di necessità potete contattarmi.
/*
* File: main.c
* Author: primok
*
* Created on 7 novembre 2021, 18.42
*/
#include <xc.h>
/*************************************************************************
CONFIGURAZIONE REGISTRI
*************************************************************************/
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (Power-up Timer is disabled)
#pragma config CP = OFF // Code Protection bit (Code protection disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
/*************************************************************************
DEFINIZIONE COSTANTI
*************************************************************************/
#define VERDE PORTBbits.RB0
#define GIALLO PORTBbits.RB1
#define ROSSO PORTBbits.RB2
#define TEMPO_DI_ON_VERDE 15 //Durata semaforo Verde in secondi
#define TEMPO_DI_ON_GIALLO 3 //Durata semaforo Giallo in secondi quando il semaforo verde è già acceso
#define TEMPO_DI_ON_ROSSO 15 //Durata semaforo Rosso in secondi
#define TIME_1SEC 125 //Costante per avere un secondo
/*************************************************************************
DEFINIZIONE VARIABILI
*************************************************************************/
volatile unsigned char Time_One_Sec=0;//Variabile per conteggio 1 sec
volatile unsigned char semaf_cont=0;//Variabile per stati semaforo
volatile unsigned char Timer_ON=0;//Variabile per durata accensione semaforo
/*************************************************************************
ROUTINE INTERRUPT
*************************************************************************/
void __interrupt () ISR(void){
if (INTCONbits.T0IF){//Interrupt ogni 8 msec
if (--Time_One_Sec==0){//Dopo 1 secondo
Time_One_Sec=TIME_1SEC;//Ricarica variabile per ottenere 1 secondo
if(--Timer_ON==0) { //Dopo TEMPO_DI_ON_VERDE
if( ++semaf_cont>2){//Aggiorna Stato semaforo
semaf_cont=0;
}
if(semaf_cont==0){
Timer_ON=TEMPO_DI_ON_VERDE;//Durata accensione led verde
}
if(semaf_cont==1){
Timer_ON=TEMPO_DI_ON_GIALLO;//Durata accensione led giallo (quando il verde è acceso)
}
if(semaf_cont==2){
Timer_ON=TEMPO_DI_ON_ROSSO;//Durata accensione led rosso
}
}//Fine di if(--Timer_ON==0) {
}//Fine di if (--Time_One_Sec==0){
TMR0=6;
INTCONbits.T0IF=0;
}//Fine di if (INTCONbits.T0IF){
}//Fine di void __interrupt () ISR(void){
/*************************************************************************
MAIN
*************************************************************************/
void main(void) {
//Impostazione porte e registri
TRISA=0b00000000;
PORTA=0b00000000;
TRISB=0b00000000;
PORTB=0b00000000;
OPTION_REG=0b00000100;
INTCON=0b10100000;
TMR0=6;
Time_One_Sec=TIME_1SEC;
VERDE=1;
Timer_ON=TEMPO_DI_ON_VERDE;
//Ciclo while
while(1){
switch (semaf_cont){
case 0:
VERDE=1;
GIALLO=0;
ROSSO=0;
break;
case 1:
VERDE=1;
GIALLO=1;
ROSSO=0;
break;
case 2:
VERDE=0;
GIALLO=0;
ROSSO=1;
break;
}
}
return;
}
Al prossimo tutorial.
Primok_V