Programació en mpasm del PIC 16F690

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

Exemple TR - Comunicació per ràdio

En aquest exemple volem comunicar dos microcontroladors per radiofreqüència.

Ens basarem en l'exemple EA. A l'emissor hi tindrem el programa d'aquest exemple però, addicionalment, enviarem per radiofreqüència el mateix valor que enviem als LED. En el receptor, rebrem el valor i el mostrarem als LED. Així doncs, els LED de les dues plaques tindran la mateixa combinació que podrem variar amb el potenciòmetre de la targeta emissora.

Per evitar saturar el canal de ràdio, esperarem 0,6 s entre una lectura i la següent.

L'emissor estarà connectat a RB4 i el receptor a RB6. Fem servir potes diferents perquè en cas de voler implementar un enllaç bidireccional tindríem emissor i receptor en el mateix microcontrolador.

Els programes es podrien fer servir també per a comunicació per cable. Si comuniquem per cable, podem emprar un filtre més acurat, com hem comentat a radiofreqüència.

Emissor

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock	0x20
Port			; Variable per al contingut del port B
			; que permet modificar els bits individualment
Comp_bits		; Variable per comptar bits
Comp_bytes		; Variable per comptar bytes
Control			; Variable per calcular el byte de control
Retard			; Comptador per al retard
Byte			; Variable de treball per enviar un byte
Bytes			; Número de bytes que voldrem enviar
			; Un paquet tindrà aquests i el byte de control
Ret:3			; Tres variables per a bucles de retard
Vector			; Lloc on es guardaran els bytes a enviar
			; Després d'aquesta ja no es poden declarar més variables
			; ja que el vector tindrà tantes posicions com hi digui a Bytes
			; més una per al byte de control
	endc
	org 0
Inici
	bsf		STATUS,RP0	; Tria el banc 1
	movlw		0xFF		; Posa l'acumulador a FFh (tot uns)
	movwf		TRISA		; Posa tots els bits del port A com a entrada
	clrf		TRISB		; Posa tots els bits del port B com a sortida
	clrf		TRISC		; Posa tots els bits del port C com a sortida
	movlw		b'00010000'	; Posa el conversor a 1/8 de la freqüència
	movwf		ADCON1		; Copia W a la configuració del conversor A/D
	bcf		STATUS,RP0
	bsf		STATUS,RP1	; Tria el banc 2
	movlw		0xFF		; Posa l'acumulador a FFh (tot uns)
	movwf		ANSEL		; Configura AN0-AN7 com entrades analògiques
	bcf		STATUS,RP0
	bcf		STATUS,RP1	; Tria el banc 0
	movlw		0		; Inicialment totes les sortides desactivades
	movwf		Port		; Ho guardem a Port
	movwf		PORTB		; I ho copiem al port B
	movlw		.2		; Número de bytes que volem enviar
	movwf		Bytes		; Ho guardem a Bytes
	movlw		0x93		; Codi d'identificació
	movwf		Vector		; El guarda sobre el primer byte de dades que enviarem
	movlw		b'00000001'	; activa el conversor A/D connectat a AN0
	movwf		ADCON0		; amb el resultat justificat per l'esquerra
Bucle
	nop				; espera un microsegon
	nop				; espera un microsegon
	nop				; espera un microsegon
	nop				; espera un microsegon
	nop				; espera un microsegon, en total 5
	bsf		ADCON0,GO	; Inicia la conversió
	btfsc		ADCON0,GO	; Quan el bit sigui 0 la conversió haurà acabat
	goto		$-1		; repetim la línia fins que deixi de ser 1
	swapf		ADRESH,w	; Permuta els nibbles dels bits superiors
	movwf		PORTC		; Copia el resultat sobre els LED
	movwf		Vector+1	; i sobre el segon byte de dades que enviarem
	call		Envia		; Envia la dada
	movlw		.3		; Bucle de retard de 3 * 0,2 = 0,6 s
	movwf		Ret+2
Bucles
	decfsz		Ret,f		
	goto		Bucles		
	decfsz		Ret+1,f		
	goto		Bucles		
	decfsz		Ret+2,f	
	goto		Bucles
	goto		Bucle
					;
					; Funció per enviar un paquet
					;
