Programació en C del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Tres en línia electrònic

Programa del grup 2

Els tres polsadors de l'esquerra de la part inferior serveixen per seleccionar la fila o la columna.

El programa és el següent:

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#include <xc.h>					// Carrega el fitxer de funcions necessari per al compilador XC8
#define _XTAL_FREQ  8000000
#define rett 10000
char Matriu[3][3]={{0,0,0},{0,0,0},{0,0,0}};
char Jugador;					// Variable que diu quin color està actiu
						// Jugador = 0		Apagat
						// matriu		Vermell
						// Jugador = 1		Verd
						// Jugador = 2		Blau
char Actiu;
char Sortida[6];
char Polsad;
char x;
char y;
int compta=0;
char victoria=0;
char Polsador(void);
char guanyar();
void Ini3max(void);	
void Apaga(void);
void memoria ();
void canvijugador(void);
void Envia3max(char Valor[6]);
void acabaireinicia();
void llegeixienvia();
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
void main (void) {
	OPTION_REG = 0b10000101;
	TRISC = 0b00100000;
	TRISB = 0;
	TRISA = 0xFF;
	ANSEL = 0b00000101;			// Configura AN0 i AN2 com entrada analògica
	ANSELH = 0;
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	ADCON0 = 0b00001001;			// Activa el conversor A/D connectat a AN2
						// amb el resultat justificat per l'esquerra
	PORTC = 0;
	CCP1CON = 0b00001100;
	CCPR1L = 49;
	PIR1bits.TMR2IF = 0;			// Desactiva el bit d'interrupció del Timer 2
	T2CON = 0b00000011;
	PORTB = 0;
	Jugador=1;
	Actiu=1;
	Ini3max();
	Apaga();
	TMR0 = 139;
	INTCON = 0b10100000;
	while (1) {
		llegeixienvia();
		if (victoria!=0){
			__delay_ms(1000);
			acabaireinicia();    
		}
		if (compta==9){
			__delay_ms(500);
			acabaireinicia();
		}
		while (Polsador()==0){
		}
		if (Polsador()<4){
			x=Polsador();
		}
		_delay(rett);
		while (Polsador()!=0){
		}
		_delay(rett);
		while (Polsador()==0){
		}
		if (Polsador()<4){
			y=Polsador();
		}
		_delay(rett);
		while (Polsador()!=0){
		}        
		_delay(rett);
		memoria();
		victoria= guanyar();
    }
}
void interrupt temporit(void) {
	INTCONbits.GIE = 0;			// Desactiva les interrupcions momentàniament
	if (INTCONbits.T0IF) {			// Comprovem que hi ha interrupció per Timer 0
		TMR0 = 139;			// Preselecció de Timer0
		INTCONbits.T0IF = 0;		// Desactiva el bit que indica interrupció pel Timer0
		if (Actiu != 0) {		// Si la matriu no està apagada
			Actiu--;		// Passem a activar un altre color
			if (Actiu == 0) {	// Si hem arribat a zero
				Actiu = 3;	// Torna a posar el 3
			}
		}
						// D'entrada els desactivem els tres
		Sortida[0] = 0x00;		// Vermell
		Sortida[2] = 0x00;		// Verd
		Sortida[4] = 0x00;		// Blau
		if (Actiu == 1) {		// Si és vermell
			Sortida[0] = 0x01;	// Vermell activat
		}
		if (Actiu == 2) {		// Si és verd
			Sortida[2] = 0x01;	// Verd activat
		}
		if (Actiu == 3) {		// Si és blau
			Sortida[4] = 0x01;	// Blau activat
		}
		Sortida[1] = 0x0C;		// Shutdown mode
		Sortida[3] = 0x0C;		// Shutdown mode
		Sortida[5] = 0x0C;		// Shutdown mode
		Envia3max(Sortida);		// Ho envia al MAX7221
	}
	INTCONbits.GIE = 1;			// Reactiva les interrupcions a l'acabar
}
void memoria (){
	for (int j = 2; j >= 0; j--){
		for (int i = 2; i >= 0; i--){
			if ((x==i+1) && (y==j+1)){  
				if (Matriu[i][j]==0){		// comprova que estigui apagat
					Matriu[i][j]=Jugador;
					canvijugador();		// si la casella esta buida canvia el jugador
					compta++;
				}
			}
		}
	}
}
void canvijugador(void){			//canvia el jugador despres de tirar 
	if (Jugador==1){
		Jugador=2;
	} else if (Jugador==2){
		Jugador=1;
	}
}
char Polsador(void) {
	char Pols = 0;
	ADCON0bits.GO = 1;			// Posa en marxa el conversor
	while (ADCON0bits.GO == 1)		// Mentre no acabi
		;				// ens esperem
	if (ADRESH < 220 && ADRESH > 200) {
		Pols = 1;			// Comprova polsador 1
	}
	if (ADRESH < 194 && ADRESH > 174) {
		Pols = 2;			// Comprova polsador 2
	}
	if (ADRESH < 163 && ADRESH > 143) {
		Pols = 3;			// Comprova polsador 3
	}
	if (ADRESH < 90 && ADRESH > 70) {
		Pols = 4;			// Comprova polsador 4
	}
	if (ADRESH < 55 && ADRESH > 35) {
		Pols = 5;			// Comprova polsador 5
	}
	return Pols;
}
void llegeixienvia(){
	int filera=1;
	char graella = 0b00100100;
	char temp1, temp2;
	for (int j = 0; j<=2 ; j++){
		char mascara=0b11000000;
		Sortida[0]= graella;
		Sortida[2]=0;
		Sortida[4]=0;                 
		for (int i=0;i<=2;i++){
			if (Matriu[i][j]==1){
				Sortida[2]=Sortida[2]|mascara;
			}
			if (Matriu[i][j]==2){
				Sortida[4]=Sortida[4]|mascara;
			}
			mascara =  mascara>>3;
		}
		temp1 = Sortida[2];		//guarda els valors de sortida
		temp2 = Sortida[4];
		Sortida[0]=graella;
		Sortida[1]=filera;
		Sortida[3]=filera;
		Sortida[5]=filera;
		Envia3max(Sortida);
		filera++;
		Sortida[0] = graella;
		Sortida[2] = temp1;		//torna a carregar els valors anteriors
		Sortida[4] = temp2;
		Sortida[1]=filera;
		Sortida[3]=filera;
		Sortida[5]=filera;
		Envia3max(Sortida);
		filera++;
		if (filera!=9){
			Sortida[1]=filera;
			Sortida[3]=filera;
			Sortida[5]=filera;
			Sortida[0]=0b11111111;
			Sortida[2]=0b00000000;
			Sortida[4]=0b00000000;                    
			Envia3max(Sortida);
			filera++;       
		}
	}
}
char guanyar(){
	char guanyador =0;
	if ((Matriu[0][0]==Matriu[0][1]) && (Matriu[0][1]==Matriu[0][2]) && (Matriu[0][0]!=0)){
		guanyador=Matriu[0][0];		// columna 0
	}
	if ((Matriu[1][0]==Matriu[1][1]) && (Matriu[1][1]==Matriu[1][2]) && (Matriu[1][0]!=0)){
		guanyador=Matriu[1][0];		// columna 1
	}
	if ((Matriu[2][0]==Matriu[2][1]) && (Matriu[2][1]==Matriu[2][2]) && (Matriu[2][0]!=0)){
		guanyador=Matriu[2][0];		// columna 2
	}
	if ((Matriu[0][0]==Matriu[1][0]) && (Matriu[1][0]==Matriu[2][0]) && (Matriu[0][0]!=0)){
		guanyador=Matriu[0][0];		// fila 0
	}
	if ((Matriu[0][1]==Matriu[1][1]) && (Matriu[1][1]==Matriu[2][1]) && (Matriu[0][1]!=0)){
		guanyador=Matriu[0][1];		// fila 1
	}
	if ((Matriu[0][2]==Matriu[1][2]) && (Matriu[1][2]==Matriu[2][2]) && (Matriu[0][2]!=0)){
		guanyador=Matriu[0][2];		// fila 2
	}
	if ((Matriu[0][0]==Matriu[1][1]) && (Matriu[1][1]==Matriu[2][2]) && (Matriu[0][0]!=0)){
		guanyador=Matriu[0][0];		// diagonal
	}
	if ((Matriu[2][0]==Matriu[1][1]) && (Matriu[1][1]==Matriu[0][2]) && (Matriu[2][0]!=0)){
		guanyador=Matriu[2][0];		// diagonal invertida
	}
	return guanyador;
}
void acabaireinicia (){
	char tot= 0b11111111;
	if (victoria!=0) {
		for (int j = 1; j<=8 ; j++){
			Sortida[0]=0;
			Sortida[2]=0;
			Sortida[4]=0;                 
			if (victoria==1){
				Sortida[2]=tot;
			}
			if (victoria==2){
				Sortida[4]=tot;
			}
			Sortida[1]=j;
			Sortida[3]=j;
			Sortida[5]=j;
			Envia3max(Sortida);
		} 
		TocaNota(189, 95, 0); 		// mi
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(178, 89, 2);		// fa
		__delay_ms(10);
		TocaNota(158, 79, 2);		// sol
		__delay_ms(10);
		TocaNota(158, 79, 2);		// sol
		__delay_ms(10);
		TocaNota(178, 89, 2);		// fa
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(212, 106, 2);		// re
		__delay_ms(10);
		TocaNota(238, 119, 2);		// do
		__delay_ms(10);
		TocaNota(238, 119, 2);		// do
		__delay_ms(10);
		TocaNota(212, 106, 2);		// re
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		TocaNota(189, 95, 0); 		// mi
		__delay_ms(5);
		TocaNota(212, 106, 2);		// re
		__delay_ms(5);
		TocaNota(212, 106, 2);		// re
		TocaNota(212, 106, 2);		// re
		TocaNota(212, 106, 2);		// re
		__delay_ms(5);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(178, 89, 2);		// fa
		__delay_ms(10);
		TocaNota(158, 79, 2);		// sol
		__delay_ms(10);
		TocaNota(158, 79, 2);		// sol
		__delay_ms(10);
		TocaNota(178, 89, 2);		// fa
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(212, 106, 2);		// re
		__delay_ms(10);
		TocaNota(238, 119, 2);		// do
		__delay_ms(10);
		TocaNota(238, 119, 2);		// do
		__delay_ms(10);
		TocaNota(212, 106, 2);		// re
		__delay_ms(10);
		TocaNota(189, 95, 0);		// mi
		__delay_ms(10);
		TocaNota(212, 106, 2);		// re
		TocaNota(212, 106, 2);		// re
		__delay_ms(5);
		TocaNota(238, 119, 2);		// do
		__delay_ms(5);
		TocaNota(238, 119, 2);		// do
		TocaNota(238, 119, 2);		// do
		TocaNota(238, 119, 2);		// do     
		__delay_ms(1000);
	}
	for (int j = 2; j >= 0; j--){
		for (int i = 2; i >= 0; i--){
			Matriu[i][j]=0;            
		}
	}
	llegeixienvia();
	compta=0;
}
void Envia3max(char Valor[6]) {			// Envia un joc de valors als tres MAX7221
	INTCONbits.GIE = 0;			// Desactiva les interrupcions momentàniament
	char Port = 0;				// Variable on guardem l'estat del port B
	char Temp;				// Variable temporal
	for (int j = 5; j >= 0; j--){		// Hem d'enviar 6 bytes
		for (int k = 1; k < 9; k++){			// De 8 bits
			Temp = Valor[j] & 0b10000000;		// Agafa el bit de més a l'esquerra
								// Temp només podrà valer 0 o 128
			if (Temp == 0) {			// Si val 0
				Port = Port & 0b11101111;	// Desactiva Data (bit 4)
			} else {				// Si val 128
				Port = Port | 0b00010000;	// Activa Data (bit 4)
			}
			Valor[j] = Valor[j] << 1;		// Rodem els bits per situar el següent
			PORTB = Port;				// Ho posa al port B
			Port = Port | 0b00100000;		// Activa Clock (bit 5) i força lectura
			PORTB = Port;				// Ho posa al port B
			Port = Port & 0b11011111;		// Desactiva Clock (bit 5)
			PORTB = Port;				// Ho posa al port B
		}
	}
	Port = Port | 0b01000000;		// Activa Latch (bit 6) per copiar a les sortides
	PORTB = Port;				// Ho posa al port B
	INTCONbits.GIE = 1;			// Reactiva les interrupcions a l'acabar
}
void Ini3max(void) {				// Inicialitza els tres MAX7221
	char Bytes[6];				// Els sis bytes que cal enviar
	Bytes[0] = 0x00;			// Desactivat
	Bytes[1] = 0x0C;			// Shutdown mode
	Bytes[2] = 0x00;
	Bytes[3] = 0x0C;
	Bytes[4] = 0x00;
	Bytes[5] = 0x0C;
	Envia3max(Bytes);			// Els envia
	Bytes[0] = 0x00;			// No decode
	Bytes[1] = 0x09;			// Decode mode
	Bytes[2] = 0x00;
	Bytes[3] = 0x09;
	Bytes[4] = 0x00;
	Bytes[5] = 0x09;
	Envia3max(Bytes);			// Els envia
	Bytes[0] = 0x07;			// Vuit fileres
	Bytes[1] = 0x0B;			// Scan limit
	Bytes[2] = 0x07;
	Bytes[3] = 0x0B;
	Bytes[4] = 0x07;
	Bytes[5] = 0x0B;
	Envia3max(Bytes);			// Els envia
}
void Apaga(void) {				// Apaga tots els LED
	char Bytes[6];				// Els sis bytes que cal enviar
	for (int j = 0; j <= 8; j++){		// Hem d'enviar 8 fileres
		Bytes[1] = j;			// Filera
		Bytes[3] = j;
		Bytes[5] = j;
		Bytes[0] = 0x00;		// Vermells
		Bytes[2] = 0x00;		// Verds
		Bytes[4] = 0x00;		// Blaus
		Envia3max(Bytes);		// Els envia
	}
}
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B) {
	TRISC = 0b00100000;			// Definim com volem les E/S del port C
						// RC5 (sortida del PWM), de moment, com a entrada
	PR2 = ValPR2;				// Carrega PR2
	CCP1CON = CCP1CON & 0b11001111;		// Posa a zero els bits que corresponen a DC1B
	ValDC1B = ValDC1B % 4;			// DC1B va de 0 a 3
	ValDC1B = ValDC1B * 16;			// Desplaça els bits a la posició que els correspon a CCP1CON
	CCP1CON = CCP1CON + ValDC1B;		// Coloca DC1B al seu lloc
	CCPR1L = ValCCPR1L;			// Carrega CCPR1L, registre que ens dona l'amplada de tON
	PIR1bits.TMR2IF = 0;			// Desactiva el bit d'interrupció del Timer 2
	T2CON = 0b00000111;			// Configura el Timer 2
						// bits T2KCPS (bits 1-0) a 11 prescalat de 16
						// bit 2 (TMR2ON) a 1, Timer activat
						// Postscaler TOUTPS (bits 6-3) no afecten al PWM
	while (PIR1bits.TMR2IF == 0)		// Espera l'activació del bit d'interrupció del Timer 2
		;    				// Esperem
	TRISC = 0b00000000;			// Posem RC5 (sortida del PWM) com a sortida
	__delay_ms(25);	   		 	// Retard de 0,2 s
	TRISC = 0b00100000;			// Posem RC5 (sortida del PWM) com a entrada
						// O sigui, silenci
}

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.