Programació en C del PIC 16F690

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

Bàscula electrònica

Programa del grup 4

En aquest cas van considerar que la bàscula tenia un límit màxim de 8 kg. L'usuari pot indicar el número de persones i la bàscula li indicarà el pes mesurat i també el pes per persona.

El polsador BTN0 serveix per activar la bàscula i el BTN1 per desactivar-la. Els polsador BTN2 serveix per indicar que volem la lectura en lb i el BTN3 si desitgem kg, El polsador BTN4 guarda el pes actual com a tara i el BTN5 mostra a la pantalla les funcions dels botons.

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 Polsador   RA3
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
unsigned short long pes;			// Valor llegit del sensor
unsigned short long tara;
unsigned short long pesreal;
unsigned short long unitat;
char Polsad;					// Polsador que s'ha premut
char Port;					// Bits del port C
						// RC0 a RC3 són els LED
						// RC4 és DAT (DOUT del sensor)
						// RC6 és CLK (PD_SCK del sensor)
						// RC5 és on hi ha el brunzidor
						// Definició de les funcions que farem servir 
unsigned short long LlegirHX(void);		// Lectura del sensor
char Polsadors(void);				// Funció de lectura dels polsadors
void Escriu(unsigned short long Valor);		// Escriu un valor de 24 bits a la pantalla
void EnviaL(char Caracter);			// Envia un caràcter
void Esborra(void);				// Esborra la pantalla i posa el cursor a l'inici
void Cursor(char Filera, char Columna);		// Posiciona el cursor (filera 1 a 2
						// i columna 1 a 32, segons pantalla)
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
void main (void) {
	ANSEL = 0b00000101;			// Configura AN0 i AN2 com entrada analògica
	ANSELH = 0;				// Desactiva les altres entrades analògiques
	TRISC = 0b00110000;			// Posa RC4 com a entrada, la resta és de sortida
	TRISB = 0;				// Tot el port B és de sortida
	TRISA = 0xFF; 				// Posa RA3 com a entrada  0b00001000
	TXSTAbits.BRGH = 1;			// Configuració de velocitat
	BAUDCTLbits.BRG16 = 0;			// Paràmetre de velocitat de 8 bits
	SPBRG = 25;				// Velocitat de 9600 baud
	TXSTAbits.SYNC = 0;			// Comunicació asíncrona
	TXSTAbits.TX9 = 0;			// Comunicació de 8 bits
	RCSTAbits.SPEN = 1;			// Activa comunicació sèrie
	TXSTAbits.TXEN = 1;			// Activa comunicació
	PORTB = 0;				// Desactiva tots els bits del port B
	PORTC = 0;				// Desactiva tots els bits del port C
	Port = 0;				// Desactiva tots els bits de Port
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	ADCON0 = 0b00001001;			// Activa el conversor A/D connectat a AN2
	CCP1CON = 0b00001100;			// Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
						// DC1B = 11 (bits 5-4) els dos bits de menys pes són 0
						// CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten
						// Ho posa com a configuració del PWM
	CCPR1L = 49;				// Valor que correspon a un cicle del 35 % a 440 Hz
						// Registre que ens dona l'amplada de tON
	PIR1bits.TMR2IF = 0;			// Desactiva el bit d'interrupció del Timer 2
	T2CON = 0b00000011;			// Configura el Timer 2
						// bits T2KCPS (bits 1-0) a 11 prescalat de 16
						// bit 2 (TMR2ON) a 0, Timer aturat
						// Postscaler TOUTPS (bits 6-3) no afecten al PWM
	_delay(500000);
	while (Polsador == 1) {			// Si el polsador no està premut
		;
	}
	tara = LlegirHX()*0.00472;            
	Esborra();				// Esborra la pantalla i posa el cursor a l'inici
	Cursor(1, 7);
	EnviaL('O');				// Lletra
	EnviaL('N');				// Lletra
	TocaNota(189, 95, 0);			// Valor que correspon aproximadament a mi3
	TocaNota(189, 95, 0);			// Valor que correspon aproximadament a mi3
	_delay(20000);
	TocaNota(189, 95, 0);			// Valor que correspon aproximadament a mi3
	_delay(20000);
	TocaNota(238, 119, 2);
	TocaNota(189, 95, 0);			// Valor que correspon aproximadament a mi3
	_delay(20000);
	TocaNota(158, 79, 2);
	_delay(200000);
	TocaNota(249, 122, 2);
	_delay(200000);
	Esborra();
	unitat=3;
	EnviaL('P');
	EnviaL('R');
	EnviaL('E');
	EnviaL('S');
	EnviaL('S');
	EnviaL(' ');
	EnviaL('5');
	EnviaL(' ');
	EnviaL('F');
	EnviaL('O');
	EnviaL('R');
	EnviaL(' ');
	EnviaL('I');
	EnviaL('N');
	EnviaL('F');
	EnviaL('O');
	_delay(2000000);
	Esborra();
	while (1){
		pes = LlegirHX()*0.00472;	// Llegeix el valor del sensor HX711
		if (Polsad  == 2){
			unitat=2;
		}
		if (Polsad ==3){
			unitat =3;
		}
		if (unitat == 3){
			pesreal = (pes-tara);
			Esborra();		// Esborra la pantalla
			Escriu(pesreal);	// Escriu la lectura a la pantalla
			Cursor(1, 7);
			EnviaL('k');		// Lletra
			EnviaL('g');
			if ((pesreal) == 0) {
				Esborra();
				Cursor(1,5);
				EnviaL('0');
				Cursor(1,7);
				EnviaL('k');
				EnviaL('g');
			}
		}
		if (unitat == 2){
			Esborra();
			pesreal = (pes-tara)*2.20462262;
			Escriu(pesreal);
			Cursor(1, 7);
			EnviaL('l');		// Lletra
			EnviaL('b');
			if ((pesreal) == 0) {
				Esborra();
				Cursor(1,5);
				EnviaL('0');
				Cursor(1,7);
				EnviaL('l');
				EnviaL('b');
			}
		}
		if ((pes-tara)>3000) {
			Esborra();
			Cursor(1,6);
			EnviaL('E');
			EnviaL('r');
			EnviaL('r');
			EnviaL('o');
			EnviaL('r');
			TocaNota(189, 95, 0);	// Valor que correspon aproximadament a mi3
			RC0 = 1;	// Activa el bit 0 del port C i, per tant, encén el LED
		}
		Polsad = Polsadors();		// Llegim els polsadors
		if (Polsad == 4) {		// Si s'ha premut el polsador 5
			tara = pes;
			Esborra();
		}
		if (Polsad  == 1){
			Esborra();
			Cursor(1, 7);
			EnviaL('O');		// Lletra
			EnviaL('F');
			EnviaL('F');
			TocaNota(189, 95, 0);
			TocaNota(212, 106, 2);
			TocaNota(238, 119, 2);
			Esborra();
			break;
		}
		if (Polsad == 5) {
			Esborra();            
			EnviaL('1');
			EnviaL(':');
			EnviaL('O');
			EnviaL('F');
			EnviaL('F');
			Cursor(1, 9);
			EnviaL('2');
			EnviaL(':');
			EnviaL('l');
			EnviaL('b');
			Cursor(2, 1);
			EnviaL('3');
			EnviaL(':');
			EnviaL('k');
			EnviaL('g');
			Cursor(2, 9);
			EnviaL('4');
			EnviaL(':');
			EnviaL('T');
			EnviaL('a');
			EnviaL('r');
			EnviaL('a');
			_delay(2000000);
		}
		__delay_ms(1000);		// Retard d'1 s
	}
}
void EnviaL(char Caracter) {
	TXREG = Caracter;			//  Agafa el caràcter i l'envia
	_delay(5);				// Donem temps
	while (PIR1bits.TXIF == 0)		// Esperem que s'acabi d'enviar
		;				// No fem res
}
void Esborra(void) {
	EnviaL(254);				// Caràcter de control
	EnviaL(1);				// Esborra la pantalla i posa el cursor a l'inici
}
void Cursor(char Filera, char Columna) {
	char Posicio = 0;			// Variable per a calcular la posició
	if (Filera == 2) {
		Posicio = 64;			// La primera columna de la segona fila és 64;
	}
	if (Columna > 0 && Columna < 33) {	// Comprovem que sigui un valor raonable
		Posicio = Posicio + Columna;	// Sumem les adreces
		Posicio = Posicio - 1;		// Restem 1 perquè numera des de 0
	}
	Posicio = Posicio + 128;		// Posa el bit de posicionat a 1
	EnviaL(254);				// Control de la posició del cursor
	EnviaL(Posicio);			// Canvia el cursor de lloc
}
unsigned short long LlegirHX(void) {
	unsigned short long Buffer;		// Valor rebut
	Port = Port & 0b10111111;		// Desactiva PD_SCK
	PORTC = Port;
	for (int j = 1; j <= 24; j++){		// 24 bits
		Port = Port | 0b01000000;	// Activa PD_SCK
		PORTC = Port;
		Buffer = Buffer << 1;		// Rodem els bits per situar el següent
						// a la dreta hi quedarà un zero
		if (RC4 == 1) {	// Si DOUT està activat, posem un 1
			Buffer = Buffer | 0b00000001;
		}
		Port = Port & 0b10111111;	// Desactiva PD_SCK
		PORTC = Port;
		__delay_us(3);	   	 	// Espera 3 us per fer els polsos de la mateixa amplada
	}
	Port = Port | 0b01000000;		// Activa PD_SCK per dir-li el guany
	PORTC = Port;
	__delay_us(6);	   	 		// Espera 6 us per fer els polsos de la mateixa amplada
	Port = Port & 0b10111111;		// Desactiva PD_SCK
	PORTC = Port;
	return Buffer+200000;			// Retorna el valor
}
void Escriu(unsigned short long Valor) {
	char Digits[8];				// Aquí guardarem els 8 dígits
	unsigned short long Result;		// Variable de treball
	Result = Valor % 10;
	Digits[0] = (char) Result;		// Unitats
	Valor = Valor / 10;
	Result = Valor % 10;
	Digits[1] = (char) Result;		// Desenes
	Valor = Valor / 10;
	Result = Valor % 10;
	Digits[2] = (char) Result;		// Centenes
	Valor = Valor / 10;
	Result = Valor % 10;
	Digits[3] = (char) Result;		// Milers
	Valor = Valor / 10;
	Result = Valor % 10;
	//Digits[4] = (char) Result;		// Desenes de miler
	//Valor = Valor / 10;
	//Result = Valor % 10;
	//Digits[5] = (char) Result;		// Centenes de miler
	//Valor = Valor / 10;
	//Result = Valor % 10;
	//Digits[6] = (char) Result;		// Unitats de milió
	//Result = Valor / 10;
	//Digits[7] = (char) Result;		// Centenes de milió
	for (int j = 3; j >= 0; j--){		// 8 dígits
		if (Digits[j]!=' '){
			Digits[j] = Digits[j] + '0';	// Li sumem el codi ASCII de 0
		}
		if ( j == 2) {			// Posem espais per separar
			EnviaL(',');		// Espai
		}
		EnviaL(Digits[j]);		// Número
	}
}
char Polsadors(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 TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B) {
	TRISC = 0b00110000;			// 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 = 0b00010000;			// Posem RC5 (sortida del PWM) com a sortida
	__delay_ms(120);	   	 	// Retard de 0,2 s
	TRISC = 0b00110000;			// Posem RC5 (sortida del PWM) com a entrada
						// O sigui, silenci
	__delay_ms(120);	   	 	// Retard de 0,2 s
}

 

 

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