Matemáticas para la Robótica |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Código en CCS:
Código:
#Include <16F876A.h> // Usamos el PIC 16F876A.
#FUSES NOWDT, XT, PUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#Use Delay(clock=4000000) // Usamos un cristal de 4MHz, por ejemplo.
#ZERO_RAM // Variables a cero.
#byte porta = 0x05 // Asignamos PortA
#byte portb = 0x06 // Asignamos PortB
#byte portc = 0x07 // Asignamos PortC
// ------ Variables Globales ------
int8 x = 0; // Declaramos el valor de X como Byte, es decir, 8 bits.
// Esta variable ha de ser global porque su valor lo usaremos
// en la interrupción y en el programa principal.
// --------- Interrupción ---------
#INT_EXT // Interrupción: Decodificación de Encoder.
void IntRB0()
{
// CCS se encarga de desactiva automáticamente cualquier interrupción.
// No hace falta guardar contextos de registros, al menos con el PIC 16F876A.
if (bit_test(portb, 0)) // Si PortB.0 = 1,
{
ext_int_edge(H_TO_L); // entonces activar la siguiente interrupción para flanco de bajada.
if (bit_test(portb, 1)) // Si PortB.1 = 1,
{
x++; // entonces incrementar una unidad el valor de X.
}
}
else // Si PortB.0 = 0,
{
ext_int_edge(L_TO_H); // entonces activar la siguiente interrupción para flanco de subida.
if (bit_test(portb, 1)) // Si PortB.1 = 1,
{
x--; // entonces decrementar una unidad el valor de X.
}
}
// Al finalizar la interrupción CCS se encarga de volver a poner automáticamente
// la badera INTF = 0 ---> borra la interrupción para poder permitir la siguiente;
// no hemos de hacer nada por nuestra parte, al menos con el PIC 16F876A.
}
void main() // Inicio y configuración.
{
port_b_pullups(FALSE); // Configuración para el PIC 16F876A.
setup_adc_ports(NO_ANALOGS); // Sin comparadores ni ADCs, todo digital, etc...
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(int_ext); // Activar Interrupción Externa.
ext_int_edge(L_TO_H); // Inicialmente detectar interrupción por flanco de subida.
enable_interrupts(GLOBAL); // Interrupciones Generales Activadas.
set_tris_a(0b111111); // Puerto A todo entradas (en este caso no usamos el Puerto A).
set_tris_b(0b11111111); // Puerto B todo entradas (sólo usamos las entradas RB0 y RB1).
set_tris_c(0b00000000); // Puerto C todo salidas (8 bits que irán a los LEDs).
// ---------- Programa Principial ----------
While (True)
{
portc = x; // El valor de X sale por el Puerto C a los 8 LED de salida.
}
}
Código en Proton IDE:
Código:
Device=16F876A
REMINDERS = FALSE
Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE
Symbol INTF = INTCON.1 ' RB0 External Interrupt Flag
Symbol INTE = INTCON.4 ' RB0 External Interrupt Enable
Symbol GIE = INTCON.7 ' Global Interrupt Enable
Symbol INTEDG = OPTION_REG.6 ' Flag = 0 int. por flanco bajada. Flag = 1 int. por flanco subida.
On_INTERRUPT GoTo Interrupcion ' Interrupción por Hardware (es la más rápida).
GIE = 1 ' Activa interrupciones generales.
INTE = 1 ' Activa la interrupción externa RB0/INT.
INTEDG = 1 ' Hace que inicialmente la interrupción se habilite
' para flanco de subida.
ALL_DIGITAL = TRUE ' Todas las entradas y salidas son digitales.
TRISA = %111111
TRISB = %11111111 ' Puerto A y B todo entradas.
TRISC = %00000000 ' Puerto C como salida para visualizar a través de los LED.
Dim x As Byte ' Variable X ---> contador de posición actual con resolución 0..255
x=0
While 1=1 ' |------ Programa Principal ------|
PORTC = x ' El contenido de X se visualiza en el Puerto C a través de los LED.
Wend ' |--------------------------------|
End
Interrupcion: '-------- Decodificador de Encoder --------------
Context SAVE ' Salva en contexto de los registros antes de operar con la interrupción.
If PORTB.0 = 1 Then ' Si RB0 se ha puesto a 1 (flanco de subida),
INTEDG = 0 ' entonces activar la siguiente interrupción para flanco de bajada.
If PORTB.1 = 1 Then ' Si RB1 está a 1,
Inc x ' entonces incrementar el contador X.
EndIf
EndIf
If PORTB.0 = 0 Then ' Si RB0 se ha puesto a 0 (flanco de bajada),
INTEDG = 1 ' entonces activar la siguiente interrupción para flanco de subida.
If PORTB.1 = 1 Then ' Si RB1 está 1,
Dec x ' entonces decrementar el contador X.
EndIf
EndIf
INTF = 0 ' Borra el "flag" de la interrupción RB0/INT para poder permitir la
' siguiente interrupción cuando ocurra.
Context Restore ' Restablece el contexto de los registros tal como estaban antes de la
' interrupción.
|
|
|
|
|
|
|
20168 visitantes (38097 clics a subpáginas) |
|
|
|
|
|
|
|