Programació en mpasm del PIC 16F690

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

Modes de funcionament del motor pas a pas

Programa del grup 4

Aquest grup va codificar el sentit de gir amb l'interruptor connectat a RA5. Els diferents modes es controlen segons la següent taula:

RB7 RB5 Mode
0 0 Aturat
0 1 Full step
1 0 Wave drive
1 1 Half step

El seu programa es basa en l'adreçament indirecte de manera que les nou possibles combinacions de sortides estan guardades a la memòria i s'agafa una o altra segons correspongui. El funcionament consisteix en tenir una part de programa per a cada mode i en cada una es gestionen els valors que cal llegir. El programa final és:

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock 0x20
Delay:2 				; Definimos un vector de 2 variables (Delay y Delay+1) para el bucle
					; de perdida de tiempo
Registro:9 				; Definimos un vector de 9 posiciones para guardar los valores por 
					; enviaremos a los LED
Inter 					; Definimos una variable intermedia para no perder el valor de la 
					; lectura de los interruptores del puerto b
s 					; Definimos una variable que utilizaremos para movernos por el vector
					; Registro
	endc
	org 0
Inici
	bsf 		STATUS,RP0	; Empezamos el programa definiendo las entradas, las
					; salidas, los interruptores y el potenciómetro de la forma que deseamos
	bcf		OPTION_REG,7
	movlw		0xFF
	movwf		TRISA
	movwf		WPUA
	movwf		TRISB
	clrf		TRISC
	movlw		0x10
	movwf		ADCON1
	bcf		STATUS,RP0
	bsf		STATUS,RP1
	movlw		0xFF
	movwf		WPUB
	movlw		0xFF
	movwf		ANSEL
	bcf		STATUS,RP0
	bcf		STATUS,RP1
	movlw		0x01
	movwf		ADCON0
	clrf		s		; Lo primero que hacemos es borrar el valor que pudiera	tomar s antes
					; de comenzar
	call		Grabar		; Lo siguiente es grabar los diferente valores de la tabla Registro en
					; una funció
MainLoop				; Comenzamos el programa con una especie de selección del modo de trabajo
					; del motor
	movf 		PORTB,w		; Primero leemos todo el PORTB de los interruptores B5 y B7 y lo guardamos
					; en el acumulador
	andlw		b'10100000'	; Filtramos el valor para forzar a 0 todos aquellos
					; valores que no correspondan con los interruptores 5 y 7
	movwf		Inter 		; Guardamos el valor resultando de la lectura una vez
					; filtrada en una variable intermedia para no perder su valor
	xorlw		b'10100000'	; Miramos si nuestro valor corresponde a tener los
					; interruptores B5 y B7 activos. Si están así Z toma el valor 1
	btfsc 		STATUS,Z	; Si Z=1, es decir B5 y B7 activos, hace la siguiente instrucción, si no,
					; la salta
	goto		Halfstep	; Va a la funció de Halfstep si B5 y B7 activos a la vez
	movf		Inter,w		; Al haber borrado w en el xorlw anterior, volvemos a
					; copiar la lectura de los interruptores guardada en la
					; variable intermedia en w
	xorlw		b'00100000'	; Miramos si nuestro valor corresponde a tener los
					; interruptores B5 activo y B7 apagado. Si están así Z toma el valor 1
	btfsc		STATUS,Z	; Si Z=1, es decir B5 activo y B7 apagado, hace la
					; siguiente instrucción, si no, la salta
	goto		Fullstep	; Va a la funció de Fullstep si B5 activo y B7 apagado
	movf 		Inter,w		; Al haber borrado w en el xorlw anterior, volvemos a
					; copiar la lectura de los interruptores guardada en la variable
					; intermedia en w
	xorlw 		b'10000000'	; Miramos si nuestro valor corresponde a tener los
					; interruptores B5 apagado y B7 activo. Si están así Z toma el valor 1
	btfsc 		STATUS,Z	; Si Z=1, es decir B5 apagado y B7 activo, hace la
					; siguiente instrucción, si no, la salta
	goto 		Wavedrive 	; Va a la funció de Wavedrive si B5 apagado y B7 activo
	movf		Inter,w 	; Al haber borrado w en el xorlw anterior, volvemos a
					; copiar la lectura de los interruptores guardada en la variable
					; intermedia en w
	xorlw 		b'00000000'	; Miramos si nuestro valor corresponde a tener los
					; interruptores B5 y B7 apagados. Si están así Z toma el valor 1
	btfsc 		STATUS,Z	; Si Z=1, es decir B5 y B7 apagados, hace la siguiente
					; instrucción, si no, la salta
	goto 		Apagado 	; Va a la funció de Apagado si B5 apagado y B7 apagados