Envia					
					; Comencem calculant el byte de control
					; Hem de sumar (sense portar-ne) tots els bytes
	clrf		Control		; El posem a zero
	movf		Bytes,w		; Llegim el número de bytes que volem enviar
	movwf		Comp_bytes	; Ho guardem al comptador de bytes
	movlw		Vector		; Llegim l'adreça de Vector
	movwf		FSR		; Ho posem al punter d'adreçament indirecte
	movlw		0		; L'acumulador contindrà la suma, comencem a 0
	addwf		INDF,w		; Hi sumem un dels bytes
	incf		FSR,f		; Desplaça el punter
	decfsz		Comp_bytes,f	; Byte següent
	goto		$-3		; Si no és el darrer, seguim
					; Ja tenim la suma, ara ho restem (sense portar-ne) de Control (= 0)
	subwf		Control,w	; W = Control - suma
	movwf		INDF		; Ho guarda al final del Vector
					; Comencem a enviar
					; Primer cal enviar la capçalera
	movlw		.15		; Primer 15 bits a 1
	movwf		Comp_bits	; Ho guarda al comptador de bits
	call		Envia_1		; Envia un 1
	decfsz		Comp_bits,f	; Decrementa els bits pendents
	goto		$-2		; Repeteix fins que s'acabi
	call		Envia_0		; Finalment un bit a 0
					; Després cal enviar els bytes
	movf		Bytes,w		; Llegim el número de bytes que volem enviar
	movwf		Comp_bytes	; Ho guardem al comptador de bytes
	incf		Comp_bytes,f	; Incrementa el comptador de bytes per afegir el byte de control
	movlw		Vector		; Llegim l'adreça de Vector
	movwf		FSR		; Ho posem al punter d'adreçament indirecte
TI	movf		INDF,w		; Agafa un dels bytes
	movwf		Byte		; Ho guarda a la variable de treball
	movlw		.8		; Un byte són 8 bits
	movwf		Comp_bits	; Ho guarda al comptador de bits
TR	rlf		Byte,f		; El bit de més a l'esquerra passa a C
	btfss		STATUS,C	; Mira sí és 0
	goto		T0		; Sí, envia un 0
	call		Envia_1		; No, envia un 1
	goto		TF
T0	call		Envia_0		; Envia un 0
TF	decfsz		Comp_bits,f	; Següent bit
	goto		TR
					; Al final de cada byte s'envia un 1 i un 0
	call		Envia_1		; Envia un 1
	call		Envia_0		; Envia un 0	
	incf		FSR,f		; Desplaça el punter
	decfsz		Comp_bytes,f	; Byte següent
	goto		TI
	bcf		Port,4		; Desactiva l'emissor
	movf		Port,w		; Ho canviem a Port
	movwf		PORTB		; I ho copiem al port B
	return
Envia_0					; Funció per enviar un 0
	bsf		Port,4		; Un bit 0 comença amb 1
	movf		Port,w		; Ho canviem a Port
	movwf		PORTB		; I ho copiem al port B
	movlw		.166		; Cada dec són 1 us i cada goto són 2 us
	movwf		Retard		; 165 * 3 (a la darrera no hi ha goto) dona 495
	decfsz		Retard,f	; que amb els 4 dels mov i 1 del dec
	goto		$-1		; fem 500 us
	bcf		Port,4		; I canvia a 0 a mig bit
	movf		Port,w		; Ho canviem a Port
	movwf		PORTB		; I ho copiem al port B
	movlw		.166		; Cada dec són 1 us i cada goto són 2 us
	movwf		Retard		; 165 * 3 (a la darrera no hi ha goto) dona 495
	decfsz		Retard,f	; que amb els 4 dels mov i 1 del dec
	goto		$-1		; fem 500 us
	return				; 0 enviat
