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

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