Halfstep 				; Aquí comienza la funció de Halfstep
	movlw 		Registro+1	; Comenzamos moviendo la primera dirección de memoria del registro en
					; el acumulador, que correspondería a la 23
	addwf 		s,w		; Le sumamos al acumulador el valor que tome la variable S
	movwf		FSR 		; Indicamos al FSR que se coloque en la dirección de memoria
					; que indica el acumulador
	movf 		INDF,w 		; Movemos al acumulador el valor al que está apuntando el FSR en el
					; registro (Que corresponde a A, AB, B, BC,..)
	movwf 		PORTC 		; Movemos el valor del acumulador al PORTC, para que se mueva el motor
					; y los LED
	call 		Bucle 		; Llamamos al bucle para perder tiempo y así controlar la velocidad
	btfsc 		PORTA,5 	; Miramos si el interruptor A5 esta activo. Si esta activo hace la
					; siguiente instrucción para ir a inversa. Si no, continua normal
	goto 		HalfI 		; Si A5 esta activo, se va a la funció de HalfI, es decir Halfstep
					; en inversa
	incf 		s 		; Incrementamos el valor de S, es decir, le sumamos 1
	movf 		s,w 		; Movemos el nuevo valor de S al acumulador
	xorlw		0x9 		; Comprobamos si S toma el valor 9. Si es así, ha llegado al final
					; del registro y Z valdrá 1
	movlw 		0x1 		; Movemos, por si se ha llegado al final, el valor 1 en
					; el acumulador para copiarlo a S
	btfsc 		STATUS,Z 	; Comprobamos si Z=1. Si es así hace la siguiente
					; instrucción. Si no, la salta
	movwf 		s 		; Copiamos el valor 1 a S para volver ha empezar el ciclo
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
HalfI 					; Aquí empieza la funció de Halfstep en inversa
	decfsz 		s 		; Utilizamos el comando Decfsz que mientras S no sea 0
					; hace la siguiente instrucción. Si S es 0 se la salta
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
	movlw 		0x8 		; Cuando S es 0, cargamos el valor 8 en el acumulador
	movwf 		s 		; Y copiamos este valor en S, para volver a empezar el ciclo
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
Fullstep 				; Aquí empieza la funció de Fullstep
	bcf 		STATUS,C 	; Forzamos que el bit de arrastre sea 0, para que al
					; dividir o multiplicar, nos quedemos con la parte entera
	RRF 		s,f 		; Dividimos entre dos el valor de S
	bcf 		STATUS,C 	; Forzamos que el bit de arrastre sea 0, para que al
					; dividir o multiplicar, nos quedemos con la parte entera
	RLF 		s,f 		; Multiplicamos por dos el valor de S
	incf 		s 		; Sumamos uno para forzar que S sea un número impar
	movlw 		Registro+1 	; Movemos la primera dirección de memoria del registro en el
					; acumulador, que correspondería a la 23
	addwf 		s,w 		; Le sumamos al acumulador el valor que tome la variable S
	movwf 		FSR 		; Indicamos al FSR que se coloque en la dirección de
					; memoria que indica el acumulador
	movf 		INDF,w 		; Movemos al acumulador el valor al que está apuntando el FSR en el
					; registro (Que corresponde a AB, BC,..)
	movwf 		PORTC 		; Movemos el valor del acumulador al PORTC, para que se
					; mueva el motor y los LED
	call 		Bucle 		; Llamamos al bucle para perder tiempo y así controlar la velocidad
	btfsc 		PORTA,5 	; Miramos si el interruptor A5 esta activo. Si esta
					; activo hace la siguiente instrucción para ir a inversa.
					; Si no, continua normal
	goto 		FWI 		; Si A5 esta activo, se va a la funció de FWI, es
					; decir Fullstep en inversa
	incf 		s 		; Incrementamos el valor de S, es decir, le sumamos 1
	movf 		s,w 		; Movemos el nuevo valor de S al acumulador
	xorlw 		0x9 		; Comprobamos si S toma el valor 9. Si es así, ha llegado al final del
					; registro y Z valdrá 1
	movlw 		0x1 		; Movemos, por si se ha llegado al final, el valor 1 en
					; el acumulador para copiarlo a S
	btfsc 		STATUS,Z 	; Comprobamos si Z=1. Si es así hace la siguiente
					; instrucción. Si no, la salta
	movwf 		s 		; Copiamos el valor 1 a S para volver ha empezar el ciclo
	incf 		s 		; Incrementamos el valor de S, es decir, le sumamos 1
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
Wavedrive 				; Aquí empieza la funció de Wavedrive
	bcf 		STATUS,C 	; Forzamos que el bit de arrastre sea 0, para que al
					; dividir o multiplicar, nos quedemos con la parte entera
	RRF 		s,f 		; Dividimos entre dos el valor de S
	bcf 		STATUS,C 	; Forzamos que el bit de arrastre sea 0, para que al
					; dividir o multiplicar, nos quedemos con la parte entera
	RLF 		s,f 		; Multiplicamos por dos el valor de S para forzar que sea un número par
	movlw 		Registro+1 	; vemos la primera dirección de memoria del registro en
					; el acumulador, que correspondería a la 23
	addwf 		s,w 		; Le sumamos al acumulador el valor que tome la variable S
	movwf 		FSR 		; Indicamos al FSR que se coloque en la dirección de
					; memoria que indica el acumulador
	movf 		INDF,w 		; Movemos al acumulador el valor al que está apuntando el FSR en
					; el registro (Que corresponde a A, B,..)
	movwf 		PORTC 		; Movemos el valor del acumulador al PORTC, para que se
					; mueva el motor y los LED
	call 		Bucle 		; Llamamos al bucle para perder tiempo y así controlar la velocidad
	btfsc 		PORTA,5 	; Miramos si el interruptor A5 esta activo. Si esta
					; activo hace la siguiente instrucción para ir a inversa.
					; Si no, continua normal
	goto 		FWI 		; Si A5 esta activo, se va a la funció de FWI, es
					; decir Wavedrive en inversa
	incf 		s 		; Incrementamos el valor de S, es decir, le sumamos 1
	incf 		s 		; Incrementamos el valor de S, es decir, le sumamos 1
	movf 		s,w 		; Movemos el nuevo valor de S al acumulador
	xorlw 		0x9 		; Comprobamos si S toma el valor 9. Si es así, ha llegado al final
					; del registro y Z valdrá 1
	movlw 		0x1 		; Movemos, por si se ha llegado al final, el valor 1 en
					; el acumulador para copiarlo a S
	btfsc 		STATUS,Z 	; Comprobamos si Z=1. Si es así hace la siguiente
					; instrucción. Si no, la salta
	movwf 		s 		; Copiamos el valor 1 a S para volver ha empezar el ciclo
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
FWI 					; Aquí empieza la funció de Fullstep y Halfstep en
					; inversa (utilizamos la misma para los dos modos)
	decfsz 		s 		; Utilizamos el comando Decfsz que mientras S no sea 0
					; hace la siguiente instrucción. Si S es 0 se la salta
	goto 		FWI2
	movlw 		0x8 		; Movemos, por si se ha llegado a 0l, el valor 8 en el
					; acumulador para copiarlo a S
	movwf 		s 		; Copiamos el valor 8 a S para volver ha empezar el ciclo
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
FWI2
	decfsz 		s 		; Utilizamos el comando Decfsz que mientras S no sea 0
					; hace la siguiente instrucción. Si S es 0 se la salta
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
	movlw 		0x8 		; Movemos, por si se ha llegado a 0l, el valor 8 en el
					; acumulador para copiarlo a S
	movwf 		s 		; Copiamos el valor 8 a S para volver ha empezar el ciclo
	goto 		MainLoop 	; Volvemos al MainLoop para comprobar si hemos cambiado de modo