Envia_1					; Funció per enviar un 1
	bcf		Port,4		; Un bit 1 comença amb 0
	movf		Port,w		; Ho canviem a Port
	movwf		PORTB		; I ho copiem al port B
	movlw		.166		; Cada dec són 1 us i cada goto són 2 us
	movwf		Retard		; 165 * 3 (a la darrera no hi ha goto) dona 495
	decfsz		Retard,f	; que amb els 4 dels mov i 1 del dec
	goto		$-1		; fem 500 us
	bsf		Port,4		; I canvia a 1 a mig bit
	movf		Port,w		; Ho canviem a Port
	movwf		PORTB		; I ho copiem al port B
	movlw		.166		; Cada dec són 1 us i cada goto són 2 us
	movwf		Retard		; 165 * 3 (a la darrera no hi ha goto) dona 495
	decfsz		Retard,f	; que amb els 4 dels mov i 1 del dec
	goto		$-1		; fem 500 us
	return				; 1 enviat
	end

Receptor

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock	0x20
Estat			; Variable per memoritzar estats
Comp_bits		; Variable per comptar bits
Comp_bytes		; Variable per comptar bytes
Byte			; Variable temporal per construir un byte
Bytes			; Número de bytes que rebrem
Temps			; Variable per comptar el temps
minS			; Valor mínim per a la durada d'un semiperíode
maxS			; Valor màxim per a la durada d'un semiperíode
minP			; Valor mínim per a la durada d'un període
maxP			; Valor màxim per a la durada d'un període
Vector			; Lloc on es guardaran els bytes rebuts
			; Després d'aquesta ja no es poden declarar més variables
			; ja que el vector tindrà tantes posicions com hi digui a Bytes
			; més una per al byte de control
	endc
	org 0
Inici					; Comencem amb la inicialització
	bsf		STATUS,RP0	; Tria el banc 1
	movlw		b'01000000'	; RB6 és entrada, la resta del port B és sortida
	movwf		TRISB
	clrf		TRISC		; Posa tots els bits del port C com a sortida
	movlw		b'10000010'	; Configuració de Timer0
					; Com a temporitzador basat en rellotge
					; 010 - Factor d'escala de 8
					; TMR0 s'incrementarà cada 8 us
					; I resistències de pull-up desactivades (valor per defecte)
	movwf		OPTION_REG	; Ho guarda al registre de configuració del Timer0
	bcf		STATUS,RP0	; Tria el banc 0
					; Inicialització de variables
	clrf		Estat		; De moment, desactiva tots els bits d'estat
	movlw		.3		; Número de bytes que rebrem
	movwf		Bytes		; Ho guardem a Bytes
					; Semiperíode de 500 us
					; Marge d'error: 30 % 	500 * 0,3 = 150
	movlw		.43		; (500 - 150)/8
	movwf		minS		; Valor mínim per a la durada d'un semiperíode
	movlw		.82		; (500 + 150)/8
	movwf		maxS		; Valor màxim per a la durada d'un semiperíode
	movlw		.87		; 2 * (500 - 150)/8
	movwf		minP		; Valor mínim per a la durada d'un període
	movlw		.163		; 2 * (500 + 150)/8
	movwf		maxP		; Valor màxim per a la durada d'un període
	clrf		PORTC		; Comencem amb els LED apagats
Bucle
	call		Rebre		; Espera que arribi un paquet
	andlw		0xFF		; Anem a veure si W és zero
	btfss		STATUS,Z	; Si és zero, and donarà zero
	goto		Bucle		; No és zero, esperem un altre paquet
	movlw		0x93		; Sí és zero, anem a veure el Codi d'identificació
	xorwf		Vector,w	; Compara amb el codi d'identificació 
	btfss		STATUS,Z	; Si Z = 1 es que són iguals
	goto		Bucle		; Z = 0, esperem un altre paquet
	movf		Vector+1,w	; Agafem el byte de dades
	movwf		PORTC		; i el copia sobre els LED
	goto		Bucle		; Acabat, esperem un altre paquet
					;
					; Funció per rebre un paquet
					;
Rebre					
					; Comencem inicialitzant variables
	movlw		Vector		; Carreguem l'adreça del lloc on es guardaran els bytes rebuts
	movwf		FSR		; Punter per a l'adreçament indirecte
	clrf		Comp_bits	; Posem a zero la variable que compta els bits rebuts
	movf		Bytes,w		; Número de bytes que rebrem
	movwf		Comp_bytes	; Variable de comptatge
	bsf		Estat,5		; Cap = 1
					; Ara esperem la primera activació (primer 1)
	btfss		PORTB,6		; S'ha activat l'entrada?
	goto		$-1		; No, doncs esperem
	clrf		TMR0		; Sí, comencem a comptar el temps
