Programació en C del PIC 16F690

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

Bàscula electrònica

Programa del grup 1

En aquest cas van considerar que la bàscula tenia un límit màxim de 2 kg. Quan s'assoleix aquest límit la bàscula avisa encenent els quatre LED i fent sonar el brunzidor. Els LED es van encenent progressivament a mesura que se superen els múltiples de 0,5 kg.

El polsador BTN1 serveix per activar i desactivar la bàscula i el BTN2 per guardar el pes actual com a tara.

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 4000000			// La freqüència del rellotge és 4 MHz
unsigned short long Lectura;			// Valor llegit del sensor
unsigned short long lectura1;
unsigned short long lectura2;
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 
char Polsad;					// Polsador que s'ha premut
bit on;						// variable per encendre
char valor;
unsigned short long tara;
unsigned short long k;
						// Definició de les funcions que farem servir
unsigned short long LlegirHX(void);		// Lectura del sensor
unsigned short long ConvertirLectura(unsigned short long y);
						// converteix la lectura segons una recta estimada
						// y = m*x + n, amb lectures previes
char Polsador(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 ASCII
void Esborra(void);				// Esborra la pantalla i posa el cursor a l'inici
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;			
  
	TRISB = 0;				// Tot el port B és de sortida
	TRISA = 0b11111111;			// Tot el port A és d'entrada
	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
	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
	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
	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
						// Desactiva tots els bits de Port
	lectura1=LlegirHX()+140000;
	tara=lectura1/216;
	on=0;
	while (1) {				// Inici del bucle de programa
		Polsad = Polsador();		// Llegim els polsadors
		if (Polsad==1){
			if (on == 1){
				on=0;
				Esborra();
			} else {
				on=1;
			}
			__delay_ms(500);
		}
		if ( on == 1 ) {
			Lectura = LlegirHX();	// Llegeix el valor del sensor HX711
			Esborra();		// Esborra la pantalla
			k=ConvertirLectura(Lectura);
			if (Polsad == 2) {		
				tara=k;
			}
			if (tara>(k+3)){ 
				Esborra();
				EnviaL('E');
				EnviaL('R');
				EnviaL('R');
				EnviaL('O');
				EnviaL('R');
			} else{
				if (tara < k){
					Escriu(k-tara);
				} else{
					EnviaL('0');
					EnviaL('0');
					EnviaL('0');
					EnviaL('0');
					EnviaL(' ');
					EnviaL('g');
				}
			}
			if (((k-tara)>=500) && ((k-tara)<=1000) ){
				valor=0b00110001;
				PORTC=valor;
				__delay_ms(200);
			}
			if (((k-tara)>=1000) && ((k-tara)<=1500) ){
				valor=0b00110011;
				PORTC=valor;
				__delay_ms(200);
			}
			if (((k-tara)>=1500) && ((k-tara)<=2000)  ){
				valor=0b00110111;
				PORTC=valor;
				__delay_ms(200);
			}
			if(k>2000){
				valor=0b00111111;
				PORTC=valor;
				__delay_ms(200);
				valor=0b00111111;
				PORTC=valor;
				__delay_ms(200);
				Esborra();
				TocaNota(238, 119, 2);	
				TocaNota(238, 119, 2);
				TocaNota(238, 119, 2);
				EnviaL('P');
				EnviaL('E');
				EnviaL('S');
				EnviaL('O');
				EnviaL(' ');
				EnviaL('M');
				EnviaL('A');
				EnviaL('X');
				EnviaL('I');
				EnviaL('M');
				EnviaL('O');
				__delay_ms(200);
			}
			__delay_ms(1000);		// Retard d'1 s
		}
	}
}
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;				// Retorna el valor
}
unsigned short long ConvertirLectura(unsigned short long y) { 
	unsigned short long x;
	y = y + 140000;
	x = (y / 216); 
	return x;
}
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
		Digits[j] = Digits[j] + '0';	// Li sumem el codi ASCII de 0
		//if (j == 2 || j == 2) {		// Posem espais per separar
		EnviaL(Digits[j]);		// Número
	}
	EnviaL(' ');
	EnviaL('g');
}
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
}
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
	}
    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(200);	   	 	// Retard de 0,2 s
	TRISC = 0b00110000;			// Posem RC5 (sortida del PWM) com a entrada
						// O sigui, silenci
	__delay_ms(200);	   	 	// 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.