Apagado 				; Aquí empieza la funció de apagado, en la cual
					; mantenemos el motor apagado para no gastar energía
	clrf 		PORTC 		; Borramos todo el puerto C de salidas.
	goto 		MainLoop 	; Volvemos a MainLoop para comprobar si hemos cambiado de modo
Grabar 					; Grabamos los diferentes valores que necesitarán los
					; LED y el motor para su funcionamiento en cada paso
	MOVLW 		0x00 		; Movemos al acumulador el valor 0
	MOVWF 		Registro 	; Lo grabamos en la primera posición del Registro
	MOVLW 		0x11 		; Movemos al acumulador la variable en hexadecimal del
					; valor en binario '00010001' correspondiente al primer LED
					; y al valor A
	MOVWF 		Registro+1 	; Lo grabamos en la segunda posición del Registro
	MOVLW 		0x93 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor AB
	MOVWF 		Registro+2 	; Lo grabamos en la tercera posición del Registro
	MOVLW 		0x82 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor B
	MOVWF 		Registro+3 	; Lo grabamos en la cuarta posición del Registro
	MOVLW 		0xA6 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor BC
	MOVWF 		Registro+4 	; Lo grabamos en la quinta posición del Registro
	MOVLW 		0x24 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor C
	MOVWF 		Registro+5 	; Lo grabamos en la sexta posición del Registro
	MOVLW 		0x6C 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor CD
	MOVWF 		Registro+6 	; Lo grabamos en la séptima posición del Registro
	MOVLW 		0x48 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor D
	MOVWF 		Registro+7 	; Lo grabamos en la octava posición del Registro
	MOVLW 		0x59 		; Movemos al acumulador la variable en hexadecimal que
					; corresponde al valor DA
	MOVWF 		Registro+8 	; Lo grabamos en la novena y última posición del registro
	Return 				; Terminamos de grabar en el registro y volvemos al
					; principio para empezar el MainLoop
Bucle 					; Aqui tenemos la funció del Bucle para perdida de tiempo
	bsf 		ADCON0,GO 	; En estos pasos leemos el valor del potenciómetro para
					; modificar el valor de la variable Delay+1
	btfsc 		ADCON0,GO 	; Con eso conseguimos variar el tiempo que pierde el
					; bucle, y por lo tanto l velocidad de motor
	goto 		$-1
	movf 		ADRESH,w
	addlw 		1
	movwf 		Delay+1
DelayLoop 				; Aquí empieza un bucle
	decfsz 		Delay,f
	goto 		DelayLoop
	decfsz 		Delay+1,f 	; Y aquí empieza el segundo bucle dentro del anterior
	goto 		DelayLoop
	return 				; Vuelve a donde se le ha llamado una vez terminado los dos bucles
end

 

 

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