Espera					; Esperem a que es desactivi l'entrada
	btfss		PORTB,6		; S'ha desactivat l'entrada?
	goto		PrimerBit	; Sí, doncs el primer bit ja està
	movf		TMR0,w		; No, agafa el valor actual del temps
	movwf		Temps		; i el guarda
	movf		maxS,w		; Mirem que no passem de maxS
	subwf		Temps,w		; W = Temps - W
	btfss		STATUS,C	; C = 1 si Temps >= maxS
	goto		Espera		; És més petit, seguim esperant
	retlw		.129		; És més gran: Error 129 - Bit d'inici massa llarg
PrimerBit				; El primer bit ja està
	movf		TMR0,w		; Agafa el valor actual del temps
	movwf		Temps		; i el guarda
	clrf		TMR0		; Comencem a comptar el temps
	movf		minS,w		; Mirem que no sigui menor que minS
	subwf		Temps,w		; W = Temps - W
	btfss		STATUS,C	; C = 1 si Temps >= minS
	retlw		.130		; És més petit: Error 130 - Bit d'inici massa curt
	incf		Comp_bits,f	; Ja tenim un bit
	bsf		Estat,6		; Pre = 1
	bcf		Estat,7		; Rebut = 0
SegTran					; Esperem al següent canvi a l'entrada
	btfsc		Estat,7		; Quin és el darrer valor de l'entrada?
	goto		Espera0		; 1, doncs hem de rebre un 0
	goto		Espera1		; 0, doncs hem de rebre un 1
Espera0					; Esperem que es desactivi l'entrada
	btfss		PORTB,6		; S'ha desactivat l'entrada?
	goto		Canvi		; Sí	
	movf		TMR0,w		; No, agafa el valor actual del temps
	movwf		Temps		; i el guarda
	movf		maxP,w		; Mirem que no passem de maxP
	subwf		Temps,w		; W = Temps - W
	btfss		STATUS,C	; C = 1 si Temps >= maxP
	goto		Espera0		; És més petit, seguim esperant
	retlw		.17		; És més gran: Error 17 - Període massa llarg
Espera1					; Esperem que s'activi l'entrada
	btfsc		PORTB,6		; S'ha activat l'entrada?
	goto		Canvi		; Sí	
	movf		TMR0,w		; No, agafa el valor actual del temps
	movwf		Temps		; i el guarda
	movf		maxP,w		; Mirem que no passem de maxP
	subwf		Temps,w		; W = Temps - W
	btfss		STATUS,C	; C = 1 si Temps >= maxP
	goto		Espera1		; És més petit, seguim esperant
	retlw		.17		; És més gran: Error 17 - Període massa llarg
Canvi					; L'entrada ja ha canviat
	movf		TMR0,w		; Agafa el valor actual del temps
	movwf		Temps		; i el guarda
	clrf		TMR0		; Comencem a comptar el temps
	movf		minS,w		; Mirem que no sigui menor que minS
	subwf		Temps,w		; W = Temps - W
	btfss		STATUS,C	; C = 1 si Temps >= minS
	retlw		.18		; És més petit: Error 18 - Semiperíode massa curt
	movlw		b'10000000'	; Invertim bit 7
	xorwf		Estat,f		; o sigui, invertim Rebut
	movf		maxS,w		; Mirem si és més gran que maxS
	subwf		Temps,w		; W = Temps - W
	btfss		STATUS,C	; C = 1 si Temps >= maxS
	goto		Curt		; És més petit, és un pols curt
	movf		minP,w		; També mirem si és més gran que minP
	subwf		Temps,w		; W = Temps - W
	btfsc		STATUS,C	; C = 1 si Temps >= minP
	goto		Llarg		; És més gran, és un pols llarg
	retlw		.19		; Ni curt ni llarg
					; Error 19 - Semiperíode massa llarg o període massa curt
Llarg					; És un pols llarg
	btfsc		Estat,6		; Pre = 1?
	retlw		.9		; Sí: Error 9 - No hi ha canvi a mig període
	goto		CanviFinal	; No, esperem canvi al final de període
Curt					; És un pols curt
	movlw		b'01000000'	; Invertim Pre ara
	xorwf		Estat,f		; per no haver-ho de fer dos cops
	btfsc		Estat,6		; Pre = 1?
	goto		SegTran		; No, esperem canvi a mig període
CanviFinal				; Sí, esperem canvi al final de període
	btfss		Estat,5		; Cap = 1?
	goto		NoCap		; No, ja no estem rebent capçalera
	btfss		Estat,7		; Rebut = 1?
	goto		Cap0		; No, hem rebut un zero a la capçalera
	incf		Comp_bits,f	; Tenim un altre 1 de capçalera
	movlw		.16		; Hem arribat al final de la capçalera?
	xorwf		Comp_bits,w	; Comp_bits = 16?
	btfsc		STATUS,Z	; Z = 1 si Comp_bits = 16
	retlw		.66		; Sí: Error 66 - Massa 1 a la capçalera
	goto		SegTran		; No, esperem el següent
Cap0					; Hem rebut un zero a la capçalera
	movlw		.15		; Hem arribat al final de la capçalera?
	xorwf		Comp_bits,w	; Comp_bits = 15?
	btfss		STATUS,Z	; Z = 1 si Comp_bits = 15
	retlw		.65		; Sí: Error 65 - Pocs 1 a la capçalera
	bcf		Estat,5		; Cap = 0 - Capçalera ja acabada, ara rebrem el missatge
	movlw		.10		; Cada byte són 10 bits
	movwf		Comp_bits	; 8 de dades i dos d'aturada
	clrf		Byte		; De moment, no hem rebut cap bit de Byte
	goto		SegTran		; Anem a esperar el primer bit
NoCap					; Ja no estem rebent capçalera
	decfsz		Comp_bits,f	; Decrementem, és 0?
	goto		NoEs0		; No, cal saber si és 1 o més gran
	btfsc		Estat,7		; Sí, darrer bit d'aturada - Rebut = 1?
	retlw		.34		; Sí: Error 34 - No hi ha 0 als bits d'aturada
	movf		Byte,w		; Agafa el byte rebut
	movwf		INDF		; I el guarda a Vector
	incf		FSR,f		; Incrementa el punter
	decfsz		Comp_bytes,f	; Decrementem, és 0?
	goto		NoFi		; No, cal rebre un altre byte
					; Ja hem acabat, anem a fer la suma de control
	movlw		Vector		; Carreguem l'adreça del lloc on es guardaran els bytes rebuts
	movwf		FSR		; Punter per a l'adreçament indirecte
	movf		Bytes,w		; Número de bytes que hem rebut
	movwf		Comp_bytes	; Variable de comptatge
	movlw		0		; Comencem amb zero per anar sumant
SumaControl				; i anem a fer el bucle de suma
	addwf		INDF,w		; Suma el valor de Vector
	incf		FSR,f		; Incrementa el punter
	decfsz		Comp_bytes,f	; Decrementa, és 0?
	goto		SumaControl	; No, sumem un altre
	andlw		0xFF		; Sí, anem a veure si surt zero
	btfss		STATUS,Z	; Si és zero, and donarà zero
	retlw		.5		; No és zero: Error 5 - La suma de control no dona 0
	retlw		0		; Sí és zero: Error 0 - Recepció correcta
NoFi					; Cal rebre un altre byte
	movlw		.10		; Cada byte són 10 bits
	movwf		Comp_bits	; 8 de dades i dos d'aturada
	clrf		Byte		; De moment, no hem rebut cap bit de Byte
	goto		SegTran		; Anem a esperar el primer bit
NoEs0					; Cal saber si és 1 o més gran
	decfsz		Comp_bits,w	; Decrementem provisionalment, és 0?
	goto		Dades		; No, doncs encara és un bit de dades
	btfss		Estat,7		; Sí, és un bit d'aturada - Rebut = 1?
	retlw		.33		; No: Error 33 - No hi ha 1 als bits d'aturada
	goto		SegTran		; Sí, esperem el següent bit d'aturada
Dades					; És un bit de dades
	rlf		Estat,w		; Passa Rebut a C
	rlf		Byte,f		; I el col·loca a la dreta de Byte desplaçant els que ja hi són
	goto		SegTran		; Esperem el següent bit
	end

 

 

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