You are on page 1of 192

Aprendizaje de la Electrnica a travs de la Robtica - ARCE -

Proyecto: Aprendizaje de la Electrnica


a travs de la Robtica
CICLO FORMATIVO DE GRADO SUPERIOR DE DESARROLLO DE PRODUCTOS ELECTRNICOS
Mdulos:

Lgica Digital y Microprogramable.


Tcnicas de Programacin.
Electrnica Analgica.
Electrnica de Sistemas.
Desarrollo y Construccin de Prototipos Electrnicos.
Mantenimiento de Equipos Electrnicos.
Desarrollo de Proyectos de Productos Electrnicos

CICLO FORMATIVO DE GRADO MEDIO DE ELECTRNICA DE CONSUMO


Mdulo:
Electrnica Digital y Microprogramable.

Profesores: Pedro Alonso Sanz.


Juan DonGil Garca
Flix Jimnez Jimnez.
Juan Carlos Vzquez Molin
Miguel ngel Garca Marcos.
Alfonso Garca Gallego.

Instituto: IES Joan Mir


Localidad: San Sebastian de los Reyes
Periodo: 2009-2011

Microcontroladores

IES Joan Mir

Pgina 1

Aprendizaje de la Electrnica a travs de la Robtica - ARCE ndice

Pgina

1.- Sistemas Microcontrolados. ................................................................................................. 6


2.- Diagrama en Bloques de un sistema Microprocesado. Estructura Von Neumann. ........ 6
2.1.- Microprocesador (uP). .................................................................................................................... 6
2.2.- Buses. .............................................................................................................................................. 7
2.2.1.- Bus de Direcciones. .................................................................................................................................. 7
2.2.2.- Bus de Datos. ............................................................................................................................................ 7
2.2.3.- Bus de Control. ......................................................................................................................................... 7

2.2.- Memorias. ........................................................................................................................................ 7


2.2.1.- ROM. .......................................................................................................................................................... 7
2.2.2.- RAM............................................................................................................................................................ 8

2.3.- Interfaces. ........................................................................................................................................ 9


2.3.1.- Interface Serie. .......................................................................................................................................... 9
2.3.2.- Interface Paralelo. ................................................................................................................................... 11

2.4.- Decodificador de Direcciones. .................................................................................................... 12


2.4.1.- Mapa de Memoria. ................................................................................................................................... 13

3.- Microcontroladores. ............................................................................................................. 14


3.1.- Microcontroladores PIC. .............................................................................................................. 14
3.1.1.- Diagrama en bloques Estructura Hardvard....................................................................................... 14
3.1.2.- Proceso Segmentado Pipeline. ........................................................................................................... 14
3.1.3.- Instrucciones RISC. ................................................................................................................................ 14
3.1.4.- Estructura Ortogonal. ............................................................................................................................. 14

3.2.- Microcontrolador PIC 16F877A. ................................................................................................... 15


3.2.1.- Diagrama en Bloques.............................................................................................................................. 16
3.2.2.- Mapa de Memoria. ................................................................................................................................... 17
3.2.2.1.- Memoria de Programa. ................................................................................................................................................. 17
3.2.2.2.- Memoria de Datos. ........................................................................................................................................................ 18

3.2.3.- Ensamblador. .......................................................................................................................................... 18


3.2.3.1.- Lenguaje Mquina. ....................................................................................................................................................... 18
3.2.3.2- Lenguaje Ensamblador. ................................................................................................................................................ 19
3.2.3.3.- Programa Ensamblador. .............................................................................................................................................. 19

3.2.4.- Set de Instrucciones. .............................................................................................................................. 20

4.- Herramientas de Desarrollo. ............................................................................................... 21


4.1.- Ensambladores y Compiladores. ................................................................................................ 21
4.2.- Simuladores. ................................................................................................................................. 21
4.2.1.- MPLAB. .................................................................................................................................................... 22
4.2.2.- PROTEUS VSM. ....................................................................................................................................... 22

4.3.- Emuladores. .................................................................................................................................. 23


4.4.- Grabadores o programadores. .................................................................................................... 23

5.- Sistema de Desarrollo << Monibot >>. ............................................................................. 24


5.1.- Fabricacin del Monibot............................................................................................................... 24
5.1.1.- Placas y Esquemas. ................................................................................................................................ 24
5.1.2.- Listado de Componentes........................................................................................................................ 24
5.1.3.- Estructura. ............................................................................................................................................... 24

5.2.- Herramientas de desarrollo utilizadas. ....................................................................................... 24

Microcontroladores

IES Joan Mir

Pgina 2

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.- Recursos bibliogrficos. .............................................................................................................. 24


5.3.- Simulador Monibot. ...................................................................................................................... 25
5.3.1.- Visualizacin de Informacin. ................................................................................................................ 27
5.3.1.1.- Led. ................................................................................................................................................................................. 27
5.3.1.1.1.- Led_1.c .................................................................................................................................................................................... 27
5.3.1.1.2.- Led_2.c .................................................................................................................................................................................... 28
5.3.1.1.3.- Led_3.c .................................................................................................................................................................................... 29
5.3.1.1.4.- Led_4.c .................................................................................................................................................................................... 29
5.3.1.2.- Display_7Segmentos. ................................................................................................................................................. 30
5.3.1.2.1.- Display_7Seg_1.c .................................................................................................................................................................... 31
5.3.1.2.2.- Display_7Seg_2.c .................................................................................................................................................................... 32
5.3.1.2.3.- Display_7Seg_3.c .................................................................................................................................................................... 33
5.3.1.3.- LCD. ................................................................................................................................................................................ 34
5.3.1.3.1.- LCD_1.c ................................................................................................................................................................................... 36
5.3.1.3.2.- LCD_2.c ................................................................................................................................................................................... 37
5.3.1.3.3.- LCD_3.c ................................................................................................................................................................................... 37
5.3.1.3.4.- LCD_4.c ................................................................................................................................................................................... 38
5.3.1.3.5.- LCD_5.c ................................................................................................................................................................................... 39
5.3.1.3.6.- LCD_6.c ................................................................................................................................................................................... 40
5.3.1.3.7.- LCD_7.c ................................................................................................................................................................................... 41

5.3.2.- Entradas Digitales. .................................................................................................................................. 42


5.3.2.1.- Simulador de Perifricos. ............................................................................................................................................ 42
5.3.2.1.1.- Interruptores_Led_1.c ............................................................................................................................................................ 42
5.3.2.1.2.- Interruptores_Led_2.c ............................................................................................................................................................ 43
5.3.2.1.3.- Interruptores_DISPL_7S_1.c ................................................................................................................................................... 44
5.3.2.1.4.- Interruptores_DISPL_7S_2.c. .................................................................................................................................................. 45
5.3.2.1.5.- Pulsadores_DISPL_7S_1.c ....................................................................................................................................................... 46
5.3.2.2.- Simulador de Perifricos y Potencia. ......................................................................................................................... 47
5.3.2.2.1.- Interruptores_LCD_1.c ............................................................................................................................................................ 48
5.3.2.2.2.- Interruptores_LCD_2.c ............................................................................................................................................................ 49
5.3.2.3.- Simulador de Potencia. ................................................................................................................................................ 50
5.3.2.3.1.- Pulsadores_LCD_1.c ................................................................................................................................................................ 50

5.3.3.- Entradas Analgicas. .............................................................................................................................. 51


5.3.3.1.- Conversin A-D_D-A .................................................................................................................................................... 53
5.3.3.1.1.- Conversin_A-D_A-D.c .......................................................................................................................................................... 54
5.3.3.2.- Conversin Analgica Digital. .................................................................................................................................... 55
5.3.3.2.1.- Conversin_A-D1.c ................................................................................................................................................................. 55
5.3.3.2.2.- Conversin_A-D2.c ................................................................................................................................................................. 56
5.3.3.2.3.- Conversin_A-D2a.c ............................................................................................................................................................... 57

5.3.4.- Modulacin por Anchura de Pulso (PWM). ............................................................................................ 58


5.3.4.1.- Control de Motores de Corriente Continua. .............................................................................................................. 58
5.3.4.1.1.- Prueba_Motor_Derecho.c ...................................................................................................................................................... 60
5.3.4.1.2.- Prueba_Control_Velocidad_Motor_Derecho.c ...................................................................................................................... 61
5.3.4.1.3.- Prueba_Control_Velocidad_Motor_Derecho_f.c ................................................................................................................... 62
5.3.4.1.4.- Prueba_Control_Velocidad_Motor_Izquierdo_Derecho_f.c .................................................................................................. 64
5.3.4.2.- Servomotores de Posicin. ......................................................................................................................................... 66
5.3.4.2.1.- Control_2_Servo_Posicin.c ................................................................................................................................................... 67
5.3.4.2.2.- Servo_ Futaba_10bit.c ............................................................................................................................................................ 68

Microcontroladores

IES Joan Mir

Pgina 3

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.5.- Interrupciones Externas. ........................................................................................................................ 70


5.3.5.1.- Interrupcin por RB0/INT. ............................................................................................................................................ 71
5.3.5.1.1.- Interrupcin_INT_RB0.c ......................................................................................................................................................... 71
5.3.5.1.2.- Interrupcin_INT_RB0a.c ....................................................................................................................................................... 73
5.3.5.1.3.- Interrupcin_INT_RB0b.c ....................................................................................................................................................... 74
5.3.5.2.- Interrupcin por cambio de nivel de RB4_5_6_7. ..................................................................................................... 76
5.3.5.2.1.- Interrupcin_INT_RB4567.c ................................................................................................................................................... 76
5.3.5.2.1.- Interrupcin_INT_RB4567a.c .................................................................................................................................................. 79

5.3.6.- Temporizadores y Contadores. (Timer 0,1 y 2). .................................................................................... 81


5.3.6.1.- Timer 0. .......................................................................................................................................................................... 81
5.3.6.1.1.- Timer0_Contador.c ................................................................................................................................................................. 82
5.3.6.1.2.- Timer0_temporizador_multitarea_1.c ................................................................................................................................... 84
5.3.6.1.3.- Timer0_temporizador_multitarea_2.c ................................................................................................................................... 85
5.3.6.2.- Timer 1. .......................................................................................................................................................................... 87
5.3.6.2.1.- Timer1_Contador.c ................................................................................................................................................................. 88
5.3.6.2.2.- Timer1_temporizador_multitarea.c ....................................................................................................................................... 89
5.3.6.3.- Timer 2. .......................................................................................................................................................................... 91
5.3.6.3.1.- Timer2_Seal_Cuadrada.c ...................................................................................................................................................... 92
5.3.6.3.2.- Timer2_Servos_Posicion.c ...................................................................................................................................................... 93

5.3.7.- Transmisin Serie de Datos. USART ..................................................................................................... 96


5.3.7.1.- Cable. ............................................................................................................................................................................. 97
5.3.7.1.1.- Transmisin_Serie_1.c ............................................................................................................................................................ 98
5.3.7.1.2.- Recepcin_Serie_Polling.c ...................................................................................................................................................... 98
5.3.7.1.3.- Recepcin_Serie_Interrupcin.c............................................................................................................................................. 99
5.3.7.1.4.- Transmisin_Serie_Multitarea.c .......................................................................................................................................... 101
5.3.7.1.5.- Recepcin_Serie_Interrupcin_Multitarea.c ....................................................................................................................... 102
5.3.7.1.6.- Transmisin_Serie_Multitarea_1.c ...................................................................................................................................... 104
5.3.7.1.7.- Recepcin_Serie_Interrupcin_Multitarea_1.c............................................................................................................. 106
5.3.7.2.- Radiofrecuencia. ......................................................................................................................................................... 109
5.3.7.2.0.- Modulacin en AM. .............................................................................................................................................................. 109
5.3.7.2.1.- Transmisin_Serie_ Radiofrecuencia_1.c...................................................................................................................... 111
5.3.7.2.2.- Transmisin_Serie_ Radiofrecuencia_2.c...................................................................................................................... 112
5.3.7.2.3.- Recepcin_Serie_Radiofrecuencia_1.c ........................................................................................................................... 113
5.3.7.3.- Radiofrecuencia Multitarea........................................................................................................................................ 115
5.3.7.3.1.- Transmisin_Serie_RF_Multitarea_1.c ........................................................................................................................... 116
5.3.7.3.2.- Transmisin_Serie_RF_Multitarea_2.c ........................................................................................................................... 117
5.3.7.3.3.- Recepcin_Serie_RF_Multitarea.c ................................................................................................................................... 120

5.3.8.- Mdulo MSSP. ....................................................................................................................................... 123


5.3.8.1.- I2C. ............................................................................................................................................................................... 123
5.3.8.1.1.- Expansor_Bus_PCF8574. ....................................................................................................................................................... 125
5.3.8.1.1.1.- PCF8574_1. ................................................................................................................................................................... 125
5.3.8.1.1.1.1.- Lectura y escritura en PCF8574 modo polling.c .................................................................................................... 126
5.3.8.1.1.1.2.- Lectura y escritura en PCF8574 en modo Interrupcin.c ...................................................................................... 127
5.3.8.1.1.2.- PCF8574_2. ................................................................................................................................................................... 129
5.3.8.1.1.2.1.- Lectura y escritura de multiples PCF8574 modo polling.c ..................................................................................... 130
5.3.8.1.1.2.2.- Lectura y escritura de multiples PCF8574 modo Interrupcin.c............................................................................ 131
5.3.8.1.1.3.- PCF8574_3. ................................................................................................................................................................... 135
5.3.8.1.1.3.1.- CAD_PCF8547.c .................................................................................................................................................... 135
5.3.8.1.1.3.2.- CAD_PCF8547_MULTIPLES.c ................................................................................................................................ 138

Microcontroladores

IES Joan Mir

Pgina 4

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.8.1.2.- Conversor A-D_D-A_PCF8591. .............................................................................................................................................. 141
5.3.8.1.2.1.- PCF8591_ADC. .............................................................................................................................................................. 141
5.3.8.1.2.1.1.- I2C_CAD_1.c ......................................................................................................................................................... 142
5.3.8.1.2.1.2.- I2C_CAD_2.c ......................................................................................................................................................... 143
5.3.8.1.2.2.- PCF8591_DAC. .............................................................................................................................................................. 144
5.3.8.1.2.2.1.- I2C_CDA_1.c ......................................................................................................................................................... 145

5.3.9.- Sensores y Hardware. ........................................................................................................................... 147


5.3.9.1.- Sensores de Infrarrojos CNY70. ............................................................................................................................... 147
5.3.9.1.1.- Prueba_Sensores_CNY70.c ................................................................................................................................................... 148
5.3.9.2.- Sensores de Distancia. .............................................................................................................................................. 149
5.3.9.2.1.- Sensor de Infrarrojos GP2D12. ............................................................................................................................................. 149
5.3.9.2.1.1.- Lectura_S1_GP2D12.c .................................................................................................................................................. 151
5.3.9.2.1.2.- Lectura_S1_GP2D12.c .................................................................................................................................................. 152
5.3.9.2.1.3.- driver1_GP2D12.c ........................................................................................................................................................ 153
5.3.9.2.1.4.- driver2_GP2D12.c ........................................................................................................................................................ 153
5.3.9.2.2.- Sensor de Ultrasonidos SRF08. ............................................................................................................................................. 154
5.3.9.2.2.1.- Lectura_S1_SRF08_Real. .............................................................................................................................................. 155
5.3.9.2.2.2.- Lectura_S1_S2_SRF08_Real.c ....................................................................................................................................... 156
5.3.9.2.2.3.- Lectura_S1_S2_SRF08_Real_Simulado.c ...................................................................................................................... 158
5.3.9.2.2.4.- Lectura_S1_SRF08_Distancia_Lumenes.c .................................................................................................................... 159
5.3.9.2.2.5.- driver SRF08.c ............................................................................................................................................................... 159
5.3.9.2.2.6.- driver_Luz_Distancia_SRF08.c...................................................................................................................................... 160
5.3.9.2.2.7.- driver PCF8591.c ........................................................................................................................................................... 162
5.3.9.2.2.8.- Cambio_Direccin.c ...................................................................................................................................................... 162
5.3.9.2.2.9.- Ejercicio 1.c ................................................................................................................................................................... 163
5.3.9.3.- Sensores de Temperatura. ........................................................................................................................................ 164
5.3.9.3.1.- PT100. ................................................................................................................................................................................... 164
5.3.9.3.1.1.- Lectura_S1_PT100.c ..................................................................................................................................................... 166
5.3.9.3.2.- Sensor de Temperatura TC74. .............................................................................................................................................. 167
5.3.9.3.2.1.- Test _TC74.c ................................................................................................................................................................. 168
5.3.9.3.3.- Sensor Trmico D-TPA81. ..................................................................................................................................................... 170
5.3.9.3.3.1.- Test1_D-TPA81.c .......................................................................................................................................................... 173
5.3.9.3.3.2.- Test2_D-TPA81.c .......................................................................................................................................................... 174
5.3.9.3.3.3.- Temperatura Mayor.c .................................................................................................................................................. 176
5.3.9.3.3.4.- Temperatura Mayor_con driver.c ................................................................................................................................ 177
5.3.9.3.3.5.- driver_D-TPA81.c ......................................................................................................................................................... 179
5.3.9.3.3.6.- driver_TC74_9_sensores.c ............................................................................................................................................ 179
5.3.9.3.3.7.- Seguimiento de un punto caliente.c ............................................................................................................................. 180
5.3.9.4.- Potencimetro Digital MCP41010. ............................................................................................................................ 182
5.3.9.4.1.- CG_Ampl_No_Inversor.c ...................................................................................................................................................... 183
5.3.9.5.- Control de mltiples servomotores de posicin SD20. ......................................................................................... 184
5.3.9.5.1.- Control_SD20.c ..................................................................................................................................................................... 184
5.3.9.5.2.- Control_Servos_Funciones_SD20.c ...................................................................................................................................... 185
5.3.9.5.3.- A-D_SD20.c ........................................................................................................................................................................... 187
5.3.9.6.- Puentes en H. .............................................................................................................................................................. 188
5.3.9.6.1.- L293B y L298. ........................................................................................................................................................................ 189
5.3.9.6.2.- Puente en H con TRT............................................................................................................................................................. 192

Microcontroladores

IES Joan Mir

Pgina 5

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 1.- Sistemas Microcontrolados.


Un sistema microcontrolado es un equipo electrnico basado en microcontroladores
que puede interactuar sobre dispositivos analgicos, digitales. Es programable.

2.- Diagrama en Bloques de un sistema Microprocesado. Estructura Von


Neumann.

2.1.- Microprocesador (uP).


Es un circuito integrado que se puede programar. Est
compuesto por tres bloques bsicos y se comunica con el exterior a
travs de cables Buses.
Unidad de Control: Es el cerebro del uP y tiene la misin de
decodificar las instrucciones y generar las microordenes que activan
los circuitos del microprocesador que realizan las funciones de las
instrucciones.
Unidad Aritmtico Lgica (ALU): Es un circuito electrnico que
realiza operaciones aritmticas (Sumas, Restas, etc.) y Lgicas
(AND, OR, etc).

Registros: Son unidades de memoria de N bit que almacenan


informacin procedente del interior y exterior del uP.

Microcontroladores

IES Joan Mir

Pgina 6

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 2.2.- Buses.


Es un conjunto de hilos, pistas o cables que tienes la misin de transportar informacin
digital.

2.2.1.- Bus de Direcciones.


Es un bus que el uP utiliza para selecciona o direcciona los dispositivos externos.

2.2.2.- Bus de Datos.


Es un bus que el uP utiliza para enviar o recibir informacin de los dispositivos
externos.

2.2.3.- Bus de Control.


Es un bus que el uP utiliza para escribir o leer los dispositivos externos.
Tambin sirve para resetear o deshabilitar al uP.

2.2.- Memorias.
Son circuitos integrados que almacenan informacin.

2.2.1.- ROM.
ROM (Read Only Memory) significa memoria de solo lectura. Se almacenan la
informacin en el proceso de fabricacin. No volatil

Proceso de Lectura:

El uP a travs del Decodificador de Direcciones selecciona la ROM [CS2]

El uP a travs del Bus de Direcciones [A2..A0] selecciona la palabra de la memoria.

El uP a travs del Bus de Control [R] da la orden de lectura a la memoria ROM.

La memoria ROM pone la informacin en el Bus de Datos [D7..D0] y el uP la almacena


en sus Registros.

Microcontroladores

IES Joan Mir

Pgina 7

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Estructura interna de la memoria:

El Bus de Direcciones nos indica el nmero de palabras que tiene la memoria.


Palabras = 2n+1, donde n=2 por la direccin A2,

22+1= 8 palabras.

El Bus de Datos nos indica el nmero de bit que tiene cada palabra.
Bit = n+1, donde n=7 por el bus de datos D7,

7+1= 8 Bit

2.2.2.- RAM.
RAM (Random Access Memory) significa memoria de acceso aleatorio. Se puede leer
(R) y escribir (W). Memoria Volatil.

Proceso de Escritura:

El uP a travs del Decodificador de Direcciones selecciona la RAM [CS2]

El uP a travs del Bus de Direcciones [A2..A0] selecciona la palabra de la memoria.

El uP pone la informacin en el Bus de Datos [D7..D0].

El uP a travs del Bus de Control [W] da la orden de escritura en la memoria RAM.

Microcontroladores

IES Joan Mir

Pgina 8

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Estructura interna de la memoria:

2.3.- Interfaces.
Son circuitos electrnicos que comunican el exterior con el uP.

2.3.1.- Interface Serie.


Comunican el exterior con el uP con un bus serie de tres hilos.

Los datos se mandan o se reciben del exterior de uno en uno.

Microcontroladores

IES Joan Mir

Pgina 9

Aprendizaje de la Electrnica a travs de la Robtica - ARCE El proceso de lectura y escritura es igual que las memorias. Se tiene que configurar
cuando queremos leer o escribir datos del exterior.
A travs Tx y GND transmitimos los datos del uP al exterior.
A travs de Rx y GND el uP recibe los datos del exterior.
El protocolo de comunicaciones tiene que estar predefinido. Existen diferentes tipos:

Asncrona.
Es tambin conocida como Start/stop. Requiere de una seal que identifique el
inicio del carcter y a la misma se la denomina bit de arranque. Tambin se requiere de
otra seal denominada seal de parada que indica la finalizacin del carcter o bloque.

Sncrona.
Sncrono significa "con reloj" y exactamente eso es lo que necesitamos, un reloj
(o dicho en ingls un Clock). La transmisin sncrona necesita de dos lneas, una de
datos sobre la que se van a representar los distintos estados de los bits a transmitir y
una de reloj donde vamos indicando cuando est disponible cada bit en la lnea de
datos. Esta lnea de reloj es la de "sincronizacin" entre ambos dispositivos, el emisor
y el receptor de la transmisin

Microcontroladores

IES Joan Mir

Pgina 10

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Tipo de Comunicaciones:

Simplex.
En este caso el transmisor y el receptor estn perfectamente definidos y la
comunicacin es unidireccional. Este tipo de comunicaciones se emplean usualmente
en redes de radiodifusin, donde los receptores no necesitan enviar ningn tipo de dato
al transmisor.

Duplex Semi Duplex.


En este caso ambos extremos del sistema de comunicacin cumplen funciones
de transmisor y receptor y los datos se desplazan en ambos sentidos pero no
simultneamente. Este tipo de comunicacin se utiliza habitualmente en la interaccin
entre terminales y un computador central.

Full Duplex.

El sistema es similar al duplex, pero los datos se desplazan en ambos sentidos


simultneamente. Para ello ambos transmisores poseen diferentes frecuencias de transmisin o
dos caminos de comunicacin separados, mientras que la comunicacin semi-duplex necesita
normalmente uno solo.

Existen diferentes interfaces serie: UART, USART, PS2, USB, FireWire, etc.

2.3.2.- Interface Paralelo.


Las conexiones paralelas consisten en transmisiones simultneas de N cantidad de bits, del uP
al Exterior o viceversa.

Microcontroladores

IES Joan Mir

Pgina 11

Aprendizaje de la Electrnica a travs de la Robtica - ARCE -

2.4.- Decodificador de Direcciones.

Es un conjunto de circuitos electrnicos que seleccionan los diferentes dispositivos


conectados a los buses (Memorias, Interfaces, etc).
El uP controla el Decodificador.
El diseo de los decodificadores est supeditado al conjunto de dispositivos que se
conecten a los buses.
Un mapa de memoria ayuda a realizar este proceso.

Microcontroladores

IES Joan Mir

Pgina 12

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 2.4.1.- Mapa de Memoria.

La trama jaspeada
representa la palabra
que se direcciona
dentro del dispositivo.
Ejemplo: Direccin 3
A2 A1 A0 = 011
Palabra 3

La trama jaspeada
representa la palabra
que se direcciona
dentro del dispositivo.
Ejemplo: Direccin 15
A2 A1 A0 = 111
Palabra 7

La trama jaspeada
representa la palabra
que se direcciona
dentro del dispositivo.
Ejemplo: Direccin 21
A2 A1 A0 = 101
Palabra 5

La trama jaspeada
representa la palabra
que se direcciona
dentro del dispositivo.
Ejemplo: Direccin 28
A2 A1 A0 = 100
Palabra 4

Microcontroladores

IES Joan Mir

Pgina 13

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.- Microcontroladores.


Un microcontrolador es un circuito integrado que contiene dentro un sistema
microprocesado (uP, Memorias, Interfaces, etc) y hardware de control de dispositivos
electrnicos (Sistema de Adquisicin de Datos Conversin Analgica/ Digital, Modulacin de
anchura de pulso Control de Velocidad de Motores, etc. Es programable.

3.1.- Microcontroladores PIC.


Los microcontroladores PIC de la casa Microchip se caracterizan por ser baratos, por
proporcionar un entorno de desarrollo integrado gratuito MPLAB . Este entorno permite editar
un el archivo fuente del proyecto, ensamblarlo, simularlo en un Ordenador Personal y
comprobar la evolucin de las variables en la memoria RAM, registros, etc.

3.1.1.- Diagrama en bloques Estructura Hardvard


Se caracteriza por utilizar dos tipos de memorias (Datos y Programa) con buses
independientes.
Memoria de

CPU
Buses

Memoria de

Memoria de

CPU

Programa y

Programa

de Datos

(EEPROM)

Datos
Buses

Arquitectura Von Neumann

(RAM)

Arquitectura Hardvard

3.1.2.- Proceso Segmentado Pipeline.


Permite realizar dos procesos simultneamente a la vez (lectura y ejecucin de
instrucciones).

PROGRAMA

1 Ciclo

2 Ciclo

Bsqueda 1

Ejecuta 1

3 Ciclo

4 Ciclo

5 Ciclo

1. BSF STATUS,RP0
2. CLRF TRISB
3. MOVLW 0XFF

Bsqueda 2

Ejecuta 2
Bsqueda 3

Ejecuta 3
Bsqueda 4

4. MOVWF TRISA

Ejecuta 4

3.1.3.- Instrucciones RISC.


Tiene un reducido grupo de instrucciones (RISC Reduced Instruction Set Computer).
Son instrucciones simples que se ejecutan en un solo ciclo mquina (4 ciclos de reloj). El
microcontrolador PIC16F876A tiene 35 instrucciones.

3.1.4.- Estructura Ortogonal.


Una instruccin puede utilizar cualquier elemento
de la arquitectura como fuente o destino de datos.

Microcontroladores

IES Joan Mir

Pgina 14

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.2.- Microcontrolador PIC 16F877A.


El microcontrolador PIC 16F877A es un CHIP de 40 patillas, que se caracteriza por lo
siguiente:

Tiene 35 Instrucciones
Tiene una Memoria de Programa de 8192 palabras FLASH
368 byte de Memoria de Datos RAM
256 byte de EEPROM
33 Patillas de entradas/salidas.
Sistema de Adquisicin de datos (8 Entradas Analgicas)
2 mdulos de CCP y PWM. (Comparacin y captura de datos y generadores de seal
por Modulacin de Anchura de Pulsos).
Un mdulo de comunicacin serie SPI (Serial Peripheral Interface) I2C (InterIntegrated Circuit).
Un transmisor-receptor asncrono serie universal USART.
3 Timer (Temporizadores/Contadores).
2 Comparadores de seales analgicas.

Microcontroladores

IES Joan Mir

Pgina 15

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.2.1.- Diagrama en Bloques.

Microcontroladores

IES Joan Mir

Pgina 16

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.2.2.- Mapa de Memoria.


3.2.2.1.- Memoria de Programa.
Es una memoria tipo FLASH, los programas son almacenados en este tipo de memoria,
cuando se desconecta la alimentacin la informacin almacenada no se pierde.(La memoria flash
es una forma desarrollada de la memoria EEPROM que permite que mltiples posiciones de memoria sean escritas
o borradas en una misma operacin de programacin mediante impulsos elctricos, frente a las anteriores que slo
permite escribir o borrar una nica celda cada vez. Por ello, flash permite funcionar a velocidades muy superiores
cuando los sistemas emplean lectura y escritura en diferentes puntos de esta memoria al mismo tiempo .), est

compuesta por:

8192 palabras de 14bit. (Cada instruccin ocupa solo una palabra).


Una pila de 8 niveles.
Un solo vector de Interrupcin.
Vector de Reset (Direccin 0000h)
4 zonas de memoria.

Microcontroladores

IES Joan Mir

Pgina 17

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.2.2.2.- Memoria de Datos.


Es una memoria de tipo RAM
(Memoria de Acceso Aleatorio), se
pierde la informacin cuando se
desconecta la alimentacin.
Est compuesta por 4 bancos de
trabajo. Contiene registros (Tipo Byte)
de 2 tipos:

Registros de funciones especiales


SFR que sirven para comunicarnos
con el hardware interno del PIC.

Registro de Propsito General que


nos sirven para almacenar nuestras
variables de nuestro programas.

3.2.3.- Ensamblador.
3.2.3.1.- Lenguaje Mquina.
Es un lenguaje binario Unos y Ceros que es el nico que entienden los
microcontroladores. El lenguaje ensamblador se compila Traduce a lenguaje mquina.
Se trabaja con formato Hexadecimal.

Ejemplo:
Instruccin en lenguaje
Ensamblador

Cdigo Binario
Compilador

BTFSS PORTA, 4

0001 1110

Cdigo Hexadecimal

Microcontroladores

IES Joan Mir

0000

0101

Pgina 18

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.2.3.2- Lenguaje Ensamblador.


El lenguaje ensamblador utiliza un lenguaje nemnico que son grupos de caracteres
alfanumricos que simbolizan ordenes o tareas a realizar con cada instruccin.
Los nemnicos se corresponden con las iniciales de cada nombre de las instrucciones
en ingles.
Ejemplo:
Suma 58 al registro de trabajo W y guarda el resultado en este mismo registro W.
addlw d58 ;

W58+W

3.2.3.3.- Programa Ensamblador.


Es un software encargado de traducir el lenguaje ensamblador a lenguaje mquina.
Al lenguaje ensamblador se le llama Fichero Fuente y al traducido Fichero Ejecutable
El programa fuente tiene la extensin asm y el ejecutable hex.

Fichero Fuente
Ejemplo1.asm

Programa Ensamblador
MPASM.EXE

Fichero Ejecutable

Fichero Errores

Fichero Listable

Ejemplo1.hex

Ejemplo1.err

Ejemplo1.lst

Microcontroladores

IES Joan Mir

Otros ficheros

Pgina 19

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 3.2.4.- Set de Instrucciones.

Microcontroladores

IES Joan Mir

Pgina 20

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 4.- Herramientas de Desarrollo.


Cuando se disean sistemas con circuitos programables se precisan h erramientas
para la puesta a punto del hardware y del software. Las ms importantes son: editores de
dores, compiladores, simuladores, grabadores, emuladores y sistemas de desarrollo

4.1.- Ensambladores y Compiladores.


El programa ensamblador traduce las instrucciones que se han escrito, usando los
nemnicos de l l e ng u aj e ens am bl a dor , a c d i g o bi n ar io ej ec ut ab l e p or el
microcontrolador. El proceso de ensamblado produce un fichero * .hex que se grabar en la
memoria del programa del PIC mediante el grabador o programador. La secuencia de
nemnicos se llama cdigo fuente del programa. El ensamblador ms utilizado para los PIC es
TM

el MPASM que trabaja dentro del entorno software MPLAB .

El programa compilador traduce las instrucciones que se han escrito en lenguaje de


alto nivel (por ejemplo en lenguaje C), a cdigo binario ejecutable por el
microcontrolador. Los compiladores para lenguaje C ms populares son el PICC por
Hi-Tech Software (www.htsoft.com) y el PCW de la empresa CCS (www.ccsinfo.com).
Un compilador para Basic es el PICBasic Pro propiedad de MicroEngineering Labs
(www.melabs.com).

4.2.- Simuladores.
Una vez que el programa se ha escrito y ensamblado o compilado se est en
binario *.hex que es el que se graba en el microcontrolador. Es casi indispensable probar
este programa, hacindolo funcionar en condiciones tan prximas como sea posible a las de
utilizacin real. Para hacer esto hay varias soluciones, las ms utilizadas son dos: utilizar un
econmico simulador software o un potente emulador.
Como su propio nombre indica, un simulador por software "simula" la ejecucin de las
instrucciones de un programa desarrollado para un modelo de microcontroladores especfico.
Representa el comportamiento interno del microcontrolador y el estado de sus lneas de
entrada/salida. Al ejecutar el simulador se pueden visualizar fcilmente las instrucciones
donde se producen funcionamientos no deseados. Como el microcontrolador se simula por
software el comportamiento no es idntico a la real sin embargo, proporciona una aproximacin
aceptable, especialmente cuando no es esencial el trabajo en tiempo real. Su gran ventaja es
el bajo precio.
El simulador realiza la ejecucin del programa mucho ms lento que lo hara el mismo
programa directamente sobre el microcontrolador, por eso determinadas operaciones en las
que son necesarios tiempos muy precisos o crticos no se puede probar mediante la
simulacin. No obstante, bien utilizado permite desarrollar aplicaciones interesantes con una
mnima inversin.
El simulador gratuito ms utilizado para los PIC es el MPLAB SIM, que trabaja dentro

del entorno MPLAB . En los ltimos est teniendo una gran aceptacin PROTEUS VSM
(www.labcenter.co.uk).

Microcontroladores

IES Joan Mir

Pgina 21

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 4.2.1.- MPLAB.


MPLAB IDE es un software de "Entorno de Desarrollo Integrado" (Integrated Development
Environment, IDE) que se ejecuta bajo Windows. Con este entorno se puede desarrollar aplicaciones para
los microcontroladores PIC.
El MPLAB incluye todas las utilidades necesarias para la realizacin de proyectos
con mivrocontroladores PIC, permite editar el archivo fuente del proyecto, adems de
ensamblarlo y simularlo en pantalla para comprobar como evolucionan tanto la memoria de datos RAM,
como la de programa ROM, los registros del SFR, etc, segn progresa la
ejecucin del programa.
El MPLAB incluye:

Un editor de texto.
Un ensamblador llamado MPASM.
Un simulador llamado MPLAB SIM.
Un organizador de proyectos.

Este programa es gratuito. Se puede bajar en la direccin Internet del fabricante www.microchip.com.
Su instalacin es muy sencilla y similar a cualquier otro programa para el sistema operativo Windows.

4.2.2.- PROTEUS VSM.


El laboratorio virtual electrnico PROTEUS VSM de LABCENTER ELECTRONICS, nos permite
simular circuitos electrnicos analgicos/ digitales y microprocesados. Es capaz de realizar
simultneamente una simulacin hardware y software (Lenguaje de bajo y alto nivel Ensamblador y C
respectivamente) en un mismo entorno grfico. Tambin enlaza con una herramienta que nos permite
desarrollar las placas para realizar los prototipos.
Para ello suministra tres potentes herramientas:

ISIS (Diseo Grfico)


VSM(Virtual System Modelling) Simulacin de Componentes.
ARES (Diseo de Placas).

Las herramientas tradicionales de diseo seguan el siguiente proceso:

Con las herramientas de diseo tradicionales, el desarrollo del software y la comprobacin del
prototipo, no puede realizarse hasta que este no se desarrolla. Esto puede suponer semanas de retraso.
Si se localiza un error hardware, la totalidad del proceso se debe repetir.

Usando Proteus VSM, el desarrollo del software puede comenzar tan pronto como el diseo
esquemtico este acabado y la combinacin del hardware y el software nos permite testear el prototipo y
ver si funciona.

Microcontroladores

IES Joan Mir

Pgina 22

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 4.3.- Emuladores.


El emulador es una potente herramienta que consiste en un complejo equipo fsico
controlado por un software desde un ordenador y que se comporta exactamente como el
microcontrolador al que reemplaza. El fabricante Microchip ofrece algunos de ellos en su
pgina WEB, tal como el MPLAB-ICE 2000.

El emulador ICE 2000 dispone de una "cabeza" con idntico patillaje que el del
microcontrolador que emula. Esta cabeza se inserta en el zcalo donde ir el
microcontrolador con el programa que trata de comprobar. El emulador hace funcionar el
sistema como si hubiese un microcontrolador real y adems con la ventaja de que visualiza
en el monitor del ordenador toda la informacin necesaria para comprobar el funcionamiento
de los programas, permitiendo realizar todo tipo de pruebas. Los resultados obtenidos
son idnticos a los del producto final, puesto que a diferencia de los simuladores
la ejecucin se realiza en tiempo real.
El emulador es el mtodo de depuracin ms sofisticado que se puede emplear, pero
su alto precio no lo hace especialmente accesible y mucho menos para uso domstico. Para
muchas aplicaciones es suficiente con el simulador software.

4.4.- Grabadores o programadores.


Una vez realizado el programa y comprobado en el simulador o emulador, se debe
proceder a grabarlo en la memoria de programa del microcontrolador mediante un grabador o
programador.
El grabador PICSTART PLUS ofrecido por Microchip es uno de los ms utilizados.
En internet se ofrecen numerosos esquemas para la construccin de econmicos
programadores de PIC. Uno de los ms populares es el JDM en sus diferentes versiones,
que se utiliza junto con el programa IC-Prog.
Otra forma de grabar los microcontroladores es utilizar el firmware boootloader (El
firmware es un bloque de instrucciones de programa para propsitos especficos, grabado en
una memoria de tipo no voltil (ROM, EEPROM, flash, etc), que establece la lgica de ms
bajo nivel que controla los circuitos electrnicos de un dispositivo de cualquier tipo)

Un bootloader es un firmware para permitir la rpida descarga de programas en los


microcontroladores. En el caso de los PIC, el bootloader permite descargar programas
Microcontroladores

IES Joan Mir

Pgina 23

Aprendizaje de la Electrnica a travs de la Robtica - ARCE directamente desde el PC sin necesidad de utilizar ningn tipo de grabador, es decir en
la propia aplicacin. La descarga se hace a travs del puerto serie, USB.
E1
2

VDD

5V

VSS

VCC

U2
21
22
23
24
25
26
27
28

Al Puerto Serie del PC


Adaptador de seales PC-uC

C6

J6
5
9
4
8
3
7
2
6
1
CONN-D9M

TXPC

14
13
7
8

RXPC

C9
VDD

2
6

1uF

1uF

1uF

C1-

C1+

T1OUT
R1IN
T2OUT
R2IN

T1IN
R1OUT
T2IN
R2OUT

11
12
13
14
15
16
17
18

U5

11
12
10
9

OSC1/CLKIN
OSC2/CLKOUT
MCLR/Vpp/THV

RA0/AN0
RA1/AN1
RA2/AN2/VREFRA3/AN3/VREF+
RA4/T0CKI
RC0/T1OSO/T1CKI
RA5/AN4/SS
RC1/T1OSI/CCP2
RC2/CCP1
RC3/SCK/SCL
RC4/SDI/SDA
RC5/SDO
RC6/TX/CK
RC7/RX/DT

9
10
1
2
3
4
5
6
7

PIC16F876_JOAN
VDD

VS+
VSC2-

C8

RB0/INT
RB1
RB2
RB3/PGM
RB4
RB5
RB6/PGC
RB7/PGD

C2+

C7

+
GND

1uF

MAX232
GND=GND
VCC=VCC

C10
100nF

Este condensador debe estar proximo a la


alimentacin del MAX 232

5.- Sistema de Desarrollo << Monibot >>.


Un sistema de desarrollo est formado por un conjunto de herramientas hardware y
software que permitan fabricar y simular prototipos, emular, depurar y grabar programas de
forma eficiente e intuitiva.

5.1.- Fabricacin del Monibot.


5.1.1.- Placas y Esquemas.
5.1.2.- Listado de Componentes.
5.1.3.- Estructura.

5.2.- Herramientas de desarrollo utilizadas.

Fabricacin de Placas. Proteus (ARES)

Simulacin hardware y software de los prototipos. Proteus (ISIS)

Compilador C. (CCS)

Grabador de programas en el Microcontrolador. (Bootloader)

5.3.- Recursos bibliogrficos.

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa.


Data book PIC16F87xA.
Curso de Microcontroladores PIC Avanzados.

Microcontroladores

IES Joan Mir

Pgina 24

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.- Simulador Monibot.


El Monibot se va a programar en Lenguaje C, el mtodo utilizado ser ensear las
estructuras bsicas de C utilizando unos esquemas bsicos de simulacin del robot. Para ello
se ha estructurado en diferentes aplicaciones prcticas:

Visualizacin de Informacin.

Entradas Digitales.

Timer 0.
Timer 1.
Timer 2.

Transmisin Serie de Datos. USART

Interrupcin por RB0/INT.


Interrupcin por cambio de nivel de RB4_5_6_7.

Temporizadores y Contadores. (Timer 0,1 y 2).

Control de Motores de Corriente Continua.


Servomotores de Posicin.

Interrupciones Externas.

Conversin A/D y D/A.


Conversin Analgica/Digital.

Modulacin por Anchura de Pulso. PWM

Simulador_Perifricos.
Simulador_Perifricos_Potencia.
Simulador_Potencia.

Entradas Analgicas.

Led.
Display de 7 Segmentos.
LCD.

Cable.
Radiofrecuencia.
Radiofrecuencia_Multitarea.

Mdulo MSSP.
I2C.

SPI.

Expansor_Bus_PCF8574.
Conversor A-D_D-A_PCF8591.

Sensores de Infrarrojos CNY70.

Sensores de Distancia.

Sensor de Infrarrojos GP2D12.


Sensor de Ultrasonidos SRF08.

Sensores de Temperatura.

PT100.
Sensor de Temperatura TC74.
Sensor Trmico D-TPA81.

Potencimetro Digital MCP41010.

Control de mltiples servomotores de posicin SD20.


Puentes en H.

L298-L293B.
Puente en H con TRT.

Microcontroladores

IES Joan Mir

Pgina 25

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Los esquemas bsicos de simulacin del Monibot son:

Simulador Potencia y Perifricos.

Simulador Potencia.

Simulador Perifricos.

Microcontroladores

IES Joan Mir

Pgina 26

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.1.- Visualizacin de Informacin.


5.3.1.1.- Led.
El entrenador utilizado es Simulador Perifricos dentro de la carpeta de Led.

5.3.1.1.1.- Led_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Led_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Encender y apagar led RB7 con una cadencia de 1 segundo.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de procesado*****************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Eleccin del uC 16F877A

#BYTE TRISB = 0x86


#BYTE portB = 0x06
#BIT rb7 = 0X06.7

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.
// Asignamos a la etiqueta rb7 el bit 7 de la direccin 06h
// de la memoria RAM.
// ENCENDIDO equivale a 1.
// APAGADO equivale a 0.

#DEFINE ENCENDIDO 1
#DEFINE APAGADO 0

// Reloj de 1 MHz

// ***************************** Funcin principal o programa principal *****************************


// Se define con un void main,
void main()

Microcontroladores

IES Joan Mir

Pgina 27

Aprendizaje de la Electrnica a travs de la Robtica - ARCE {


TRISB = 0B00000000;
portB = 0B00000000;

// Defines Puerto B como SALIDA de datos.


// Resteamos el puerto B Led apagados.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
rb7 = ENCENDIDO;
delay_ms(1000);

// Enciende el Led que esta en la patilla rb7.


// Espero 1 segundo.

rb7 = APAGADO;
delay_ms(1000);

// Apago el Led que esta en la patilla rb7.


// Espero 1 segundo.

}
}

5.3.1.1.2.- Led_2.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Led_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Encender y apagar todos los Led con una cadencia de 2 segundos y 1
//
//
segundo respectivamente
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************ Directivas de procesado****************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Eleccin del uC 16F877A

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

// Reloj de 1 MHz

// ***************************** Funcin principal o programa principal *****************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
portB = 0B00000000;

// Defines Puerto B como SALIDA de datos.


// Resteamos el puerto B Led apagados.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
portB =0b11111111;
delay_ms(2000);

// Enciende todos los Led


// Espero 2 segundo

portB =0b00000000;
delay_ms(1000);

// Apago todos los led


// Espero 1 segundo

}
}

Microcontroladores

IES Joan Mir

Pgina 28

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.1.1.3.- Led_3.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Led_3.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Contador en binario de 0 a 9
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************ Directivas de procesado****************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Eleccin del uC 16F877A

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

int8 n=0;

// Declaramos la variable n con 8 bit y la inicializamos con 0.

// Reloj de 1 MHz

// ****************************** Funcin principal o programa principal ****************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
portB = 0B00000000;

// Defines Puerto B como SALIDA de datos.


// Resteamos el puerto B Led apagados.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
for (n=0;n<=9;n++)

// Ejecuta el contenido que est entre corchetes 10 veces


//de 0 a 9

{
portB=n;
delay_ms(1000);

// Asignamos la variable n al puertoB.


// Espero 1 segundo.

}
}
}

5.3.1.1.4.- Led_4.c
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Led_4.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Simular Coche Fantstico
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de procesado******************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Eleccin del uC 16F877A

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

int8 n=0 ;

// Declaramos la variable n con 8 bit y la inicializamos con 0.

Microcontroladores

// Reloj de 1 MHz

IES Joan Mir

Pgina 29

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // **************************** Funcin principal o programa principal ******************************
// Se define con un void main,
void main()
{
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

portB = 0b00000001;
delay_ms(500);

// Activamos PB0.
// Esperamos 0,5 segundo.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
for (n=0;n<=6;n++)

// Ejecuta el contenido que est entre corchetes 7 veces de 0 a 6

{
portB<<=1;
delay_ms(500);

// Movemos un bit a la izquierda


// Esperamos 0,5 segundo.

}
for(n=7;n>0;n--)

// Ejecuta el contenido que est entre corchetes 7 veces de 7 a 1

{
portB>>=1;
delay_ms(500);

// Movemos un bit a la derecha.


// Esperamos 0,5 segundo.

}
}
}

5.3.1.2.- Display_7Segmentos.
Los entrenadores utilizados son Simulador Perifricos y Dispay_7Seg dentro de la
carpeta de Display_7Segmentos.
Un display de 7 segmentos son diodos LED encapsulados con una determinada
configuracin. Si queremos que aparezcan los nmeros decimales sobre el display es
necesario realizar una conversin de nmero decimal a 7 segmentos. Dicha conversin
depender de la conexin del display al microcontrolador.

Microcontroladores

IES Joan Mir

Pgina 30

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Tabla de conversin de Nmero Decimal a Binario de 7 segmentos

Nmero
Decimal
0
1
2
3
4
5
6
7
8
9

Puerto B
B7 B6 B5 B4 B3 B2 B1 B0
g f e d c b a
0
0
0
0
0
0
0
0
0
0

0
0
1
1
1
1
1
0
1
1

1
0
0
0
1
1
1
0
1
1

1
0
1
0
0
0
1
0
1
0

1 Dgito en
Hexadecimal

1
0
1
1
0
1
1
0
1
1

1
1
0
1
1
1
1
1
1
1

1
1
1
1
1
0
0
1
1
1

Nmero
Hexadecimal

1
0
1
1
0
1
1
1
1
1

3F
06
5B
4F
66
6D
7D
07
7F
6F

2 Dgito en
Hexadecimal

5.3.1.2.1.- Display_7Seg_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Display_7Seg_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar los nmeros desde 0 al 9 en un display de 7 Segmentos.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ******************************* Directivas de procesado*********************************************


// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )
// Reloj de 1 MHz

#define Numeros_Tabla 10

// Nmeros de la Tabla.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

int8 n=0 ;

// Declaramos la variable n con 8 bit y la inicializamos con 0.

byte CONST DISPLAY[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

// Tabla de conversin de
// BCD a 7 Seg.

// ************************ Funcin principal o programa principal **********************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
portB = 0B00000000;

// Defines Puerto B como SALIDA de datos.


// Reseteamos el Puerto B.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

Microcontroladores

IES Joan Mir

Pgina 31

Aprendizaje de la Electrnica a travs de la Robtica - ARCE {


for (n=0; n<Numeros_Tabla; n++)

// Se ejecuta un bucle desde n=0 hasta


// n<=Numeros_Tabla en orden
// ASCENDENTE de uno en uno

{
portB = DISPLAY[n];

// Mostramos en el Puerto B el valor que


// tiene la tabla DISPLAY[n]
// Retardo de 1 Segundo.

delay_ms(1000);
}
}
}

5.3.1.2.2.- Display_7Seg_2.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Display_7Seg_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar los nmeros desde 9 al 0 en un display de 7 Segmentos.
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// *********************************** Directivas de procesado*****************************************


// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#define Numeros_Tabla 10

// Nmeros de la Tabla.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

signed int8 n=0 ;

// Declaramos la variable n con 8 bit y signo , la inicializamos con 0.

byte CONST DISPLAY[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

// Tabla de conversin de
// BCD a 7 Seg.

// ****************************** Funcin principal o programa principal ****************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
portB = 0B00000000;

// Defines Puerto B como SALIDA de datos.


// Reseteamos el Puerto B.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
for (n=Numeros_Tabla-1; n>=0; n--)

// Se ejecuta un bucle desde n=Numero_Tabla-1 hasta


// n>=0 en orden DESCENDENTE de uno en uno

{
portB = DISPLAY[n];
delay_ms(1000);

// Mostramos en el Puerto B el valor que tiene DISPLAY[n]


// Retardo de 1 Segundo.

}
}
}

Microcontroladores

IES Joan Mir

Pgina 32

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.1.2.3.- Display_7Seg_3.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Display_7Seg_1b.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar mi nombre.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de procesado******************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#define Numeros_Tabla 5

// Nmeros de la Tabla.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

int8 n=0;

// Declaramos la variable n con 8 bit y la inicializamos con 0.

byte CONST DISPLAY[5] = {0x73,0x79,0x5E,0x50,0x3F};


//
P
E
d
r
O

// Tabla de 5 datos.

// ***************************** Funcin principal o programa principal ****************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
portB = 0;

// Defines Puerto B como SALIDA de datos.


// Reseteamos el Puerto B.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
for (n=0;n<Numeros_Tabla;n++)

// Se ejecuta un bucle desde n=0 hasta


// n<Numeros_Tabla en orden ASCENDENTE
// de uno en uno

{
portB = DISPLAY[n];
delay_ms(1000);

// Mostramos en el Puerto B el valor que tiene DISPLAY[n]


// Retardo de 1 Segundo.

}
}
}

Microcontroladores

IES Joan Mir

Pgina 33

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.1.3.- LCD.


Los entrenador utilizados son Simulador Potencia y LCD dentro de la carpeta de LCD.

La pantalla de cristal lquido o display LCD (Liquid Crystal Display) se utiliza para
mostrar mensajes. Puede mostrar cualquier carcter alfanumrico.
La pantalla consta de una matriz de de caracteres (Normalmente de 5x7 punto por
carcter), distribuidos en una, dos, tres, cuatro lneas (Hasta 40 caracteres por lnea). El
proceso de visualizacin es gobernado por un microcontrolador incorporado en la propia
pantalla. El modelo ms utilizados es el Hitachi HD44780.
Uno de los modelos utilizados es el LM16L cuyas caractersticas son:

Consumo reducido, del orden de 7,5 mW.


Pantalla de caracteres ASCII, caracteres griegos, smbolos matemticos, etc.
Desplaza los caracteres hacia la izquierda o a la derecha.
Memoria de 40 caracteres por lnea de pantalla, visualizacin de 16 caracteres
por lnea.

Microcontroladores

IES Joan Mir

Pgina 34

Aprendizaje de la Electrnica a travs de la Robtica - ARCE

Movimiento del cursor y cambio de su aspecto.


Permite programas ocho caracteres.
Puede ser gobernado de dos formas principales:
Conexin con bus de 4 bits
Conexin con un bus de 8 bits
LCD1
LCD-16 X 2_JOAN

SEAL

DEFINICIN

PINES

D7..D0
E

Data Bus
Enable

14..7
6

R/W

Read/Write

RS

Register Select

VEE VLC

Liquid Cristal driving Voltage

VDD

Power Supply Voltage

VSS

Ground

D0
D1
D2
D3
D4
D5
D6
D7
7
8
9
10
11
12
13
14

Las lneas del bus de datos (D7..D0) son triestado y


pasan a estado de alta impedancia cuando el LCD no se utiliza.

4
5
6

1
2
3

VSS
VDD
VEE

La alimentacin es de 5V. La regulacin de contraste se


realiza por la patilla VEE con un potencimetro de 10K. Si
ponemos VEE a masa tiene el mximo contraste.

RS
RW
E

El patillaje es el siguiente:

FUNCIN
Bus de datos
E=0
LCD no habilitado.
E=1
LCD habilitado.
R/W =0 escribe en LCD.
R/W =1 lee del LCD.
RS=0
Modo Comando
RS=1
Modo Caracter
Tensin para ajustar el
contraste
Tensin de Alimentacin
+5V
Masa.

Utilizaremos el driver flex_lcd.c que es una variacin del creado por CCS, con las
siguientes funciones:
Lcd_init(); Inicializa el LCD.

Borra el LCD y lo configura en el formato de 4 bits, con dos


lneas de caracteres (5x7 puntos), en modo encendido, cursor
apagado y sin parpadeo.

Lcd_gotoxy (byte x, byte y); Indica la posicin y lnea donde se posiciona el cursor.
byte x es posicin del cursor y byte y el lnea.
Utilizamos funciones del compilador de C de CCS para escribir en el LCD.
PRINTF(function, string, values)
La funcin de impresin formateada PRINTF saca una cadena de caracteres al
estndar serie RS-232 o a una funcin especificada. El formato est relacionado con el
argumento que ponemos dentro de la cadena (string).
function es una funcin. Ejemplo ( Lcd_putc)
values es una lista de variables separadas por comas. Ejemplo V1,I1,DATO
string es una cadena de caracteres, donde se indica, mensaje, nmero, tipo ,\c.
mensaje

Texto a escribir en el LCD

nmero

(nmero de caracteres) es opcional

1-9

Microcontroladores

Cuantos caracteres se escriben.

IES Joan Mir

Pgina 35

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 01-09


1.1-9.9
t ipo

Indica cuantos ceros existen a la Izquierda.


para coma flotante.
(tipo de carcter) puede ser:

c
s
u
d
Lu
Ld
x
X
Lx
LX
f
g
e
w

Carcter.
Cadena o Carcter.
Entero sin signo.
Entero con signo.
Entero Largo sin signo.
Entero Largo con signo.
Entero Hexadecimal (minsculas).
Entero Hexadecimal (maysculas).
Entero largo Hexadecimal (minsculas).
Entero largo Hexadecimal(maysculas).
Flotante con truncado.
Flotante con redondeo.
Flotante en formato exponencial.
Entero sin signo con decimales insertados. La 1 cifra indica el
total de nmeros, la 2 cifra indica el nmero de decimales.

\c puede ser:
\f
\n
\b

Se limpia el LCD.
El cursor va a la posicin (1,2)
El cursor retrocede una posicin.

5.3.1.3.1.- LCD_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar mensajes en el LCD
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ******************************** Directivas de Preprocesado****************************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

#include <flex_lcd.c>

// Reloj de 1 MHz

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

// *********************** Funcin principal o programa principal ***********************************


void main()
{
lcd_init();
printf(lcd_putc, "I.E.S. Joan Miro\n");
printf(lcd_putc, " Ciclo GM de EC");

// Inicializamos el LCD.
// Escribimos "I.E.S. Joan Miro" y
// saltamos a la siguiente lnea.
// Escribimos " Ciclo GM de EC".

while (1);

// Ejecuta est instruccin indefinidamente.

Microcontroladores

IES Joan Mir

Pgina 36

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.1.3.2.- LCD_2.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar nmeros en diferentes formatos en el LCD
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ******************************* Directivas de Preprocesado****************************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )
// Reloj de 1 MHz

#include <flex_lcd.c> // Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.
int8 numero_1 = 254;
signed int8 numero_2 = -128;
int8 numero_3 = 142;
float numero_4 = -2.35;

// Nmeros comprendidos de 0 a 255


// Nmeros comprendidos de -128 hasta 127
// Nmeros comprendidos de 0 a 255
(8E en Hexadecimal)
// Nmeros con decimales

// *********************** Funcin principal o programa principal ***********************************


void main()
{
lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(1,1);
printf(lcd_putc,"%3u",numero_1);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .


// Escribimos 3 dgitos de la variable "numero_1" en formato entero y
// sin signo.

lcd_gotoxy(8,1);
printf(lcd_putc,"%4d",numero_2);

// Posicionamos el Cursor del LCD en la posicin 8 lnea 1 .


// Escribimos 4 dgitos de la variable "numero_2" en formato entero
// con signo.

lcd_gotoxy(1,2);
printf(lcd_putc,"%2X",numero_3);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .


// Escribimos 2 dgitos de la variable "numero_3" en formato entero
// hexadecimal maysculas.

lcd_gotoxy(8,2);
printf(lcd_putc,"%5.2f",numero_4);

// Posicionamos el Cursor del LCD en la posicin 8 lnea 2 .


// Escribimos 5 dgitos de la variable "numero_4" en formato flotante.
// La 1 cifra indica el total de dgitos y la 2 el nmero de decimales.
// Fin.

while (1);
}

5.3.1.3.3.- LCD_3.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_3.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar mensajes y array de nmeros en formatos Decimal
//
//
y Hexadecimal en el LCD
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ******************************** Directivas de Preprocesado****************************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP

Microcontroladores

IES Joan Mir

Pgina 37

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #use delay( clock = 1000000 )

// Reloj de 1 MHz

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones


// de control del LCD.

byte CONST DIGIT_MAP[10]={162,5,64,100,245,11,255,16,217,5};

// Array de 10 nmeros tipo byte

// ************************ Funcin principal o programa principal **********************************


void main()
{
int8 i=0;
lcd_init();

// Declaramos la variable i en formato de 8 bit y la inicializamos con 0.


// Inicializamos el LCD.

lcd_gotoxy(5,1);
printf(lcd_putc, "Decimal");

// Posicionamos el Cursor del LCD en la posicin 5 lnea 1 .


// Escribimos la palabra "Decimal".

lcd_gotoxy(5,2);
printf(lcd_putc, "Hexadecimal");

// Posicionamos el Cursor del LCD en la posicin 5 lnea 2 .


// Escribimos la palabra "Hexadecimal".

for(i=0; i <= 9; ++i)

// Sacamos los diez nmeros del array uno a uno y los


// representamos en el Display en diferentes formatos.

{
lcd_gotoxy(1,1);
printf(lcd_putc,"%3u",DIGIT_MAP[i]);
lcd_gotoxy(2,2);
printf(lcd_putc,"%2X",DIGIT_MAP[i]);

delay_ms(1000);

// Posicionamos el Cursor del LCD en la posicin


// 1 lnea 1 .
// Escribimos 3 dgitos del dato sacado del array
// DIGITAL_MAP en formato entero y sin signo.
// Posicionamos el Cursor del LCD en la posicin
// 2 lnea 2 .
// Escribimos 2 dgitos del nmero sacado del
// array DIGITAL_MAP en formato entero
// hexadecimal maysculas.
// Retardo de 1 segundo.

}
while (1);

// Fin.

5.3.1.3.4.- LCD_4.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_4.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar mensajes y array de nmeros en formatos entero 16 bit en el LCD //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// *********************************** Directivas de Preprocesado*************************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

#include <flex_lcd.c>

// Reloj de 1 MHz

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

int16 CONST NUMEROS[10]={267,456,856,23984,123,65535,65536,12,7,5};

Microcontroladores

IES Joan Mir

// Array de 10 nmeros tipo


// entero de 16 bit.

Pgina 38

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // ************************** Funcin principal o programa principal ********************************
void main()
{
int8 i=0;

// Declaramos la variable i en formato de 8 bit y la inicializamos con 0.

lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(9,1);
printf(lcd_putc, "int16");

// Posicionamos el Cursor del LCD en la posicin 9 lnea 1 .


// Escribimos la palabra "int16".

for(i = 0;i <= 9; ++i)

// Sacamos los diez nmeros del array uno a uno y los representamos
// en el Display.

{
lcd_gotoxy(1,1);
printf(lcd_putc,"%5Lu",NUMEROS[i]);

// Posicionamos el Cursor del LCD en la


// posicin 1 lnea 1 .
// Escribimos 5 dgitos del dato sacado del array
// NUMEROS en formato entero largo sin signo.
// (No representa los ceros a la izquierda)

delay_ms(1000);

// Retardo de 1 segundo.

}
while (1);

// Fin.

5.3.1.3.5.- LCD_5.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_5.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar mensajes y array de nmeros en formatos entero 32
//
//
bit con signo en el LCD
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ************************************** Directivas de Preprocesado *********************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control


// del LCD.
Signed Int32 CONST DATOS[10]={-26745,-456232,856323,234,123,235336,233,-12,-778,895};
// Array de 10
// nmeros tipo
// entero de 32 bit
// con signo.

// *************************** Funcin principal o programa principal ******************************


void main()
{
int8 i=0;

// Declaramos la variable i en formato de 8 bit y la inicializamos con 0.

lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(9,2);
printf(lcd_putc, "S_int32");

// Posicionamos el Cursor del LCD en la posicin 9 lnea 2 .


// Escribimos la palabra "S_int32".

Microcontroladores

IES Joan Mir

Pgina 39

Aprendizaje de la Electrnica a travs de la Robtica - ARCE for (i = 0;i <= 9; ++i)

// Sacamos los diez nmeros del array uno a uno y los


// representamos en el Display.

{
lcd_gotoxy(1,2);
printf(lcd_putc,"%7Ld",DATOS[i]);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .


// Escribimos 7 dgitos del dato sacado del array
// DATOS en formato entero largo con signo. (No
// representa los ceros a la izquierda)

delay_ms(1000);

// Retardo de 1 segundo.

}
while (1);

// Fin.

5.3.1.3.6.- LCD_6.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_6.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Mostrar mensajes y array de caracteres en el LCD
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ************************************ Directivas de Preprocesado***********************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

#include <flex_lcd.c>

// Reloj de 1 MHz

// Incluimos el driver flex_lcd.c que contiene las funciones de


// control del LCD.

Char CONST CARACTER[17]={"arthgsupHF12erfj"};

// Array tipo Char de 16 caracteres.


// nmeros tipo entero de 32 bit con signo.

// *************************** Funcin principal o programa principal *******************************


void main()
{
int8 i=0;

// Declaramos la variable i en formato de 8 bit y la inicializamos con 0.

lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(3,1);
printf(lcd_putc, "(Caracteres)");

// Posicionamos el Cursor del LCD en la posicin 3 lnea 1.


// Escribimos la palabra "(Caracteres)".

lcd_gotoxy(8,2);

// Posicionamos el Cursor del LCD en la posicin 8 lnea 2.

for (i = 0;i <= 9; ++i)

// Sacamos los diez nmeros del array uno a uno y los


// representamos en el Display en diferentes formatos.

{
printf(lcd_putc,"%1c\b",CARACTER[i]);

// Escribimos 1 dgitos tipo carcter sacado del


// array CARACTER. Posicionamos el cursor
// constantemente en la posicin 8 lnea 2.

delay_ms(1000);

// Retardo de 1 segundo.

}
while (1);

// Fin.

Microcontroladores

IES Joan Mir

Pgina 40

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.1.3.7.- LCD_7.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: LCD_7.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Queremos que aparezcan en la pantalla de un LCD las notas de un
//
//
alumno de CM EC, en la primera lnea el nombre y en la segunda
//
//
Lnea la nota y la signatura con una cadencia de un segundo
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ************************************* Directivas de Preprocesado **********************************


#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de


// control del LCD.

byte CONST NOTAS[4]={10,8,2,6};

// Array de 4 nmeros tipo byte

char CONST ASIGNATURAS[4][12]={"Matematicas","Ingles

","Dibujo

","Fisica

"}; // Array de 4 filas 12 columnas

// ***************************** Funcin principal o programa principal *****************************


void main()
{
int8 i=0;

// Declaramos la variable i en formato de 8 bit y la inicializamos con 0.

lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(1,1);
printf(lcd_putc,"Jose Luengo");

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1.


// Escribimos las palabra "Jose Luengo".

while(1)
{
for(i = 0;i <= 3; i++)

// Sacamos los 4 notas y asignaturas de los


// arrays.

{
lcd_gotoxy(13,2);
printf(lcd_putc,"%2u",NOTAS[i]);

// Posicionamos el Cursor en la posicin 13


// lnea 2.
// Escribimos 2 dgitos del dato sacado del
// array NOTAS en formato entero y sin signo.

lcd_gotoxy(1,2);

// Posicionamos el Cursor en la posicin 1


// lnea 2.
printf(lcd_putc,"%s",ASIGNATURAS[i]);
// Escribimos los caracteres del array
// ASIGNATURAS
delay_ms(1000);

// Retardo de 1 segundo.

}
}
}

Microcontroladores

IES Joan Mir

Pgina 41

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.2.- Entradas Digitales.


Utilizaremos diferentes entrenadores, contenidos en la carpeta de Entradas Digitales.

5.3.2.1.- Simulador de Perifricos.

5.3.2.1.1.- Interruptores_Led_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interruptores_Led_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Leer la posicin de los interruptores y llevar dicha informacin a los LED
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de procesado ****************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT, NOWDT, NOPROTECT, NOLVP
#use delay( clock = 1000000 )

// Eleccin del uC 16F877A


// Reloj de 1 MHz

#BYTE TRISB = 0x86


#BYTE TRISA = 0x85

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta TRISA la direccin 85h de memoria RAM.

#BYTE portB = 0x06


#BYTE portA = 0x05

// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.


// Asignamos a la etiqueta portA la direccin 05h de memoria RAM.

// *************************** Funcin principal o programa principal *******************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;

Microcontroladores

// Defines Puerto B como SALIDA de datos.

IES Joan Mir

Pgina 42

Aprendizaje de la Electrnica a travs de la Robtica - ARCE TRISA = 0B11111111;


portB = 0;

// Defines Puerta A como ENTRADA de datos.


// Reseteas el puerto B.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
portB = portA;

// Introducimos el contenido del puerto A en el puerto B.

}
}

5.3.2.1.2.- Interruptores_Led_2.c
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interruptores_Led_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Entrenador: Simulador Perifricos.DSN
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Leer puerto A si es menor o igual que 7 activar el Led RBO
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de procesado*******************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
// Eleccin del uC 16F877A
#fuses XT, NOWDT, NOPROTECT, NOLVP
#use delay( clock = 1000000 )
// Reloj de 1 MHz
#BYTE TRISB = 0x86
#BYTE TRISA = 0x85

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta TRISA la direccin 85h de memoria RAM.

#BYTE portB = 0x06


#BYTE portA = 0x05
#BIT RB0 = 0x06.0

// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.


// Asignamos a la etiqueta portA la direccin 05h de memoria RAM.
// Asignamos a la etiqueta RB0 la direccin 06.0h de memoria RAM.

// ************************** Funcin principal o programa principal *******************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
RISA = 0B11111111;
portB = 0;

// Defines Puerto B como SALIDA de datos.


// Defines Puerta A como ENTRADA de datos.
// Reseteas el puerto B.

while (1)
{

// Ejecuta indefinidamente lo que est entre corchetes.


if(portA<=7)
{
RB0 = 1;
}
else
{
RB0 = 0;
}

// Si portA es menor o igual que 7 realiza lo que est entre corchetes.


// Encender el Led de RBO.
// Si portA es mayor que 7 realiza lo que est entre corchetes.
// Apagar el Led de RBO.

}
}

Microcontroladores

IES Joan Mir

Pgina 43

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.2.1.3.- Interruptores_DISPL_7S_1.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interruptores_DISPL_7S_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Leer el Puerto A y mostrar la informacin en un display de 7 Segmentos.
//
//
Si el nmero es mayor de 9 poner la letra E.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************* Directivas de procesado***************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#BYTE TRISB = 0x86


#BYTE TRISA = 0x85

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta TRISA la direccin 85h de memoria RAM.

#BYTE portB = 0x06


#BYTE portA = 0x05

// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.


// Asignamos a la etiqueta portA la direccin 05h de memoria RAM.

byte CONST DISPLAY[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

// Tabla de conversin de
// BCD a 7 Seg.

// *************************** Funcin principal o programa principal *******************************


// Se define con un void main,
void main()
{
TRISA = 0B11111111;
TRISB = 0B00000000;
portB = 0B00000000;

// Defines Puerto A como ENTRADA de datos.


// Defines Puerto B como SALIDA de datos.
// Reseteamos el Puerto B.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
if(portA<=9)

// Si portA <=9 mostrar en el Display 7Seg el valor en BCD.

{
portB=DISPLAY[portA];

// Mostramos en el Puerto B el valor que tiene


// DISPLAY[portA].

portB = 0B11111001;

// Poner la letra E

}
else
{
}
}
}

Microcontroladores

IES Joan Mir

Pgina 44

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.2.1.4.- Interruptores_DISPL_7S_2.c.


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interruptores_DISPL_7S_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Leer el Puerto A y mostrar la informacin en un display de 7 Segmentos.
//
//
Siguiendo el siguiente patrn:
//
//
Si portA=0B00000000 aparecera en el Display 7Seg "0" parapadenado con una cadencia de 1 Seg.
//
//
Si portA=0B00000001 aparecera en el Display 7Seg "1" parapadenado con una cadencia de 0,5 Seg.
//
//
Si portA=0B00000010 aparecera en el Display 7Seg "2" parapadenado con una cadencia de 0,25 Seg.
//
//
Si portA=0B00000011 aparecera en el Display 7Seg "3" parapadenado con una cadencia de 0,1 Seg.
//
//
Si portA>0B00000011 aparecera en el Display 7Seg " "
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************* Directivas de procesado***************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Eleccin del uC 16F877A

#BYTE TRISB = 0x86


#BYTE TRISA = 0x85

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta TRISA la direccin 85h de memoria RAM.

#BYTE portB = 0x06


#BYTE portA = 0x05

// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.


// Asignamos a la etiqueta portA la direccin 05h de memoria RAM.

// Reloj de 1 MHz

byte CONST DISPLAY [4]={0x3F,0x06,0x5B,0x4F};

// Tabla de conversin de BCD a 7 Seg.

// **************************** Funcin principal o programa principal ******************************


// Se define con un void main,
void main()
{
TRISB = 0B00000000;
TRISA = 0B11111111;
portB = 0;

// Defines Puerto B como SALIDA de datos.


// Defines Puerta A como ENTRADA de datos.
// reseteas el puerto B.

while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
switch (portA)
{
case 0:

// Preguntamos por portA


// Si portA=0 realiza lo que viene a continuacin.
portB = DISPLAY [0];
delay_ms(1000);
portB = 0;
delay_ms(1000);

// Mostramos en el Puerto B el valor que tiene


// DISPLAY[0].
// Retardo de 1 Segundo.
// Apagar Display.
// Retardo de 1 Segundo.

break;

// No realiza los siguientes casos.

case 1:

// Si portA=1 realiza lo que viene a continuacin


portB = DISPLAY[1];
delay_ms(500);
portB = 0;
delay_ms(500);

// Mostramos en el Puerto B el valor que tiene


// DISPLAY[1].
// Retardo de 0,5 Segundos.
// Apagar Display.
// Retardo de 0,5 Segundos.

break;

// No realiza los siguientes casos.

case 2:

// Si portA=2 realiza lo que viene a continuacin


portB = DISPLAY [2];

Microcontroladores

// Mostramos en el Puerto B el valor que tiene

IES Joan Mir

Pgina 45

Aprendizaje de la Electrnica a travs de la Robtica - ARCE delay_ms(250);


portB = 0;
delay_ms(250);

// DISPLAY[2].
// Retardo de 0,25 Segundos.
// Apagar Display.
// Retardo de 0,25 Segundos.

break;

// No realiza los siguientes casos.

case 3:

// Si portA=3 realiza lo que viene a continuacin


portB = DISPLAY [3];
delay_ms(100);
portB = 0;
delay_ms(100);

// Mostramos en el Puerto B el valor que tiene


// DISPLAY[3].
// Retardo de 0,1 Segundos.
// Apagar Display.
// Retardo de 0,1 Segundos.

break;

// No realiza los siguientes casos.

default:

// Si portA>3 realiza lo que viene a continuacin


portB = 0;

// Apagar Display.

}
}
}

5.3.2.1.5.- Pulsadores_DISPL_7S_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Pulsadores_DISPL_7S_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Leer los pulsadores RCO(incremento) y T0CKI(Decremento) y mostrar la
//
//
informacin en un Display de 7 Segmentos.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ********************************* Directivas de procesado*******************************************


// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )
// Reloj de 1 MHz
#BYTE TRISC = 0x87
#BYTE portC = 0x07

// Asignamos a la etiqueta TRISC la direccin 87h de memoria RAM.


// Asignamos a la etiqueta portC la direccin 07h de memoria RAM.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

#BYTE TRISA = 0x85


#BYTE portA = 0x05

// Asignamos a la etiqueta TRISA la direccin 85h de memoria RAM.


// Asignamos a la etiqueta portA la direccin 05h de memoria RAM.

#BIT rc0 = 0X07.0


#BIT t0cki = 0X05.4

// Asignamos a la etiqueta rc0 el bit 0 de la direccin 07h de la memoria RAM.


// Asignamos a la etiqueta t0cki el bit 4 de la direccin 05h de la memoria RAM.

byte CONST DISPLAY[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; // Tabla de conversin de


BCD a 7 Seg.

// ************************* Funcin principal o programa principal *********************************


// Se define con un void main,
void main()
{
signed int8 n=0;
TRISC = 0B10000001;
TRISA = 0B11111111;
TRISB = 0B00000000;

// Defines Puerto C como SALIDA de datos a excepcin de


// RC7 y RC0.
// Defines Puerto A como ENTRADA de datos.
// Defines Puerto B como SALIDA de datos.

portB = DISPLAY[0];

// Ponemos en el Display de 7Seg. "0".

Microcontroladores

IES Joan Mir

Pgina 46

Aprendizaje de la Electrnica a travs de la Robtica - ARCE while (1)

// Ejecuta indefinidamente lo que est entre corchetes.

{
WHILE(rc0==1)

// Mientras rc0=1 haz lo que existe entre corchetes.

{
n++;

// Incrementar la variable n.

if (n>9)

// Si n>9 el Display de 7 Segmentos representa 9.

{
portB = DISPLAY[9];
n=9;

// Ponemos en el Display de 7Seg. "0".


// Inicializar n=9.

portB=DISPLAY[n];

// Mostramos en el Puerto D el valor que tiene


// DISPLAY[n].
// Retardo de 1 Segundo.

}
else
{

delay_ms(1000);
}
}
WHILE(t0cki==0)

// Mientras t0cki=0 haz lo que existe entre corchetes.

{
n--;

// Decrementar la variable n.

if (n<0)

// Si n<0 el Display de 7 Segmentos representa 0.

{
portB = DISPLAY[0];
n=0;

// Ponemos en el Display de 7Seg. "0".


// Inicializar n=0.

portB=DISPLAY[n];

// Mostramos en el Puerto D el valor que tiene


// DISPLAY[n].
// Retardo de 1 Segundo.

}
else
{

delay_ms(1000);
}
}
}
}

5.3.2.2.- Simulador de Perifricos y Potencia.

Microcontroladores

IES Joan Mir

Pgina 47

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.2.2.1.- Interruptores_LCD_1.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interruptores_LCD_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Entrenador: Simulador Potencia y Perifricos.DSN
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Si RA0= 1 mostrar en el LCD Apagado. Si RA0= 0 mostrar en el LCD
//
//
Encendido.
//
//
Aparecera en LCD las veces que RA0=0
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado*************************************
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control


// del LCD.

#BIT TA0 = 0X85.0


#BIT RA0 = 0X05.0

// Asignamos TA0 el bit 0 de la direccin asociada a TRISA.


// Asignamos a la etiqueta pulsador el bit 0 de la direccin 05h de la
// memoria RAM.

#define ON 1

// ON equivale a 1.

int8 contador=0;
int1 cambio=0;

// **************************** Funcin principal o programa principal ******************************


void main()
{
lcd_init();

// Inicializamos el LCD.

TA0 = 1;

// Configuramos la patilla RA0 com entrada de datos

while(1)
{
lcd_gotoxy(1,1);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .

if(RA0==ON)
{
if (cambio==0)
{
printf(lcd_putc, "Encendido");
contador++;
lcd_gotoxy(11,1);
printf(lcd_putc,"%3u",contador);
cambio=1;
}
delay_ms(50);
}
else
{
printf(lcd_putc, "Apagado ");
cambio=0;
delay_ms(50);
}

// Escribimos la palabra "Encendido".

// Escribimos la palabra "Apagado ".

}
}

Microcontroladores

IES Joan Mir

Pgina 48

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.2.2.2.- Interruptores_LCD_2.c


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Pulsadores_LCD_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Entrenador: Simulador Potencia.DSN
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Si RC0= 0 mostrar en el LCD Apagado. Si RC0= 1 mostrar en el LCD Encendido.
//
//
aparecera en LCD y en el DISPLAY_7s las veces que RC0=1
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ************************************* Directivas de Preprocesado***********************************


#include <16F877A.h>
#fuses XT, NOWDT, NOPROTECT, NOLVP
#use delay( clock = 1000000 )
// Reloj de 1 MHz
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// Asignamos a la etiqueta TRISB la direccin 86h de memoria RAM.


// Asignamos a la etiqueta portB la direccin 06h de memoria RAM.

#BIT TC0 = 0X87.0


#BIT RC0 = 0X07.0

// Asignamos TA0 el bit 0 de la direccin asociada a TRISA.


// Asignamos a la etiqueta pulsador el bit 0 de la direccin 05h de la memoria
// RAM.
// ON equivale a 1.

#define ON 1
int8 contador=0;
int1 cambio=0;

byte CONST DISPLAY[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; // Tabla de conversin de


BCD a 7 Seg.

// *********************** Funcin principal o programa principal ***********************************


void main()
{
lcd_init();
TC0 = 1;

// Inicializamos el LCD.
// Configuramos la patilla RA0 com entrada de datos

TRISB = 0B00000000;
portB = DISPLAY[0];

// Defines Puerto B como SALIDA de datos.

while(1)
{
lcd_gotoxy(1,1);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .

if(RC0==ON)
// Si RA0=ON haz lo que viene a continuacin.
{
if (cambio==0)
// Haz una sola vez elte proceso si RA0=ON
{
printf(lcd_putc, "Encendido");
// Escribimos la palabra "Encendido".
contador++;
// Incremento la variable contador.
lcd_gotoxy(11,1);
printf(lcd_putc,"%3u",contador);

portB = DISPLAY[contador];

// Posicionamos el Cursor del LCD en la


// posicin 11 lnea 1 .
// Escribimos 3 dgitos de la variable
// "contador" en formato entero y sin
// signo.
// Mostramos en el Puerto B el valor
// que tiene la tabla DISPLAY[n]

cambio=1;
}
delay_ms(50);

// Cambiamos la variable.

printf(lcd_putc, "Apagado ");


cambio=0;
delay_ms(50);

// Escribimos la palabra "Apagado ".


// Cambiamos la variable.
// Espereramos 50 mS.

// Espereramos 50 mS.

}
else
{

}
}
}

Microcontroladores

IES Joan Mir

Pgina 49

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.2.3.- Simulador de Potencia.

5.3.2.3.1.- Pulsadores_LCD_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Pulsadores_LCD_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Si RC0= 1 mostrar en el LCD Apagado. Si RC0= 0 mostrar en el LCD Encendido. //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )
// Reloj de 1 MHz
#include <flex_lcd.c>
// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.
#BYTE TRISC = 0X87
#BIT pulsador = 0X07.0
#define ON 1

// Asignamos a la etiqueta TRISC la direccin 87h de memoria RAM.


// Asignamos a la etiqueta pulsador el bit 0 de la direccin 07h
// de la memoria RAM.
// ON equivale a 1.

// **************************** Funcin principal o programa principal ******************************


void main()
{
lcd_init();
TRISC=0B10000001;

// Inicializamos el LCD.
// Ponemos el Puerto C como ENTRADA de
// datos a excepcin de RC7.

while(1)
{
lcd_gotoxy(1,1);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .

if(pulsador==ON)
{
printf(lcd_putc, "Encendido");
}
else
{
printf(lcd_putc, "Apagado ");
}

// Escribimos la palabra "Encendido".

// Escribimos la palabra "Apagado ".

}
}

Microcontroladores

IES Joan Mir

Pgina 50

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.3.- Entradas Analgicas.


Los microcontroladores PIC llevan un sistema de adquisicin de datos. Est compuesto por :

Multiplexor Analgico (Selecciona la patilla a digitalizar).


Circuito de muestreo y retencin (Sample & Hold) (Retiene la seal analgica un
instante para poderla muestrear).
Conversor Analgico/Digital de aproximaciones sucesivas (Convierte las seales
analgicas en cdigos digitales).

Las caractersticas principales son:

Rango de Entrada.
Simboliza que tensiones puede digitalizar (En los PIC de 0 .. 5V)

Nmero de bits de salida del Conversor A/D.


En los PIC de gama media es de 10 bits.

Resolucin. (Indica que tensin mnima necesito para aumentar un cdigo digital)
Resolucin = q = 1LSB =

= 4,8 mV.

q= Intervalo de cuantificacin.
LSB= Bit menos significativo
Si trabajamos con tensiones comprendidas entre Vref+ = 5V y Vref- =0V y con 10bits de salida
obtenemos una resolucin de 4,8 mV.

Tempo de conversin (Tiempo que tarda el sistema de adquisicin de datos en obtener


una muestra digital proporcional a la tensin analgica)
En un uCPIC trabajando con un oscilador interno (RC) tarda entorno a 20uS

Microcontroladores

IES Joan Mir

Pgina 51

Aprendizaje de la Electrnica a travs de la Robtica - ARCE

Error de Cuantificacin.( Indica para que rango mnimo de tensiones se asigna un valor
digital)
En un uCPIC el Conversor A/D, trabaja con error por redondeo.
Error = 2,4 mV.

Error = LSB

La relacin existente entre tensiones de entrada Ve y cdigos digitales de salida D se refleja en la


siguiente tabla.

Cdigo Digital de salida del Conversor


Analgico/Digital
D9 D8 D7 D 6 D5 D4 D3 D2 D1 D0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 1 0 0

Ve
0 < Ve 2,4 mV
2,4mV < Ve 7,2 mV
7,2mV < Ve 12 mV
12mV < Ve 16,8 mV
16,8mV < Ve 21,6 mV
4,9736mV < Ve 4,9904mV
4,9904mV < Ve 4,9952 mV

1
1

1
1

1 1
1 1

1
1

1
1

1
1

1
1

1
1

D
N Decimal
0
1
2
3
4

0
1

1022
1023

Una frmula vlida para trabajar sera: Ve =


Ejemplo: (Trabajando con tensiones comprendidas entre VREF+ = 5V y VREF+ = 0V )
Cunto vale Ve si D=512? :
Ve =
= 2,5V
El sistema de adquisicin de datos te permite elegir el canal a digitalizar actuando
sobre el Multiplexor Analgico (CHS2..CHS0)
Te permite configurar las patillas actuando sobre un registro llamado (ADCON1)
Indicando si son analgicas o digitales o si vas a utilizar Vref externas
PCFG(3..0)

AN7

AN6

AN5

AN4

AN3

AN2

AN1

AN0

VREF+

VREF-

0000
0001
0010
0011
0100
0101
011X
1000
1001
1010
1011
1100
1101
1110
1111

A
A
D
D
D
D
D
A
D
D
D
D
D
D
D

A
A
D
D
D
D
D
A
D
D
D
D
D
D
D

A
A
D
D
D
D
D
A
A
A
A
D
D
D
D

A
A
A
A
D
D
D
A
A
A
A
A
D
D
D

A
VREF+
A
VREF+
A
VREF+
D
VREF+
A
VREF+
VREF+
VREF+
VREF+
D
VREF+

A
A
A
A
D
D
D

A
A
A
A
A
A
D
A
A
A
A
A
A
D
D

A
A
A
A
A
A
D
A
A
A
A
A
A
A
A

VDD
AN3D
VDD
AN3
VDD
AN3
AN3
VDD
AN3
AN3
AN3
AN3
VDD
AN3

GND
GND
GND
GND
GND
GND
AN2
GND
GND
AN2
AN2
AN2
GND
AN2

VREFA
A
VREFVREFVREFD
VREF-

Trabajando en C el compilador CCS maneja unas funciones propias para la conversin


analgica-digital.
Para ms informacin ver Conversin Analgica (3 bit).

Microcontroladores

IES Joan Mir

Pgina 52

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.3.1.- Conversin A-D_D-A

VDD

C1
15p

X1
CRYSTAL

C2

4MHz

15p

V entrada
+

AM

U1
9
10
1

FM

2
3
4
5
6
7

OSC1/CLKIN
OSC2/CLKOUT
MCLR/Vpp/THV

RB0/INT
RB1
RB2
RB3/PGM
RB4
RB5
RB6/PGC
RB7/PGD

RA0/AN0
RA1/AN1
RA2/AN2/VREFRA3/AN3/VREF+
RA4/T0CKI
RA5/AN4/SS
RC0/T1OSO/T1CKI
RC1/T1OSI/CCP2
RC2/CCP1
RC3/SCK/SCL
RC4/SDI/SDA
RC5/SDO
RC6/TX/CK
RC7/RX/DT

21
22
23
24
25
26
27
28

CONVERSOR DIGITAL/ANALGICO

11
12
13
14
15
16
17
18

D0
D1
D2
D3
D4
D5
D6
D7
LE

PIC16F876

V salida

VOUT
VREF+
VREF-

R1

R2

5k

5k

DAC_8
VDD

GENERADOR DE FUNCIONES

VDD

OSCILOSCOPIO
B

V ENTRADA

V SALIDA

Microcontroladores

IES Joan Mir

Pgina 53

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.3.1.1.- Conversin_A-D_A-D.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Conversin_A-D_A-D.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Digitalizar la seal Analgica procedente de la patilla AN0 y sacarla por el //
//
Puerto C
//
//
Comprobar el Teorema de Nyquist fm>=2*fmax(Seal)
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F876A.h>
#device adc=10

// Conversor Analgico Digital de 10 bit el PIC 16F876A puede trabajar


// con 8 o 10 bit de resolucion.

#FUSES XT,NOWDT
#use delay(clock=4000000)
//#use delay(clock=20000000)

// Ojo Cambiar la frecuencia de reloj en el uC.

#BYTE TRISC = 0x87


#BYTE portC = 0x07

// TRISC en 87h.
// PORTC en 07h.

// ************************** Funcin principal o programa principal *******************************


void main()
{
int16 q;
TRISC = 0B00000000;
portC = 0;

// Defines Puerto C como SALIDA de datos.

setup_adc_ports(0);

// Seleccionamos el Puerto A como entradas Analgicas.


// Mirar ADCON1.

setup_adc(ADC_CLOCK_INTERNAL);

// Fuente de reloj RC interno.

// setup_adc(ADC_CLOCK_DIV_2);

// Fuente de reloj RC la marca el Cristal y un divisor de


// frecuencia interno.

set_adc_channel(0);

// Habilitacin canal 0 "AN0"

while(1)
{

// Bucle infinito.
delay_us(5);

// Retardo de 20uS necesaria para respetar el tiempo de


// Adquisicion Tad.

// delay_us(1);
q = read_adc();

// Lectura canal 0 "AN0"

portC = q;
}
}

Microcontroladores

IES Joan Mir

Pgina 54

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.3.2.- Conversin Analgica Digital.


Utilizaremos los entrenadores Simulacin Proteus.DSN y Conversin A-D.DSN,
contenidos en la carpeta de Conversin Analgica Digital.

5.3.3.2.1.- Conversin_A-D1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Conversin_A-D1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Conversin Analgica Digital de la Patilla AN0
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************ Directivas de Preprocesado************************************
#include <16F877A.h>
#device adc=10
de resolucion.

// Conversor Analogico Digital de 10 bit el PIC 16F876A puede trabajar con 8 o 10 bit

#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

// *********************** Funcin principal o programa principal ***********************************


void main()
{
int16 q;
float v;
lcd_init();

// Inicializamos el LCD.

setup_adc_ports(2);
Mirar ADCON1.

// Seleccionamos el Puerto A como entradas Analgicas.

setup_adc(ADC_CLOCK_INTERNAL);

// Fuente de reloj RC interno.

set_adc_channel(0);

// Habilitacin canal 0 "AN0"

for (;;)

// Bucle infinito.

{
delay_us(20);
q = read_adc();

Microcontroladores

// Retardo de 20uS necesaria para respetar el tiempo de


// Adquisicin Tad.
// Lectura canal 0 "AN0"

IES Joan Mir

Pgina 55

Aprendizaje de la Electrnica a travs de la Robtica - ARCE v = 5.0 * q / 1024.0;

// Conversin a tensin del cdigo digital "q".

printf(lcd_putc, "ADC = %4lu", q);

// Escribimos en el LCD "ADC =" y 4 dgitos de "q" en


// formato largo sin signo.

printf(lcd_putc, "\nVOLTAGE = %04.3fV", v);

// Saltamos de lnea y escribimos en el LCD


// "VOLTAJE =" y 4 dgitos de "v"
// en formato float de 4 dgitos con 3 decimales y
// el carcter "V".

}
}

5.3.3.2.2.- Conversin_A-D2.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Conversin_A-D2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Conversin Analgica Digital de la Patilla AN0 y AN3
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#device adc=10

// Conversor Analogico Digital de 10 bit el PIC 16F876A puede trabajar


// con 8 o 10 bit de resolucion.

#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

// **************************** Funcin principal o programa principal *****************************


void main()
{
int16 q;
float p;
setup_adc(ADC_CLOCK_INTERNAL);

// Fuente de reloj RC interno.

setup_adc_ports(2);

// Seleccionamos el Puerto A como entradas Analgicas.


// Mirar ADCON1.
// Inicializamos el LCD.

lcd_init();
while (true)
{
set_adc_channel(0);
delay_us(20);
q = read_adc();
p = 5.0 * q / 1024.0;

// Bucle infinito.
// Habilitacin canal 0 "AN0"
// Retardo de 20uS necesaria para respetar el
// Tiempo de Adquisicin Tad.
// Lectura canal 0 "AN0"
// Conversin a tensin del cdigo digital "q".

lcd_gotoxy(1,1);
printf(lcd_putc, "V1=%04.3fv", p);

// Situamos el Cursor en la posicin 1, lnea 1.


// Escribimos en el LCD "V1=" y 4 dgitos de "P"
// en formato float de 4 dgitos con 3 decimales
// y el caracter "V".

set_adc_channel(3);
delay_us(20);

// Habilitacin canal 3 "AN3"


// Retardo de 20uS necesaria para respetar el
// Tiempo de Adquisicin Tad.
// Lectura canal 1 "AN1"
// Conversin a tensin del cdigo digital "q".

q = read_adc();
p = 5.0 * q / 1024.0;
lcd_gotoxy(1,2);
printf(lcd_putc, "V2=%04.3fv", p);

// Situamos el Cursor en la posicin 1, lnea 2.


// Escribimos en el LCD "V2=" y 4 dgitos de "P"
// en formato float de 4 dgitos con 3 decimales
// y el caracter "V".

}
}

Microcontroladores

IES Joan Mir

Pgina 56

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.3.2.3.- Conversin_A-D2a.c

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Conversin_A-D2a.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Si RA2=1 digitalizamos la seal ANO y presentamos
//
//
la Informacin en el LCD
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ******************************** Directivas de Preprocesado ***************************************
#include <16F877A.h>
#device adc=10

// Conversor Analogico Digital de 10 bit el PIC 16F877A puede trabajar


// con 8 o 10 bit de resolucion.

#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <flex_lcd.c>

// Incluimos el driver LCD1.c que contiene las funciones de control del LCD.

#BIT RA2 = 0x05.2


#BIT TA2 = 0x85.2

// ********************* Funcin principal o programa principal ************************************


void main()
{
int16 q;
float p;
setup_adc(ADC_CLOCK_INTERNAL);

// Fuente de reloj RC interno.

setup_adc_ports(4);

// Seleccionamos el Puerto A como entradas Analgicas.


// Mirar ADCON1.

lcd_init();

// Inicializamos el LCD.

TA2=1;

Microcontroladores

IES Joan Mir

Pgina 57

Aprendizaje de la Electrnica a travs de la Robtica - ARCE while (true)

// Bucle infinito.

{
if(RA2 == 1)
{
set_adc_channel(0);
delay_us(20);

// si RA2=1 se pone en funcionamiento pot R17A


// Habilitacin canal 0 "AN0"
// Retardo de 5uS necesaria para respetar el
// Tiempo de Adquisicin Tad.
// Lectura canal 0 "AN0"
// Conversin a tensin del cdigo digital "q".

q = read_adc();
p = 5.0 * q / 1024.0;
lcd_gotoxy(1,1);
printf(lcd_putc, "V1=%04.3fv", p);

// Situamos el Cursor en la posicin 1, lnea 1.


// Escribimos en el LCD "V1=" y 4 dgitos de "P"
// en formato float de 4 dgitos con 3 decimales y
// el caracter "V".

set_adc_channel(3);
delay_us(20);

// Habilitacin canal 3 "AN3"


// Retardo de 5uS necesaria para respetar el
// Tiempo de Adquisicin Tad.
// Lectura canal 1 "AN1"
// Conversin a tensin del cdigo digital "q".

}
else
{

q = read_adc();
p = 5.0 * q / 1024.0;
lcd_gotoxy(1,1);
printf(lcd_putc, "V2=%04.3fv", p);
}

// Situamos el Cursor en la posicin 1, lnea 1.


// Escribimos en el LCD "V2=" y 4 dgitos de "P"
// en formato float de 4 dgitos con 3 decimales y
// el caracter "V".

}
}

5.3.4.- Modulacin por Anchura de Pulso (PWM).


5.3.4.1.- Control de Motores de Corriente Continua.
La velocidad de un Motor de Corriente Continua depende del valor medio de la tensin
aplicada en sus extremos.
El sistema ms utilizado para controlar la velocidad de un motor DC de pequea
potencia es mediante la modulacin por ancho de pulso PWM (Pulse Width Modulation) de una
seal cuadrada TTL. El motor gira a una velocidad proporcional a la media del nivel de
tensin de la seal cuadrada aplicada.

La tensin media aplicada al motor se controla aplicando una seal cuadrada de


frecuencia constante (Periodo constante T) y variando el tiempo a nivel alto TH de la seal, es
decir variando su ciclo de trabajo CT= T H/T. Si el CT es del 50% la tensin media aplicada al
motor ser del 50%. A mayor tensin mayor velocidad.
El microcontrolador PIC16F876A tiene incorporado dos circuito electrnicos que
generan seal es PWM. Cada seal PWM sale por diferentes patillas RC1 y RC2. La
frecuencia para ambas seales es la misma, ya que utilizan el mismo temporizador para
generar dicha frecuencia (TIMER2).
El compilador C de CCS nos proporciona unas funciones para trabajar con PWM. Para
entender mejor lo explicado utilizaremos unos ejemplos.

Microcontroladores

IES Joan Mir

Pgina 58

Aprendizaje de la Electrnica a travs de la Robtica - ARCE V motor


Vmedia= 0% x 5v = 0v

TH
0%

(Motor Parado)
16

32

CT =

TH
T

x 100 =

0 mS
16 mS

= 0%

(mSeg)

V motor
Vmedia= 20% x 5v = 1v

5v

TH
CT =
20%
3,2

16

32

T
V motor

5v

TH
T

x 100 =

3,2 mS
16 mS

= 20 %

(mSeg)

Vmedia= 50% x 5v = 2,5v

TH
50%

16

32

T
V motor

CT =

TH
T

x 100 =

8 mS
16 mS

= 50 %

(mSeg)

Vmedia= 80% x 5v = 4v

5v

80%
TH
12,8

16

32

CT =

TH
T

x 100 =

12,8 mS
16 mS

= 80 %

(mSeg)

Vmedia= 100% x 5v = 5v
V motor

5v

100%
CT =
TH
T

(Velocidad Mxima)
16

32

TH
T

x 100 =

16 mS
16 mS

(mSeg)

Utilizaremos el entrenador Simulador Potencia.DSN, contenidos en la carpeta de


PWM\Control de Motores de CC\Motores de CC.

Microcontroladores

IES Joan Mir

Pgina 59

= 100 %

Aprendizaje de la Electrnica a travs de la Robtica - ARCE -

5.3.4.1.1.- Prueba_Motor_Derecho.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Prueba_Motor_Derecho.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de Motor Derecho sin control de velocidad
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directiva de Preprocesado ****************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>

// Incluye el fichero 16F877A al programa tiene que estar en la misma carpeta


// del programa define funciones, patillas y registros.

#fuses XT,NOWDT

// Define la palabra de configuracin del microcontrolador PIC


// Trabaja con un reloj tipo XT y no utiliza perro guardin Wathdog
// Define la frecuencia del reloj de 1 MHz

#use delay( clock = 1000000 )


#BYTE TRISC = 0x87
#BYTE portC = 0x07
#BYTE TRISB = 0x86
#BYTE portB = 0x06
#BIT giro_d = 0x06.3
#BIT en2 = 0x07.2

Microcontroladores

// Asignamos TRISC a la direccin 87h


// (Registro de configuracin del Puerto C).
// Asignamos portC a la direccin 07h (Puerto de entrada y salida).
// Asignamos TRISB a la direccin 86h
// (Registro de configuracin del Puerto A).
// Asignamos portB a la direccin 06h (Puerto de entrada y salida).
// Asignamos "giro_d" a la patilla 3 del Puerto B del
// Microcontrolador PIC 16f876a.
// Asignamos "en2" a la patilla 2 del Puerto C del Microcontrolador PIC 16f876a.

IES Joan Mir

Pgina 60

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // *************************** Funcin principal o programa principal *******************************
void main()
{
// *********************** Configuracin de los Puertos del PIC y reseteos del Rastreador ********************
TRISC = 0B10000001;
TRISB = 0B00000000;

// Defines Puerto C como SALIDA de datos a excepcin de RC7/Rx y RC0


// Defines Puerto B como SALIDA de datos.

/ / ************************************************* Inicio *****************************************************************


while (1)
{

// Ejecuta indefinidamente lo que est entre corchetes.


en2 = 1;
giro_d=0;

// Activamos Motor Derecho.MOT2


// Motor Derecho hacia adelante.

delay_ms(2000);

// Retardo de 2 segundo.

en2 = 0;

// Paramos el Motor Derecho.

delay_ms(2000);

// Retardo de 2 segundo.

en2 = 1;
giro_d=1;

// Activamos Motor Derecho.


// Motor Derecho hacia atras.MOT2

delay_ms(2000);

// Retardo de 2 segundo.

en2 = 0;

// Paramos el Motor Derecho.

delay_ms(2000);

// Retardo de 2 segundo.

}
}

5.3.4.1.2.- Prueba_Control_Velocidad_Motor_Derecho.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Prueba_Control_Velocidad_Motor_Derecho.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de velocidad y sentido de giro de un motor de corriente
//
//
continua. MOT2
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************ Directiva de Preprocesado *************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>

// Incluye el fichero 16F877A al programa tiene que estar en la misma


// carpeta del programa define funciones, patillas y registros.

#fuses XT,NOWDT

// Define la palabra de configuracin del microcontrolador PIC


// Trabaja con un reloj tipo XT y no utiliza perro guardin Wathdog
// Define la frecuencia del reloj de 4 MHz

#use delay( clock = 1000000 )


#BYTE TRISB = 0x86
#BYTE portB = 0x06
#BYTE TRISC = 0x87

// Asignamos TRISB a la direccin 86h


// (Registro de configuracin del Puerto A).
// Asignamos portB a la direccin 06h (Puerto de entrada y salida).

#BYTE portC = 0x07

// Asignamos TRISC a la direccin 87h


// (Registro de configuracin del Puerto C).
// Asignamos portC a la direccin 07h (Puerto de entrada y salida).

#BIT giro_d = 0x06.3

// Asignamos "giro_d" a la patilla RB3 del Microcontrolador PIC 16f876a.

Microcontroladores

IES Joan Mir

Pgina 61

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // ***************************** Funcin principal o programa principal ****************************
void main()
{
int16 i=0;
/ / ************************ Configuracin de los Puertos del PIC y reseteos el dispositivo *********************
setup_timer_2(T2_DIV_BY_16,249,1);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. Si el Periodo = 16mS ---->
// T = 16000uS
// T = [PR2+1] x Tcm x Postscaler x Prescaler
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1.
// 16000uS = [PR2+1] x 1 x 16
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[16000uS/(4uS x 16 x 1)]-1 = 249

(en C 249)

setup_ccp1(CCP_PWM);

// CCP2 en modo PWM (Salida por RC2)(Motor Derecho)MOT2

TRISC = 0B10010001;

// Defines Puerto C como SALIDA de datos a excepcin de


// RC7, RC4 Y RCO.

set_pwm1_duty(i);

// Refresca el nivel alto de la seal PWM.


// Salida por RC2. (Motor Derecho)

TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

// ************************************************** Inicio ****************************************************************


while (1)
{

// Ejecuta indefinidamente lo que est entre corchetes.


giro_d=0;

// Motor Derecho hacia adelante.

for(i=0;i<=1000;i=i+100)
{
set_pwm1_duty(i);
delay_ms(1000);

// Refresca el nivel alto de la seal PWM. Salida por RC2.


// (Motor Derecho)
// Retardo de 1 segundo. Este tiempo tiene que ser superior
// al periodo de de la seal "T= 16 ms".

}
giro_d=1;

// Motor Derecho hacia atrs.

for(i=0;i<=1000;i=i+100)
{
set_pwm1_duty(i);
delay_ms(1000);

// Refresca el nivel alto de la seal PWM. Salida por RC2.


// (Motor Derecho)
// Retardo de 1 segundo. Este tiempo tiene que ser superior
// al periodo de la seal "T= 16 ms".

}
}
}

5.3.4.1.3.- Prueba_Control_Velocidad_Motor_Derecho_f.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Prueba_Control_Velocidad_Motor_Derecho_f.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de velocidad y sentido de giro de un motor de
//
// corriente continua. MOT2
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Microcontroladores

IES Joan Mir

Pgina 62

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // *********************************** Directiva de Preprocesado **************************************


// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F877A.h>

// Incluye el fichero 16F877A al programa tiene que estar en la misma


// carpeta del programa define funciones, patillas y registros.

#fuses XT,NOWDT

// Define la palabra de configuracin del microcontrolador PIC


// Trabaja con un reloj tipo XT y no utiliza perro guardin Wathdog
// Define la frecuencia del reloj de 4 MHz

#use delay( clock = 1000000 )


#BYTE TRISB = 0x86
#BYTE portB = 0x06
#BYTE TRISC = 0x87

// Asignamos TRISB a la direccin 86h


// (Registro de configuracin del Puerto A).
// Asignamos portB a la direccin 06h (Puerto de entrada y salida).

#BYTE portC = 0x07

// Asignamos TRISC a la direccin 87h


// (Registro de configuracin del Puerto C).
// Asignamos portC a la direccin 07h (Puerto de entrada y salida).

#BIT giro_d = 0x06.3

// Asignamos "giro_d" a la patilla RB3 del Microcontrolador PIC 16f876a.

// ************************************************** Declaracin de funciones ***************************************************


void Inicio_PWM(void);
void Refresco_PWM(void);

// Inico seal PW
// Refresco seal PWM.

// ************************ Funcin principal o programa principal **********************************


void main()
{
// ************************** Configuracin de los Puertos del PIC y reseteos el dispositivo *******************
Inicio_PWM();
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

// ****************************************************** Inicio ************************************************************


while (1)
{

// Ejecuta indefinidamente lo que est entre corchetes.


giro_d=0;
Refresco_PWM();

// Motor Derecho hacia adelante.

giro_d=1;
Refresco_PWM();

// Motor Derecho hacia atrs.

}
}
// **************************************************** Funcion Inicio_PWM *******************************************************
void Inicio_PWM(void)
{
int16 i=0;
setup_timer_2(T2_DIV_BY_16,249,1);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. Si el Periodo = 16mS ---->
// T = 16000uS
// T = [PR2+1] x Tcm x Postscaler x Prescaler
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1.
// 16000uS = [PR2+1] x 1 x 16
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[16000uS/(4uS x 16 x 1)]-1 = 249

(en C 249)

setup_ccp1(CCP_PWM);

// CCP2 en modo PWM (Salida por RC2)


//(Motor Derecho)MOT2

TRISC = 0B10010001;

// Defines Puerto C como SALIDA de datos a excepcin


// de RC7, RC4 Y RCO.

set_pwm1_duty(i);

// Refresca el nivel alto de la seal PWM. Salida por RC2.


// (Motor Derecho)

Microcontroladores

IES Joan Mir

Pgina 63

Aprendizaje de la Electrnica a travs de la Robtica - ARCE //************************************************** Funcion Refresco_PWM ******************************************************


void Refresco_PWM(void)
{
int16 i=0;
for(i=0;i<=1000;i=i+100)
{
set_pwm1_duty(i);
delay_ms(1000);
}

// Refresca el nivel alto de la seal PWM. Salida por RC2. (Motor Derecho)
// Retarodo de 1 segundo.

5.3.4.1.4.- Prueba_Control_Velocidad_Motor_Izquierdo_Derecho_f.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Prueba_Control_Velocidad_Motor_Izquierdo_Derecho_f.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de velocidad y sentido de giro de los motores de corriente
//
//
continua. MOT1 y 2
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directiva de Preprocesado **************************************
// (Controlan la conversin del programa a cdigo mquina por parte del compilador)
#include <16F876A.h>

// Incluye el fichero 16F876A al programa tiene que estar en la misma


// carpeta del programa define funciones, patillas y registros.

#fuses XT,NOWDT

// Define la palabra de configuracin del microcontrolador PIC


// Trabaja con un reloj tipo XT y no utiliza perro guardin Wathdog
// Define la frecuencia del reloj de 4 MHz

#use delay( clock = 1000000 )


#BYTE TRISC = 0x87
#BYTE portC = 0x07
#BYTE TRISB = 0x86
#BYTE portB = 0x06

// Asignamos TRISC a la direccin 87h


// (Registro de configuracin del Puerto C).
// Asignamos portC a la direccin 07h (Puerto de entrada y salida).
// Asignamos TRISB a la direccin 86h
// (Registro de configuracin del Puerto A).
// Asignamos portB a la direccin 06h (Puerto de entrada y salida).

#BIT giro_d = 0x06.3

// Asignamos "giro_d" a la patilla 3 del Puerto B del


// Microcontrolador PIC 16f876a.

#BIT giro_i = 0x06.2

// Asignamos "giro_i" a la patilla 2 del Puerto B del


// Microcontrolador PIC 16f876a.

// ******************************************** Declaracin de funciones *********************************************************


void Inicio_PWM(void);
void Refresco_PWM(void);

// Inico seal PW
// Refresco seal PWM.

// *************************** Funcin principal o programa principal ******************************


void main()
{
// ********************** Configuracin de los Puertos del PIC y reseteos el dispositivo ***********************
Inicio_PWM();
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

// ****************************************************** Inicio ************************************************************


while (1)
{

// Ejecuta indefinidamente lo que est entre corchetes.


giro_d=0;
giro_i=0;
Refresco_PWM();

Microcontroladores

// Motor Derecho hacia adelante.


// Motor Izquierdo hacia adelante.

IES Joan Mir

Pgina 64

Aprendizaje de la Electrnica a travs de la Robtica - ARCE giro_d=1;


giro_i=1;
Refresco_PWM();

// Motor Derecho hacia atrs.


// Motor Izquierdo hacia atrs.

}
}
// ************************************************ Funcion Inicio_PWM ***********************************************************
void Inicio_PWM(void)
{
int16 i=0;
setup_timer_2(T2_DIV_BY_16,249,1);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. Si el Periodo = 16mS ---->
// T = 16000uS
// T = [PR2+1] x Tcm x Postscaler x Prescaler
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1.
// 16000uS = [PR2+1] x 1 x 16
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[16000uS/(4uS x 16 x 1)]-1 = 249

setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);

(en C 249)

// CCP2 en modo PWM (Salida por RC2)


// (Motor Derecho)MOT2
// CCP2 en modo PWM (Salida por RC1)
// (Motor Derecho)MOT1

TRISC = 0B10010001;

// Defines Puerto C como SALIDA de datos a


// excepcin de RC7, RC4 Y RCO.

set_pwm1_duty(i);

// Refresca el nivel alto de la seal PWM. Salida por RC2.


// (Motor Derecho)
// Refresca el nivel alto de la seal PWM. Salida por RC1.
// (Motor Izquierdo)

set_pwm2_duty(i);
}

// ************************************************* Funcion Refresco_PWM ******************************************************


void Refresco_PWM(void)
{
int16 i=0;
for(i=0;i<=1000;i=i+100)
{
set_pwm2_duty(i);
set_pwm1_duty(i);
delay_ms(1000);

// Refresca el nivel alto de la seal PWM.Salida por RC1. (Motor Izquierdo)


// Refresca el nivel alto de la seal PWM.Salida por RC2. (Motor Derecho)
// Retardo de 1 segundo.

}
}

Microcontroladores

IES Joan Mir

Pgina 65

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.4.2.- Servomotores de Posicin.


Un Servomotor de posicin, da una posicin angular proporcional a una variable
elctrica. Si se intenta variar la posicin angular (Quitando o poniendo Inercia en su eje) este
debe mantener su posicin angular.
Los servos de posicin ms utilizados en microcrobtica son los controlados por PWM.
(Hitec HS-300, Futaba S3003, etc.)
Estn constituidos por un pequeo motor de corriente continua, unas ruedas dentadas
que trabajan como reductoras, (dando una potencia considerable) y una pequea tarjeta de
control.
Debido a la reductora mecnica formada por las ruedas mecnicas se pueden
conseguir pares de fuerzas de 3 Kg/cm o superiores.
La seal de PWM que ataca a los servos est comprendida entre 4 y 8V. El consumo puede
ser considerable hasta que el servo alcanza su posicin (hasta 500 mA).
Funcionamiento:

Utilizaremos el entrenador Simulacin_Servomotores_Posicin.DSN, contenido en la


carpeta de PWM\ Control de un Servo de Posicin.

Microcontroladores

IES Joan Mir

Pgina 66

Aprendizaje de la Electrnica a travs de la Robtica - ARCE -

5.3.4.2.1.- Control_2_Servo_Posicin.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Control_2_Servo_Posicin.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de 2 Servos de Posicin
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#device adc=8

// Conversor Analgico Digital de 10 bit el PIC 16F876A puede trabajar con


// 8 o 10 bit de resolucion.

#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <Servo_Futaba_10bit.c>

// Incluimos el driver que contiene las funciones de control de los


// Servos de Futaba.

// ******************************** Funcin principal o programa principal **************************


void main()
{
int16 TH;
Inicializacion_Futaba_RC1();
Inicializacion_Futaba_RC2();

// Inicializacin del Servo en RC1


// Inicializacin del Servo en RC2

// While (1);

// Vemos posicin central.

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(0);

// Fuente de reloj RC interno.


// Seleccionamos el Puerto A como entradas Analgicas.
// Mirar ADCON1.

Microcontroladores

IES Joan Mir

Pgina 67

Aprendizaje de la Electrnica a travs de la Robtica - ARCE while (true)


{
set_adc_channel(0);
delay_us(5);

// Bucle infinito.

TH = read_adc();

// Habilitacin canal 0 "AN0"


// Retardo de 20uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 0 "AN0"

Futaba_RC1(TH);

// Posicionar el Servo de la patilla RC1.

set_adc_channel(3);
delay_us(5);
TH = read_adc();

// Habilitacin canal 3 "AN3"


// Retardo de 20uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 1 "AN3"

Futaba_RC2(TH);

// Posicionar el Servo de la patilla RC2.

}
}

5.3.4.2.2.- Servo_ Futaba_10bit.c


/* *********** Driver de control de un Servomotor de Posicin de Futaba con PWM **********
/* ************************************ utilizando 10 bit de resolucin ********************************
; Con TH=0 corresponde a -90 grados de Posicin del servo
; Con TH=57 corresponde a 0 grados de Posicin del servo
; Con TH=113 corresponde a 90 grados de Posicin del servo

;El microcontrolador PIC 16f876a tiene un hardware integrado que puede generar 2 seales PWM
;por las patillas RC2 y RC1.
;El periodo para ambas seales se fija con la siguiente frmula
;T =[(PR2+1)*4*Tosc]*(TMR2_Valor_preescalar)
;El nivel alto T1H se controla con 10 bit ( Los 8 bit ms significativo con el registro CCPR1L y
;los dos bit menos significativos con CCP1X y CCP1Y que estn en el registro CCP1CON)
;Esta seal sale por la patilla RC2.
;El nivel alto T2H se controla con 10 bit ( Los 8 bit ms significativo con el registro CCPR2L y
;los dos bit menos significativos con CCP2X y CCP2Y que estn en el registro CCP2CON)
;Esta seal sale por la patilla RC1.
;Para refrescar el nivel alto T1H que haber transcurrido un tiempo superior a un periodo "T".
;El Servomotor de Futaba se controla con una seal cuadrada de periodo "T1".
;La posicin del Servomotor lo determina el nivel alto de la senal "T1H"
;El Servomotor de Futaba necesita un periodo "T1" entre 10ms y 30 ms.
;Cargando los registros de forma correcta sale T1 =[(249+1)*4*1uS](16)=16 mS (Cristal de cuarzo 1 MHz)
;Tiene un control de Posicin de -90 Grados < P (Angular)< +90 Grados controlado con T1H.
;Para -90 Grados corresponde un nivel alto T1H = 0,6 ms
;Para 0 Grados corresponde un nivel alto T1H = 1,2 ms
;Para +90 Grados corresponde un nivel alto T1H = 2,4 ms
*/
// ****************************************************** Declaracin de funciones ***********************************************
void Inicializacion_Futaba_RC1();
void Inicializacion_Futaba_RC2();
void Futaba_RC1(int16 TH);
void Futaba_RC2(int16 TH);

// Inicializar PWM por RC1


// Inicializar PWM por RC2
// Generar PWM por RC1
// Generar PWM por RC2

//*************************************************** Igualdades ******************************************************************


#define THmin 37
#define THmax 150

Microcontroladores

// THmin=37 equivale a 600uS a nivel alto a -90


// THmax=150 equivale a 2400uS a nivel alto a +90

IES Joan Mir

Pgina 68

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #define THmed 94

// THmed=94 equivale a 1500uS a nivel alto a 0

// ************************************************** Funcin Inicializacion_Futaba_RC1() **************************************


void Inicializacion_Futaba_RC1()
{
int16 TH;
setup_timer_2(T2_DIV_BY_16,249,1);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. Si el Periodo = 16mS ---->
// T = 16000uS
// T = [PR2+1] x Tcm x Postscaler
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1.
// 16000uS = [PR2+1] x 1 x 16
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[16000uS/(4uS x 16 x 1)]-1 = 249

setup_ccp2(CCP_PWM);

// CCP2 en modo PWM (Salida por RC1)

TH = THmed;

// Cargar TH con valor medio

set_pwm2_duty(TH);
delay_ms(5);

// Refrescamos el Tiempo alto TH de la seal.

(en C 249)

}
// ************************************************* Funcin Inicializacion_Futaba_RC2() **************************************
void Inicializacion_Futaba_RC2()
{
int16 TH;
setup_timer_2(T2_DIV_BY_16,249,1);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. Si el Periodo = 16mS ---->
// T = 16000uS
// T = [PR2+1] x Tcm x Postscaler
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1.
// 16000uS = [PR2+1] x 1 x 16
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[16000uS/(4uS x 16 x 1)]-1 = 249

setup_ccp1(CCP_PWM);

// CCP1 en modo PWM (Salida por RC2)

TH = THmed;

// Cargar TH con valor medio

set_pwm1_duty(TH);
delay_ms(5);

// Refrescamos el Tiempo alto TH de la seal.

(en C 249)

}
// *********************************************** Funcin Futaba_RC1(int16 TH) ************************************************
void Futaba_RC1(int16 TH)
{
TH = TH+THmin;

// Cargar TH con valor mnimo

if(TH>THmin && TH<THmax) set_pwm2_duty(TH);

// Si THmin < TH < THmax


// Refrescamos el Tiempo alto TH de la seal.
// Si TH <= THmin

if(TH<=THmin)
{
TH=THmin+1;

Microcontroladores

// Cargar TH con valor mnimo

IES Joan Mir

Pgina 69

Aprendizaje de la Electrnica a travs de la Robtica - ARCE set_pwm2_duty(TH);

// Refrescamos el Tiempo alto TH de la seal.

}
if(TH>=THmax)
{
TH=THmax-1;
set_pwm2_duty(TH);
}

delay_ms(5);

// Si TH >= THmax
// Cargar TH con valor mximo
// Refrescamos el Tiempo alto TH de la seal.

// Tiene que transcurrir un tiempo mayor que el periodo de la seal T =16000 us,
// para refrescar el nivel alto de la seal.
// Si utilizamos la funcin delay_ms(5)el tiempos de retardo equivale al
// valor puesto multiplicado por 4 (Estamos utilizando un cristal de 1 MHz).
// es decir 20ms.

}
// ************************************************ Funcin Futaba_RC2(int16 TH) ***********************************************
void Futaba_RC2(int16 TH)
{
TH = TH+THmin;

// Cargar TH con valor mnimo

if(TH>THmin && TH<THmax) set_pwm1_duty(TH);

// Si THmin < TH < THmax


// Refrescamos el Tiempo alto TH de la seal.
// Si TH <= THmin

if(TH<=THmin)
{
TH=THmin+1;
set_pwm1_duty(TH);
}
if(TH>=THmax)
{
TH=THmax-1;
set_pwm1_duty(TH);
}

delay_ms(5);

// Cargar TH con valor mnimo


// Refrescamos el Tiempo alto TH de la seal.

// Si TH >= THmax
// Cargar TH con valor mximo
// Refrescamos el Tiempo alto TH de la seal.

// Tiene que transcurrir un tiempo mayor que el periodo de la seal T =16000 us,
// para refrescar el nivel alto de la seal.
// Si utilizamos la funcin delay_ms(5)el tiempos de retardo equivale al
// valor puesto multiplicado por 4 (Estamos utilizando un cristal de 1 MHz).
// es decir 20ms.

5.3.5.- Interrupciones Externas.


Las Interrupciones tienen la misin de poder detener un programa principal y ejecutar
otro programa (Rutina de Interrupcin) y volver al programa principal.
Los C tienen hardware
especifico que se puede
habilitar en modo
interrupcin.
El PIC 16F877a tiene 14
modos diferentes de
interrupcin:
En CCS existen diferentes
funciones que permiten
trabajar de forma sencilla las
interrupciones.
Las interrupciones
externas como su nombre indica son patillas que permiten interrumpir programas principales.

Microcontroladores

IES Joan Mir

Pgina 70

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.5.1.- Interrupcin por RB0/INT.


Utilizaremos los entrenadores Simulacin_Perifricos.DSN y Simulador Potencia y
Perifricos.DSN, contenidos en la carpeta de Interrupciones Externas\ Interrupcin_RB0.

5.3.5.1.1.- Interrupcin_INT_RB0.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interrupcin_INT_RB0.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Manejo de Interrupcin externa INT
//
//
Un programa principal, simula las luces del Coche Fantstico.
//
//
Cuando pulso la patilla RB0 interrumpimos el programa principal y
//
//
ejecutamos un programa (rutina de interrupcin)
//
//
La rutina de interrupcin, activa un buzzer tres veces con una cadencia
//
//
de de 0,5 segundos
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT buzzer =0x06.2

// Patilla RB2 buzzer.

int8 luces= 0B00001000;

Microcontroladores

IES Joan Mir

Pgina 71

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* ******************************************** Declaracin de funciones ******************************************************* */


void Coche_Fantastico (void);
void Pitido (void);

// Coche fantstico.
// Pitido.

/* ****************************** Funcin principal o programa principal ************************* */


void main()
{
TRISB = 0B00000001;

// Defines Puerto B como SALIDA de datos a excepcin de RB0.

portB=luces;
delay_ms(100);

// retraso.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

enable_interrupts(int_ext);
ext_int_edge(L_TO_H);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de subida.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while (1)

// Bucle infinito de espera

{
Coche_Fantastico();
}
}
/* ********************************** Atencin a la interrupcin por cambio en RB0 **************************************** */
#INT_EXT
void Pitido()
{
int8 i;
for(i=0; i<3; i++)
{
buzzer=1;
delay_ms(500);
buzzer=0;
delay_ms(500);
}
}
/* ************************************************ Coche_Fantastico ************************************************************ */
void Coche_Fantastico (Void)
{
static int8 luces=0B00001000;
int8 n;
for(n=0;n<4;n++)
{
luces<<=1;
portB=luces;
delay_ms(500);
}
for(n=4;n>0;n--)
{
luces>>=1;
portB=luces;
delay_ms(500);
}

// Movemos un bit a la izquierda


// retraso.

//Movemos un bit a la derecha.


//Retraso.

Microcontroladores

IES Joan Mir

Pgina 72

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.5.1.2.- Interrupcin_INT_RB0a.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interrupciones_RB0a.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Manejo de Interrupcin externa INT
//
//
Un programa principal, simula las luces del Coche Fantstico.
//
//
Cuando pulso la patilla RB0 interrumpimos el programa principal
//
//
y ejecutamos un programa (rutina de interrupcin)
//
//
La rutina de interrupcin, genera un sonido bitonal en un altavoz tres veces //
//
con una cadencia de de 0,5 segundos.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#BYTE TRISB = 0x86
#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT altavoz =0x06.1

// Patilla RB1 altavoz.

int8 luces=0B00001000;
/* ******************************************* Declaracin de funciones ******************************************************** */
void Coche_Fantastico (void);
void Tono (void);

// Coche fantstico.
// pitidos.

/* ********************************** Funcin principal o programa principal ************************************************ */


void main()
{
TRISB = 0B00000001;

// Defines Puerto B como SALIDA de datos a excepcin de RB0.

portB = luces;
delay_ms(100);

// inicializamos el puerto B.
// Retraso.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

enable_interrupts(int_ext);
ext_int_edge(L_TO_H);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de subida.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while (1)
{

// Bucle infinito de espera


Coche_fantastico();

}
}
/* ***************************** Atencin a la interrupcin por cambio en RB0 ********************************************* */
#INT_EXT
void Tono()
{
int16 i;
// for(i=0;i<5000;i++)
for(i=0;i<500;i++)
{
altavoz=1;
delay_us(100);
altavoz=0;
delay_us(100);
}

Microcontroladores

// Real
// Simulado

IES Joan Mir

Pgina 73

Aprendizaje de la Electrnica a travs de la Robtica - ARCE //for(i=0;i<1000;i++)


for(i=0;i<100;i++)
{
altavoz=1;
delay_us(500);
altavoz=0;
delay_us(500);
}

// Real
// Simulado

}
/* ************************************************ Coche_Fantastico ************************************************************ */
void Coche_Fantastico (void)
{
static int8 luces=0B00001000;
int8 n=0;
for (n=0;n<4;n++)
{
luces<<=1;
portB=luces;
delay_ms(100);
}
for (n=4;n>0;n--)
{
luces>>=1;
portB=luces;
delay_ms(100);
}

// Movemos un bit a la izquierda


// Retraso.

// Movemos un bit a la derecha.


// Retraso.

5.3.5.1.3.- Interrupcin_INT_RB0b.c

Microcontroladores

IES Joan Mir

Pgina 74

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// Programa.....: Interrupcin_INT_RB0b.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Manejo de Interrupcin externa INT
//
//
Un programa principal, pone dos mensajes en el LCD con una
//
//
cadencia de 1 Segundo. Cuando pulso la patilla RB0, interrumpimos el
//
//
programa principal y ejecutamos un programa (rutina de interrupcin)
//
//
La rutina de interrupcin, generar nmeros "0,1,2,3" en el DISPLAY_7SEG //
//
con una cadencia de 0,5 segundos
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

#define Numeros_Tabla 3

// Nmeros de la Tabla.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

byte CONST DISPLAY[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; // Tabla de conversin de


BCD a 7 Seg.
/* *********************************************** Declaracin de funciones **************************************************** */
void Mensajes (void);
void Display_7s (void);

// Funcin Mensaje.
// Funcin Display_7s.

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
TRISB = 0B00000001;

// Defines Puerto B como SALIDA de datos a excepcin de RB0.

lcd_init();

// Inicializamos el LCD.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

enable_interrupts(int_ext);
ext_int_edge(L_TO_H);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de subida.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while (1)
{

// Bucle infinito de espera


Mensajes();

}
}
/* ********************************* Atencin a la interrupcin por cambio en RB0 ***************************************** */
#INT_EXT
void Display_7s()
{
int8 n=0 ;

// Declaramos la variable n con 8 bit y la inicializamos con 0.

for (n=0; n<=Numeros_Tabla; n++)

// Se ejecuta un bucle desde n=0 hasta n<Numeros_Tabla en orden


//ASCENDENTE de uno en uno

{
portB = DISPLAY[n];
delay_ms(500);
}
portB = 0B00000000;

// Mostramos en el Puerto B el valor que tiene la tabla DISPLAY[n]


// Retardo de 0,5 Segundo.
// Apagar DISPLAY_7SEG.

Microcontroladores

IES Joan Mir

Pgina 75

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* ************************************************ Coche_Fantastico ************************************************************ */


void Mensajes (Void)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"IES Joan Miro");
delay_ms(1000);
lcd_gotoxy(1,1);
printf(lcd_putc,"CFGS DPE
delay_ms(1000);

");

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .


// Escribimos el mensaje "IES Joan Miro".

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .


// Escribimos el mensaje "CFGS DPE ".

5.3.5.2.- Interrupcin por cambio de nivel de RB4_5_6_7.

5.3.5.2.1.- Interrupcin_INT_RB4567.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interrupcin_INT_RB4567.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Manejo de las Interrupciones de INT y por cambio de nivel
//
//
de RB4, RB5, RB6, RB7.
//
//
Un programa principal, ejecuta un programa que mueve un Motor PAP.
//
//
Cuando plso la patilla RB0 interrumpimos el programa principal y
//
//
activamos un Motor de CC y si volvemos a pulsar lo desactivamos.
//
//
Cuando abrimos o cerramos la patilla RB4,RB5,RB6 RB7,
//
//
interrumpimos el programa principal y activamos desactivamos un LED
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Microcontroladores

IES Joan Mir

Pgina 76

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // *********************************** Directivas de Preprocesado ************************************


#include <16F876A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 4000000)
#BYTE TRISC = 0x87
#BYTE portC = 0x07

// TRISC en 87h.
// PORTC en 07h.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT rc0 = 0x07.0


#BIT rc1 = 0x07.1
#BIT rc2 = 0x07.2
#BIT rc3 = 0x07.3
#BIT rc4 = 0x07.4
#BIT rc5 = 0x07.5

// RC0 en 0x07 patilla 0.


// RC1 en 0x07 patilla 1.
// RC2 en 0x07 patilla 2.
// RC3 en 0x07 patilla 3.
// RC4 en 0x07 patilla 4.
// RC5 en 0x07 patilla 5.

#BIT RBIF = 0x0B.0

// RBIF en 0x0B patilla 0.

/* *************************************** Declaracin de funciones ************************************************************ */


void Activar_Motor (void);

// Activa el Motor.

void Led (void);

// Encender Led.

void Motor_PAP (Void);

// Motor_PAP.

/* ************************* Funcin principal o programa principal ****************************** */


void main()
{
int n;

// Necesario para borrar el flag en el Proteus

TRISB = 0B11111111;
TRISC = 0B00000000;

// Defines Puerto B como ENTRADA de datos.


// Defines Puerto C como SALIDA de datos.

portC = 0B00000000;

// Reseteamos el Puerto C.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

n = portB;
RBIF = 0;

// Necesario para borrar el flag en el Proteus


// Necesario para borrar el flag en el Proteus

enable_interrupts(int_rb);

// Habilitamos la interrupcin por cambio de nivel de RB4, RB5, RB6, RB7.

enable_interrupts(int_ext);
ext_int_edge(L_TO_H);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de subida.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while (1)
{

// Bucle infinito de espera


Motor_PAP();

}
}
/* ********************************* Atencin a la interrupcin por cambio en RB0 ***************************************** */
#INT_EXT
void Activar_Motor()
{
rc5 = ~rc5;
}

Microcontroladores

// Lee rc5 lo complementa a 1 y lo carga en rc5.

IES Joan Mir

Pgina 77

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* ********************** Atencin a la interrupcin por cambio en RB4,RB5,RB6 y RB7. ******************************** */
#INT_RB
void Led()
{
int n;

// Necesario en el Proteus, para poder borrar el flag RBIF.

rc4 = ~rc4;

// Lee rc4 lo complementa a 1 y lo carga en rc4.

n = portB;

// Necesario en el Proteus, para poder borrar el flag RBIF.

}
/* *********************************************** Motor Paso a Paso ************************************************************ */
void Motor_PAP (Void)
{
rc3 = 0;
rc2 = 0;
rc1 = 0;
rc0 = 1;

// Posicionamos el Motor PAP en la 1 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 0;
rc1 = 1;
rc0 = 1;

// Posicionamos el Motor PAP en la 2 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 0;
rc1 = 1;
rc0 = 0;

// Posicionamos el Motor PAP en la 3 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 1;
rc1 = 1;
rc0 = 0;

// Posicionamos el Motor PAP en la 4 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 1;
rc1 = 0;
rc0 = 0;

// Posicionamos el Motor PAP en la 5 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 1;
rc2 = 1;
rc1 = 0;
rc0 = 0;

// Posicionamos el Motor PAP en la 6 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 1;
rc2 = 0;
rc1 = 0;
rc0 = 0;

// Posicionamos el Motor PAP en la 7 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 1;
rc2 = 0;
rc1 = 0;
rc0 = 1;

// Posicionamos el Motor PAP en la 8 Posicin.

delay_ms(500);

// Retardo de 500 ms

Microcontroladores

IES Joan Mir

Pgina 78

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.5.2.1.- Interrupcin_INT_RB4567a.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Interrupcin_INT_RB4567a.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Manejo de las Interrupciones de INT y por cambio de
//
//
nivel de RB4, RB5, RB6, RB7.
//
//
Un programa principal, ejecuta un programa que mueve un Motor PAP.
//
//
Cuando pulso la patilla RB0 interrumpimos el programa principal
//
//
y activamos y desactivamos un Motor de CC, 10 veces con una
//
//
cadencia de 1 Segundo.
//
//
Cuando abrimos o cerramos la patilla RB4, RB5, RB6 RB7,
//
//
interrumpimos el programa principal
//
//
y activamos desactivamos un LED, 5 veces con una cadencia de
//
//
0,5 Segundo.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F876A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 4000000)

#BYTE TRISC = 0x87


#BYTE portC = 0x07

// TRISC en 87h.
// PORTC en 07h.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT rc0 = 0x07.0


#BIT rc1 = 0x07.1
#BIT rc2 = 0x07.2
#BIT rc3 = 0x07.3
#BIT rc4 = 0x07.4
#BIT rc5 = 0x07.5

// RC0 en 0x07 patilla 0.


// RC1 en 0x07 patilla 1.
// RC2 en 0x07 patilla 2.
// RC3 en 0x07 patilla 3.
// RC4 en 0x07 patilla 4.
// RC5 en 0x07 patilla 5.

#BIT RBIF = 0x0B.0

// RBIF en 0x0B patilla 0. Necesario para Proteus

/* ************************************* Declaracin de funciones ************************************************************** */


void Activar_Motor (void);
void Led (void);
void Motor_PAP (Void);

// Activa el Motor.
// Encender Led.
// Motor_PAP.

/* ********************** Funcin principal o programa principal ********************************* */


void main()
{
int n;

// Necesario para borrar el flag en el Proteus

TRISB = 0B11111111;
TRISC = 0B00000000;

// Defines Puerto B como ENTRADA de datos.


// Defines Puerto C como SALIDA de datos.

portC = 0B00000000;

// Reseteamos el Puerto C.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

n = portB;
RBIF = 0;

// Necesario para borrar el flag en el Proteus


// Necesario para borrar el flag en el Proteus

enable_interrupts(int_rb);

// Habilitamos la interrupcin por cambio de nivel


// de RB4, RB5, RB6, RB7.

enable_interrupts(int_ext);
ext_int_edge(L_TO_H);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de subida.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

Microcontroladores

IES Joan Mir

Pgina 79

Aprendizaje de la Electrnica a travs de la Robtica - ARCE while (TRUE)

// Bucle infinito de espera

{
Motor_PAP();
}
}
/* ******************************* Atencin a la interrupcin por cambio en RB0 ******************************************* */
#INT_EXT
void Activar_Motor(void)
{
int i;
for(i=0;i<10;i++)
{
rc5 = ~rc5;
delay_ms(1000);
}

// Lee rc5 lo complementa a 1 y lo carga en rc5.

}
/* ******************** Atencin a la interrupcin por cambio en RB4, RB5, RB6 y RB7. ******************************** */
#INT_RB
void Led(void)
{
int i;

// Necesario en el Proteus, para poder borrar el flag RBIF.

for(i=0;i<5;i++)
{
rc4 = ~rc4;
delay_ms(500);
}

// Lee rc4 lo complementa a 1 y lo carga en rc4.

i = portB;

// Necesario en el Proteus, para poder borrar el flag RBIF.

}
/* ********************************************** Motor Paso a Paso ************************************************************* */
void Motor_PAP (Void)
{
rc3 = 0;
rc2 = 0;
rc1 = 0;
rc0 = 1;

// Posicionamos el Motor PAP en la 1 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 0;
rc1 = 1;
rc0 = 1;

// Posicionamos el Motor PAP en la 2 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 0;
rc1 = 1;
rc0 = 0;

// Posicionamos el Motor PAP en la 3 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 1;
rc1 = 1;
rc0 = 0;

// Posicionamos el Motor PAP en la 4 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 0;
rc2 = 1;
rc1 = 0;

// Posicionamos el Motor PAP en la 5 Posicin.

Microcontroladores

IES Joan Mir

Pgina 80

Aprendizaje de la Electrnica a travs de la Robtica - ARCE rc0 = 0;


delay_ms(500);

// Retardo de 500 ms

rc3 = 1;
rc2 = 1;
rc1 = 0;
rc0 = 0;

// Posicionamos el Motor PAP en la 6 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 1;
rc2 = 0;
rc1 = 0;
rc0 = 0;

// Posicionamos el Motor PAP en la 7 Posicin.

delay_ms(500);

// Retardo de 500 ms

rc3 = 1;
rc2 = 0;
rc1 = 0;
rc0 = 1;

// Posicionamos el Motor PAP en la 8 Posicin.

delay_ms(500);

// Retardo de 500 ms

5.3.6.- Temporizadores y Contadores. (Timer 0,1 y 2).


Los timer o temporizadores es un hardware especfico contenido en los
microcontroladores que tienen la misin de contar pulsos del exterior o temporizar (Si
trabajamos con los timer en modo interrupcin podemos crear sistemas multitarea). El C
PIC16F877A tiene 3 timer. Utilizaremos las funciones del compilador CCS para programarlos.

5.3.6.1.- Timer 0.
Se trata de un
temporizador/contador de 8 bits.
La fuente de eventos puede ser
interna (Temporizador) o externa
(Contador de pulsos, patilla RA4)

Si trabaja como contador de


pulsos del exterior, se pude
seleccionar que la cuenta sea por
la deteccin de un flanco se
subida (T0SE=0) o de bajada
(T0SE=1) en RA4.
Dispone de una pre-escala
programable de 8 bits que se
selecciona va software
Cuando TMR0 supera el valor
de 255 el Timer se ha desbordado y el flag T0IF se pone a 1
Se puede trabajar en modo POLLING (Preguntando si T0IF=1 constantemente por un valor del registro
o interrupcin si T0IF=1(Para ello es necesario que estas estn activadasT0IE=1 y GIE=1).

TMR0)

Est asociado al temporizador Watchdog si PSA=1.

Microcontroladores

IES Joan Mir

Pgina 81

Aprendizaje de la Electrnica a travs de la Robtica - ARCE El tiempo o pulsos contados estn en funcin de esta frmula:

T = Tcm x Prescaler x (256 - INICIO_CUENTA)

Donde Tcm = 4/Fosc donde Fosc es el reloj que pongamos al C.

Prescaler puede valer (1,2,4,8,16,32,64,128,256)

INICIO_CUENTA es el valor de carga inicial en el registro TMR0 (0 a 255)

El valor mximo de T es cuando Prescaler= 256 e INICIO_CUENTA= 0


Ejemplo: Si el reloj es de Fosc=4Mhz Tcm = 4/Fosc= 4/4Mhz= 1S.
Tmax= Tcm x Preescaler x (256 - INICIO_CUENTA) = 1S. x 256 x (256-0)= 65536 S.

Utilizaremos los entrenadores Simulacin Proteus.DSN y


Simulacin_Perifricos_y_Servos.DSN, contenidos en la carpeta de Timer\ Timer 0.

5.3.6.1.1.- Timer0_Contador.c

Microcontroladores

IES Joan Mir

Pgina 82

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// Programa.....: Timer0_Contador.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre_2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Manejo del Timer 0 como contador de pulsos del exterior
//
//
Cada 4 pulso producidos en la patilla RA4/TOCKI incrementamos una
//
//
variable y la representamos en el LCD. Cuando la variable supere 5 se
//
//
pondr a 0
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#include <flex_lcd.c>
#BYTE TRISB = 0x87
#BYTE portB = 0x07

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.
// TRISB en 86h.
// PORTB en 06h.

#define numero 5

/* ***************************** Funcin principal o programa principal ************************** */


void main()
{
int8 contador=0;
int8 contador_anterior=0;
lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(1,1);
printf(lcd_putc,"%3u",contador);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .


// Escribimos 3 dgitos de la variable "contador" en formato
// entero y sin signo.

setup_timer_0(RTCC_DIV_4|RTCC_EXT_L_TO_H);

// Programamos el Timer 0 en modo contador de


// pulsos con prescaler de 4

set_timer0(0);

// Inicializamos el contador timer 0 con inicio de


// cuenta.

while (TRUE)
{
do
{

// Bucle infinito de espera

contador = get_timer0();

// Leemos el Contador.

if(contador!=contador_anterior)
// Escribir en el el LCD si contador ha variado.
{
contador_anterior=contador;
// Preguntamos si ha llegado el final de
// la cuenta.
lcd_gotoxy(1,1);
printf(lcd_putc,"%3u",contador);

// Posicionamos el Cursor del LCD en la


// posicin 1 lnea 1 .
// Escribimos 3 dgitos de la variable
// "contador" en formato entero y sin
// signo.

}
}
while(contador<=numero);
set_timer0(0);

// Inicializamos el contador timer 0 con


// inicio de cuenta.

}
}

Microcontroladores

IES Joan Mir

Pgina 83

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.6.1.2.- Timer0_temporizador_multitarea_1.c

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Timer0_temporizador_multitarea_1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Un programa principal activa un servo en 2 posiciones y cada 0.20ms
//
//
se interrumpe el programa principal y generamos una seal cuadrada
//
//
de 0,2 mS por la patilla RB0
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)

#include <Servo_Futaba_10bit.c>

// Incluimos el driver que contiene las funciones de control de los Servos


// de Futaba.

#BIT TB0 = 0x86.0


#BIT RB0 = 0x06.0

// TB0 en la direccn 86.Oh.


// RB0 en la direccin 06.0h.

int8 INICIO_CUENTA=61;

// Si el periodo de la seal T=200000 uS Cargamos inicio de cuenta con


// T/2=100000 uS
// T = 100000 uS.
// T = Tcm x Preescaler x (256 - INICIO_CUENTA)
// Despejando INICIO_CUENTA = 256 - [T/(Tcm x Prescaler)]
// Tcm es el tiempo de Ciclo Maquina. Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// INICIO_CUENTA = 256 - [100000uS/(4uS x 128)] = 61
// Esto es cierto si se trabaja en ensamblador. El tiempo de ejecucin en C es
// mayor.
// Utilizando herramientas de proteus o MPLAB sacamos que T = 61

Microcontroladores

IES Joan Mir

Pgina 84

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* *************************************** Declaracin de funciones ************************************************************ */


void Senal_Cuadrada (Void);

// Generar una seal cuadrada por RBO.

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int16 TH;
TB0 = 0;
RB0 = 0;

// Defines RB0 como SALIDA de datos.


// Apagamos el Led de RB0.

Inicializacion_Futaba_RC1();

// Inicializacin del Servo en RC1

//while(1);

setup_timer_0(RTCC_DIV_128|RTCC_INTERNAL);

// Programamos el Timer 0 en modo contador de


// pulsos con prescaler de 256

set_timer0(INICIO_CUENTA);

// Inicializamos el contador timer 0 con inicio de cuenta.

enable_interrupts(INT_TIMER0);

// Habilitamos la interrupcin por Timer 0.

enable_interrupts(global);

// Habilitamos la interrupcin global.

while (1)
{

// Bucle infinito de espera


TH = 0;
Futaba_RC1(TH);
delay_ms(500);

// Posicionar el Servo de la patilla RC1.


// Retardo de 0.5 seg.

TH = 56;
Futaba_RC1(TH);
delay_ms(500);

// Posicionar el Servo de la patilla RC1.


// Retardo de 0.5 seg.

}
}
/* ******************* Atencin a la interrupcin por desbordamiento del TIMER 0 ************************************** */
#INT_TIMER0
void Senal_Cuadrada (Void)
{
RB0 = ~RB0;

// Lee RB0 lo complementa a 1 y lo carga en RB0.


// Pulsar AltGr 4 y barra espaciadora para el smbolo "~"

set_timer0(INICIO_CUENTA);

// Inicializamos el Timer 0 para temporizar 0,25 segundos.

5.3.6.1.3.- Timer0_temporizador_multitarea_2.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Timer0_temporizador_multitarea_2.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Un programa principal activa un servo en 2 posiciones y cada 0.25ms
//
//
se interrumpe el programa principal y simula las luces del coche fantstico. //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Microcontroladores

IES Joan Mir

Pgina 85

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // *********************************** Directivas de Preprocesado ************************************


#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)

#include <Servo_Futaba_10bit.c>

// Incluimos el driver que contiene las funciones de control de los


// Servos de Futaba.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en la direccn 86h.


// PORTB en la direccin 06h.

int8 INICIO_CUENTA=12;

// Cargamos inicio de cuenta


// T = 250000 uS.
// T = Tcm x Preescaler x (256 - INICIO_CUENTA)
// Despejando INICIO_CUENTA = 256 - [T/(Tcm x Prescaler)]
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// INICIO_CUENTA = 256 - [250000uS/(4uS x 256)] = 11
// Esto es cierto si se trabaja en ensamblador. El tiempo de ejecucin
// en C es mayor.
// Utilizando herramientas de proteus o MPLAB sacamos que T = 12

/* ********************************************* Declaracin de funciones ****************************************************** */


void coche_fantastico (Void);

// Simulacin del coche fantastico.

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int16 TH;
TRISB = 0B00000000;
portB = 0b00000001;
delay_ms(245);

// Defines Puerto B como SALIDA de datos.


// inicializamos el puerto B.
// Retraso.

Inicializacion_Futaba_RC1();

// Inicializacin del Servo en RC1

//while(1);

setup_timer_0(RTCC_DIV_256|RTCC_INTERNAL);

// Programamos el Timer 0 en modo contador de


// pulsos con prescaler de 256

set_timer0(INICIO_CUENTA);

// Inicializamos el contador timer 0 con inicio de cuenta.

enable_interrupts(INT_TIMER0);

// Habilitamos la interrupcin por Timer 0.

enable_interrupts(global);

// Habilitamos la interrupcin global.

while (1)
{

// Bucle infinito de espera


TH = 0;
Futaba_RC1(TH);
delay_ms(500);

// Posicionar el Servo de la patilla RC1.


// Retardo de 0.5 seg.

TH = 56;
Futaba_RC1(TH);
delay_ms(500);

// Posicionar el Servo de la patilla RC1.


// Retardo de 0.5 seg.

}
}

Microcontroladores

IES Joan Mir

Pgina 86

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* **************** Atencin a la interrupcin por desbordamiento del TIMER 0 ***************************************** */
#INT_TIMER0
void coche_fantastico (Void)
{
#DEFINE DERECHA 0
#DEFINE IZQUIERDA 1
static int8 ir=derecha;
switch (ir)

// Preguntamos por la variable "ir" si es 0 ejecuta el case 0,


//si es 1 el case 1,

{
case 0:
portB<<=1;
if(portB==128) ir=IZQUIERDA;
break;

// Rotamos el portB hacia la izquierda

case 1:
portB>>=1;
if(portB==1) ir=DERECHA;
break;
}
set_timer0(INICIO_CUENTA);

// Rotamos el portB hacia la derecha

// Inicializamos el Timer 0 para temporizar 0,25 segundos.

5.3.6.2.- Timer 1.

Se trata de un temporizador/contador de 16 bits.


La fuente de eventos puede ser interna (Temporizador) o externa (Contador de pulsos, patilla
RC0)

Puede seleccionar una fuente de reloj interna (T1CON.TMR1CS = 0) o externa


(T1CON.TMR1CS = 1)

Dispone de una preescaler programable de (1,2,4,8) que se selecciona va software


Cuando TMR1 supera el valor de 65535 el Timer se ha desbordado y el flag TMR1IF se
pone a 1

Microcontroladores

IES Joan Mir

Pgina 87

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Se puede trabajar en modo POLLING (Preguntando si TMR1IF =1 constantemente por un valor del
o interrupcin si TMR1IF =1(Para ello es necesario que estas estn activadasTMR1IE=1 y

registro TMR1)
GIE=1).

El tiempo o pulsos contados estn en funcin de esta frmula:

T = Tcm x Prescaler x (65536 - INICIO_CUENTA)

Donde Tcm = 4/Fosc donde Fosc es el reloj que pongamos al C.

Prescaler puede valer (1,2,4,8)

INICIO_CUENTA es el valor de carga inicial en el registro TMR1 (0 a 65535)

El valor mximo de T es cuando Prescaler= 8 e INICIO_CUENTA= 0


Ejemplo: Si el reloj es de Fosc=4Mhz Tcm = 4/Fosc= 4/4Mhz= 1S.
Tmax= Tcm x Preescaler x (65535 - INICIO_CUENTA) = 1S. x 8 x (65535-0)= 524280 S.

Utilizaremos los entrenadores Simulacin Proteus.DSN y Simulacin_Potencia.DSN,


contenidos en la carpeta de Timer\ Timer 1.

5.3.6.2.1.- Timer1_Contador.c

Microcontroladores

IES Joan Mir

Pgina 88

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


// Programa.....: Timer1_Contador.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Contar pulsos de exterior (T1CK) y Mostrar en el LCD
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int16 contador;
int16 pulsos=20;
LCD_init();

// inicializamos LCD

//setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);

// Programamos el Timer 1 en modo contador de


// pulsos; ESTA ES REAL
//setup_timer_1(T1_EXTERNAL||T1_DIV_BY_2);
// ESTA ES SIMULADA

setup_timer_1(T1_EXTERNAL|T1_DIV_BY_2);

while (TRUE)
{
set_timer1(0);

// Bucle infinito de espera


// Inicializamos el contador timer 1 con 0.

Do
{
contador = get_timer1();
//delay_ms(200);

// Leemos el Contador.

lcd_gotoxy(1,1);

// Posicionamos el Cursor del LCD en la posicin


// 1 lnea 1 .
// Mostramos contador en el LCD.

printf(lcd_putc,"%2lu",contador);
}
While (contador<= pulsos);

// Preguntamos si ha llegado el final de la cuenta.

}
}

5.3.6.2.2.- Timer1_temporizador_multitarea.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Timer1_temporizador_multitarea.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Un programa principal realiza la simulacin del coche fantstico y se
//
//
interrumpe cada 100 mS realizando una conversin analgica/digital
//
//
por AN0 y muestra su valor en tensin en el LCD.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#device adc=10

// Conversor Analogico Digital de 10 bit el PIC 16F877A puede trabajar con


// 8 o 10 bit de resolucion.

#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#include <flex_lcd.c>

Microcontroladores

// Incluimos el driver LCD1.c que contiene las funciones de control del LCD.

IES Joan Mir

Pgina 89

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en la direccn 86h.


// PORTB en la direccin 06h.

int16 INICIO_CUENTA = 40536;

// Cargamos inicio de cuenta


// T = 100.000 uS.
// El semiperiodo viene definido por
// T = Tcm x Prescaler x (65536 - INICIO_CUENTA)
// Despejando INICIO_CUENTA = 65536 - [T/(Tcm x Prescaler)]
// Tcm es el tiempo de Ciclo Maquina. Tcm = 4/Fosc = 4/1.000.000 hz = 4uS.
// INICIO_CUENTA = 65536 - [100000uS/(4uS x 1)] = 40536
// Esto es cierto si se trabaja en ensamblador.
// El tiempo de ejcucion en C es mayor.
// Utilizando herramientas de proteus o MPLAB sacamos que T = 40536

/* ************************************************* Declaracin de funciones ************************************************** */


void Voltimetro (Void);

// Simulacin de un voltimetro de 0 a 5v.

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int8 n=0 ;

// Entero que usaremos como contador y salida de datos

//******************************** Inicializar los led *********************************************************************


TRISB = 0B00000000;
portB = 0b00000001;
delay_ms(50);

// Defines Puerto B como SALIDA de datos.


// inicializamos el puerto B.
// Retraso.

//******************************* Inicializar la conversin analgica/digital *****************************************


setup_adc(ADC_CLOCK_INTERNAL);

// Fuente de reloj RC interno.

setup_adc_ports(4);

// Seleccionamos el Puerto A como entradas Analgicas.


// Mirar ADCON1.

//******************************** Inicializar el LCD *********************************************************************


lcd_init();

// Inicializamos el LCD.

//*************************** Inicializamos el timer1 en modo interrupcin ***************************************


setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
set_timer1(INICIO_CUENTA);

// Programamos el Timer 1 en modo temporizador


// Con prescaler de 1
// Inicializamos el contador timer 1 con inicio de cuenta.

enable_interrupts(INT_TIMER1);

// Habilitamos la interrupcin del Timer 1

enable_interrupts(global);

// Habilitamos la Interrupcin General.

//************************************ Coche fantstico *****************************************************************


while (1)
{

// Bucle infinito de espera


for(n=0;n<7;n++)
{
portB<<=1;
delay_ms(200);
}
for(n=7;n>0;n--)
{
portB>>=1;
delay_ms(200);
}

// Movemos un bit a la izquierda


// Retraso.

// Movemos un bit a la derecha.


// Retraso.

}
}

Microcontroladores

IES Joan Mir

Pgina 90

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* **************************** Atencin a la interrupcin por desbordamiento del TIMER 1 ***************************** */
#INT_TIMER1
void Voltimetro (Void)
{
int16 q;
float p;
set_adc_channel(0);
delay_us(5);
q = read_adc();
p = 5.0 * q / 1024.0;

// Habilitacin canal 0 "AN0"


// Retardo de 20uS necesaria para respetar el Tiempo de
// Adquisicin Tad.
// Lectura canal 0 "AN0"
// Conversin a tensin del cdigo digital "q".

lcd_gotoxy(1,1);
printf(lcd_putc, "V1=%01.3fv", p);

// Situamos el Cursor en la posicin 1, lnea 1.


// Escribimos en el LCD "V1=" y 4 dgitos de "P"
// en formato truncado de 4 dgitos con 3 decimales y el
// caracter "V".

set_timer1(inicio_cuenta);

// Inicializamos el contador timer 1 con inicio de cuenta.

5.3.6.3.- Timer 2.
Se trata de un temporizador de 8
bits con pre-escala y post-escala.
Cuenta ciclos de instruccin
(Fosc=4). Se activa con
T2CON.TMR2ON = 1
Pre-escala seleccionable entre 1:1,
1:4 1:16 mediante
T2CON.T2CKPS1:T2CKPS0.
Dispone de un registro periodo PR2
El registro TMR2
se incrementa partiendo de cero hasta
alcanzar PR2.
(Configurable de 0 a 255).

La salida del temporizador TMR2 pasa por una post-escala programable: 1:1 ...1:16
(T2CON.TOUTPS3:TOUTPS0) antes de generar una interrupcin.
Genera interrupciones si:

INTCON.GIE = 1, habilitacin global.


INTCON.PEIE=1 y PIE1.TMR2IE = 1, habilitacin local.

Cuando el campo PIR1.TMR2IF = 1, indica que se alcanz el periodo. Hay que borrarlo
despus. (Cuando TMR2 se iguala con PR2, teniendo en cuenta el Prescaler y Postscaler)
El tiempo o pulsos contados estn en funcin de esta frmula:

T = Tcm x [Prescaler x (PR2+1) x Postscaler]

Donde Tcm = 4/Fosc donde Fosc es el reloj que pongamos al C.

Prescaler puede valer (1,4,16)

Microcontroladores

IES Joan Mir

Pgina 91

Aprendizaje de la Electrnica a travs de la Robtica - ARCE

Postscaler puede valer (1,2, ,16)

El valor mximo de T es cuando Prescaler= 16 y Postscaler= 16 y PR2= 255


Ejemplo: Si el reloj es de Fosc=4Mhz Tcm = 4/Fosc= 4/4Mhz= 1S.
Tmax= Tcm x [Prescaler x (PR2+1) x Postscaler] = 1S. x [16 x (255+1) x 16] = 65536 S.

Utilizaremos el entrenador Timer2.DSN contenido en la carpeta de Timer\ Timer 2.

5.3.6.3.1.- Timer2_Seal_Cuadrada.c

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Timer2_Seal_Cuadrada.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Generar una seal cuadrada de 1 KHz
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#INCLUDE <16F877A.h>
#use delay(clock=20000000)
#fuses XT,NOWDT
#BYTE TRISB = 0x86
#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT rb0 = 0x06.0

// RB0 en 0x06 patilla 0.

Microcontroladores

IES Joan Mir

Pgina 92

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* *************************************** Declaracin de funciones ************************************************************ */


void Timer2 (void);

// Declaracin de la funcin del Timer 2.

/* *********************** Funcin principal o programa principal ******************************** */


void main()
{
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

portB = 0B00000000;

// Reseteamos el Puerto B.

setup_timer_2(T2_DIV_BY_4,124,5);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. Si el Periodo = 1mS ----> T = 500uS
// T = Tcm[Prescaler x(PR2+1)x Postscaler]
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/20.000.000 hz = 0,2uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1,2,3,...,15,16.
// 500uS = 0,2uS[1.(PR2+1)1]
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[500uS/(0,2uS x 4 x 5)]-1 = 124

enable_interrupts(INT_TIMER2);
enable_interrupts(global);

// Habilita interrupcin timer2


// Habilita interrupcin general

while (1);

// bucle infinito

}
/* ************************** Atencin a la interrupcin por desbordamiento del TIMER 2 ****************************** */
#int_TIMER2
void Timer2 (void)
{
rb0 = ~rb0;
}

5.3.6.3.2.- Timer2_Servos_Posicion.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Timer2_Servos_Posicion.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de 4 Servomotores de Posicin va software
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#INCLUDE <16F877A.h>
#device adc=8

// Conversor Analgico Digital de 10 bit el PIC 16F876A puede


// trabajar con 8 o 10 bit de resolucin.

#use delay(clock=20000000)
#fuses XT,NOWDT

#BYTE TRISD = 0x88


#BYTE portD = 0x08

// TRISD en 88h.
// PORTD en 08h.

#BIT rd0 = 0x08.0

// RD0 en 0x08 patilla 0.

Microcontroladores

IES Joan Mir

Pgina 93

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #BIT rd1 = 0x08.1


#BIT rd2 = 0x08.2
#BIT rd3 = 0x08.3

// RD1 en 0x08 patilla 1.


// RD2 en 0x08 patilla 2.
// RD2 en 0x08 patilla 2.

/* ***************************** Declaracin de funciones ****************************************** */


void Timer2 (int16,int16,int16,int16,int16,int16,int16,int16);

// Declaracin de la funcin del Timer 2.

/* *********************** Funcin principal o programa principal ******************************** */


void main()
{
int16 h1,l1,h2,l2,h3,l3,h4,l4;
TRISD = 0B00000000;

// Defines Puerto D como SALIDA de datos.

portD = 0B00000000;

// Reseteamos el Puerto D.

setup_timer_2(T2_DIV_BY_1,199,1);

// setup_timer(Prescaler,PR2,Postscaler)
// Configuracin timer2. T = 40uS
// T = Tcm[Prescaler x(PR2+1)x Postscaler]
// PR2 puede valer de 0 a 255.
// Tcm es el tiempo de Ciclo Maquina.
// Tcm = 4/Fosc = 4/20.000.000 hz = 0,2uS.
// Prescaler puede valer 1,4,16
// Postscaler puede valer 1,2,3,...,15,16.
// 40uS = 0,2uS[1.(PR2+1)1]
// PR2 =[T/(Tcm x Preescaler x Postscaler)]-1
// PR2 =[40uS/(0,2uS x 1 x 1)]-1 = 199

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(0);

// Fuente de reloj RC interno.


// Seleccionamos el Puerto A como entradas Analgicas.
// Mirar ADCON1.
// Habilita interrupcin timer2
// Habilita interrupcin general

enable_interrupts(INT_TIMER2);
enable_interrupts(global);
while (1)
{

// bucle infinito
set_adc_channel(0);
delay_us(5);
h1 = read_adc();
h1=(h1/5)+15;
if(h1>60) h1=60;
l1=400-h1;
set_adc_channel(1);
delay_us(5);
h2 = read_adc();
h2=(h2/5)+15;
if(h2>60) h2=60;
l2=400-h2;
set_adc_channel(2);
delay_us(5);
h3 = read_adc();
h3=(h3/5)+15;
if(h3>60) h3=60;
l3=400-h3;
set_adc_channel(3);
delay_us(5);
h4 = read_adc();
h4=(h4/5)+15;
if(h4>60) h4=60;
l4=400-h4;

// Habilitacin canal 0 "AN0"


// Retardo de 5uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 0 "AN0"
// THmn (h1=0) --> h1=(0/5)+15=15 -->
// THmn(uS)= 15*40uS= 600uS.
// Limita el tiempo THmax -->
// THmax(uS)=60*40uS= 2400uS.
// Periodo(h1=0)--> T(uS)= 400*40uS= 16000uS= 16mS.
// Habilitacin canal 1 "AN1"
// Retardo de 5uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 1 "AN1"

// Habilitacin canal 2 "AN2"


// Retardo de 5uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 2 "AN0"

// Habilitacin canal 3 "AN3"


// Retardo de 5uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 3 "AN0"

Timer2 (h1,l1,h2,l2,h3,l3,h4,l4);
}
}

Microcontroladores

IES Joan Mir

Pgina 94

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* ******************************* Atencin a la interrupcin por desbordamiento del TIMER 2 ************************** */
int_TIMER2
void Timer2 (int16 h1,int16 l1,int16 h2,int16 l2,int16 h3,int16 l3,int16 h4,int16 l4)
{
int16 th1,tl1,th2,tl2,th3,tl3,th4,tl4;
// ************************************* Control del Servomotor 1 ********************************
if(th1<h1)
{
rd0 = 1;
th1++;
}
else
{
if(tl1<l1)
{
rd0 = 0;
tl1++;
}
else
{
th1=0;
tl1=0;
}
}
// ************************************* Control del Servomotor 2 ********************************
if(th2<h2)
{
rd1 = 1;
th2++;
}
else
{
if(tl2<l2)
{
rd1 = 0;
tl2++;
}
else
{
th2=0;
tl2=0;
}
}
// ************************************* Control del Servomotor 3 ********************************
if(th3<h3)
{
rd2 = 1;
th3++;
}
else
{
if(tl3<l3)
{
rd2 = 0;
tl3++;
}
else
{
th3=0;
tl3=0;
}
}

Microcontroladores

IES Joan Mir

Pgina 95

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // ************************************* Control del Servomotor 4 ********************************
if(th4<h4)
{
rd3 = 1;
th4++;
}
else
{
if(tl4<l4)
{
rd3 = 0;
tl4++;
}
else
{
th4=0;
tl4=0;
}
}
}

5.3.7.- Transmisin Serie de Datos. USART


El mdulo USART (Universal Synchronous Asynchronous Receiver Transmitter) es un
interfaz de comunicaciones serie, tambin conocido como SCI (Serial Communication
Interface).
Puede ser configurado como:

Modo asncrono (full duplex).


Modo sncrono maestro (half duplex).
Modo sncrono esclavo (half duplex).

Independientemente del modo debemos, habilitarlo con RCSTA.SPEN = 1.


Y dependiendo del modo (TX salida, RX entrada), configurar TRISC.6 = 0 (pin
RC6/TX/CK como salida) y TRISC.7 = 1 (pin RC7/RX/DT como entrada).
Modo asncrono: transmisin
Funcionamiento

El dato a transmitir se
deposita en TXREG.

Cuando se termina de
transmitir el dato anterior se
traslada automticamente
al registro de desplazamiento
TSR y se indica con
PIR1.TXIF (TXREG vaco). Si
PIE1.TXIE = 1 se produce
una interrupcin para
recargarlo.

Se extraen de TSR los bits (LSBit...MSBit) al ritmo


indicado por el generador de baudios a travs de
RC6/TX.

El dato se precede de un bit de inicio (0) y al final


se aade un bit de parada (1).

El bit TXSTA.TRMT indica cuando se ha terminado de transmitir el contenido de TSR.

Microcontroladores

IES Joan Mir

Pgina 96

Aprendizaje de la Electrnica a travs de la Robtica - ARCE Modo asncrono: recepcin


Funcionamiento

Los bits recibidos en RC7/RX/DT se muestrean (a un ritmo de SPBRG x 16) y son


introducidos en el registro de desplazamiento RSR al ritmo indicado por SPBRG.

Despus de recibir el bit de stop el


dato es copiado en RCREG si est
vaco y se indica (PIR1.RCIF = 1). Si
estn activadas (PIE1.RCIE = 1,
INTCON.PEIE = 1 y INTCON.GIE = 1)
se producir una interrupcin.

PIR1.RCIF se pondr a cero cuando


se lea el dato de RCREG.

RCREG es un registro doble que


funciona como un pila FIFO (First In,
First Out: primero en entrar, primero
en salir).

Si se recibe un tercer dato sin haber ledo los anteriores se producir un error de
desbordamiento (RCSTA.OERR = 1) y se inhibirn futuras recepciones hasta que
se borre.

Si el dato es de 9 bits, se debe leer primero RCSTA.RX9D y despus RCREG para no


perder informacin.

Si el dato se recibe incompleto (bit de stop incompleto) se indica con RCSTA.FERR.

5.3.7.1.- Cable.
Utilizaremos el entrenador Simulacin del TRANSMISOR-RECEPTOR_Cable.DSN
contenido en la carpeta de Transmisin Serie Asncrona\ Cable.

Microcontroladores

IES Joan Mir

Pgina 97

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.7.1.1.- Transmisin_Serie_1.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_1.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Si RA0=0 transmito va serie el 1
//
//
Si RA0=1 transmito va serie un 13
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)
#use rs232(baud=4800, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.
// TRISB en 86h.
// TRISB en 86h.

#BYTE TRISA = 0x85


#BYTE portA = 0x05
int8 ra0=0;
int8 ra0_anterior=0;
int8 dato=0;

// ****************************** Funcin principal o programa principal ****************************


void main()
{
TRISA = 0B11111111;

// Defines Puerto A como ENTRADA de datos.

while(1)
{

// bucle infinito.
ra0= portA & 0B00000001;

// Filtramos los RA0

if (ra0!=ra0_anterior)
{
ra0_anterior=ra0;

// Si varia ra0, transmitimos el dato.


// Guardamos el contenido de ra0;

if(ra0==0)
{
dato=0B00000001;

// dato=1

dato=0B00001101;

// dato=13

}
else
{
}
putc(dato);
delay_ms(100);

// Enviamos va serie la variable dato.


// Esperamos 100 mS.

}
}
}

5.3.7.1.2.- Recepcin_Serie_Polling.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Recepcin_Serie_Polling.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Cuando el dato recibido va serie es "1" escribimos "Si" en el LCD
//
//
Cuando el dato recibido va serie es "13" escribimos "No" en el LCD
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Microcontroladores

IES Joan Mir

Pgina 98

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // ********************************* Directivas de Preprocesado **************************************


#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)

#use rs232(baud=4800,xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


//4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones


// de control del LCD.

int8 dato=0;

// *************************** Funcin principal o programa principal *******************************


void main()
{
lcd_init();

// Inicializamos el LCD.

while(1)
{
dato=getc();

// Leo el dato recibido va serie.

if(dato==1)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"Si");
}
if(dato==13)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"No");
}

// Si dato=1 realizo lo que est entre corchetes.


// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .
// Escribimos el mensaje "Si".
// Si dato=13 realizo lo que est entre corchetes.
// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .
// Escribimos el mensaje "No".

}
}

5.3.7.1.3.- Recepcin_Serie_Interrupcin.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Recepcin_Serie_Interrupcin.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Un programa principal simula las luces del coche fantstico
//
//
Cuando se recibe va serie un "1" en el LCD aparecera "Si"
//
//
Cuando se recibe va serie un "13" en el LCD aparecera "No"
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)
#use rs232(baud=4800,xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones


// del LCD.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

Microcontroladores

IES Joan Mir

Pgina 99

Aprendizaje de la Electrnica a travs de la Robtica - ARCE int8 luces=0B00000001;


/* ********************************************** Declaracin de funciones ***************************************************** */
void Coche_Fantastico (void);
void Leer_dato_serie (void);

// Simulacin Coche fantastico.


// Leer datos via serie

// ************************** Funcin principal o programa principal ********************************


void main()
{
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

portB = luces;
delay_ms(100);

// inicializamos el puerto B.
// Retraso.

lcd_init();

// Inicializamos el LCD.

printf(lcd_putc,"IES Joan Miro");

// Escribimos mensaje.

enable_interrupts(INT_RDA);

// Habilitamos la interrupcin serie de datos.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while(1)
{

// Bucle sin fin.


Coche_Fantastico ();

}
}
/************************************************** Coche_Fantastico *************************************************************/
void Coche_Fantastico (void)
{
int8 n=0;
for (n=0;n<7;n++)
{
luces<<=1;
portB=luces;
delay_ms(100);
}
for (n=7;n>0;n--)
{
luces>>=1;
portB=luces;
delay_ms(100);
}

// Movemos un bit a la izquierda


// Retraso.

// Movemos un bit a la derecha.


// Retraso.

}
/* ***************************** Atencin a la interrupcin por recepcin serie de datos ********************************* */
#int_RDA
void Leer_dato_serie (void)
{
static int8 dato_recibido=0;
dato_recibido=getc();

// Recibimos el dato serie.

if(dato_recibido==1)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"Si");
}
if(dato_recibido==13)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"No");
}

// Si dato=1 realizo lo que est entre corchetes.


// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .
// Escribimos el mensaje "Si".
// Si dato=13 realizo lo que est entre corchetes.
// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .
// Escribimos el mensaje "No".

Microcontroladores

IES Joan Mir

Pgina 100

Aprendizaje de la Electrnica a travs de la Robtica - ARCE 5.3.7.1.4.- Transmisin_Serie_Multitarea.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_Multitarea.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Si RA0=0 transmito va serie el 1
//
//
Si RA0=1 transmito va serie un 13
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ******************************* Directivas de Preprocesado ****************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)

#use rs232(baud=4800, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISA = 0x85


#BYTE portA = 0x05

// TRISB en 86h.
// TRISB en 86h.

#define CLAVE_RA0 63
#define CLAVE_RA1 135
int8 ra0=0;
int8 ra0_anterior=0;
int8 ra1=0;
int8 ra1_anterior=0;
int8 dato=0;

// **************************** Funcin principal o programa principal ******************************


void main()
{
TRISA = 0B11111111;

// Defines Puerto A como ENTRADA de datos.

while(1)
{

// bucle infinito.
ra0= portA & 0B00000001;

// Filtramos los RA0

if (ra0!=ra0_anterior)
{
ra0_anterior=ra0;

// Si varia ra0, transmitimos el dato.


// Guardamos el contenido de ra0;

if(ra0==0)
{
dato=0B00000001;

// dato=1

dato=0B00001101;

// dato=13

}
else
{
}
putc(CLAVE_RA0);
delay_ms(5);
putc(dato);
delay_ms(50);

// Enviamos va serie la CLAVE_RA0.


// Esperamos 5 mS.
// Enviamos va serie la variable dato.
// Esperamos 5 mS.

}
ra1= portA & 0B00000010;

// Filtramos los RA1

if (ra1!=ra1_anterior)
{
ra1_anterior=ra1;

// Si varia ra1, transmitimos el dato.

Microcontroladores

// Guardamos el contenido de ra1;

IES Joan Mir

Pgina 101

Aprendizaje de la Electrnica a travs de la Robtica - ARCE if(ra1==0)


{
dato=0;

// dato=0

dato=56;

// dato=56

}
else
{
}
putc(CLAVE_RA1);
delay_ms(5);
putc(dato);
delay_ms(5);

// Enviamos va serie la CLAVE_RA1.


// Esperamos 5 mS.
// Enviamos va serie la variable dato.
// Esperamos 5 mS.

}
}
}

5.3.7.1.5.- Recepcin_Serie_Interrupcin_Multitarea.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Recepcin_Serie_Interrupcin_Multitarea.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Un programa principal simula las luces del coche fantstico
//
//
Cuando se recibe va serie la clave "63" y el dato "1" en el LCD aparecer "Si"
//
//
Cuando se recibe va serie la clave "63" y el dato "13" en el LCD aparecer "No" //
//
Cuando se recibe va serie la clave "135" y el dato "0" el Servomotor de
//
//
Posicin se posicionara en -90.
//
//
Cuando se recibe va serie la clave "135" y el dato "56" el Servomotor de
//
//
Posicin se posicionara en 0.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)

#use rs232(baud=4800,xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones


// del LCD.
// Incluimos el driver que contiene las funciones de control

#include <Servo_Futaba_10bit.c>
de los Servos de Futaba.
#BYTE TRISB = 0x86
#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#define CLAVE_RA0 63
#define CLAVE_RA1 135
int8 luces=0B00000001;
/* ********************************************** Declaracin de funciones ***************************************************** */
void Coche_Fantastico (void);
void Leer_dato_serie (void);
void Mensaje_LCD (int8);
void Posicion_Servo (int8);

// Simulacin Coche fantastico.


// Leer datos via serie
// Escribir un mensaje en el LCD
// Posicionar el Sevomotor.

Microcontroladores

IES Joan Mir

Pgina 102

Aprendizaje de la Electrnica a travs de la Robtica - ARCE // **************************** Funcin principal o programa principal ******************************
void main()
{
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

portB = luces;
delay_ms(100);

// inicializamos el puerto B.
// Retraso.

lcd_init();

// Inicializamos el LCD.

printf(lcd_putc,"IES Joan Miro");

// Escribimos mensaje.

Inicializacion_Futaba_RC1();

// Inicializacin del Servo en RC1

enable_interrupts(INT_RDA);

// Habilitamos la interrupcin serie de datos.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while(1)
{

// Bucle sin fin.


Coche_Fantastico ();

}
}
/************************************************** Coche_Fantastico *************************************************************/
void Coche_Fantastico (void)
{
int8 n=0;
for(n=0;n<7;n++)
{
luces<<=1;
portB=luces;
delay_ms(100);
}

// Movemos un bit a la izquierda


// Retraso.

for(n=7;n>0;n--)
{
luces>>=1;
portB=luces;
delay_ms(100);
}

// Movemos un bit a la derecha.


// Retraso.

}
/* ******************************** Atencin a la interrupcin por recepcin serie de datos ****************************** */
#int_RDA
void Leer_dato_serie (void)
{
#DEFINE ES_CLAVE_RA0 0
#DEFINE ES_CLAVE_RA1 1
#DEFINE IR_LCD 2
#DEFINE IR_SERVO 3
static int8 caso=ES_CLAVE_RA0;
static int8 dato_recibido=0;
dato_recibido=getc();

// Recibimos el dato serie.

switch (caso)
// Preguntamos por la variable "ir" si es 0 ejecuta el case 0, si es 1 el case 1,
{
case ES_CLAVE_RA0:
if(dato_recibido==CLAVE_RA0)
{
caso=IR_LCD;
}
case ES_CLAVE_RA1:
if(dato_recibido==CLAVE_RA1)

Microcontroladores

IES Joan Mir

Pgina 103

Aprendizaje de la Electrnica a travs de la Robtica - ARCE {


caso=IR_SERVO;
}
break;
case IR_LCD:
Mensaje_LCD (dato_recibido);

// Escribir un mensaje en el LCD

caso=ES_CLAVE_RA0;
break;
case IR_SERVO:
Posicion_Servo (dato_recibido);

// Posicionar el Sevomotor.

caso=ES_CLAVE_RA0;
break;
default:
caso=ES_CLAVE_RA0;
}
}
/* ************************************************ Funcin Mensaje_LCD ****************************************************** */
void Mensaje_LCD (int8 dato)
{
if(dato==1)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"Si");
}
if(dato==13)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"No");
}

// Escribir un mensaje en el LCD


// Si dato=1 realizo lo que est entre corchetes.
// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .
// Escribimos el mensaje "Si".

// Si dato=13 realizo lo que est entre corchetes.


// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .
// Escribimos el mensaje "No".

}
/* ******************************************* Funcin Posicion_Servo ********************************************************* */
void Posicion_Servo (int8 TH)
{
Futaba_RC1(TH);
}

// Posicionar el Sevomotor.
// Posicionar el Servo de la patilla RC1.

5.3.7.1.6.- Transmisin_Serie_Multitarea_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_Multitarea_1.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Si RA0=0 transmito via serie el 1
//
//
Si RA0=1 transmito via serie un 13
//
//
Si RA1=0 transmito via serie un 30
//
//
Si RA1=1 transmito via serie un 90
//
//
Si RA2=0 transmito via serie un 20
//
//
Si RA2=1 transmito via serie un 80
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F877A.h>

Microcontroladores

IES Joan Mir

Pgina 104

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #FUSES XT,NOWDT


#use delay(clock=1000000)

#use rs232(baud=4800, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISA = 0x85


#BYTE portA = 0x05

// TRISB en 86h.
// TRISB en 86h.

#BIT ra0 = 0X05.0


#BIT ra1 = 0X05.1
#BIT ra2 = 0X05.2
#define CLAVE_LCD 63
#define CLAVE_SERVO1 135
#define CLAVE_SERVO2 211
int1 ra0_anterior=0;
int1 ra1_anterior=0;
int1 ra2_anterior=0;
int8 informacion_LCD=0;
int8 informacion_SERVO1=0;
int8 informacion_SERVO2=0;

// **************************** Funcin principal o programa principal ******************************


void main()
{
TRISA = 0B11111111;

// Defines Puerto A como ENTRADA de datos.

while(1)
{

// bucle infinito.
// ****************************** Transmisin de RA0 ***************************************************
if (ra0!=ra0_anterior)
{
ra0_anterior=ra0;

// Si varia ra0, transmitimos el dato.


// Guardamos el contenido de ra0;

if(ra0==0)
{
informacion_LCD=0B00000001;

// informacion_LCD=1

informacion_LCD=0B00001101;

// informacion_LCD=13

}
else
{
}
putc(CLAVE_LCD);
delay_ms(1);

// Enviamos va serie la CLAVE_LCD.


// Esperamos 1 mS.

putc(informacion_LCD);

// Enviamos va serie la variable


// informacion_LCD.
// Esperamos 1 mS.

delay_ms(1);
}

// ****************************** Transmisin de RA1 ***************************************************


if (ra1!=ra1_anterior)
{
ra1_anterior=ra1;

// Si varia ra1, transmitimos el dato.


// Guardamos el contenido de ra1;

if(ra1==0)
{
informacion_SERVO1=30;

// informacion_SERVO=30

informacion_SERVO1=90;

// informacion_SERVO=90

}
else
{
}
putc(CLAVE_SERVO1);
delay_ms(1);

Microcontroladores

// Enviamos va serie la CLAVE_SERVO1.


// Esperamos 1 mS.

IES Joan Mir

Pgina 105

Aprendizaje de la Electrnica a travs de la Robtica - ARCE putc(informacion_SERVO1);

// Enviamos va serie la variable


//informacion_SERVO1.
// Esperamos 1 mS.

delay_ms(1);
}

// ****************************** Transmisin de RA2 ***************************************************


if (ra2!=ra2_anterior)
{
ra2_anterior=ra2;

// Si varia ra2, transmitimos el dato.


// Guardamos el contenido de ra2;

if(ra2==0)
{
informacion_SERVO2=20;

// informacion_SERVO2=20

informacion_SERVO2=80;

// informacion_SERVO2=80

}
else
{
}
putc(CLAVE_SERVO2);
delay_ms(1);

// Enviamos va serie la CLAVE_SERVO2.


// Esperamos 1 mS.

putc(informacion_SERVO2);

// Enviamos va serie la variable


// informacion_SERVO2.
// Esperamos 1 mS.

delay_ms(1);
}
}
}

5.3.7.1.7.- Recepcin_Serie_Interrupcin_Multitarea_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Recepcin_Serie_Interrupcin_Multitarea.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Un programa principal simula las luces del coche fantstico
//
//
Cuando se recibe va serie la clave "63" y el dato "1" en el LCD aparecer "Si"
//
//
Cuando se recibe va serie la clave "63" y el dato "13" en el LCD aparecer "No"
//
//
Cuando se recibe va serie la clave "135" y el dato "30" el Servomotor 1 de
//
//
Posicin se posicionar en 42
//
//
Cuando se recibe va serie la clave "135" y el dato "90" el Servomotor 1 de
//
//
Posicin se posicionar en 53
//
//
Cuando se recibe va serie la clave "135" y el dato "20" el Servomotor 2 de
//
//
Posicin se posicionar en 37
//
//
Cuando se recibe va serie la clave "135" y el dato "80" el Servomotor 2 de
//
//
Posicin se posicionar en 58
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)

#use rs232(baud=4800,xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 4800 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones


// del LCD.
// Incluimos el driver que contiene las funciones de control
// de los Servos de Futaba.

#include <Servo_Futaba_10bit.c>

Microcontroladores

IES Joan Mir

Pgina 106

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#define CLAVE_LCD 63
#define CLAVE_SERVO1 135
#define CLAVE_SERVO2 211
int8 luces=0B00000001;
/* ********************************************** Declaracin de funciones ***************************************************** */
void Coche_Fantastico (void);
void Leer_dato_serie (void);
void Mensaje_LCD (int8);
void Posicion_Servo1 (int8);
void Posicion_Servo2 (int8);

// Simulacin Coche fantstico.


// Leer datos va serie
// Escribir un mensaje en el LCD
// Posicionar el Sevomotor 1.
// Posicionar el Sevomotor 2.

// **************************** Funcin principal o programa principal ******************************


void main()
{
TRISB = 0B00000000;

// Defines Puerto B como SALIDA de datos.

portB = luces;
delay_ms(100);

// inicializamos el puerto B.
// Retraso.

lcd_init();

// Inicializamos el LCD.

printf(lcd_putc,"IES Joan Miro");

// Escribimos mensaje.

Inicializacion_Futaba_RC1();
Inicializacion_Futaba_RC2();

// Inicializacin del Servo en RC1


// Inicializacin del Servo en RC2

enable_interrupts(INT_RDA);

// Habilitamos la interrupcin serie de datos.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while(1)

// Bucle sin fin.

{
Coche_Fantastico ();
}
}
/************************************************** Coche_Fantastico *************************************************************/
void Coche_Fantastico (void)
{
int8 n=0;
for(n=0;n<7;n++)
{
luces<<=1;
portB=luces;
delay_ms(100);
}
for(n=7;n>0;n--)
{
luces>>=1;
portB=luces;
delay_ms(100);
}

// Movemos un bit a la izquierda


// Retraso.

// Movemos un bit a la derecha.


// Retraso.

}
/* ******************************** Atencin a la interrupcin por recepcin serie de datos ****************************** */
#int_RDA
void Leer_dato_serie (void)
{
#DEFINE ES_PROCESO_LCD 0
#DEFINE ES_PROCESO_SERVO1 1
#DEFINE ES_PROCESO_SERVO2 2
#DEFINE IR_LCD 3

Microcontroladores

IES Joan Mir

Pgina 107

Aprendizaje de la Electrnica a travs de la Robtica - ARCE #DEFINE IR_SERVO1 4


#DEFINE IR_SERVO2 5
static int8 caso=ES_PROCESO_LCD;
static int8 dato_recibido=0;
dato_recibido=getc();

// Recibimos el dato serie.

switch (caso)
// Preguntamos por la variable "ir" si es 0 ejecuta el case 0, si es 1 el case 1,
{
case ES_PROCESO_LCD:
if(dato_recibido==CLAVE_LCD)
{
caso=IR_LCD;
}
case ES_PROCESO_SERVO1:
if(dato_recibido==CLAVE_SERVO1)
{
caso=IR_SERVO1;
}
case ES_PROCESO_SERVO2:
if(dato_recibido==CLAVE_SERVO2)
{
caso=IR_SERVO2;
}
break;
case IR_LCD:
Mensaje_LCD (dato_recibido);
caso=ES_PROCESO_LCD;
break;

// Escribir un mensaje en el LCD

case IR_SERVO1:
Posicion_Servo1 (dato_recibido);
caso=ES_PROCESO_LCD;
break;

// Posicionar el Sevomotor 1.

case IR_SERVO2:
Posicion_Servo2 (dato_recibido);
caso=ES_PROCESO_LCD;
break;

// Posicionar el Sevomotor 2.

default:
caso=ES_PROCESO_LCD;
}
}
/* ******************************************* Funcin Mensaje_LCD ****************************************************** */
void Mensaje_LCD (int8 dato)
{
if(dato==1)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"Si");
}
if(dato==13)
{
lcd_gotoxy(1,2);
printf(lcd_putc,"No");
}

// Escribir un mensaje en el LCD


// Si dato=1 realizo lo que est entre corchetes.
// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .
// Escribimos el mensaje "Si".

// Si dato=13 realizo lo que est entre corchetes.


// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .
// Escribimos el mensaje "No".

Microcontroladores

IES Joan Mir

Pgina 108

Aprendizaje de la Electrnica a travs de la Robtica - ARCE /* ******************************************* Funcin Posicion_Servo1 **************************************************** */


void Posicion_Servo1 (int8 TH)
{
Futaba_RC1(TH);
}

// Posicionar el Servomotor 1.
// Posicionar el Servo de la patilla RC1.

/* ******************************************* Funcin Posicion_Servo2 **************************************************** */


void Posicion_Servo2 (int8 TH)
{
Futaba_RC2(TH);
}

// Posicionar el Servomotor 2.
// Posicionar el Servo de la patilla RC2.

5.3.7.2.- Radiofrecuencia.
5.3.7.2.0.- Modulacin en AM.
Es introducir una seal moduladora (En nuestro caso una seal cuadrada
procedente de la transmisin serie de datos) en la Amplitud de la portadora.
La Tarjeta Transmisora de Datos CEBEK C-0503 es un circuito hbrido encargado de
transmitir va radiofrecuencia, los datos digitales SERIE procedentes de la patilla RC6/TX del
microcontrolador PIC 16f876a del mando. La seal digital tiene que tener una frecuencia entre
20 Hz < fo < 4 KHz. Y se modular con una portadora de 433,92 MHz.

Protocolo de Comunicaciones entre el Mando y el Receptor.


Se ha utilizado una transmisin serie asncrona de datos. Se transmite una rfaga
de datos de la siguiente manera:

1bit de START + 8bit de DATOS + 1bit de STOP (Llave que identifica un proceso, se
ha activado un pulsador o se ha variado el Potencimetro del Mando.)
1bit de START + 8bit de DATOS + 1bit de STOP (Informacin del proceso, que
pulsador se ha activado o la tensin digitalizada del Potencimetro del Mando.)

Esta rfaga (Seal que sale de la patilla RC6/TX del microcontrolador PIC16F876A) se
transmite va serie 10 veces a una velocidad de 2400 bit/segundo. El modulador CEBEK C0503 genera una seal de AM con esta seal moduladora.

Microcontroladores

IES Joan Mir

Pgina 109

Aprendizaje de la Electrnica a travs de la Robtica - ARCE -

Microcontroladores

IES Joan Mir

Pgina 110

Aprendizaje de la Electrnica a travs de la Robtica - ARCE El receptor serie CEBEK C-0504 demodula la seal, es decir filtra la portadora de
433,92 MHz obteniendo la seal moduladora (Rfaga de datos)
El microcontrolador del Receptor trabaja en modo interrupcin Serie de Datos.
Es decir cada vez que le llega un dato con el protocolo asincrono serie ( 1bit de START 8 bit
de DATOS, 1 bit de STOP y a una frecuencia de 2400 bit/segundo.) interrumpir un
programa principal y ejecutar una rutina de interrupcin para este proceso.
La rutina de interrupcin realiza el proceso de validar los datos que le llegan. Se validan
los datos si llegan dos rfagas de 20bits consecutivas y tienen la mismas llaves que identifican
el proceso e informacin del proceso.

Utilizaremos el entrenador TRANSMISOR-RECEPTOR_Radiofrecuencia.DSN


contenido en la carpeta de Transmisin Serie Asncrona\ Radiofrecuencia.

5.3.7.2.1.- Transmisin_Serie_ Radiofrecuencia_1.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_Radiofrecuencia_1.c
//
// Plataforma hw: MONIBOT
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Cada vez que pulso una patilla del puerto A se transmite este va serie
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ******************************* Directivas de Preprocesado ****************************************
#include <16F876A.h>
#FUSES XT,NOWDT
#use delay(clock=4000000)

Microcontroladores

IES Joan Mir

Pgina 111

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


#use rs232(baud=2400, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


//2400 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISA = 0x85


#BYTE portA = 0x05

// TRISA en 85h.
// PORTA en 05h.

#define Clave_Pulsadores 63
// ****************************************** Funcin principal o programa principal *******************************************
void main()
{
int8 i=1;
int8 q;

// Definimos la variable "i" como tipo byte.


// Definimos la variable "q" como tipo byte.

TRISA = 0B11111111;

// Defines Puerto A como ENTRADA de datos.

while(1)
{

// bucle infinito.
q= portA & 0B00111111;
q=q | 0B11000000;
q=~q;

// Filtramos los 6 bit menos significativos del Puerto A.


// Le aadimos dos 1 al bit 6 y 7.
// Invertimos para obtener el resultado en lgica positiva.

if (q!=0B00000000)
{
putc(Clave_Pulsadores);
putc(q);
}

// Si se activa un pulsador, transmitir datos.


// Enviamos va serie la Clave_Pulsador.
// Enviamos va serie la variable cambio.

}
}

5.3.7.2.2.- Transmisin_Serie_ Radiofrecuencia_2.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_Radiofrecuencia_2.c
//
// Plataforma hw: MONIBOT
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Cada vez que pulso una patilla del puerto A se transmite esta patilla
//
//
va serie se conserva los datos de las pulsaciones anteriores.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F876A.h>
#FUSES XT,NOWDT
#use delay(clock=4000000)
#use rs232(baud=2400, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 2400 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISA = 0x85


#BYTE portA = 0x05

// TRISA en 85h.
// PORTA en 05h.

#BIT ra0 = 0x05.0


#BIT ra1 = 0x05.1
#BIT ra2 = 0x05.2
#BIT ra3 = 0x05.3
#BIT ra4 = 0x05.4
#BIT ra5 = 0x05.5

// RA0 en 0x05 patilla 0.


// RA1 en 0x05 patilla 1.
// RA2 en 0x05 patilla 2.
// RA3 en 0x05 patilla 3.
// RA4 en 0x05 patilla 4.
// RA5 en 0x05 patilla 5.

#BYTE cambio = 0x20

// cambio1 en 0x20h.

#BIT c0 = 0x20.0
#BIT c1 = 0x20.1
#BIT c2 = 0x20.2
#BIT c3 = 0x20.3

// c0 en 0x20.0
// c1 en 0x20.1
// c2 en 0x20.2
// c3 en 0x20.3

Microcontroladores

IES Joan Mir

Pgina 112

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


#BIT c4 = 0x20.4
#BIT c5 = 0x20.5

// c4 en 0x20.4
// c5 en 0x20.5

#define Clave_Pulsadores 63
#define Numero_Repeticiones 10

// ***************************** Funcin principal o programa principal *****************************


void main()
{
int8 i=1;
int8 q;

// Definimos la variable "i" como tipo byte.


// Definimos la variable "q" como tipo byte.

TRISA = 0B11111111;

// Defines Puerto A como ENTRADA de datos.

cambio=0;

// Inicializamos la variable cambio con 0.

while(1)
{

// bucle infinito.
q= portA & 0B00111111;
q=q | 0B11000000;
q=~q;

// Filtramos los 5 bit menos significativos del Puerto A.


// Le aadimos dos 1 al bit 6 y 7.
// Invertimos para obtener el resultado en lgica positiva.

if (q!=0B00000000)
{
if (ra0==0) c0=~c0;
if (ra1==0) c1=~c1;
if (ra2==0) c2=~c2;
if (ra3==0) c3=~c3;
if (ra4==0) c4=~c4;
if (ra5==0) c5=~c5;

// Si se activa un pulsador, transmitir datos.


// Si se pulsa rb0 cambiar el valor de c0.
// Si se pulsa rb1 cambiar el valor de c1.
// Si se pulsa rb2 cambiar el valor de c2.
// Si se pulsa rb3 cambiar el valor de c3.
// Si se pulsa rb4 cambiar el valor de c4.
// Si se pulsa rb4 cambiar el valor de c5.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pulsadores);
putc(cambio);
}
delay_ms(500);

// Enviamos va serie la
// Clave_Pulsador.
// Enviamos va serie la variable
// cambio.

// Esperamos un tiempo suficiente hasta dejar de pulsar.

}
}
}

5.3.7.2.3.- Recepcin_Serie_Radiofrecuencia_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Recepcin_Serie_Radiofrecuencia_1.c
//
// Plataforma hw: MONIBOT
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Recepcin de un dato va serie con tarjeta de radiofrecuencia
//
//
Un programa principal representa en el LCD el pulsador activado del
//
//
mando de radiofrecuencia.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=4000000)
#use rs232(baud=9600,xmit=pin_c6, rcv=pin_c7)

#include <flex_lcd.c>

Microcontroladores

// Definimos la velocidad de transmisin de


// 9600 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.
// Incluimos el driver flex_lcd.c que contiene las funciones
// del LCD.

IES Joan Mir

Pgina 113

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


#BYTE dato_valido = 0x22

// dato en 0x20h.

#BIT d0 = 0x22.0
#BIT d1 = 0x22.1
#BIT d2 = 0x22.2
#BIT d3 = 0x22.3
#BIT d4 = 0x22.4
#BIT d5 = 0x22.5

// c0 en 0x20.0
// c1 en 0x20.1
// c2 en 0x20.2
// c3 en 0x20.3
// c4 en 0x20.4
// c5 en 0x20.5

#define Clave_Pulsadores 63
int8 dato_recibido;
int8 dato_anterior=0;
/* ********************************************** Declaracin de funciones ***************************************************** */
void Leer_dato_serie (void);

// Leer Dato.

// *************************** Funcin principal o programa principal *******************************


void main()
{
dato_valido=0;
lcd_init();

// Inicializamos el LCD.

printf(lcd_putc,"IES Joan Miro");

// Escribimos mensaje.

lcd_gotoxy(1,2);

// Posicionamos el Cursor del LCD


// en la posicin 1 lnea 2 .
printf(lcd_putc,"%1u%1u%1u%1u%1u%1u",d5,d4,d3,d2,d1,d0);
// Escribimos 5 variables
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);

// Habilitamos la interrupcin serie de datos.


// Habilitamos la Interrupcin General.

while(1)
{

// Bucle sin fin.


if(dato_valido!=dato_anterior)
{
dato_anterior=dato_valido;
lcd_gotoxy(1,2);

// Si es el mismo dato no escribir en el LCD.


// Guardamos el dato anterior
// Posicionamos el Cursor del LCD en la posicin
// 1 lnea 2 .

printf(lcd_putc,"%1u%1u%1u%1u%1u%1u",d5,d4,d3,d2,d1,d0);

// Escribimos 5
// variables
// "Pulsadores del
// mando"

}
}
}
/* ******************************* Atencin a la interrupcin por recepcin serie de datos ******************************* */
#int_RDA
/* Validamos el dato serie si cumple las siguiente condiciones.
Si dos palabras consecutivas de 2 byte son iguales se valida el dato.
clave,dato,clave,dato,......,clave,dato
Se lee el 1 dato serie recibido con la funcin "getc()"
y se compara con la "clave" del transmisor que tiene que ser la misma que la del receptor,
si son iguales se lee el 2 dato serie recibido con la funcin "getc()" y se guarda.
Se lee el 3 dato serie recibido con la funcin "getc()"
y se compara con la "clave" del transmisor que tiene que ser la misma que la del receptor,
si son iguales se lee el 4 dato serie recibido con la funcin "getc()" y se compara con
el 2 dato ledo, si son iguales se valida el dato con la variable global "Valor".
*/
void leer_dato_serie (void)
{
static int8 numero_datos1=0;
static int8 dato1=0;
dato_recibido=getc();

Microcontroladores

// La variable solo valdra 0 la primera vez.


// Recibimos el dato serie.

IES Joan Mir

Pgina 114

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


switch (numero_datos1)

// Es un autmata modelo Moore, que valida los datos


// si llegan dos tramas iguales consecutivas

{
case 0:
if(dato_recibido==Clave_Pulsadores)
{
numero_datos1=1;
}
break;
case 1:
dato1=dato_recibido;
numero_datos1=2;
break;
case 2:
if(dato_recibido==Clave_Pulsadores)
{
numero_datos1=3;
}
else
{
numero_datos1=0;
}
break;
case 3:
if(dato_recibido==dato1)
{
dato_valido=dato_recibido;
}
numero_datos1=0;
}
}

5.3.7.3.- Radiofrecuencia Multitarea.


Utilizaremos el entrenador TRANSMISOR-RECEPTOR_RF_Multitarea.DSN contenido
en la carpeta de Transmisin Serie Asncrona\ Radiofrecuencia_Multitarea.

Microcontroladores

IES Joan Mir

Pgina 115

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.7.3.1.- Transmisin_Serie_RF_Multitarea_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_RF_Multitarea_1.c
//
// Plataforma hw: MONIBOT
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Transmisin serie va radiofrecuencia (Pulsadores y Potencimetros)
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F876A.h>
#device adc=8
#FUSES XT,NOWDT
#use delay(clock=4000000)
#use rs232(baud=2400, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 2400 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT TC3 = 0x87.3


#BIT rc3 = 0x07.3
#BIT rb5 = 0x06.5

// TC3 en 0x87 patilla 7.


// RC3 en 0x07 patilla 3.
// RB5 en 0x06 patilla 5.

#define Clave_Pot_Der 235


#define Clave_Pot_Izq 134
#define Clave_Pulsadores 63
#define Numero_Repeticiones 10

// **************************** Funcin principal o programa principal ******************************


void main()
{
int8 cambio0=0;
int8 cambio1=0;

// Definimos la variable "cambio0" como tipo bit.


// Definimos la variable "cambio1" como tipo bit.

int8 i=1;
int8 q;

// Definimos la variable "i" como tipo byte.


// Definimos la variable "q" como tipo byte.

TRISB = 0B11111111;
TC3 = 0;
RC3 = 1;

// Defines Puerto B como ENTRADA de datos.


// Defines la patilla 3 Puerto C como SALIDA de datos.
// Inhabilitamos la tarjeta CEBEK C-0503.

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(0);

// Fuente de reloj RC interno.


// Seleccionamos el Puerto A como entradas
// Analgicas. Mirar ADCON1.
// bucle infinito.

while(1)
{

if (rb5==1)
// Si se Cierra el Interruptor de rb5 no transmitir ms datos.
{
//**************** Transmisin de datos "Potencimetro Derecho" ************************
set_adc_channel(0);
delay_us(20);
q = read_adc();
if (cambio0!=q)

// Habilitacin canal 0 "AN0"


// Retardo de 20uS necesaria para respetar el tiempo
// de Adquisicin Tad.
// Lectura canal 0 "AN0"
// Si se ha variado el Potencimetro Derecho transmitir
// dato.

{
cambio0=q;
RC3 = 0;

Microcontroladores

// Habilitamos la tarjeta CEBEK C-0503.

IES Joan Mir

Pgina 116

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pot_Der);
putc(q);

}
RC3 = 1;

// Enviamos va serie la
// Clave_Pot_Der.
// Enviamos va serie la variable q.
// (Tensin digitalizada del
// Potencimetro Derecho)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
//**************** Transmisin de datos "Potencimetro Izquierdo" ***********************
set_adc_channel(1);
delay_us(20);

// Habilitacin canal 1 "AN1"


// Retardo de 20uS necesaria para respetar el
// tiempo de Adquisicin Tad.
// Lectura canal 1 "AN1"

q = read_adc();
if (cambio1!=q)

// Si se ha variado el Potencimetro Izquierdo


// transmitir dato.

{
cambio1=q;
RC3 = 0;

// Habilitamos la tarjeta CEBEK C-0503.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pot_Izq);
putc(q);

}
RC3 = 1;

// Enviamos va serie la
// Clave_Pot_Der.
// Enviamos va serie la variable q.
// (Tensin digitalizada del
// Potencimetro Izquierdo)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
//********************* Transmisin de datos "Pulsadores" ***********************************
q= portB & 0B00111111;

// Filtramos los 5 bit menos significativos del


// Puerto B.

if (q!=0B00111111)
{
RC3 = 0;

// Si se activa un pulsador, transmitir datos.


// Habilitamos la tarjeta CEBEK C-0503.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pulsadores);
putc(~q);
}
RC3 = 1;

// Enviamos va serie la
// Clave_Pulsadores.
// Enviamos va serie la variable q
// invertida.(Pulsador Activado)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
}
}
}

5.3.7.3.2.- Transmisin_Serie_RF_Multitarea_2.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Transmisin_Serie_RF_Multitarea_2.c
//
// Plataforma hw: MONIBOT
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Transmisin serie va radiofrecuencia (Pulsadores y Potencimetros)
//
//
se conserva los datos de las pulsaciones anteriores.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Microcontroladores

IES Joan Mir

Pgina 117

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


// *********************************** Directivas de Preprocesado ************************************
#include <16F876A.h>
#device adc=8
#FUSES XT,NOWDT
#use delay(clock=4000000)
#use rs232(baud=2400, xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 2400 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT TC3 = 0x87.3


#BIT rc3 = 0x07.3

// TC3 en 0x87 patilla 7.


// RC3 en 0x07 patilla 3.

#BIT rb0 = 0x06.0


#BIT rb1 = 0x06.1
#BIT rb2 = 0x06.2
#BIT rb3 = 0x06.3
#BIT rb4 = 0x06.4
#BIT rb5 = 0x06.5

// RB0 en 0x06 patilla 0.


// RB1 en 0x06 patilla 1.
// RB2 en 0x06 patilla 2.
// RB3 en 0x06 patilla 3.
// RB4 en 0x06 patilla 4.
// RB5 en 0x06 patilla 5.

#BYTE cambio2 = 0x20


#BIT c0 = 0x20.0
#BIT c1 = 0x20.1
#BIT c2 = 0x20.2
#BIT c3 = 0x20.3
#BIT c4 = 0x20.4
#BIT c5 = 0x20.5

// cambio2 en 0x20h.
// c0 en 0x20.0
// c1 en 0x20.1
// c2 en 0x20.2
// c3 en 0x20.3
// c4 en 0x20.4
// c5 en 0x20.5

#define Clave_Pot_Der 235


#define Clave_Pot_Izq 134
#define Clave_Pulsadores 63
#define Numero_Repeticiones 10

// **************************** Funcin principal o programa principal ******************************


void main()
{
int8 cambio0=0;
int8 cambio1=0;

// Definimos la variable "cambio0" como tipo bit.


// Definimos la variable "cambio1" como tipo bit.

int8 i=1;
int8 q;

// Definimos la variable "i" como tipo byte.


// Definimos la variable "q" como tipo byte.

int1 rb5_1=0;

// Definimos la variable "rb5_1" como tipo bit.

cambio2=0;

// Reseteamos la variable cambio2.

TRISB = 0B11111111;
TC3 = 0;
RC3 = 1;

// Defines Puerto B como ENTRADA de datos.


// Defines la patilla 3 Puerto C como SALIDA de datos.
// Inhabilitamos la tarjeta CEBEK C-0503.

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(0);

while(1)
{

// Fuente de reloj RC interno.


// Seleccionamos el Puerto A como entradas
// Analgicas. Mirar ADCON1.
// bucle infinito.

//*********************** Transmisin de datos "Potencimetro Derecho" *****************************


set_adc_channel(0);
delay_us(20);
q = read_adc();

Microcontroladores

// Habilitacin canal 0 "AN0"


// Retardo de 20uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 0 "AN0"

IES Joan Mir

Pgina 118

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


if (cambio0!=q)

// Si se ha variado el Potencimetro Derecho transmitir


// dato.

{
cambio0=q;
RC3 = 0;

// Habilitamos la tarjeta CEBEK C-0503.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pot_Der);
putc(q);

}
RC3 = 1;

// Enviamos va serie la Clave_Pot_Der.


// Enviamos va serie la variable q.
// (Tensin digitalizada del
// Potencimetro Derecho)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
//******************* Transmisin de datos "Potencimetro Izquierdo" ********************************
set_adc_channel(1);
delay_us(20);
q = read_adc();
if (cambio1!=q)

// Habilitacin canal 1 "AN1"


// Retardo de 20uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 1 "AN1"
// Si se ha variado el Potencimetro Izquierdo
// transmitir dato.

{
cambio1=q;
RC3 = 0;

// Habilitamos la tarjeta CEBEK C-0503.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pot_Izq);
putc(q);

}
RC3 = 1;

// Enviamos va serie la Clave_Pot_Der.


// Enviamos va serie la variable q.
// (Tensin digitalizada del
// Potencimetro Izquierdo)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
//*********************** Transmisin de datos "Pulsadores" ********************************************
q= portB & 0B00011111;

// Filtramos los 5 bit menos significativos del Puerto B.

if (q!=0B00011111)
{
if (rb0==0) c0=~c0;
if (rb1==0) c1=~c1;
if (rb2==0) c2=~c2;
if (rb3==0) c3=~c3;
if (rb4==0) c4=~c4;

// Si se activa un pulsador, transmitir datos.

RC3 = 0;

// Si se pulsa rb0 cambiar el valor de c0.


// Si se pulsa rb1 cambiar el valor de c1.
// Si se pulsa rb2 cambiar el valor de c2.
// Si se pulsa rb3 cambiar el valor de c3.
// Si se pulsa rb4 cambiar el valor de c4.
// Habilitamos la tarjeta CEBEK C-0503.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga la variable
// Nmero_Repeticiones

{
putc(Clave_Pulsadores);
putc(cambio2);
}
RC3 = 1;

// Enviamos va serie la
// Clave_Pulsadores.
// Enviamos va serie la variable
// cambio2. (Pulsador Activado)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
//**************************** Transmisin de datos "Interruptor" ****************************************
if (rb5!=rb5_1)

// Si se ha cambiado el Interruptor de la patilla rb5


// transmitir dato.

{
rb5_1=rb5;
c5=~rb5;

Microcontroladores

IES Joan Mir

Pgina 119

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


RC3 = 0;

// Habilitamos la tarjeta CEBEK C-0503.

for(i=1;i<=Numero_Repeticiones;i++)

// Enviamos el dato va serie, tantas


// veces como diga a variable
// Nmero_Repeticiones

{
putc(Clave_Pulsadores);
putc(cambio2);
}
RC3 = 1;

// Enviamos va serie la
// Clave_Pulsadores.
// Enviamos va serie la variable
// cambio2. (Interruptor Activado)

// Inhabilitamos la tarjeta CEBEK C-0503.

}
}
}

5.3.7.3.3.- Recepcin_Serie_RF_Multitarea.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Recepcin_Serie_RF_Multitarea.c
//
// Plataforma hw: MONIBOT
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso Sanz
//
// Descripcin..: Recepcin de datos va serie con tarjeta de radiofrecuencia (Multitarea)
//
//
Un programa principal est en modo sueo
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=4000000)
#use rs232(baud=2400,xmit=pin_c6, rcv=pin_c7)

// Definimos la velocidad de transmisin de


// 2400 baudios/segundo
// Elegimos RC6 como patilla transmisora de datos.
// Elegimos RC7 como patilla receptora de datos.

#BYTE TRISD = 0x88


#BYTE portD = 0x08

// TRISD en 88h.
// PORTD en 08h.

#BYTE TRISC = 0x87


#BYTE portC = 0x07

// TRISC en 87h.
// PORTC en 07h.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#define Clave_Pot_Der 235

// Definimos claves.

#define Clave_Pot_Izq 134


#define Clave_Pulsadores 63
int1 valido_Aut_Pul=1;
int1 valido_Aut_Pot_Der=1;
int1 valido_Aut_Pot_Izq=1;
int8 dato_recibido=0;

// Inicializamos variables

/* ************************************** Declaracin de funciones ************************************************************* */


void Leer_dato_serie (void);
void Automata_Pulsadores (void);
void Automata_Pot_Der (void);
void Automata_Pot_Izq (void);

Microcontroladores

// Leer Dato.
// Valida los datos serie procedentes de los Pulsadores.
// Valida los datos serie procedentes del Potencimetro Derecho.
// Valida los datos serie procedentes del Potencimetro Izquierdo.

IES Joan Mir

Pgina 120

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


// ****************************** Funcin principal o programa principal ****************************
void main()
{
TRISD = 0B00000000;
TRISC = 0B10000000;
TRISB = 0B00000000;

// Defines Puerto D como SALIDA de datos.


// Defines Puerto C como SALIDA de datos
// a excepcin de RC7/Rx que es entrada de datos.
// Defines Puerto B como SALIDA de datos.

portD = 0B00000000;
portC = 0B00000000;
portB = 0B00000000;

// Reseteamos el Puerto D.
// Reseteamos el Puerto C.
// Reseteamos el Puerto B.

enable_interrupts(INT_RDA);

// Habilitamos la interrupcin serie de datos.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while(1)
{

// Bucle sin fin.


sleep();

// Se pone el uC en bajo consumo. Cuando le llega una


// transmisin serie de datos se activa el uC. Atiende la interrupcin
// y vuelve a bajo consumo.

}
}
/* ************************* Atencin a la interrupcin por recepcin serie de datos ************************************* */
#int_RDA
/* Validamos el dato serie si cumple las siguiente condiciones.
Si dos palabras consecutivas de 2 byte son iguales se valida el dato.
clave,dato,clave,dato,......,clave,dato
Se lee el 1 dato serie recibido con la funcin "getc()"
y se compara con la "clave" del transmisor que tiene que ser la misma que la del receptor,
si son iguales se lee el 2 dato serie recibido con la funcin "getc()" y se guarda.
Se lee el 3 dato serie recibido con la funcin "getc()"
y se compara con la "clave" del transmisor que tiene que ser la misma que la del receptor,
si son iguales se lee el 4 dato serie recibido con la funcin "getc()" y se compara con
el 2 dato leido, si son iguales se valida el dato con la variable global "Valor".
*/

void Leer_dato_serie (void)


{
dato_recibido=getc();
if (valido_Aut_Pul==1)

// Recibimos el dato serie.


Automata_Pulsadores();

if (valido_Aut_Pot_Der==1)

Automata_Pot_Der();

if (valido_Aut_Pot_Izq==1)

Automata_Pot_Izq();

// Ejecutas la funcin Autmata_Pulsadores si la


// variable Valido_Aut_Pul==1.
// Ejecutas la funcin Automata_Pot_Der si la
// variable Valido_Aut_Pot_Der==1.
// Ejecutas la funcin Automata_Pot_Izq si la
// variable Valido_Aut_Pot_Izq==1.

}
/*********************************************Funcin Automata_Pulsadores ************************************************* */
void Automata_Pulsadores(void)
{
static int8 numero_datos=0;
static int8 dato=0;
switch (numero_datos)

// Es un autmata modelo Moore, que valida los datos si llegan dos


// tramas iguales consecutivas. Variacin de los Pulsadores e
// Interruptor del Transmisor.

{
case 0:
if(dato_recibido==Clave_Pulsadores)
{
numero_datos=1;
valido_Aut_Pot_Der=0;
valido_Aut_Pot_Izq=0;
}

Microcontroladores

IES Joan Mir

Pgina 121

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


break;
case 1:
dato=dato_recibido;
numero_datos=2;
break;
case 2:
if(dato_recibido==Clave_Pulsadores)
{
numero_datos=3;
}
else
{
numero_datos=0;
valido_Aut_Pot_Der=1;
valido_Aut_Pot_Izq=1;
}
break;
case 3:
if(dato_recibido==dato) portC=dato_recibido;
numero_datos=0;
valido_Aut_Pot_Der=1;
valido_Aut_Pot_Izq=1;
}
}
/************************************************Funcin Automata_Pot_Der ************************************************** */
void Automata_Pot_Der(void)
{
static int8 numero_datos=0;
static int8 dato=0;
switch (numero_datos)

// Es un autmata modelo Moore, que valida los datos si llegan dos


// tramas iguales consecutivas. Variaciones del Potencimetro
// Derecho del Transmisor.

{
case 0:
if(dato_recibido==Clave_Pot_Der)
{
numero_datos=1;
valido_Aut_Pul=0;
valido_Aut_Pot_Izq=0;
}
break;
case 1:
dato=dato_recibido;
numero_datos=2;
break;
case 2:
if(dato_recibido==Clave_Pot_Der)
{
numero_datos=3;
}
else
{
numero_datos=0;
valido_Aut_Pul=1;
valido_Aut_Pot_Izq=1;
}
break;
case 3:
if(dato_recibido==dato) portD =dato_recibido;
numero_datos=0;
valido_Aut_Pul=1;
valido_Aut_Pot_Izq=1;
}
}

Microcontroladores

IES Joan Mir

Pgina 122

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


/* *********************************************Funcin Automata_Pot_Izq **************************************************** */
void Automata_Pot_Izq(void)
{
static int8 numero_datos=0;
static int8 dato=0;
switch (numero_datos)

// Es un autmata modelo Moore, que valida los datos si llegan dos


// tramas iguales consecutivas. Variaciones del Potencimetro
// Izquierdo del Transmisor.

{
case 0:
if(dato_recibido==Clave_Pot_Izq)
{
numero_datos=1;
valido_Aut_Pul=0;
valido_Aut_Pot_Der=0;
}
break;
case 1:
dato=dato_recibido;
numero_datos=2;
break;
case 2:
if(dato_recibido==Clave_Pot_Izq)
{
numero_datos=3;
}
else
{
numero_datos=0;
valido_Aut_Pul=1;
valido_Aut_Pot_Der=1;
}
break;
case 3:
if(dato_recibido==dato)
numero_datos=0;
valido_Aut_Pul=1;
valido_Aut_Pot_Der=1;

portB=dato_recibido;

}
}

5.3.8.- Mdulo MSSP.


El mdulo MSSP (Master Synchronous Serial Port) es un interfaz de comunicaciones
serie. Puede trabajar en dos modos:

Modo I2C (Inter-Integrated Circuit). Las patillas asociadas a este modo sern
RC3/SCL y RC4/SDA.

Modo SPI (Serial Peripheral Interface). Las patillas asociadas sern


RC3/SCK, RC4/SDI, RC5/SDO y RA5/SS.

5.3.8.1.- I2C.

Funciona en modo maestro esclavo.


Permite el direccionamiento de 7 bits o de 10 bits.
Atiende a la llamada general (dir = 00000000b).
Funciona a 100 kHz, a 400 kHz y a 1 MHz.
La patilla RC3/SCL es el reloj (bidireccional).
La patilla RC4/SDA son los datos (bidireccional).
Se activa el modulo con SSPCON.SSPEN = 1.
TRISC debe configurar RC3/SCL y RC4/SDA como entradas.

Microcontroladores

IES Joan Mir

Pgina 123

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

Se controla con 5 registros:


SSPCON, registro de control del mdulo
MSSP.
SSPCON2, registro de control nmero 2
del mdulo MSSP.
SSPSTAT, registro de estado del mdulo
MSSP.
SSPBUF, bfer de recepcin/envo.
SSPADD, registro de direccin.

Modos de operacin:

I2C esclavo (direccin de 7 bits).


I2C esclavo (direccin de 10 bits).
I2C maestro, Fi2c = Fosc=(4(SSPADD+1)).

Funcionamiento:

SSPSTAT.CKE = 0, configurar niveles compatibles I2C.


SSPSTAT.CKE = 1, configurar niveles elctricos compatibles SMBus (Intel
1995).
SSPSTAT.S indicar la condicin de start.
SSPSTAT.P indicar la condicin de stop.
SSPSTAT.D_A indicar si se recibi dato o direccin.
SSPSTAT.UA indicar si el dato es la extensin a 10 bits de la direccin.

Modo I2C maestro:


Funcionamiento:

SSPCON.WCOL indica que ha habido una colisin en una escritura.


Secuencia de transmisin:
Se genera la condicin de start con SSPCON2.SEN = 1.
PIR1.SSPIF estar a 1. Se espera la inicializacin del mdulo.
Se escribe la direccin del dispositivo en SSPBUF.
La direccin es transmitida.
El mdulo MSSP lee el bit ACK y lo copia en SSPCON2.ACKSTAT.
Se activa PIR1.SSPIF y se produce una interrupcin, si est habilitada.
Se escribe el dato en SSPBUF.
El dato es transmitido.
El mdulo MSSP lee el bit ACK y lo copia en SSPCON2.ACKSTAT.
Se genera la condicin de stop con SSPCON2.PEN.
Se genera una interrupcin si estn habilitadas.

El compilador C de CCS nos proporciona unas funciones para trabajar con I2C. Para
entender mejor lo explicado utilizaremos unos ejemplos.

Microcontroladores

IES Joan Mir

Pgina 124

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.1.- Expansor_Bus_PCF8574.
2

El dispositivo es un expansor remoto de 8bits I/O para bus I C, consiste en un puerto


2
cuasi bidireccional de 8 bit y una interfaz I C-bus.
El PCF8574 tiene una baja corriente
consumo e incluye salidas tipo latch con alta
capacidad de corriente para activar
directamente LEDs.
Este, tambin posee una lnea de
interrupcin (INT), que puede ser conectada a
la lgica interrupt del microcontrolador.
Mediante el envo de una seal interrupt sobre
esta lnea, la E/S remota puede informar al
microcontrolador si hay datos entrantes en sus
puertos sin necesidad de comunicarse a
2
travs del I C-bus. Esto quiere decir que el
PCF8574 puede seguir siendo un simple
dispositivo esclavo.

5.3.8.1.1.1.- PCF8574_1.
Utilizaremos el entrenador PCF8574_1.DSN contenido en la carpeta de I2C\
Expansor_Bus_PCF8574\ PCF8574_1.

Microcontroladores

IES Joan Mir

Pgina 125

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.1.1.1.- Lectura y escritura en PCF8574 modo polling.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura y escritura en PCF8574 modo polling.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control con I2C de dos expansores de Bus paralelo PCF8574
//
//
en modo polling
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

/* ***************************************** Declaracin de funciones ********************************************************** */


int8 Lectura_Interruptores(void);

// Declaramos la funcin Lectura_Interruptores


// (Nos devuelve una variable tipo entero de 8 bit)
// Declaramos la funcin Escritura (Lleva una variable
// asociada de tipo entero de 8 bit)

void Escritura(int8);

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int8 dato_recibido;
while (1)
{

// Bucle infinito de espera


dato_recibido = Lectura_Interruptores();
delay_ms(1);

// Leemos el dato a travs del bus I2c del


// esclavo U4

Escritura(~dato_recibido);
delay_ms(1);

// Escribimos el dato a travs del bus I2c en el


// esclavo U3

}
}
/* ******************************** Funcin de int8 Lectura_Interruptores() ************************************************* */
int8 Lectura_Interruptores()
{
int8 data;
i2c_start();
i2c_write(0B01000001);

// Inicializa la recepcin.
// Seleccionar esclavo U4 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(000) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.

data=i2c_read(0);
i2c_stop();

// Lectura del dato


// Finalizacin de la transmisin.

return(data);
}
/* ****************************** Funcin de Escritura(int8 dato_recibido) ************************************************** */
void Escritura(int8 dato_recibido)
{
i2c_start();
i2c_write(0x48);

Microcontroladores

// Inicializa la transmisin
// Seleccionar esclavo U3 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.

IES Joan Mir

Pgina 126

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


//
//
i2c_write(dato_recibido);
i2c_stop();

(A2,A1,A0)=(100) por hardware.


El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.

// Dato a escribir
// Finalizacin de la transmisin.

5.3.8.1.1.1.2.- Lectura y escritura en PCF8574 en modo Interrupcin.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura y escritura en PCF8574 en modo Interrupcin.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control con I2C de un expansor de Bus paralelo PCF8574 (U4) en modo
//
//
interrupcin.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware

interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
#BYTE TRISA = 0x85
#BYTE portA = 0x05

// TRISA en 85h.
// PORTA en 05h.

#BIT INTF = 0x0B.1

// INTF en 0x0B patilla 1.

#BIT ra1 = 0x05.1


#BIT ra2 = 0x05.2
#BIT ra3 = 0x05.3
#BIT ra4 = 0x05.4
#BIT ra5 = 0x05.5

// RA1 en 0x05 patilla 1.


// RA2 en 0x05 patilla 2.
// RA3 en 0x05 patilla 3.
// RA4 en 0x05 patilla 4.
// RA5 en 0x05 patilla 5.

/* *************************************** Declaracin de funciones ************************************************************ */


int8 Lectura_Interruptores();
void Escritura(int8);

// Declaramos la funcin Lectura_Interruptores (Nos devuelve una


// variable tipo entero de 8 bit)
// Declaramos la funcin Escritura (LLeva una variable asociada de
// tipo entero de 8 bit)

void Motor_PAP (void);


void Lectura_Escritura_PCF8476(void);

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
TRISA = 0B00000000;

// Defines Puerto A como SALIDA de datos.

portA = 0B00101000;

// Reseteamos el Puerto A.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

enable_interrupts(int_ext);
ext_int_edge(H_TO_L);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de BAJADA.

INTF = 1;

// Forzamos la Interrupcin.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcin General.

while (1)

// Bucle infinito de espera

Microcontroladores

IES Joan Mir

Pgina 127

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


{
Motor_PAP();
}
}
/* ************************************* Atencin a la interrupcin por cambio en RB0 ************************************* */
#INT_EXT
void Lectura_Escritura_PCF8476(void)
{
int8 dato_recibido;
dato_recibido = Lectura_Interruptores();

// Leemos el dato a travs del bus I2c del esclavo U4

Escritura(~dato_recibido);

// Escribimos el dato a travs del bus I2c en el esclavo U3

}
/* ******************************************** Motor Paso a Paso *************************************************************** */
void Motor_PAP (void)
{
ra3 = 0;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 1 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 1;

// Posicionamos el Motor PAP en la 2 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 3 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 1;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 4 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 5 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 1;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 6 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 7 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;

// Posicionamos el Motor PAP en la 8 Posicin.

Microcontroladores

IES Joan Mir

Pgina 128

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


ra5 = 1;
delay_ms(500);

// Retardo de 500 ms

}
/* *************************************** Funcin de int8 Lectura_Interruptores() ****************************************** */
int8 Lectura_Interruptores()
{
int8 data;
i2c_start();
i2c_write(0x41);

// Inicializa la recepcin.
// Seleccionar esclavo U4 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(000) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.

data=i2c_read(0);
i2c_stop();

// Lectura del dato


// Finalizacin de la transmisin.

return(data);
}
/* ************************************* Funcin de Escritura(int8 dato_recibido) ******************************************* */
void Escritura(int8 dato_recibido)
{
i2c_start();
i2c_write(0x48);

i2c_write(dato_recibido);
i2c_stop();

// Inicializa la transmisin
// Seleccionar esclavo U3 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.
// Dato a escribir
// Finalizacin de la transmisin.

5.3.8.1.1.2.- PCF8574_2.
Utilizaremos el entrenador PCF8574_2.DSN contenido en la carpeta de I2C\
Expansor_Bus_PCF8574\ PCF8574_2.

Microcontroladores

IES Joan Mir

Pgina 129

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.1.2.1.- Lectura y escritura de multiples PCF8574 modo polling.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura y escritura de multiples PCF8574 modo polling.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control con I2C de cuatro expansores de Bus paralelo PCF8574
//
//
en modo polling.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

/* ********************************************* Declaracin de funciones ****************************************************** */


int8 Lectura_Interruptores_1(void);
void Escritura_Led_1(int8);
int8 Lectura_Interruptores_2(void);
void Escritura_Led_2(int8);

// Declaramos la funcin Lectura_Interruptores_1


// (Nos devuelve una variable tipo entero de 8 bit)
// Declaramos la funcin Escritura_Led_1
// (LLeva una variable asociada de tipo entero de 8 bit)
// Declaramos la funcin Lectura_Interruptores_2
// (Nos devuelve una variable tipo entero de 8 bit)
// Declaramos la funcin Escritura_Led_2
// (LLeva una variable asociada de tipo entero de 8 bit)

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int8 dato_recibido;
while (1)
{

// Bucle infinito de espera


dato_recibido = Lectura_Interruptores_1();

// Leemos el dato a travs del bus I2c del


// esclavo U3

delay_ms(50);
Escritura_Led_1(dato_recibido);

// Escribimos el dato a travs del bus I2c en el


// esclavo U4

delay_ms(50);
dato_recibido = Lectura_Interruptores_2();

// Leemos el dato a travs del bus I2c del


// esclavo U5

delay_ms(50);
Escritura_Led_2(dato_recibido);

// Escribimos el dato a travs del bus I2c en el


// esclavo U6

delay_ms(50);
}
}
/* ********************************* Funcin de int8 Lectura_Interruptores_1() ********************************************* */
int8 Lectura_Interruptores_1()
{
int8 data;
i2c_start();
i2c_write(0B01000001);

data=i2c_read(0);

Microcontroladores

// Inicializa la recepcin.
// Seleccionar esclavo U3 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(000) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.
// Lectura del dato

IES Joan Mir

Pgina 130

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_stop();

// Finalizacin de la transmisin.

return(data);
}
/* ********************************* Funcin de Escritura_1(int8 dato_recibido) ******************************************** */
void Escritura_Led_1(int8 dato_recibido)
{
i2c_start();
i2c_write(0x48);

i2c_write(dato_recibido);
i2c_stop();

// Inicializa la transmisin
// Seleccionar esclavo U4 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.
// Dato a escribir
// Finalizacin de la transmisin.

}
/* ********************************* Funcin de int8 Lectura_Interruptores_2() ********************************************* */
int8 Lectura_Interruptores_2()
{
int8 data;
i2c_start();
i2c_write(0B01001011);

data=i2c_read(0);
i2c_stop();

// Inicializa la recepcin.
// Seleccionar esclavo U5 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(101) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.
// Lectura del dato
// Finalizacin de la transmisin.

return(data);
}
/* ********************************* Funcin de Escritura_2(int8 dato_recibido) ******************************************** */
void Escritura_Led_2(int8 dato_recibido)
{
i2c_start();
i2c_write(0x4E);

i2c_write(dato_recibido);
i2c_stop();

// Inicializa la transmisin
// Seleccionar esclavo U6 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(111) por hardware.
// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.
// Dato a escribir
// Finalizacin de la transmisin.

5.3.8.1.1.2.2.- Lectura y escritura de multiples PCF8574 modo Interrupcin.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura y escritura de multiples PCF8574 modo Interrupcin.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control con I2C de cuatro expansores de Bus paralelo PCF8574
//
//
en modo Interrupcin.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

Microcontroladores

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware

IES Joan Mir

Pgina 131

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
#BYTE TRISA = 0x85
#BYTE portA = 0x05

// TRISA en 85h.
// PORTA en 05h.

#BYTE TRISB = 0x86


#BYTE portB = 0x06

// TRISB en 86h.
// PORTB en 06h.

#BIT rb4 = 0x06.4


#BIT rb5 = 0x06.5

// RA4 en 0x05 patilla 4.


// RA5 en 0x05 patilla 5.

#BIT ra1 = 0x05.1


#BIT ra2 = 0x05.2
#BIT ra3 = 0x05.3
#BIT ra4 = 0x05.4
#BIT ra5 = 0x05.5

// RA1 en 0x05 patilla 1.


// RA2 en 0x05 patilla 2.
// RA3 en 0x05 patilla 3.
// RA4 en 0x05 patilla 4.
// RA5 en 0x05 patilla 5.

#BIT RBIF = 0x0B.0

// RBIF en 0x0B patilla 0. Necesario para Proteus

/* ********************************************* Declaracin de funciones ****************************************************** */


void Motor_PAP (void);
void Lectura_Escritura_PCF8476(void);
int8 Lectura_Interruptores_1(void);

// Declaramos la funcin Lectura_Interruptores_1


// (Nos devuelve una variable tipo entero de 8 bit)
void Escritura_Led_1(int8);
// Declaramos la funcin Escritura_Led_1
// (LLeva una variable asociada de tipo entero de 8 bit)
int8 Lectura_Interruptores_2(void);
// Declaramos la funcin Lectura_Interruptores_2
//(Nos devuelve una variable tipo entero de 8 bit)
void Escritura_Led_2(int8);
// Declaramos la funcin Escritura_Led_2
//(LLeva una variable asociada de tipo entero de 8 bit)
/* ****************************************** Funcin principal o programa principal **************************************** */
void main()
{
TRISA = 0B00000000;
TRISB = 0B11111111;

// Defines Puerto A como SALIDA de datos.


// Defines Puerto B como ENTRADA de datos.

portA = 0B00101000;

// Reseteamos el Puerto A.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

enable_interrupts(int_rb);

// Habilitamos la interrupcin INT de la patilla RB0.

enable_interrupts(GLOBAL);

// Habilitamos la Interrupcion General.

RBIF = 1;

// Forzamos la Interrupcin.

while (1)
{

// Bucle infinito de espera


Motor_PAP();

}
}
/* ************************************************ Motor Paso a Paso *********************************************************** */
void Motor_PAP (void)
{
ra3 = 0;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 1 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 1;

// Posicionamos el Motor PAP en la 2 Posicin.

Microcontroladores

IES Joan Mir

Pgina 132

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 3 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 1;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 4 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 0;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 5 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 1;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 6 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 7 Posicin.

delay_ms(500);

// Retardo de 500 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 8 Posicin.

delay_ms(500);

// Retardo de 500 ms

}
/* ******************************* Atencin a la interrupcin por cambio en RB0 ******************************************* */
#INT_RB
void Lectura_Escritura_PCF8476(void)
{
int n;

// Necesario en el Proteus, para poder borrar el flag RBIF.

int8 dato_recibido;
if(rb4==0)
// Preguntamos si ha interrumpido (U3)
{
dato_recibido = Lectura_Interruptores_1();
// Leemos el dato a travs del bus I2c del
// esclavo U3.
Escritura_Led_1(dato_recibido);
// Escribimos el dato a travs del bus I2c en el
// esclavo U4.
}
if(rb5==0)
// Preguntamos si ha interrumpido (U4)
{
dato_recibido = Lectura_Interruptores_2();
// Leemos el dato a travs del bus I2c del
// esclavo U5.
Escritura_Led_2(dato_recibido);
// Escribimos el dato a travs del bus I2c en el
// esclavo U6.
}
n = portB;

// Necesario en el Proteus, para poder borrar el flag RBIF.

Microcontroladores

IES Joan Mir

Pgina 133

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


/* **************************** Funcin de int8 Lectura_Interruptores_1() ************************************************** */
int8 Lectura_Interruptores_1()
{
int8 data;
i2c_start();
i2c_write(0B01000001);

// Inicializa la recepcin.
// Seleccionar esclavo U3 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(000) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.

data=i2c_read(0);
i2c_stop();

// Lectura del dato


// Finalizacin de la transmisin.

return(data);
}
/* ***************************** Funcin de Escritura_1(int8 dato_recibido) ************************************************ */
void Escritura_Led_1(int8 dato_recibido)
{
i2c_start();
i2c_write(0x48);

i2c_write(dato_recibido);
i2c_stop();

// Inicializa la transmisin
// Seleccionar esclavo U4 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.
// Dato a escribir
// Finalizacin de la transmisin.

/* ********************************* Funcin de int8 Lectura_Interruptores_2() ********************************************* */


int8 Lectura_Interruptores_2()
{
int8 data;
i2c_start();
i2c_write(0B01001011);

// Inicializa la recepcin.
// Seleccionar esclavo U5 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(101) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.

data=i2c_read(0);
i2c_stop();

// Lectura del dato


// Finalizacin de la transmisin.

return(data);
}
/* ****************************** Funcin de Escritura_2(int8 dato_recibido) *********************************************** */
void Escritura_Led_2(int8 dato_recibido)
{
i2c_start();
i2c_write(0x4E);

i2c_write(dato_recibido);
i2c_stop();

// Inicializa la transmisin
// Seleccionar esclavo U6 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(111) por hardware.
// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.
// Dato a escribir
// Finalizacin de la transmisin.

Microcontroladores

IES Joan Mir

Pgina 134

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.1.3.- PCF8574_3.
Utilizaremos el entrenador PCF8574_3.DSN contenido en la carpeta de I2C\
Expansor_Bus_PCF8574\ PCF8574_3.

5.3.8.1.1.3.1.- CAD_PCF8547.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: CAD_PCF8547.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Un programa principal controla un motor PAP.
//
//
El Conversor A/D interrumpe el programa principal digitalizando la patilla RA0
//
//
y llevar su resultado a el expansor de Bus paralelo PCF8574 (U7).
//
//
El cristal de cuarzo tiene que ser de 20 MHz
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F876A.h>
#device adc=8

// Conversor Analogico Digital de 8 bit el PIC 16F876A puede trabajar


// con 8 o 10 bit de resolucion.

#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 20000000)

// Cambiar el reloj a 20 MHz

#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#BYTE TRISA = 0x85

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

// TRISA en 85h.

Microcontroladores

IES Joan Mir

Pgina 135

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


#BYTE portA = 0x05

// PORTA en 05h.

#BIT ra1 = 0x05.1


#BIT ra2 = 0x05.2
#BIT ra3 = 0x05.3
#BIT ra4 = 0x05.4
#BIT ra5 = 0x05.5

// RA1 en 0x05 patilla 1.


// RA2 en 0x05 patilla 2.
// RA3 en 0x05 patilla 3.
// RA4 en 0x05 patilla 4.
// RA5 en 0x05 patilla 5.

#BIT ta1 = 0x85.1


#BIT ta2 = 0x85.2
#BIT ta3 = 0x85.3
#BIT ta4 = 0x85.4
#BIT ta5 = 0x85.5

// TA1 en 0x85 patilla 1.


// TA2 en 0x85 patilla 2.
// TA3 en 0x85 patilla 3.
// TA4 en 0x85 patilla 4.
// TA5 en 0x85 patilla 5.

/* ******************************************* Declaracin de funciones ******************************************************** */


void Escritura(int8);

// Declaramos la funcin Escritura


// (LLeva una variable asociada de tipo entero de 8 bit)

void Motor_PAP (void);


void Lectura_Escritura_PCF8476(void);
/* ************************************* Funcin principal o programa principal ********************************************* */
void main()
{
setup_adc_ports(14);

// Seleccionamos el PA0 como entrada Analgica y


// PA1..PA5 digitales. Mirar ADCON1.
// Fuente de reloj RC interno.
// Habilitacin canal 0 "AN0"

setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
ta1 = 0;
ta2 = 0;
ta3 = 0;
ta4 = 0;
ta5 = 0;

// Defines PA1 como SALIDA de datos.


// Defines PA2 como SALIDA de datos.
// Defines PA3 como SALIDA de datos.
// Defines PA4 como SALIDA de datos.
// Defines PA5 como SALIDA de datos.

ra1 = 0;
// Activamos el Motor PAP y encendemos LED.
ra2 = 0;
ra3 = 1;
ra4 = 0;
ra5 = 1
enable_interrupts(int_ad);
// Habilitamos la interrupcin por Conversin A/D.
enable_interrupts(GLOBAL);
// Habilitamos la Interrupcion General.
read_adc(adc_start_only);

// Lanzamos el Conversor A/D.

while (1)
{

// Bucle infinito de espera.


Motor_PAP();

// Ejecuta la funcion Motor PAP.

}
}
/* ********************************* Atencin a la interrupcin por Conversin A/D **************************************** */
#INT_AD
void Lectura_Escritura_PCF8476(void)
{
int8 dato_recibido;
delay_ms(10);

// Retardo de 10 mS. (No es necesario, solo se hace para


// dar tiempo al motor PAP a posicionarse)

dato_recibido = read_adc(adc_read_only);

// Lectura canal 0 "AN0". (Solo leemos el dato digitalizado)

Escritura(dato_recibido);

// Escribimos el dato a travs del bus I2c en el esclavo U3

read_adc(adc_start_only);

// Lanzamos el Conversor A/D.

Microcontroladores

IES Joan Mir

Pgina 136

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


/* ******************************************************* Motor Paso a Paso **************************************************** */
void Motor_PAP (void)
{
ra3 = 0;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 1 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 1;

// Posicionamos el Motor PAP en la 2 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 3 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 1;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 4 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 5 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 1;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 6 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 7 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 8 Posicin.

delay_ms(100);

// Retardo de 100 ms

/* **************************** Funcin de Escritura(int8 dato_recibido) **************************************************** */


void Escritura(int8 dato_recibido)
{
i2c_start();
i2c_write(0x4C);

i2c_write(dato_recibido);
i2c_stop();

// Inicializa la transmisin
// Seleccionar esclavo U3 en modo escritura. ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(110) por hardware.
// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.
// Dato a escribir
// Finalizacin de la transmisin.

Microcontroladores

IES Joan Mir

Pgina 137

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.1.3.2.- CAD_PCF8547_MULTIPLES.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: CAD_PCF8547_MULTIPLES.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Un programa principal controla un motor PAP.
//
//
El Conversor A/D interrumpe el programa principal digitalizando la patilla RA0
//
//
y llevar su resultado a el expansor de Bus paralelo PCF8574 (U7).
//
//
El expansor de Bus paralelo PCF8574 (U4) tambin interrumpe el programa
//
//
principal y sus datos son al expansor de Bus paralelo PCF8574 (U3)
//
//
El cristal de cuarzo tiene que ser de 20 MHz
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F876A.h>
#device adc=8

// Conversor Analgico Digital de 8 bit el PIC 16F876A puede


// trabajar con 8 o 10 bit de resolucin.

#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 20000000)

// Cambiar el reloj a 20 MHz

#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#BYTE TRISA = 0x85


#BYTE portA = 0x05

// TRISA en 85h.
// PORTA en 05h.

#BIT ra1 = 0x05.1


#BIT ra2 = 0x05.2
#BIT ra3 = 0x05.3
#BIT ra4 = 0x05.4
#BIT ra5 = 0x05.5

// RA1 en 0x05 patilla 1.


// RA2 en 0x05 patilla 2.
// RA3 en 0x05 patilla 3.
// RA4 en 0x05 patilla 4.
// RA5 en 0x05 patilla 5.

#BIT ta1 = 0x85.1


#BIT ta2 = 0x85.2
#BIT ta3 = 0x85.3
#BIT ta4 = 0x85.4
#BIT ta5 = 0x85.5

// TA1 en 0x85 patilla 1.


// TA2 en 0x85 patilla 2.
// TA3 en 0x85 patilla 3.
// TA4 en 0x85 patilla 4.
// TA5 en 0x85 patilla 5.

#BIT INTF = 0x0B.1

// INTF en 0x0B patilla 1.

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

#define U3 0x48
#define U7 0x4C
/* ************************************** Declaracin de funciones ************************************************************* */
void Escritura(int8, int8);
tipo entero de 8 bit)

// Declaramos la funcin Escritura (LLeva dos variable asociada de

int8 Lectura_Interruptores();

// Declaramos la funcin Lectura_Interruptores


// (Nos devuelve una variable tipo entero de 8 bit)

void Motor_PAP (void);


void Lectura_Escritura_AD_PCF8476(void);
void Lectura_Escritura_INT_PCF8476(void);

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
setup_adc_ports(14);
setup_adc(ADC_CLOCK_INTERNAL);

Microcontroladores

// Seleccionamos el PA0 como entrada Analgica y


// PA1..PA5 digitales. Mirar ADCON1.
// Fuente de reloj RC interno.

IES Joan Mir

Pgina 138

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


set_adc_channel(0);

// Habilitacin canal 0 "AN0"

ta1 = 0;
ta2 = 0;
ta3 = 0;
ta4 = 0;
ta5 = 0;

// Defines PA1 como SALIDA de datos.


// Defines PA2 como SALIDA de datos.
// Defines PA3 como SALIDA de datos.
// Defines PA4 como SALIDA de datos.
// Defines PA5 como SALIDA de datos.

ra1 = 0;
ra2 = 0;
ra3 = 1;
ra4 = 0;
ra5 = 1;

// Activamos el Motor PAP y encendemos LED.

port_b_pullups(TRUE);

// Habilitamos resistencias pullup.

enable_interrupts(int_ext);
ext_int_edge(H_TO_L);

// Habilitamos la interrupcin INT de la patilla RB0.


// Que la interrupcin de INT sea por flanco de BAJADA.

INTF = 1;

// Forzamos la Interrupcin.

enable_interrupts(int_ad);
enable_interrupts(GLOBAL);

// Habilitamos la interrupcin por Conversin A/D.


// Habilitamos la Interrupcin General.

read_adc(adc_start_only);

// Lanzamos el Conversor A/D.

while (1)

// Bucle infinito de espera.

{
Motor_PAP();

// Ejecuta la funcin Motor PAP.

}
}
/* **************************** Atencin a la interrupcin por Conversin A/D ********************************************* */
#INT_AD
void Lectura_Escritura_AD_PCF8476(void)
{
int8 dato_recibido;
delay_ms(10);

// Retardo de 10 mS. (No es necesario, solo se hace para


// dar tiempo al motor PAP a posicionarse)

dato_recibido = read_adc(adc_read_only);

// Lectura canal 0 "AN0". (Solo leemos el dato digitalizado)

Escritura(dato_recibido,U7);

// Escribimos el dato a travs del bus I2c en el esclavo U3

read_adc(adc_start_only);

// Lanzamos el Conversor A/D.

}
/* *************************************** Atencin a la interrupcin por cambio en RB0 *********************************** */
#INT_EXT
void Lectura_Escritura_INT_PCF8476(void)
{
int8 dato_recibido;
dato_recibido = Lectura_Interruptores();

// Leemos el dato a travs del bus I2c del esclavo U4

Escritura(~dato_recibido,U3);

// Escribimos el dato a travs del bus I2c en el esclavo U3

}
/* ************************** Funcin de Escritura(int8 dato_recibido, int8 esclavo) ************************************** */
void Escritura(int8 dato_recibido, int8 esclavo)
{
i2c_start();
i2c_write(esclavo);

Microcontroladores

// Inicializa la transmisin
// Seleccionar esclavo U3 en modo escritura.
// ( 0100,A2,A1,A0,0 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(100) por hardware.

IES Joan Mir

Pgina 139

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_write(dato_recibido);
i2c_stop();

// El ultimo bit a 0 para poner el C.I. PCF8476 en modo escritura.


// Dato a escribir
// Finalizacin de la transmisin.

}
/* *************************************** Funcin de int8 Lectura_Interruptores() ****************************************** */
int8 Lectura_Interruptores()
{
int8 data;
i2c_start();
i2c_write(0x41);

// Inicializa la recepcin.
// Seleccionar esclavo U4 en modo lectura. ( 0100,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8476.
// (A2,A1,A0)=(000) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8476 en modo lectura.

data=i2c_read(0);
i2c_stop();

// Lectura del dato


// Finalizacin de la transmisin.

return(data);
}
/* ********************************************* Motor Paso a Paso ************************************************************** */
void Motor_PAP (void)
{
ra3 = 0;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 1 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 1;

// Posicionamos el Motor PAP en la 2 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 0;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 3 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 1;
ra1 = 1;
ra5 = 0;

// Posicionamos el Motor PAP en la 4 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 0;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 5 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 1;
ra2 = 1;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 6 Posicin.

delay_ms(100);

// Retardo de 100 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 0;

// Posicionamos el Motor PAP en la 7 Posicin.

Microcontroladores

IES Joan Mir

Pgina 140

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


delay_ms(100);

// Retardo de 100 ms

ra3 = 1;
ra2 = 0;
ra1 = 0;
ra5 = 1;

// Posicionamos el Motor PAP en la 8 Posicin.

delay_ms(100);

// Retardo de 100 ms

5.3.8.1.2.- Conversor A-D_D-A_PCF8591.


El PCF8591 es un conversor
analgico/digital y digital/analgico con
salida I2C, est compuesto por un sistema
de adquisicin de datos con cuatro entradas
analgicas y un conversor digital/analgico.
Tres pines de direccin A0, A1 y A2
se utilizan para la programacin de la
direccin de hardware, permitiendo el uso
de ocho dispositivos conectados al bus I2C.
La resolucin es de 8 bit.

5.3.8.1.2.1.- PCF8591_ADC.
Utilizaremos el entrenador PCF8591_AD.DSN contenido en la carpeta de I2C\
Conversor A-D_D-A_PCF8591\ PCF8591_ADC

Microcontroladores

IES Joan Mir

Pgina 141

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.2.1.1.- I2C_CAD_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: I2C_CAD_1.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Conversin Analgica/Digital en formato I2C
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <flex_lcd.c>

#define PCF8591

#define CANAL

0b10011001
// 0x 9
9

0B00000000

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Incluimos el driver flex_lcd.c que contiene las
// funciones de control del LCD.

// Direccin I2C del PCF8591 (1001) identifica al C.I. PCF8591.


// Seleccionar esclavo U1 en modo lectura. ( 1001,A2,A1,A0,1 )
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8591 en modo lectura.
// Seleccionamos el PCF8591 como C A/D y el Canal AIN0

/* ************************ Funcin principal o programa principal ******************************* */


void main()
{
int8 q;
float v1;
lcd_init();

// Inicializamos el LCD.

i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591&0B11111110);

// Enva direccin I2C del dispositivo en modo escritura

i2c_write(CANAL);

// Seleccionamos el canal y modo conversin A/D.

while (1)
{

// Bucle infinito de espera


i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591);

// Enva direccin I2C del dispositivo en modo lectura

q=i2c_read(0);

// Lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

v1 = 5.0 * q / 256.0;

// Conversin a tensin del cdigo digital "q".

lcd_gotoxy(1,1);
printf(lcd_putc,"V1=%3.1gv",v1);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1 .


// Visualiza sobre la pantalla LCD la lectura de V1

lcd_gotoxy(1,2);
printf(lcd_putc,"q=%3u",q);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .


// Visualiza sobre la pantalla LCD la lectura de q "Cdigo
// digital proporcional a la tensin"

}
}

Microcontroladores

IES Joan Mir

Pgina 142

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.2.1.2.- I2C_CAD_2.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: I2C_CAD_2.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Conversin Analgica/Digital en formato I2C de los 4 canales AIN0..3
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <flex_lcd.c>

#define AIN0 0
#define AIN1 1
#define AIN2 2
#define AIN3 3

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Incluimos el driver flex_lcd.c que contiene las
// funciones de control del LCD.

// Eleccin del Canal 0 y modo conversin A/D.


// Eleccin del Canal 1 y modo conversin A/D.
// Eleccin del Canal 2 y modo conversin A/D.
// Eleccin del Canal 3 y modo conversin A/D.

// ************************************************** Declaracin de Funciones ***************************************************


float Leer_PCF8591(int8);

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int8 entrada_analogica;
lcd_init();
while (1)
{

// Inicializamos el LCD.
// Bucle infinito de espera

entrada_analogica=AIN0;
lcd_gotoxy(1,1);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1.

printf(lcd_putc,"V1=%3.1gv",Leer_PCF8591(entrada_analogica));

// Visualiza sobre la pantalla


// LCD la lectura del canal 0
// AIN0

entrada_analogica=AIN1;
lcd_gotoxy(9,1);

// Posicionamos el Cursor del LCD en la posicin 9 lnea 1.

printf(lcd_putc,"V2=%3.1gv",Leer_PCF8591(entrada_analogica));

// Visualiza sobre la pantalla


// LCD la lectura del canal 1
// AIN1

entrada_analogica=AIN2;
lcd_gotoxy(1,2);

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2 .

printf(lcd_putc,"V3=%3.1gv",Leer_PCF8591(entrada_analogica));

// Visualiza sobre la pantalla


// LCD la lectura del canal 2
// AIN2

entrada_analogica=AIN3;
lcd_gotoxy(9,2);

// Posicionamos el Cursor del LCD en la posicin 9 lnea 2 .

printf(lcd_putc,"V4=%3.1gv",Leer_PCF8591(entrada_analogica));

// Visualiza sobre la pantalla


// LCD la lectura del canal 3
// AIN3

}
}

Microcontroladores

IES Joan Mir

Pgina 143

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


// ***************************************** Funcin floatint8 Leer_PCF8159(int8) **********************************************
float Leer_PCF8591(int8 canal)
#define PCF8591

0b10011001
// 0x 9
9

// Direccin I2C del PCF8591 (1001) identifica al C.I. PCF8591.


// Seleccionar esclavo U1 en modo lectura. ( 1001,A2,A1,A0,1 )
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8591 en modo lectura.

{
int8 q;
float v;
i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591&0B11111110);

// Enva direccin I2C del dispositivo en modo escritura

i2c_write(canal);

// Seleccionamos el canal y modo conversin A/D.

//********************************************* Leer Canal ************************************************************


i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591);

// Enva direccin I2C del dispositivo en modo lectura

q=i2c_read(0);

// Lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

//********************************************* Leer Canal ************************************************************


i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591);

// Enva direccin I2C del dispositivo en modo lectura

q=i2c_read(0);

// Lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

//********************************* Convertir el cdigo digital en tensin *******************************************


v = 5.0 * q / 256.0;

// Conversin a tensin del cdigo digital "q".

return(v);
}

5.3.8.1.2.2.- PCF8591_DAC.
Utilizaremos el entrenador PCF8591_DA.DSN contenido en la carpeta de I2C\
Conversor A-D_D-A_PCF8591\ PCF8591_DAC

Microcontroladores

IES Joan Mir

Pgina 144

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.8.1.2.2.1.- I2C_CDA_1.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: I2C_CDA_1.c
//
// Plataforma hw: Placa Monibot
//
// Fecha........: Septiembre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Conversin Analgica/Digital y Digital/Analgica en formato I2C
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <flex_lcd.c>

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Incluimos el driver flex_lcd.c que contiene las
// funciones de control del LCD.

#define AIN0 0
#define AIN1 1
#define AIN2 2
#define AIN3 3

// Eleccin del Canal 0 y modo conversin A/D.


// Eleccin del Canal 1 y modo conversin A/D.
// Eleccin del Canal 2 y modo conversin A/D.
// Eleccin del Canal 3 y modo conversin A/D.

// ********************************************** Declaracin de Funciones *******************************************************


int8 Leer_U2_PCF8591(int8);
void Escribir_U1_PCF8591(int8);

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int8 entrada_analogica,q1;
float v;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


entrada_analogica=AIN1;
q1=Leer_U2_PCF8591(entrada_analogica);

// Leemos el Cdigo digital proporcional a la seal


// analgica de la patilla AIN1

v = 5.0 * q1 / 256.0;
lcd_gotoxy(1,1);

// Conversin a tensin del cdigo digital "q1".


// Posicionamos el Cursor del LCD en la posicin
// 1 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura de v.

printf(lcd_putc,"V1=%3.1gv",v);
Escribir_U1_PCF8591(q1);

// Obtenemos una seal analgica proporcional al


// cdigo digital q1.

}
}
// ***************************************** Funcin int8 Leer_U2_PCF8159(int8) ***********************************************
int8 Leer_U2_PCF8591(int8 canal)
#define PCF8591_U2

0b10011001
// 0x 9
9

// Direccin I2C del PCF8591_U2 (1001) identifica al C.I. U2 PCF8591.


// Seleccionar esclavo U1 en modo lectura. ( 1001,A2,A1,A0,1 )
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8591 en modo lectura.

{
int8 q;

Microcontroladores

IES Joan Mir

Pgina 145

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591_U2&0B11111110);

// Enva direccin I2C del dispositivo en modo escritura

i2c_write(canal);

// Seleccionamos el canal y modo conversin A/D.

//********************************************* Leer Canal ************************************************************


i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591_U2);

// Enva direccin I2C del dispositivo en modo lectura

q=i2c_read(0);

// Lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

//********************************************* Leer Canal ************************************************************


i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591_U2);

// Enva direccin I2C del dispositivo en modo lectura

q=i2c_read(0);

// Lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

/ /Secuencia de stop

return(q);
}
// ***************************************** Funcin Escribir_U1_PCF8159(int8) ************************************************
void Escribir_U1_PCF8591(int8 dato)
#define PCF8591_U1

0B10010011
// 0x 9 3

// Direccin I2C del PCF8591_U1 (1001) identifica al C.I. U1 PCF8591.


// Seleccionar esclavo U1 en modo lectura. ( 1001,A2,A1,A0,1 )
// (A2,A1,A0)=(001) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8591 en modo lectura.

{
i2c_start();

// Enva secuencia de inicio

i2c_write(PCF8591_U1&0B11111110);

// Enva direccin I2C del dispositivo en modo escritura

i2c_write(0B01000000);

// Seleccionamos el modo conversin D/A.

i2c_write(dato);

// Enva el contenido de la variable dato y se convierte en


// seal analgica.
// Enva el contenido de la variable dato y se convierte en
// seal analgica.
// Secuencia de stop

i2c_write(dato);
i2c_stop();
}

Microcontroladores

IES Joan Mir

Pgina 146

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.- Sensores y Hardware.
5.3.9.1.- Sensores de Infrarrojos CNY70.
El CNY70 es un sensor de infrarrojos de corto alcance basado en un emisor de luz y un
receptor, ambos apuntando en la misma direccin, y cuyo funcionamiento se basa en la
capacidad de reflexin del objeto, y la deteccin del rayo reflectado por el receptor.
3
A

CNY70

Vista externa y circuitos internos del sensor CNY70


Funcionamiento:

R1= 220
I1

R2= 47K

I3

74HC14

I2
CNY70

E1= 5V

Diodo
Emisor
de Luz

Optotransistor
Cortado

V1= 5V

Luz Infrarroja

V2= 0V

Lnea negra absorbe la luz

I3
R1= 220
I1

R2= 47K
Ic

I2

I4

74HC14

CNY70
E1= 5V

Diodo
Emisor
de Luz

Luz Infrarroja

Optotransistor
Saturado

V1= 0V

V2= 5V

Lnea blanca refleja la luz

Utilizaremos el entrenador Robot Rastreador_Monibot.DSN contenido en la carpeta de


Sensores y Hardware\ CNY70.

Microcontroladores

IES Joan Mir

Pgina 147

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

5.3.9.1.1.- Prueba_Sensores_CNY70.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Prueba_Sensores_CNY70.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Mayo-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Leer los sensores CNY70 y visualizarlo en el LCD.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay( clock = 1000000 )

// Reloj de 1 MHz

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones


// de control del LCD.

#BYTE TRISA = 0x85


#BYTE PORTA = 0x05

// TRISA en 85h.
// PORTA en 05h.

#BYTE TRISD = 0x88


#BYTE PORTD = 0x08

// TRISD en 88h.
// PORTD en 08h.

#BIT rd0 = 0x08.0


#BIT rd1 = 0x08.1
#BIT rd2 = 0x08.2
#BIT rd3 = 0x08.3
#BIT ra4 = 0x05.4
#BIT ra5 = 0x05.5

// RD0 en 0x08 patilla 0.


// RD1 en 0x08 patilla 1.
// RD2 en 0x08 patilla 2.
// RD3 en 0x08 patilla 3.
// RA4 en 0x05 patilla 4.
// RA5 en 0x05 patilla 5.

// ****************************** Funcin principal o programa principal ****************************


// Se define con un void main,
void main()
{
lcd_Init();

Microcontroladores

// Inicializamos el LCD.

IES Joan Mir

Pgina 148

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


TRISA = 0B11111111;
TRISD = 0B00001111;

// Defines Puerto A como ENTRADA de datos.


// Configurar el Puerto D como ENTRADAS (RD3..0) y
// SALIDAS (RD7..4) de datos.

while (1)
{
lcd_gotoxy(6,1);

// Posicionamos el Cursor del LCD en la posicin


// 6 lnea 1 .
// Escribimos 1 dgitos de la variables "rd3 y rd2"
// invertidas en formato entero y sin signo.

printf(lcd_putc,"%2u%2u",~rd3,~rd2);

lcd_gotoxy(3,2);

// Posicionamos el Cursor del LCD en la


// posicin 3 lnea 2 .

printf(lcd_putc,"%2u%2u%4u%2u",~ra5,~ra4,~rd1,~rd0);

// Escribimos 1 dgitos de la variables


// "ra5, ra4, rd1 y rd0" invertidas en
// formato entero y sin signo.

}
}

5.3.9.2.- Sensores de Distancia.


5.3.9.2.1.- Sensor de Infrarrojos GP2D12.
Los IR Sharp GP2DXX son una familia de sensores de infrarrojos para la
deteccin y medida de distancia a los objetos.
Proporciona una tensin en funcin de la distancia (0-3V)
Rango de medida de 10 a 80 cm con una respuesta en 39 mS.

Estos dispositivos emplean el mtodo de triangulacin


utilizando un pequeo Sensor Detector de Posicin (PSD) lineal para
determinar la distancia o la presencia de los objetos dentro de su
campo de visin. Bsicamente su modo de funcionamiento consiste
en la emisin de un pulso de luz infrarroja, que se transmite a travs
de su campo de visn que se refleja contra un objeto o que por el
contrario no lo hace. Si no encuentra ningn obstculo, el haz de luz
no refleja y en la lectura que se hace indica que no hay ningn
obstculo. En el caso de encontrar un obstculo el haz de luz
infrarroja se reflecta y crea un triangulo formado por el emisor, el
punto de reflexin (obstculo) y el detector.
La informacin de la distancia se extrae midiendo el ngulo
recibido. Si el ngulo es grande, entonces el objeto est cerca, por
que el triangulo es ancho. Si el ngulo es pequeo, entonces el

Microcontroladores

IES Joan Mir

Pgina 149

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


objeto est lejos, por que el triangulo formado es estrecho. Por lo tanto, si el ngulo es
pequeo, quiere decir que el objeto est lejos, porque el triangulo es largo y delgado.
El LED infrarrojo emite el has de luz a travs
de una pequea lente convergente que hace que el
haz emisor llegue de forma paralela al objeto.
Cuando la luz choca con un obstculo, una cierta
cantidad de luz se refleja, si el obstculo fuera un
espejo perfecto , todos los rayos del haz de luz
pasaran, y sera imposible medir la distancia. Sin
embargo, casi todas las sustancias tienen un grado
bastante grande de rugosidad de la superficie que
produce una dispersin hemisfrica de la luz ( la
llamada reflexin no terica). Alguno de estos haces
de esta luz rebota hacia el sensor que es recibido por
la lente.
La lente receptora tambin es una lente convexa, pero ahora sirve para un propsito
Diferente. Acta para convertir el ngulo de posicin. Si un objeto se pone en el plano
focal de una lente convexa y los otros rayos de luz paralelos en otro lado, el rayo que
pasa por el centro de la lente atraviesa inalterado o marca el lugar focal. Los rayos
restantes tambin enfocan a este punto.
Puesto en el plano focal es un Sensor Detector de Posicin (PSD). ste dispositivo
semiconductor entrega una salida cuya intensidad es proporcional a la posicin respecto
al centro (centro eficaz) de la luz que incide en l. En el caso del GP2D12, los
rendimientos de PSD la salida es proporcional a la posicin del punto focal. Esta seal
analgica tratada es la que se obtiene a la salida del sensor.
Consideraciones Prcticas

Las lentes del dispositivo deben de


estar siempre limpias, no utilizar
para su limpieza agua o aceite.

Cuando la superficie del detector


recibe la luz directa del sol o de
una lmpara de tungsteno, puede
darse el caso de que no se pueda
medir la distancia. Tener
esto en cuenta para que el
detector no reciba la luz directa de
una fuente de luz potente.

Para estabilizar la tensin de


alimentacin del dispositivo, se
recomienda conectar un
condensador de 10 mF o ms
entre VCC y GND cerca del
GP2D12.

La ecuacin que relaciona la distancia d con la tensin v es una ecuacin de


4 grado para una distancia desde (10 cm hasta 80 cm):

d= 16,75 v4 119,26 v3 + 311,7 v2 - 365,71 v + 183,03


Utilizaremos el entrenador Monibot_GP2D12.DSN contenido en la carpeta de
Sensores y Hardware\ GP2D12.

Microcontroladores

IES Joan Mir

Pgina 150

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

5.3.9.2.1.1.- Lectura_S1_GP2D12.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_GP2D12.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de un sensor GP2D12
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// *********************************** Directivas de Preprocesado ************************************
#include <16F877A.h>
#device adc=10

// Conversor Analgico Digital de 10 bit el PIC 16F876A puede


// trabajar con 8 o 10 bit de resolucion.

#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <flex_lcd.c>
#include <driver2_GP2D12.c>
// #include <driver1_GP2D12.c>

// Incluimos el driver "flex_lcd.c" que contiene las funciones de


// control del LCD.
// Incluimos el driver "driver2_GP2D12.c" que contiene la funcin de
// control del GP2D12. Curva matemtica
// Incluimos el driver "driver1_GP2D12.c" que contiene la funcin de
// control del GP2D12. Aproximacin por rectas.

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int16 q;
float d,v;
setup_adc_ports(2);
setup_adc(ADC_CLOCK_INTERNAL);
lcd_init();
for (;;)
{

Microcontroladores

// Seleccionamos el Puerto A como entradas Analgicas.


// Mirar ADCON1.
// Fuente de reloj RC interno.
// Inicializamos el LCD.
// Bucle infinito.

IES Joan Mir

Pgina 151

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


set_adc_channel(0);
delay_us(20);

// Habilitacin canal 0 "AN0"


// Retardo de 20uS necesaria para respetar el tiempo de
// adquisicin Tad.
// Lectura canal 0 "AN0"
// Conversin a tensin del cdigo digital "q".

q = read_adc();
v = (5.0 * q) / 1024.0;
d=Gp2d12_v_d(v);
lcd_gotoxy(1,1);
printf(lcd_putc, "Voltios = %2.1fV", v);
lcd_gotoxy(1,2);
printf(lcd_putc, "S1 = %5.1fcm",d );

// Posicionamos el Cursor en la posicin 1, lnea 1.


// Escribimos en el LCD "Voltios =" y 3 dgitos de "v"
// en formato truncado con 1 decimales y el carcter "V".
// Posicionamos el Cursor en la posicin 1, lnea 2.
// Saltamos de lnea y escribimos en el LCD "d =" y 6
// dgitos de "d" en formato truncado de 6 dgitos con
// 1 decimal y los caracteres "cm".

}
}

5.3.9.2.1.2.- Lectura_S1_GP2D12.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_S2_GP2D12.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de dos sensor GP2D12
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ******************************* Directivas de Preprocesado ****************************************
#include <16F877A.h>
#device adc=10

// Conversor Analgico Digital de 10 bit el PIC 16F876A puede


// trabajar con 8 o 10 bit de resolucin.

#FUSES XT,NOWDT
#use delay(clock=4000000)
#include <flex_lcd.c>
#include <driver2_GP2D12.c>
// #include <driver1_GP2D12.c>

// Incluimos el driver "flex_lcd.c" que contiene las funciones de control


// del LCD.
// Incluimos el driver "driver2_GP2D12.c" que contiene la funcin de
// control del GP2D12. Curva matemtica
// Incluimos el driver "driver1_GP2D12.c" que contiene la funcin de
// control del GP2D12. Aproximacin por rectas

//******************************* PROGRAMA PRINCIPAL *********************************************


void main()
{
int16 q;
float d, v;
setup_adc_ports(2);
setup_adc(ADC_CLOCK_INTERNAL);
lcd_init();
for (;;)
{

// Seleccionamos el Puerto A como entradas analgicas.


// Mirar ADCON1.
// Fuente de reloj RC interno.
// Inicializamos el LCD.
// Bucle infinito.

set_adc_channel(0);
delay_us(20);
q = read_adc();
v = (5.0 * q) / 1024.0;
d=Gp2d12_v_d(v);

// Habilitacin canal 0 "AN0"


// Retardo de 20uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 0 "AN0"
// Conversin a tensin del cdigo digital "q".

lcd_gotoxy(1,1);
printf(lcd_putc, "S1 = %4.1fcm",d );

// Posicionamos el Cursor en la posicin 1, lnea 1.


// Escribimos en el LCD "S1 =" y 4 dgitos de "d"
// en formato truncado con 1 decimal y los caracteres "cm".

set_adc_channel(1);
delay_us(20);

// Habilitacin canal 0 "AN1"


// Retardo de 20uS necesaria para respetar el tiempo de
// Adquisicin Tad.
// Lectura canal 0 "AN0"
// Conversin a tensin del cdigo digital "q".

q = read_adc();
v = (5.0 * q) / 1024.0;

Microcontroladores

IES Joan Mir

Pgina 152

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


d=Gp2d12_v_d(v);
lcd_gotoxy(1,2);
printf(lcd_putc, "S2 = %4.1fcm",d );

// Posicionamos el Cursor en la posicin 1, lnea 2.


// Escribimos en el LCD "S2 =" y 4 dgitos de "d"
// en formato truncado con 1 decimal y los caracteres "cm".

}
}

5.3.9.2.1.3.- driver1_GP2D12.c
//*********** Driver de Control del Sensor de Infrarrojos Gp2d12, para una distancia
//*********** entre 8 cm y 55 cm.*
// Se obtiene una distancia "d" (Formato float) en funcin de la tensin "v" (Formato float).
// Se realiza aproximaciones a la curva con rectas.
// Ecuacin de la recta con dos puntos:
// d=d1+[(v-v1)/(v2-v1)](d2-d1)
// Mirar archivo Ecuacin de la Recta.
//******************************** DECLARACIN DE FUNCIONES***************************************************************
float Gp2d12_v_d(float);
//***********************************************FUNCIN Gp2d12_v_d************************************************************
float Gp2d12_v_d(float v)
{
float l;
l=0;
if(v>2.6)
else if(v<2.6&&v>=1.9)
else if(v<1.9&&v>=1.65)
else if(v<1.65&&v>=1.38)
else if(v<1.38&&v>=1.15)
else if(v<1.15&&v>=0.95)
else if(v<0.95&&v>=0.75)
else if(v<0.75&&v>=0.68)
else if(v<0.68&&v>=0.58)
else if(v<0.58)
return(l);

l = 8;
l = 13.5 + ((8-13.5)* (v - 1.9) /(2.6-1.9));
l = 16 + ((13.5-16)* (v- 1.65) / (1.9-1.65));
l = 20 + ((16-20)* (v- 1.38) / (1.65-1.38));
l = 25 + ((20-25)* (v- 1.15) / (1.38-1.15));
l = 30 + ((25-30)* (v- 0.95) / (1.15-0.95));
l = 40 + ((30-40)* (v- 0.75) / (0.95-0.75));
l = 45 + ((40-45)* (v- 0.68) / (0.75-0.68));
l = 55 + ((45-55)* (v- 0.58) / (0.68-0.58));
l=55;

5.3.9.2.1.4.- driver2_GP2D12.c
//********* Driver de Control del Sensor de Infrarrojos Gp2d12, para una distancia entre
//********* 8 cm y 55 cm.
// Se obtiene una distancia "d" (Formato float)en funcin de la tensin "v"(Formato float).
// Se utiliza una ecuacin de 4 grado.
//****************************** DECLARACIN DE FUNCIONES ****************************************************************
float Gp2d12_v_d(float);
//****************************************FUNCIN Gp2d12_v_d ******************************************************************
float Gp2d12_v_d(float v)
{
float i; //variable auxiliar de cuenta
float r;
float s;
float d;
r=v*v;
s=v*v*v;
i=v*v*v*v;
d=((16.75*i)-119.26*s)+(311.7*r)-(365.71*v)+183.03;
return(d);
}

Microcontroladores

IES Joan Mir

Pgina 153

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.2.2.- Sensor de Ultrasonidos SRF08.
El mdulo SRF08 consiste en un medidor ultrasnico
de distancia de bajo costo desarrollado por la firma
DEVANTECH Ltd. y es una versin mejorada del mdulo
SRF04. Emplea un microcntrolador PIC16F872 que realiza
todas las funciones de control e interface, dos capsulas
ultrasnicas de 40 KHz y una clula LDR capaz de
proporcionar una medida de luz ambiente.

Se comunica va I2C.

Reducido consumo (3 mA en Standby 15 mA en


funcionamiento).

Es capaza de medir diferentes ecos recibidos por la


seal ultrasnica.

La ganancia de los amplificadores internos son


ajustables al igual que el rango de medidas.

Ofrece una lectura directa (centmetros, pulgadas o


microsegundos)

Un diodo led en la parte posterior del mdulo genera un cdigo de intermitencias que
expresa la direccin del I2C actual del mdulo as com el inicio de una nueva medida.

La direccin del mdulo es por defecto 0XE0, aunque existe la posibilidad de cambiarla
por otras 15 (0XE2, 0XE4, 0XE6, 0XE8, 0XEA, 0XEC, 0XEE, 0XF0, 0XF2, 0XF4, 0XF6,
0XF8, 0XFA, 0XFC o 0XFE. Esto permite controlar hasta 16 mdulo SRF08 con el bus
I2C.

Adems de las direcciones anteriores, todos los sonares conectados al bus I2C
respondern a la direccin 0x00 de llamada general. Esto significa que escribir un
comando de medicin de la distancia para la direccin 0x00 de I2C,iniciar las
mediciones en todos los sensores al mismo tiempo. Esto es til en el modo ANN (Red
Neuronal Artificial). Los resultados deben leerse de manera individual de cada uno de
las direcciones reales de los sensores.

Utilizaremos el entrenador Monibot_SRF08.DSN contenido en la carpeta de Sensores


y Hardware\ SRF08.
Nota: El sensor SFR08 no est simulado utilizaremos dos driver que tienen las mismas
funciones.

driver_PCF8591.c (Vlido para la simulacin)


driver_SRF08.c
(Real)

Microcontroladores

IES Joan Mir

Pgina 154

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

5.3.9.2.2.1.- Lectura_S1_SRF08_Real.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_SRF08_Real.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Lectura de un Sensor SRF08
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************* Directivas de Preprocesado **********************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware

interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las


// funciones de control del LCD.

#define SRF08

// Direccin I2C del SRF08

0xE2

/* ************************************************* Declaracin de funciones ************************************************** */


int16 Lectura_SRF08(void);
variable tipo entero de 8 bit)

Microcontroladores

// Declaramos la funcin Lectura_Interruptores (Nos devuelve una

IES Joan Mir

Pgina 155

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


/* *************************** Funcin principal o programa principal **************************** */
void main()
{
int16 dato_recibido;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


dato_recibido = Lectura_SRF08();
lcd_gotoxy(1,1);
printf(lcd_putc,"%03lu cm",dato_recibido);

// Leemos el dato a travs del bus I2c del


// esclavo U4
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// sensor (3 dgitos)

}
}
/* ************************************* Funcin de int16 Lectura_SRF08() *************************************************** */
int16 Lectura_SRF08()
#define SRF08_cm 0x51
{
int16 resultado=0;
int8 byte_alto=0;
int8 byte_bajo=0;

// Medida en cm

i2c_start();
i2c_write(SRF08);
i2c_write(0x00);
i2c_write(SRF08_cm);
i2c_stop();
delay_ms(70);

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura
// Direccin interna 0x00 (registro de comandos)
// Enviar comando a ejecutar, lectura en cm
// Secuencia de stop
// Temporizacin de 70mS necesaria para realizar la ejecucin

i2c_start();
i2c_write(SRF08);
i2c_write(0x02);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Enva direccin interna del dispositivo, nos posicionamos en el
// registro del 1 eco
// Enva secuencia de stop

i2c_start();
i2c_write(SRF08|0b00000001);

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura

byte_alto=i2c_read();

// No, leer el byte, enviar ACK y almacenar en el buffer

byte_bajo=i2c_read(0);

// Si, lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

//Secuencia de stop

resultado=make16(byte_alto, byte_bajo);

// Convierte parta alta y baja en un entero de 16 bit

return (resultado);
}

5.3.9.2.2.2.- Lectura_S1_S2_SRF08_Real.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_S2_SRF08_Real.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Lectura de dos Sensor SRF08
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************** Directivas de Preprocesado *********************************
#include <16F876A.h>

Microcontroladores

IES Joan Mir

Pgina 156

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <LCD1.c>

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Incluimos el driver LCD1.c que contiene las
// funciones de control del LCD.

#define SENSOR_1
#define SENSOR_2

0xE4
0xE2

// Direccin I2C del Sensor 1 SRF08


// Direccin I2C del Sensor 2 SRF08

/* *********************************************** Declaracin de funciones **************************************************** */


int16 Lectura_SRF08(int8);

// Declaramos la funcin Lectura_Interruptores


// (Nos devuelve una variable tipo entero de 8 bit)

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int16 dato_recibido;
int8 sensor;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


sensor=SENSOR_2;
dato_recibido = Lectura_SRF08(sensor);
lcd_gotoxy(1,1);
printf(lcd_putc,"S2=%03lu",dato_recibido);

sensor=SENSOR_1;
dato_recibido = Lectura_SRF08(sensor);
lcd_gotoxy(9,1);
printf(lcd_putc,"S1=%03lu",dato_recibido);

// Leemos el dato a travs del bus I2c del


// Sensor 2
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 2

// Leemos el dato a travs del bus I2c del


// Sensor 1
// Posicionamos el Cursor del LCD en la
// posicin 9 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 1

}
}
/* *************************************** Funcin de int8 Lectura_SRF08() ************************************************** */
int16 Lectura_SRF08(int8 SRF08)
#define SRF08_cm 0x51
{
int16 resultado=0;
int8 byte_alto=0;
int8 byte_bajo=0;

// Medida en cm

i2c_start();
i2c_write(SRF08);
i2c_write(0x00);
i2c_write(SRF08_cm);
i2c_stop();
delay_ms(20);

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura
// Direccin interna 0x00 (registro de comandos)
// Enviar comando a ejecutar, lectura en cm
// Secuencia de stop
// Temporizacin de 80mS necesaria para realizar la ejecucin

i2c_start();
i2c_write(SRF08);
i2c_write(0x02);

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Enva direccin interna del dispositivo, nos posicionamos en el
// registro del 1 eco
// Enva secuencia de stop

i2c_stop();

Microcontroladores

IES Joan Mir

Pgina 157

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_start();
i2c_write(SRF08|0b00000001);

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura

byte_alto=i2c_read();
byte_bajo=i2c_read(0);
i2c_stop();

// No, leer el byte, enviar ACK y almacenar en el buffer


// Si, lee ltimo byte, enva NACK y almacena en el buffer
// Secuencia de stop

resultado=make16(byte_alto, byte_bajo);

// Convierte parta alta y baja en un entero de 16 bit

return(resultado);
}

5.3.9.2.2.3.- Lectura_S1_S2_SRF08_Real_Simulado.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_S2_SRF08_Real_Simulado.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Lectura de dos Sensor SRF08 real y simulado
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************* Directivas de Preprocesado***********************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <driver_SRF08.c>
// #include <driver_PCF8591.c>
// #include <driver_Luz_Distancia_SRF08.c>
#include <flex_lcd.c>

#define SENSOR_1
#define SENSOR_2

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Real
// Simulado
// Simulado
// Incluimos el driver LCD1.c que contiene las
// funciones de control del LCD.

0xE4
0xE2

// Direccin I2C del Sensor 1 SRF08


// Direccin I2C del Sensor 2 SRF08

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int16 dato_recibido;
int8 sensor;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


sensor=SENSOR_1;
dato_recibido = Lectura_SRF08(sensor);
lcd_gotoxy(1,1);
printf(lcd_putc,"S1=%03lu",dato_recibido);
sensor=SENSOR_2;
dato_recibido = Lectura_SRF08(sensor);
lcd_gotoxy(9,1);
printf(lcd_putc,"S2=%03lu",dato_recibido);

// Leemos el dato a travs del bus I2c del


// Sensor 1
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 1
// Leemos el dato a travs del bus I2c del
// Sensor 2
// Posicionamos el Cursor del LCD en la
// posicin 9 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 2

}
}

Microcontroladores

IES Joan Mir

Pgina 158

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.2.2.4.- Lectura_S1_SRF08_Distancia_Lumenes.c
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_SRF08_Distancia_Lumenes.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Lectura de dos Sensor SRF08 real y simulado
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************* Directivas de Preprocesado **********************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

// #include <driver_SRF08.c>
// #include <driver_PCF8591.c>
#include <driver_Luz_Distancia_SRF08.c>

// Real
// Simulado
// Simulado

#include <flex_lcd.c>

// Incluimos el driver LCD1.c que contiene las


// funciones de control del LCD.

#define SENSOR_1

0xE2

// Direccin I2C del Sensor 1 SRF08

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int16 distancia;
int8 luz;
int8 sensor;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


sensor=SENSOR_1;
distancia = Lectura_SRF08(sensor);
lcd_gotoxy(1,1);
printf(lcd_putc,"S1=%03lu cm",distancia);
luz = Lectura_Lumenes_SRF08(sensor);
lcd_gotoxy(1,2);
printf(lcd_putc,"S1=%03u lumenes",luz);

// Leemos el dato a travs del bus I2c del


// Sensor 1
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 1
// Leemos el dato a travs del bus I2c del
// Sensor 1
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 2 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 1

}
}

5.3.9.2.2.5.- driver SRF08.c


/* **************************************** driver SRF08.c ******************************************** */
#define SRF08_cm 0x51

// Medida en cm

/* ************************************************ Declaracin de funciones *************************************************** */


int16 Lectura_SRF08(int8);

Microcontroladores

// Declaramos la funcin Lectura_SRF08


// (Nos devuelve una variable tipo entero de 8 bit)

IES Joan Mir

Pgina 159

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


/* *************************************** Funcin de int8 Lectura_SRF08() ************************************************** */
int16 Lectura_SRF08(int8 SRF08)
{
int16 resultado=0;
int8 byte_alto=0;
int8 byte_bajo=0;
//************************************ Seleccionamos el dispositivo SRF08 *****************************************
i2c_start();
i2c_write(SRF08);

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura

//**** Seleccionamos el registro de Comandos e indicamos que vamos a realizar una lectura en cm ****
i2c_write(0x00);
i2c_write(SRF08_cm);
i2c_stop();

// Direccin interna 0x00 (registro de comandos)


// Enviar comando a ejecutar, lectura en cm
// Secuencia de stop

//******************************* Esperamos un tiempo mnimo de 70 mS ******************************************


delay_ms(70);

// Temporizacin de 70mS necesaria para realizar la ejecucin

//************************************ Seleccionamos el dispositivo SRF08 *****************************************


i2c_start();
i2c_write(SRF08);

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura

//*************************************** Nos posicionamos en el 1 Eco *********************************************


i2c_write(0x02);
i2c_stop();

// Enva direccin interna del dispositivo, nos posicionamos en el


// registro del 1 eco
// Enva secuencia de stop

//********************** Leemos los datos obtenidos del sensor (Byte Alto y Byte Bajo) **********************
i2c_start();
i2c_write(SRF08|0b00000001);

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura

byte_alto=i2c_read();

// No, leer el byte, envar ACK y almacenar en el buffer

byte_bajo=i2c_read(0);

// Si, lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

resultado=make16(byte_alto,byte_bajo);

// Convierte parta alta y baja en un entero de 16 bit

return(resultado);
}

5.3.9.2.2.6.- driver_Luz_Distancia_SRF08.c
/* ********************************* driver_Luz_Distancia_SRF08.c ******************************** */
#define SRF08_cm 0x51
#define SRF08_Lumenes 0x01

// Medida en cm
// Medida en Lumenes

/* ************************************************ Declaracin de funciones *************************************************** */


int16 Lectura_SRF08(int8);
int8 Lectura_Lumenes_SRF08(int8);

// Declaramos la funcin Lectura_SRF08


// (Nos devuelve una variable tipo entero de 8 bit)
// Declaramos la funcin Lectura_ Lumenes_SRF08
// (Nos devuelve una variable tipo entero de 8 bit)

/* *************************************** Funcin de int8 Lectura_SRF08() ************************************************** */


int16 Lectura_SRF08(int8 SRF08)
{
int16 resultado=0;
int8 byte_alto=0;
int8 byte_bajo=0;
//************************************ Seleccionamos el dispositivo SRF08 *****************************************

Microcontroladores

IES Joan Mir

Pgina 160

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_start();
i2c_write(SRF08);

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura

//**** Seleccionamos el registro de Comandos e indicamos que vamos a realizar una lectura en cm ****
i2c_write(0x00);
i2c_write(SRF08_cm);
i2c_stop();

// Direccin interna 0x00 (registro de comandos)


// Enviar comando a ejecutar, lectura en cm
// Secuencia de stop

//******************************* Esperamos un tiempo mnimo de 70 mS *****************************************


delay_ms(70);

// Temporizacin de 65mS necesaria para realizar la ejecucin

//************************************ Seleccionamos el dispositivo SRF08 *****************************************


i2c_start();
i2c_write(SRF08);

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura

//*************************************** Nos posicionamos en el 1 Eco *********************************************


i2c_write(0x02);
i2c_stop();

// Enva direccin interna del dispositivo, nos posicionamos


// en el registro del 1 eco
// Enva secuencia de stop

//*********************Leemos los datos obtenidos del sensor (Byte Alto y Byte Bajo) ************************
i2c_start();
i2c_write(SRF08|0b00000001);

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura

byte_alto=i2c_read();

// No, leer el byte, envar ACK y almacenar en el buffer

byte_bajo=i2c_read(0);

// Si, lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

resultado=make16(byte_alto,byte_bajo);

// Convierte parta alta y baja en un entero de 16 bit

return(resultado);
}
/* ******************************** Funcin de int8 Lectura_Lumenes_SRF08(int8 SRF08) ******************************* */
int8 Lectura_Lumenes_SRF08(int8 SRF08)
{
int8 lumenes=0;
//************************************ Seleccionamos el dispositivo SRF08 *****************************************
i2c_start();
i2c_write(SRF08);

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura

//* Seleccionamos el registro de Comandos e indicamos que vamos a realizar una lectura en Lumenes
i2c_write(SRF08_Lumenes);
i2c_stop();

// Enviar comando a ejecutar, lectura


// Secuencia de stop

//************************************ Leemos el dispositivo SRF08 **************************************************


i2c_start();

// Secuencia de inicio

i2c_write(SRF08|0b00000001);

// Enva direccin I2C del dispositivo en modo lectura

lumenes=i2c_read(0);

// Si, lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

return(lumenes);
}

Microcontroladores

IES Joan Mir

Pgina 161

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.2.2.7.- driver PCF8591.c
/* *************************************** driver PCF8591.c ******************************************* */
/* ********************************************* Declaracin de funciones ****************************************************** */
int16 Lectura_SRF08(int8);

// Declaramos la funcin Lectura_SRF08


// (Nos devuelve una variable tipo entero de 8 bit)

/* ************************************** Funcin de int8 Lectura_PCF8591() ************************************************ */


int16 Lectura_SRF08(int8 SRF08)
{
int16 resultado=0;
int8 PCF8591=0;
if(SRF08==0xE4) PCF8591=0x99;

//
0x99 = 0B10011001
// Seleccionar esclavo U1 en modo lectura. ( 1001,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8591.
// (A2,A1,A0)=(100) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8591 en modo lectura.

if(SRF08==0xE2) PCF8591=0x95;

//
0x95 = 0B10010101
// Seleccionar esclavo U3 en modo lectura. ( 1001,A2,A1,A0,1 )
// (0100) identifica al C.I. PCF8591.
// (A2,A1,A0)=(010) por hardware.
// El ultimo bit a 1 para poner el C.I. PCF8591 en modo lectura.

i2c_start();
i2c_write(PCF8591);

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura

resultado=i2c_read(0);

// Si, lee ltimo byte, enva NACK y almacena en el buffer

i2c_stop();

// Secuencia de stop

return(resultado);
}

5.3.9.2.2.8.- Cambio_Direccin.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Cambio_Direccin.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Cambiar las direcciones de los sensores de ultrasonidos SRF08
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado **************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#define SRF08_inicial 0xE0


#define SRF08_final
0xEE

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

// Direccin I2C del SRF08 inicial


// Direccin I2C del SRF08 final

// ***************************** Funcin principal o programa principal *****************************************************


void main()
{
i2c_start();
i2c_write(SRF08_inicial);

Microcontroladores

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura

IES Joan Mir

Pgina 162

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_write(0x00);
i2c_write(0xA0);
i2c_stop();

// Direccin interna 0x00 (registro de comandos)


//1 secuencia para el cambio de direccin
// Secuencia de stop

i2c_start();
i2c_write(SRF08_inicial);
i2c_write(0x00);
i2c_write(0xAA);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura
// Direccin interna 0x00 (registro de comandos)
// 2 secuencia para el cambio de direccin
// Secuencia de stop

i2c_start();
i2c_write(SRF08_inicial);
i2c_write(0x00);
i2c_write(0xA5);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura
// Direccin interna 0x00 (registro de comandos)
// 3 secuencia para el cambio de direccin
// Secuencia de stop

i2c_start();
i2c_write(SRF08_inicial);
i2c_write(0x00);
i2c_write(SRF08_final);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del SRF08 modo escritura
// Direccin interna 0x00 (registro de comandos)
// Nueva direccin I2C
// Secuencia de stop

while(1);
}

5.3.9.2.2.9.- Ejercicio 1.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Ejercicio 1.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Guiado de un robot en funcin de la distancia
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************* Directivas de Preprocesado *************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware

interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
#include <driver_SRF08.c>
// #include <driver_PCF8591.c>
// #include <driver_Luz_Distancia_SRF08.c>

// Real
// Simulado
// Simulado

#include <flex_lcd.c>

// Incluimos el driver LCD1.c que contiene las


// funciones de control del LCD.

#BIT tc1_EN1= 0X87.1


#BIT tc2_EN2= 0X87.2
#BIT tb2_MI= 0X86.2
#BIT tb3_MD= 0X86.3
#BIT rc1_EN1= 0X07.1
#BIT rc2_EN2= 0X07.2
#BIT rb2_MI= 0X06.2
#BIT rb3_MD= 0X06.3
#define SENSOR_1
#define
#define
#define
#define

0xE2

// Direccin I2C del Sensor 1 SRF08

ON 1
OFF 0
ADELANTE 0
ATRAS 1

Microcontroladores

IES Joan Mir

Pgina 163

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


/* *************************** Funcin principal o programa principal **************************** */
void main()
{
int16 distancia;
int8 sensor;
tc1_EN1= 0;
tc2_EN2= 0;
tb2_MI= 0;
tb3_MD= 0;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


sensor=SENSOR_1;
distancia = Lectura_SRF08(sensor);

// Leemos el dato a travs del bus I2c del


// Sensor 1
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 1 .
// Visualiza sobre la pantalla LCD la lectura del
// Sensor 1

lcd_gotoxy(1,1);
printf(lcd_putc,"S1=%03lu",distancia);
if(distancia<20)
{
rc1_EN1= ON;
rb2_MI= ATRAS;
rc2_EN2= ON;
rb3_MD= ATRAS;
}
else
{
if(distancia>=20 && distancia<40)
{
rc1_EN1= ON;
rb2_MI= ADELANTE;
rc2_EN2= ON;
rb3_MD= ADELANTE;
}
else
{
rc1_EN1= OFF;
rc2_EN2= OFF;
}
}
}
}

5.3.9.3.- Sensores de Temperatura.


5.3.9.3.1.- PT100.
Un Pt100 es un sensor de temperatura.
Consiste en un alambre de platino que a 0 C
tiene 100 ohms y que al aumentar la temperatura
aumenta su resistencia elctrica. (Coeficiente positivo
de temperatura)

El incremento de la resistencia no es
lineal pero si creciente y caracterstico del platino
de tal forma que mediante tablas es posible
encontrar la temperatura exacta a la que
corresponde.
Un Pt100 es un tipo particular de RTD
(Dispositivo Termo Resistivo)
Normalmente las Pt100 industriales se
consiguen encapsuladas en la misma forma que

Microcontroladores

IES Joan Mir

Pgina 164

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


los termopares, es decir dentro de un tubo de acero
inoxidable u otro material (vaina), en un extremo est
el elemento sensible (alambre de platino) y en el otro
est el terminal elctrico de los cables protegido
dentro de una caja redonda de aluminio ( cabezal ).
La frmula matemtica es:
2

RPT100= R0 (1 + a1 x t + a2 x t )
o

Donde R0 es 100 a (100 C)


a1 = 0.0039083
a2 = -0.0000005775

(Coeficiente de temperatura)
(Coeficiente de temperatura)

Utilizaremos el entrenador PT100.DSN contenido en la carpeta de Sensores y


Hardware\ PT100.

Las formulas que determinan la conversin de tensin a temperatura son:


Ve= [ E1 / (R1+RPT100)] x RPT100
VS= [(R4 +R5)/R5] x Ve
El resultado es:
RPT100 = [(VS x R5 x R1) / ((R4 +R5) x E1 - VS x R5))]
2

R0 (1 + a1 x t + a2 x t ) = [(VS x R5 x R1) / ((R4 +R5) x E1 - VS x R5))]


2

1 + a1 x t + a2 x t = [(VS x R5 x R1) / ((R4 +R5) x E1 - VS x R5)) x R0]


2

1 + a1 x t + a2 x t = A
Una vez introducidos los valores queda:

Microcontroladores

IES Joan Mir

Pgina 165

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


A = (VS x 70.5) / (117.5 - VS x 1.5);
2

a2 x t + a1 x t + (1-A) = 0
t = (-b

) / 2a =

t = (- a1+

)/ 2 a2
Factor de Correccin

t = - 2 + (-a1 + raiz) / (2*a2)


if (t<0) t = t - 0.5

5.3.9.3.1.1.- Lectura_S1_PT100.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Lectura_S1_PT100.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de un sensor PT100
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************ Directivas de Preprocesado ***********************************
#include <16F877A.h>
#device adc=10

// Conversor Analgico Digital de 10 bit el PIC 16F876A puede


// trabajar con 8 o 10 bit de resolucin.

#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <MATH.H>
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control


// del LCD.

#define a1 0.0039083
#define a2 -0.0000005775
//******************************************************** Declaracin de Funciones *********************************************
float Con_V_T(float);
//********************************************************* Programa Principal *****************************************************
void main()
{
int16 q;
float tension;
float temperatura;
lcd_init();
setup_adc_ports(2);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
for (;;)
{

// Inicializamos el LCD.
// Seleccionamos el Puerto A como entradas Analgicas.
// Mirar ADCON1.
// Fuente de reloj RC interno.
// Habilitacin canal 0 "AN0"
// Bucle infinito.

delay_us(5);

Microcontroladores

// Retardo de 20uS necesaria para respetar el tiempo de


// Adquisicin Tad.

IES Joan Mir

Pgina 166

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


q = read_adc();
tension = 5.0 * q / 1024.0;

// Lectura canal 0 "AN0"


// Conversin a tensin del cdigo digital "q".

temperatura = Con_V_T(tension);
lcd_gotoxy(1,1);
printf(lcd_putc, "V1= %04.3f v", tension);

lcd_gotoxy(1,2);
printf(lcd_putc, "T1= %3.0g C", temperatura);

// Posicionamos el Cursor en la posicin 1,


// lnea 1.
// Salta lnea y escribe en el LCD "V1=" y
// 4 dgitos de "tensin" en formato truncado de
// con 3 decimales y el carcter "V".
// Posicionamos el Cursor en la posicin 1,
// lnea 2.
// Escribe en el LCD "t=" y 3 dgitos de
// "temperatura" en formato truncado con
// 0 decimales.

}
}
//*************************************************** Funcin Con_V_T ************************************************************
float Con_V_T(float p)
{
float t;
float a;
float b;
float raiz;
a = (p*70.5)/(117.5 - p*1.5);
b = (a1*a1)-4*a2*(1-a);
raiz = sqrt(b);
t =-2+(-a1 + raiz)/(2*a2) ;
if(t<0) t=t-0.5;
return(t);
}

5.3.9.3.2.- Sensor de Temperatura TC74.


El sensor es un combinacin de sensor de T, conversor A/D de 8 bits e interface I2C
en un solo C.I.
Siempre ser dispositivo esclavo y estar recibiendo o emitiendo datos cuando se lo
solicite el Maestro del bus

Direccin asignada en I2C como esclavo: 1-0-0-1-1-0-1


(Hay otras 7 direcciones distintas que se
podran asignar bajo pedido a Microchip)
Medida de temperatura: de -65C a 127C
Precisin de 2C de +25C a 85C y 3C de
0C a 125C
Resolucin de 8 bits: 1C
Proporciona valor en binario y valores
negativos en complemento a 2
Tensin de alimentacin: 2,7V a 5,5V
Consumo en operacin de 200 A y en
standby de 5 A

Funcionamiento: MEDIDA DE LA TEMPERATURA


El integrado realiza la adquisicin y conversin de temperaturas mediante un sensor
de estado slido con una resolucin de 1C
En modo de operacin normal, se toman y convierten 8 muestras por segundo y el
resultado de la conversin se almacena en un registro interno al que se puede acceder
en cualquier momento va serie mediante el bus I2C.

Microcontroladores

IES Joan Mir

Pgina 167

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


El C.I. se puede situar en modo
de bajo consumo (Stand-by) en el que se
suspende la adquisicin de temperatura
y queda retenido en el registro interno el
resultado de la ltima conversin.
Internamente existe un registro
de configuracin (CONFIG) donde hay
un bit (SHDN) que establece el modo de
trabajo: normal (SHDN a 0) o de bajo
consumo (SHDN a 1)
El registro de configuracin
interno se puede escribir y se puede leer,
mientras que el registro de temperatura
slo puede ser ledo.
Las lecturas y escrituras siguen las tramas tpicas en un bus I2C
Utilizaremos el entrenador TC74.DSN contenido en la carpeta de Sensores y
Hardware\ Sensor de Temperatura TC74.

5.3.9.3.2.1.- Test _TC74.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Test1_TC74.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Octubre-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de un sensor TC74
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

Microcontroladores

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware

IES Joan Mir

Pgina 168

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


//interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
#include <flex_lcd.c>

#define TC74_1
#define TC74_2

0x90
0x92

// Incluimos el driver flex_lcd.c que contiene las


// funciones de control del LCD.
//Direccin I2C del TC74_1
//Direccin I2C del TC74_2

/* ******************************************** Declaracin de funciones ******************************************************* */


signed int8 Lectura_TC74(int8);

// Declaramos la funcin Lectura_TC74


// (Nos devuelve una variable tipo entero de 8 bit con signo)

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
signed int8 dato_recibido;
int8 sensor;
lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(1,1);
printf(lcd_putc,"S1=");

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1.


// Visualiza sobre la pantalla LCD el mensaje "S1=".

lcd_gotoxy(1,2);
printf(lcd_putc,"S2=");

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2.


// Visualiza sobre la pantalla LCD el mensaje "S2=".

while (1)
{

// Bucle infinito de espera


sensor = TC74_1;
dato_recibido = Lectura_TC74(sensor);
lcd_gotoxy(4,1);
printf(lcd_putc,"%3d C",dato_recibido);
sensor = TC74_2;
dato_recibido = Lectura_TC74(sensor);
lcd_gotoxy(4,2);
printf(lcd_putc,"%3d C",dato_recibido);

// Leemos el dato a travs del bus I2c del


// esclavo TC74_1
// Posicionamos el Cursor del LCD en la
// posicin 4 lnea 1 .
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


// esclavo TC74_2
// Posicionamos el Cursor del LCD en la
// posicin 4 lnea 2 .
// Visualiza sobre la pantalla LCD la temperatura.

delay_ms(40);
}
}
/* *********************************** Funcin de int8 Lectura_SRF08() ****************************************************** */
signed int8 Lectura_TC74(int8 sensor)
{
signed int8 temperatura=0;
i2c_start();
i2c_write(sensor);
i2c_write(0x00);

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Enva direccin interna del dispositivo, nos posicionamos en
// el registro.

i2c_start();
i2c_write(sensor|0b00000001);
temperatura=i2c_read(0);
i2c_stop();

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura
// Si, lee ltimo byte, enva NACK y almacena en el buffer
// Secuencia de stop

return (temperatura);
}

Microcontroladores

IES Joan Mir

Pgina 169

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.3.3.- Sensor Trmico D-TPA81.
TPA81 es un sensor trmico de 8 pxeles capaz de
medir la temperatura de un objeto a distancia.
Desarrollado por la firma Devantech Ltd., el sensor
trmico TPA81 consiste en una matriz lineal de clulas
sensibles a la temperatura y que reciben el nombre de
termopilas (TPA). Estas detectan luz infra roja con una
longitud de onda en el rango de 2m a 22m y que
corresponde a la luz que desprenden los objetos calientes.
Otro tipo de sensores son los piroelctricos (PIR). Se usan normalmente para detectar
presencia en sistemas de alarmas, control de alumbrados, etc. y trabajan en la misma longitud
de onda que las termopilas (TPA). Los sensores PIR nicamente pueden detectar cambios de
temperatura producidas por el movimiento.
Por su parte las termopilas (TPA) pueden medir la temperatura en cuestin, sin
contacto fsico con el objeto y como si de un termmetro a distancia se tratara. Su campo o
ngulo de deteccin se muy amplio, en torno a los 100, pero se puede reducir mediante el
empleo de carcasas y lentes de silicona.
El sensor TPA81 consta de un total de 8 termopilas o pixels agrupadas en una nica
hilera o matriz lineal, pudiendo por tanto tomar temperaturas de 8 puntos adyacentes y de
forma simultnea. Cada termopila es capaz de detectar la llama de una vela a una distancia de
2m sin que se vea afectado por la luz ambiente.
El sensor tambin dispone del control y las conexiones necesarias para gobernar un
servo opcional al que puede estar fijado el propio sensor. Mediante el software de control
apropiado se puede hacer que dicho servo vaya rotando de un sentido al otro, a modo de
barrido, al tiempo que se van tomando muestras de las distintas temperaturas que suministran
las 8 TPAs integradas. Se puede as obtener mapas trmicos de diferentes zonas u objetos.
Caracteristicas:
Las caractersticas ms importantes se resumen a continuacin:

Tensin nica de alimentacin + 5Vcc


Consumo reducido de tan slo 5mA. Se excluye el posible servo que pudiera estar
conectado.
Rango de temperaturas de 4C hasta 100C
Resolucin en pleno campo de visin de +/- 3C en el rango de 4C a 10C y de +/- 2C
o el +/- 2% en el rango de 10C a 100C
Campo de visin 41 x 6 lo que hace que cada pxel o TPA tenga un campo de 5 x 6
Informacin de salida que indica la temperatura ambiente y la que capta cada uno de
los pixels o TPAs.
Comunicacin con el microcontrolador principal a travs del interfaz I2C.
Posibilidad de controlar un servo opcional con 32 pasos de unos 5,6 para conseguir
una rotacin de 180 en cualquiera de los sentidos.
Tamao reducido de 31 mm x 18 mm.
Se controla con bus I2c.

Campo de visin:
El campo de visin del sensor TPA81 es de 41 x 6, con
lo que a cada uno de los pixels o termopilas que forman la matriz
lneas le corresponde un campo de 5,12 x 6. Esta matriz esta
orientada segn se muestra en la figura. El pxel n 1 es el que
est ms prximo a la pestaa de referencia del propio sensor.

Microcontroladores

IES Joan Mir

Pgina 170

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


Sensibilidad:
Aqu se muestran los resultados de alguna de las pruebas realizadas por el fabricante
Devatech Ltd. Se emplea una vela a una distancia de 1m del sensor en una habitacin a 12 de
temperatura ambiente. Los valores ledos en cada uno de los 8 pixels o termopilas son los
siguientes (en grados centgrados):
11 10 11 12 12 29 15 13
La vela se encuentra frente al pxel cuya lectura indica una lectura de 29C. Si se
aumenta la distancia de la vela a 2m esa temperatura se reduce a 20C, unos 8C por encima
de la temperatura ambiente (12C) por lo que todava la fuente de calor es fcilmente
detectable. A una distancia de 0.6m la temperatura sube hasta unos 64C y a 0.3m a ms de
100C.
En la misma habitacin pero con una temperatura ambiente de 18, esa vela a una
distancia de 2 m nos proporciona una temperatura de 27C aproximadamente. Esto se debe a
que la vela ocupa una pequea parte del campo de visin del sensor y su temperatura se suma
a la temperatura ambiente, no se superpone por completo. El cuerpo humano aparecer con
una temperatura de 29C a 20 de temperatura ambiente.
Conexiones:
La comunicacin entre el sensor TPA81 con el
microcontrolador principal se realiza segn el protocolo I2C,
mediante un conector de 4 lneas. Tal y como se muestra en la
figura. Las lneas SCL y SDA son las seales de reloj y datos
respectivamente. Se deben conectar con unas resistencias pullup a +5Vcc. Estas resistencias normalmente ya forman parte del
bus y las suele proporcionar el Master del mismo. El TPA81
acta siempre como un slave, pero si hicieran falta se
recomienda emplear unos valores en torno a 1.8K.
Tambin dispone de un conector para la conexin
directa con un servo motor estndar alimentado a +5V. El sensor
TPA81 dispone de los comandos necesarios para expresar la
posicin del servo. El TPA81 se encarga de generar la seal de
control con el ancho de pulso necesario.
Registros internos:
Un total de 10 registros a los que se puede acceder va I2C, son los que dispone el
sensor TPA81 para su total control.
nicamente los registros 0 y 1 se pueden escribir. El registro 0 es el registro de
comandos y se emplea para ajustar la nueva posicin del servo y para cambiar la direccin
base I2C del TPA81. En caso de leer este registro se obtiene la versin del firmware interno del
sensor. Escribiendo sobre el registro 1 se establece el rango de movimiento del servo. Cuando
se lee se obtiene la medida de la temperatura ambiente.
N de Reg.

Lectura

Escritura

0
1

Revisin del firmware interno


Temperatura ambiente en C

Registro de comandos
Rango del servo (versin 6 del firmware o superior)

2
3
4
5
6
7
8
9

Temperatura del pxel 1 en C


Temperatura del pxel 2 en C
Temperatura del pxel 3 en C
Temperatura del pxel 4 en C
Temperatura del pxel 5 en C
Temperatura del pxel 6 en C
Temperatura del pxel 7 en C
Temperatura del pxel 8 en C

No disponible
No disponible
No disponible
No disponible
No disponible
No disponible
No disponible
No disponible

Microcontroladores

IES Joan Mir

Pgina 171

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


Dispone de 9 registros para la lectura de las temperaturas expresadas en C. El
registro 1 devuelve el valor de la temperatura ambiente. Los registros del 2 al 9 ofrecen las
temperaturas de cada uno de los pixels. La adquisicin de las temperaturas es constante y son
vlidas aproximadamente 40mS despus de que el sensor apunte a una nueva posicin.
Posicin del servo:
En el registro 0 se escriben los diferentes comandos admitidos. Los comandos
numerados del 0 al 31 (0x00 a 0x1F) permiten ajustar la anchura del pulso que se aplica al
servo, llevndole as a una nueva posicin. Dicha anchura se calcula:
Anchura = (n comando x 60) + 540
Se consigue un pulso cuya anchura vara de 540S (0.54mS) a 2400S (2,4mS) en
pasos de 60S. Esta anchura es aceptada por la mayor parte de servos.

Cambiando la direccin I2C:


La direccin por defecto que tiene el sensor TPA81 es la 0xD0. Esta direccin es
posible cambiarla con objeto de que en el mismo bus I2C puedan convivir ms de dos sensores
idnticos o cualquier otro dispositivo pero sin que se repita la direccin. Segn el protocolo I2C
NO es posible que dos o ms dispositivos tengan la misma direccin.
Para ello existen tres comandos que, escritos en el orden apropiado sobre el registro
de comandos (registro n 0), permite cambiar la direccin base del sensor TPA81: 160 (0xA0),
165 (0xA5) y 170 (0xAA). Por ejemplo, para cambiar la actual direccin 0xD0 por la nueva
0xD2 basta con escribir la siguiente secuencia sobre el registro 0: 0xA0, 0xAA, 0xA5, 0xD2.
Las direcciones que puede admitir el TPA81 son: 0xD0 (defecto), 0xD2, 0xD4, 0xD6,
0xD8, 0xDA, 0xDC o 0xDE.
Utilizaremos el entrenador Simulacion_9_Sensores.DSN contenido en la carpeta de
Sensores y Hardware\ Sensor Trmico D-TPA81.

Microcontroladores

IES Joan Mir

Pgina 172

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.3.3.1.- Test1_D-TPA81.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Test1_D-TPA81.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de un sensor D-TPA81
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

#include <flex_lcd.c>
funciones de control del LCD.

// Incluimos el driver flex_lcd.c que contiene las

#define DTPA81
int8 sensor=1;

// Direccin I2C del D-TPA81


// N de sensor

0xD0

/* ********************************************* Declaracin de funciones ****************************************************** */


int8 Lectura_DTPA81(int8);

// Declaramos la funcin Lectura_DTPA81.


// (Introducimos una variable tipo entero de 8 bit y
// nos devuelve una variable tipo entero de 8 bit)

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
int8 dato_recibido;
lcd_init();

// Inicializamos el LCD.

while (1)
{

// Bucle infinito de espera


sensor=1;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(1,1);
printf(lcd_putc,"%1u C",dato_recibido);

sensor=2;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(5,1);
printf(lcd_putc,"%1u C",dato_recibido);

// Leemos el dato a travs del bus I2c del sensor1


// DTPA81.
// Posicionamos el Cursor del LCD en la posicin
// 1 lnea 1 .
// Visualiza sobre la pantalla LCD la temperatura
// del sensor1.

// Leemos el dato a travs del bus I2c del sensor2


// DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 5 lnea 1 .
// Visualiza sobre la pantalla LCD la temperatura
// del sensor2.

delay_ms(40);
}
}
/* ***************************** Funcin int8 Lectura_DTPA81(int8 sensor) ************************************************ */
int8 Lectura_DTPA81(int8 sensor)
{
int8 temperatura=0;

Microcontroladores

IES Joan Mir

Pgina 173

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_start();
i2c_write(DTPA81);
i2c_write(sensor);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Envia direccin interna del dispositivo, nos posicinamos
// en el registro.
// Enva secuencia de stop

i2c_start();
i2c_write(DTPA81|0b00000001);
temperatura=i2c_read(0);
i2c_stop();

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura
// Si, lee ltimo byte, enva NACK y almacena en el buffer
// Secuencia de stop

return(temperatura);
}

5.3.9.3.3.2.- Test2_D-TPA81.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Test2_D-TPA81.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Prueba de un sensor D-TPA81
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <flex_lcd.c>
#define DTPA81
int8 sensor;

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Incluimos el driver flex_lcd.c que contiene las
// funciones de control del LCD.
// Direccin I2C del D-TPA81
// N de sensor

0xD0

/* ****************************************** Declaracin de funciones ********************************************************* */


int8 Lectura_DTPA81(int8);

// Declaramos la funcin Lectura_DTPA81


// (Introducimos una variable tipo entero de 8 bit y nos devuelve
// una variable tipo entero de 8 bit)

/* ************************* Funcin principal o programa principal ****************************** */


void main()
{
int8 dato_recibido;
lcd_init();
while (1)
{

// Inicializamos el LCD.
// Bucle infinito de espera

sensor=1;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(1,1);
printf(lcd_putc,"%1u",dato_recibido);

sensor=2;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(4,1);

Microcontroladores

// Leemos el dato a travs del bus I2c del


//sensor 1 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 1 lnea 1 .
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


// sensor 2 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 4 lnea 1 .

IES Joan Mir

Pgina 174

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


printf(lcd_putc,"%1u",dato_recibido);

// Visualiza sobre la pantalla LCD la temperatura.

sensor=3;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(7,1);
printf(lcd_putc,"%1u",dato_recibido);

sensor=4;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(10,1);
printf(lcd_putc,"%1u",dato_recibido);

sensor=5;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(13,1);
printf(lcd_putc,"%1u",dato_recibido);

sensor=6;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(4,2);
printf(lcd_putc,"%1u",dato_recibido);

sensor=7;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(7,2);
printf(lcd_putc,"%1u",dato_recibido);

sensor=8;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(10,2);
printf(lcd_putc,"%1u",dato_recibido);

sensor=9;
dato_recibido = Lectura_DTPA81(sensor);
lcd_gotoxy(13,2);
printf(lcd_putc,"%1u",dato_recibido);

// Leemos el dato a travs del bus I2c del


// sensor 3 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 7 lnea 1 .
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


// sensor 4 DTPA81.
// Posicionamos el Cursor del LCD en la posicin
// 10 lnea 1.
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


// sensor 5 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 13 lnea 1.
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


//sensor 6 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 4 lnea 2 .
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


// sensor 7 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 7 lnea 2 .
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


// sensor 8 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 10 lnea 2 .
// Visualiza sobre la pantalla LCD la temperatura.

// Leemos el dato a travs del bus I2c del


//sensor 9 DTPA81.
// Posicionamos el Cursor del LCD en la
// posicin 13 lnea 2 .
// Visualiza sobre la pantalla LCD la temperatura.

delay_ms(100);
}
}
/* *************************************** Funcin de int8 Lectura_SRF08() ************************************************** */
int8 Lectura_DTPA81(int8 sensor)
{
int8 temperatura=0;
i2c_start();
i2c_write(DTPA81);
i2c_write(sensor);
i2c_stop();

Microcontroladores

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Envia direccin interna del dispositivo, nos posicinamos
// en el registro.
// Enva secuencia de stop

IES Joan Mir

Pgina 175

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_start();
i2c_write(DTPA81|0b00000001);
temperatura=i2c_read(0);
i2c_stop();

// Enva secuencia de inicio


// Enva direccin I2C del dispositivo en modo lectura
// Si, lee ltimo byte, enva NACK y almacena en el buffer
//Secuencia de stop

return(temperatura);
}

5.3.9.3.3.3.- Temperatura Mayor.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Temperatura Mayor.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Detectar la temperatura mayor del sensor D-TPA81
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las


// funciones de control del LCD.

#define Numero_Maximo 8

// Nmero pixel-1

byte CONST Direccion_Pixel[9] = {0x90,0x92,0x94,0x96,0x98,0x9A,0x9C,0x9E,0xA0};


//
{Ta, Pixel1,Pixel2,Pixel3,Pixel4,Pixel5,Pixel6,Pixel7,Pixel8}

// Tabla de 9 datos.

/* ******************************************** Declaracin de funciones ******************************************************* */


int8 Lectura_DTPA81(int8);

// Declaramos la funcin Lectura_DTPA81


// (Introducimos una variable tipo entero de 8 bit y
// nos devuelve una variable tipo entero de 8 bit)

/* ************************* Funcin principal o programa principal ****************************** */


void main()
{
int8 sensor;
int8 n;
int8 temperatura_ambiente=0;
int8 temperatura_mayor=0;
int8 temperatura_real=0;
int8 temperatura;
int8 sensor_mayor;
lcd_init();

// Inicializamos el LCD.

lcd_gotoxy(1,1);
printf(lcd_putc,"Sensor= ");

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1.


// Visualiza sobre la pantalla LCD el mensaje "Sensor= ".

lcd_gotoxy(1,2);
printf(lcd_putc,"Tmax=

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2.


// Visualiza sobre la pantalla LCD el mensaje "Tmax= C ".

C ");

while (1)
{

// Bucle infinito de espera

sensor = Direccion_Pixel[0];

Microcontroladores

// Sacamos la direccin del sensor TAMBIENTE de la tabla


// Direccion_Pixel[0]

IES Joan Mir

Pgina 176

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


temperatura_ambiente= Lectura_TC74(sensor);

sensor = Direccion_Pixel[1];
temperatura_mayor= Lectura_TC74(sensor);
sensor_mayor=1;
for (n=2; n<=Numero_Maximo; n++)

// Leemos la temperatura ambiente a


// travs del bus I2c del esclavo
// TAMBIENTE.
// Sacamos la direccin del sensor
// PIXEL1 de la tabla Direccion_Pixel[1]
// Leemos la temperatura del sensor
// PIXEL1 a travs del bus I2c.
// Asignamos a sensor_mayor=1;
// Se ejecuta un bucle desde n=2 hasta
// n<=Numero_Maximo en orden
// ASCENDENTE de uno en uno

{
sensor = Direccion_Pixel[n];
temperatura= Lectura_TC74(sensor);
if(temperatura>temperatura_mayor)
{
temperatura_mayor=temperatura;
sensor_mayor=n;

// Sacamos la direccin del sensor de la


// tabla Direccion_Pixel[n]
// Leemos la temperatura del sensor a
// travs del bus I2c.
// Detectamos la temperatura mayor.
// Guardamos la temperatura mayor.
// Guardamos el sensor que tiene la
// temperatura mayor.

}
}
temperatura_real = temperatura_mayor-temperatura_ambiente;
lcd_gotoxy(9,1);
printf(lcd_putc,"%1u",sensor_mayor);
lcd_gotoxy(6,2);
printf(lcd_putc,"%3u",temperatura_mayor);

// Obtenemos la temperatura
// real del punto caliente
// Posicionamos el Cursor del LCD en la
// posicin 9 lnea 1.
// Visualiza sobre la pantalla LCD la
// variables sensor_mayor.
// Posicionamos el Cursor del LCD en la
// posicin 6 lnea 2.
// Visualiza sobre la pantalla LCD la
// variables temperatura_mayor.

delay_ms(40);
}
}
/* *********************************** Funcin de int8 Lectura_SRF08() ****************************************************** */
int8 Lectura_TC74(int8 sensor)
{
int8 temperatura=0;
i2c_start();
i2c_write(sensor);
i2c_write(0x00);
i2c_start();
i2c_write(sensor|0b00000001);
temperatura=i2c_read(0);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Envia direccin interna del dispositivo, nos posicinamos
// en el registro.
// Enva secuencia de inicio
// Enva direccin I2C del dispositivo en modo lectura
// Si, lee ltimo byte, enva NACK y almacena en el buffer
// Secuencia de stop

return(temperatura);
}

5.3.9.3.3.4.- Temperatura Mayor_con driver.c


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Temperatura Mayor_con driver.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Detectar la temperatura mayor del sensor D-TPA81
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F877A.h>

Microcontroladores

IES Joan Mir

Pgina 177

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

#include <flex_lcd.c>

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
// Incluimos el driver flex_lcd.c que contiene las
// funciones de control del LCD.
// Incluimos el driver TC74_9_sensores.c que
// contiene las funciones de control del TC74.
// Incluimos el driver D-TPA81.c que contiene las
// funciones de control del D-TPA81.
// Nmero pixel.

// #include <driver_TC74_9_sensores.c>
#include <driver_D-TPA81.c>
#define Numero_Maximo 8

/* ************************** Funcin principal o programa principal ***************************** */


void main()
{
int8 sensor;
int8 n;
int8 temperatura_ambiente=0;
int8 temperatura_mayor=0;
int8 temperatura_real=0;
int8 temperatura;
int8 sensor_mayor;
lcd_init();
lcd_gotoxy(1,1);
printf(lcd_putc,"Sensor= ");
lcd_gotoxy(1,2);
printf(lcd_putc,"Tmax= C ");

// Inicializamos el LCD.
// Posicionamos el Cursor del LCD en la posicin 1 lnea 1.
// Visualiza sobre la pantalla LCD el mensaje "Sensor= ".
// Posicionamos el Cursor del LCD en la posicin 1 lnea 2.
// Visualiza sobre la pantalla LCD el mensaje "Tmax= C ".

while (1)
{

// Bucle infinito de espera


sensor = 0;
// Seleccionamos el sensor 0 (TAMBIENTE).
temperatura_ambiente= Lectura_DTPA81(sensor);
// Leemos la temperatura ambiente a
// travs del bus I2c del esclavo
// TAMBIENTE.
sensor = 1;
// Seleccionamos el sensor PIXEL1.
temperatura_mayor= Lectura_DTPA81(sensor);
// Leemos la temperatura del sensor
// PIXEL1 a travs del bus I2c.
sensor_mayor=1;
// Asignamos a sensor_mayor=1;
for (n=2; n<=Numero_Maximo; n++)

// Se ejecuta un bucle desde n=2 hasta


// n<=Numero_Maximo en orden
// ASCENDENTE de uno en uno

{
temperatura= Lectura_DTPA81(n);
if(temperatura>temperatura_mayor)
{
temperatura_mayor=temperatura;
sensor_mayor=n;

// Leemos la temperatura del sensor a


// travs del bus I2c.
// Detectamos la temperatura mayor.
// Guardamos la temperatura mayor.
// Guardamos el sensor que tiene la
// temperatura mayor.

}
}
temperatura_real = temperatura_mayor-temperatura_ambiente;
lcd_gotoxy(9,1);
printf(lcd_putc,"%1u",sensor_mayor);
lcd_gotoxy(6,2);
printf(lcd_putc,"%3u",temperatura_mayor);

// Obtenemos la temperatura
// real del punto caliente
// Posicionamos el Cursor del LCD en la
// posicin 9 lnea 1.
// Visualiza sobre la pantalla LCD la
// variables sensor_mayor.
// Posicionamos el Cursor del LCD en
// la posicin 6 lnea 2.
// Visualiza sobre la pantalla LCD la
// variables temperatura_mayor.

delay_ms(100);
}
}

Microcontroladores

IES Joan Mir

Pgina 178

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.3.3.5.- driver_D-TPA81.c
// ***************************** Driver de Control del sensor DTPA81 *******************************
#define DTPA81

0xD0

//Direccin I2C del D-TPA81

/* *********************************************** Declaracin de funciones **************************************************** */


int8 Lectura_DTPA81(int8);

// Declaramos la funcin Lectura_DTPA81


// (Introducimos una variable tipo entero de 8 bit y nos devuelve
// una variable tipo entero de 8 bit)

/* *************************************** Funcin de int8 Lectura_SRF08() ************************************************** */


int8 Lectura_DTPA81(int8 sensor)
{
int8 temperatura=0;
i2c_start();
i2c_write(DTPA81);
i2c_write(sensor+1);
i2c_start();
i2c_write(DTPA81|0b00000001);
temperatura=i2c_read(0);
i2c_stop();

// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Envia direccin interna del dispositivo, nos posicinamos en
// el registro.
// Enva secuencia de inicio
// Enva direccin I2C del dispositivo en modo lectura
// Si, lee ltimo byte, enva NACK y almacena en el buffer
// Secuencia de stop

return(temperatura);
}

5.3.9.3.3.6.- driver_TC74_9_sensores.c
// ****************************** Driver de Control de 9 sensor TC74 ********************************
// Debemos abrir el menu contestual de cada sensor y asignarle una direccin en el apartado {DEVADDR=$92},
// asignamos la direccin 92.
// Cuando copiamos el hardware en otra carpeta debemos asegurarnos que tiene la direccin asignada.
byte CONST Direccion_Pixel[9] = {0x90,0x92,0x94,0x96,0xA2,0x9A,0x9C,0x9E,0xA0};
//
{Ta, Pixel1, Pixel2,Pixel3,Pixel4,Pixel5,Pixel6,Pixel7,Pixel8}

// Tabla de 9 datos.

/* ********************************************** Declaracin de funciones ***************************************************** */


int8 Lectura_DTPA81(int8);

// Declaramos la funcin Lectura_DTPA81


// (Introducimos una variable tipo entero de 8 bit y nos devuelve una variable
// tipo entero de 8 bit)

/* *************************************** Funcin de int8 Lectura_SRF08() ************************************************** */


int8 Lectura_DTPA81(int8 sensor)
{
int8 temperatura=0;
sensor = Direccion_Pixel[sensor];
i2c_start();
i2c_write(sensor);
i2c_write(0x00);
i2c_start();
i2c_write(sensor|0b00000001);
temperatura=i2c_read(0);
i2c_stop();

// Sacamos la direccin del sensor de la table


// Direccion_Pixel[n]
// Secuencia de inicio
// Direccin I2C del dispositivo modo escritura
// Envia direccin interna del dispositivo, nos posicinamos
// en el registro.
// Enva secuencia de inicio
// Enva direccin I2C del dispositivo en modo lectura
// Si, lee ltimo byte, enva NACK y almacena en el buffer
// Secuencia de stop

return(temperatura);
}

Microcontroladores

IES Joan Mir

Pgina 179

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.3.3.7.- Seguimiento de un punto caliente.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Seguimiento de un punto caliente.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: El sensor D-TPA81 est montado sobre un servo de posicin
//
//
y sigue a un punto caliente.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ****************************** Directivas de Preprocesado *****************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

#include <Servo_Futaba_10bit.c>

// Incluimos el driver que contiene las funciones


// de control de los Servos de Futaba.

#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las


//funciones de control del LCD.

// #include <driver_TC74_9_sensores.c>

// Incluimos el driver TC74_9_sensores.c que


// contiene las funciones de control del TC74.
// Incluimos el driver D-TPA81.c que contiene las
// funciones de control del D-TPA81.

#include <driver_D-TPA81.c>

#BIT TR0 = 0x87.0


#BIT TR1 = 0x87.1
#BIT TR5 = 0x87.5
#define Numero_Maximo 8

// Nmero pixel.

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int8 sensor;
int8 n;
int8 temperatura_ambiente=0;
int8 temperatura_mayor=0;
int8 temperatura_real=0;
int8 temperatura;
int8 sensor_mayor;
int8 posicion=56;
lcd_init();

// Inicializamos el LCD.

Inicializacion_Futaba_RC2();

// Inicializacin del Servo en MANGUERA1.

TR0=0;
TR1=0;
TR5=0;
lcd_gotoxy(1,1);
printf(lcd_putc,"Sensor= ");

// Posicionamos el Cursor del LCD en la posicin 1 lnea 1.


// Visualiza sobre la pantalla LCD el mensaje "Sensor= ".

lcd_gotoxy(1,2);
printf(lcd_putc,"Tmax=

// Posicionamos el Cursor del LCD en la posicin 1 lnea 2.


// Visualiza sobre la pantalla LCD el mensaje "Tmax= C ".

Microcontroladores

C ");

IES Joan Mir

Pgina 180

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

while (1)
{

// Bucle infinito de espera


sensor = 0;
temperatura_ambiente= Lectura_DTPA81(sensor);

sensor = 1;
temperatura_mayor= Lectura_DTPA81(sensor);
sensor_mayor=1;
for (n=2; n<=Numero_Maximo; n++)

// Seleccionamos el sensor 0
// (TAMBIENTE).
// Leemos la temperatura ambiente a
// travs del bus I2c del esclavo
// TAMBIENTE.
// Seleccionamos el sensor PIXEL1.
// Leemos la temperatura del sensor
// PIXEL1 a travs del bus I2c.
// Asignamos a sensor_mayor=1;
// Se ejecuta un bucle desde n=2 hasta
// n<=Numero_Maximo en orden
// ASCENDENTE de uno en uno

{
temperatura= Lectura_DTPA81(n);
if(temperatura>temperatura_mayor)
{
temperatura_mayor=temperatura;
sensor_mayor=n;

// Leemos la temperatura del sensor a


// travs del bus I2c.
// Detectamos la temperatura mayor.
// Guardamos la temperatura mayor.
// Guardamos el sensor que tiene la
// temperatura mayor.

}
}
temperatura_real = temperatura_mayor-temperatura_ambiente;

lcd_gotoxy(9,1);

// Obtenemos la temperatura
// real del punto caliente

// Posicionamos el Cursor del LCD en la


// posicin 9 lnea 1.
// Visualiza sobre la pantalla LCD la
// variables sensor_mayor.

printf(lcd_putc,"%1u",sensor_mayor);

if(temperatura_mayor>45)
{
if(sensor_mayor>4)
{
posicion++;
if(posicion>68) posicion=68;
}
if(sensor_mayor<4)
{
posicion--;
if(posicion<47) posicion=47;
}
Futaba_RC2(posicion);
}
lcd_gotoxy(6,2);
printf(lcd_putc,"%3u",temperatura_mayor);

// Posicionamos el Cursor del LCD en la


// posicin 6 lnea 2.
// Visualiza sobre la pantalla LCD la
// variables temperatura_mayor.

delay_ms(50);
}
}

Microcontroladores

IES Joan Mir

Pgina 181

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.4.- Potencimetro Digital MCP41010.
Es un circuito electrnico que toma diferentes valores de resistencia en funcin de un cdigo digital.
Caractersticas:

256 valores diferentes.


Los valores del potencimetro de 10 K, 50 K
y 10 K.
SPI interfaz en serie (modo 0,0 y 1,1)
Trabaja con tensiones de 2,7 a 5,5V.

Utilizaremos el entrenador Simulacin del MCP41010.DSN contenido en la carpeta de


Sensores y Hardware\ MCP41010.

Microcontroladores

IES Joan Mir

Pgina 182

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.4.1.- CG_Ampl_No_Inversor.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: CG_Ampl_No_Inversor.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Mayo-2011
//
// Programador..: Pedro Alonso
//
// Descripcin..: Potenciometro Digital MCP41010 con protocolo SPI
//
//
Control de ganancia de un amplificador no inversor
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F877A.h>
#FUSES XT,NOWDT
#use delay(clock=1000000)
#include <flex_lcd.c>

// Incluimos el driver flex_lcd.c que contiene las funciones de control del LCD.

#BYTE TRISA = 0x85


#BYTE portA = 0x05
#BIT TC6 = 0x87.6
#BIT TC5 = 0x87.5
#BIT TC3 = 0x87.3
#BIT cs = 0x07.6

//**************************************** Programa Principal ***************************************


void main()
{
float dato=0;
float dato_anterior=0;
float ganancia=0;
setup_spi( spi_master | spi_L_to_H | spi_clk_div_16 );
TC6 =0;
TC5 =0;
TC3 =0;
TRISA=0B00000000;
lcd_init();

// Inicializamos el LCD.

while(true)
{
dato=portA;

// Bucle infinito.

if(dato!=dato_anterior)
{
dato_anterior=dato;
cs=0;
spi_write(0x0);
cs=1;
cs=0;
spi_write(0x11);
spi_write(portD);
delay_us(120);
cs=1;

// 0x11

ganancia=((dato*10)/256)+1;
lcd_gotoxy(1,1);
printf(lcd_putc,"PORTA=%3u",portA);

Microcontroladores

IES Joan Mir

// Posicionamos el Cursor del LCD en la


//posicin 1 lnea 1 .
// Escribimos 3 dgitos de la variable
// "PORTA" en formato entero y sin
// signo.

Pgina 183

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


lcd_gotoxy(1,2);
printf(lcd_putc,"Ganancia=%5.2f",ganancia);

// Posicionamos el Cursor del LCD en la


// posicin 1 lnea 2 .
// Escribimos 5 dgitos de la variable
// "ganancia" en formato float, con
// 2 decimales.

}
}
}

5.3.9.5.- Control de mltiples servomotores de posicin SD20.


El SD20 es un microcontrolador PIC16F872 corriendo a 8 Mhz, capaz
de controlar y mover hasta 20 servo motores.
Las ordenes de control entre el procesador principal y el sd20 se
realiza mediante un bus I2C, consiguiendose una comunicacin de alta
velocidad que permite controlar los servos de una forma muy precisa.
Todos los canales permanecen inicialmente inactivos, hasta que se
enva la primera orden de posicionamiento.
Puede funcionar en
modo estndar con pulsos de
1 a 2 ms, o bien en modo
expandido ampliando la
anchura de los impulsos de
control fuera de estos limites.
Todas las ordenes, as como
las posicin de los servos se
almacenan en registros que
pueden leerse o escribirse
fcilmente desde cualquier
microcontrolador.
El circuito resulta muy
til como coprocesador en
robots con una gran numero
de servos, pues libera al
procesador principal de gran
parte del trabajo, pudiendose
dedicar a otras tareas.

5.3.9.5.1.- Control_SD20.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Control_SD20.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control del Servo 1 con SD20
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 1000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

Microcontroladores

// Configuracin de I2C
// Definimos el PIC como maestro

IES Joan Mir

Pgina 184

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

/* ****************************** Funcin principal o programa principal ************************* */


void main()
{
// Fijamos el rango de trabajo de los servor desde THmin= 0,480 mS hasta THmax= 2,520 mS.
// THmin = Reg22,Reg23 + 20uS
// THmax =(256x255)/Reg21 +(Reg22,Reg23+20)=
// THmin = Reg22,Reg23 +20 uS = 460uS + 20uS = 480 uS ( 460d --> 1CCH )
// THmax =(256x255)/32 +(460+20)= 2520 uS
i2c_start();
i2c_write(0xC2);
i2c_write(21);
i2c_write(32);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Registro de configuracin extandar o control modo expandido.

i2c_start();
i2c_write(0xC2);
i2c_write(22);
i2c_write(0x1);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Direccin 22H del SD20 Modo expansor de offset (Parte Alta)
// 460D -->01CCH (Se introduce la parte alta 01H)
// Finalizacin de la transmisin.

i2c_start();
i2c_write(0xC2);
i2c_write(23);
i2c_write(0xCC);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Direccin 23H del SD20 Modo expansor de offset (Parte Baja)
// 460D -->01CCH (Se introduce la parte baja CCH)
// Finalizacin de la transmisin.

while (1)
{

// Bucle infinito

// Finalizacin de la transmisin.

i2c_start();
i2c_write(0xC2);
i2c_write(1);
i2c_write(240);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Seleccionamos el Servo1
// Posicionamos el Servo en el extremo A
// Finalizacin de la transmisin.

delay_ms(1000);

// Retardamos 1 segundos

i2c_start();
i2c_write(0xC2);
i2c_write(1);
i2c_write(10);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Seleccionamos el Servo1
// Posicionamos el Servo en el extremo B
// Finalizacin de la transmisin.

delay_ms(1000);

// Retardamos 1 segundos

}
}

5.3.9.5.2.- Control_Servos_Funciones_SD20.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: Control_Servos_Funciones_SD20.c
//
// Plataforma hw: Placa Monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de los servos del SD20 con funciones.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* ************************************* Control del SD20 ********************************************* */
#include <16F877A.h>
#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 4000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

Microcontroladores

// Configuracin de I2C
// Definimos el PIC como maestro

IES Joan Mir

Pgina 185

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.
/* ************************************************ Declaracin de funcionesa ***************************************************/
void Sd20_ini (void);
void Sd20(int8,int8);

/* *************************** Funcin principal o programa principal **************************** */


void main()
{
Sd20_ini();
While(1)
{
Sd20(1,100);
delay_ms(100);
Sd20(1,50);
delay_ms(100);
Sd20(2,100);
delay_ms(100);
Sd20(2,50);
delay_ms(100);

// Posicionamos el Servo1 del SD20 en 100.


// Posicionamos el Servo1 del SD20 en 50.
// Posicionamos el Servo2 del SD20 en 100.
/ / Posicionamos el Servo2 del SD20 en 50.

}
}
/* *********************************************** Funcin Sd20_ini ************************************************************** */
void Sd20_ini (void)
{
// Fijamos el rango de trabajo de los servor desde THmin= 0,480 mS hasta THmax= 2,520 mS.
// THmin = Reg22,Reg23 + 20uS
// THmax =(256x255)/Reg21 +(Reg22,Reg23+20)=
// THmin = Reg22,Reg23 +20 uS = 460uS + 20uS = 480 uS ( 460d --> 1CCH )
// THmax =(256x255)/32 +(460+20)= 2520 uS
i2c_start();
i2c_write(0xC2);
i2c_write(21);
i2c_write(32);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Registro de configuracin extandar o control modo expandido.

i2c_start();
i2c_write(0xC2);
i2c_write(22);
i2c_write(0x1);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Direccin 22H del SD20 Modo expansor de offset(Parte Alta)
// 460D -->01CCH (Se introduce la parte alta 01H)
// Finalizacin de la transmisin.

i2c_start();
i2c_write(0xC2);
i2c_write(23);
i2c_write(0xCC);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Direccin 23H del SD20 Modo expansor de offset(Parte Baja)
// 460D -->01CCH (Se introduce la parte baja CCH)
// Finalizacin de la transmisin.

// Finalizacin de la transmisin.

}
/* ********************************************** Funcin Sd20(int8,int8) ******************************************************* */
void Sd20(int8 servo, int8 posicion)
{
i2c_start();
i2c_write(0xC2);
i2c_write(servo);
i2c_write(posicion);
i2c_stop();
}

Microcontroladores

// Inicializa la transmisin
// Seleccionamos el SD20
// Seleccionamos el Servo1
// Posicionamos el Servo en el extremo A
// Finalizacin de la transmisin.

IES Joan Mir

Pgina 186

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.5.3.- A-D_SD20.c
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Programa.....: A-D_SD20.c
//
// Plataforma hw: Placa monibot 16F877A
//
// Fecha........: Octubre-2010
//
// Programador..: Pedro Alonso
//
// Descripcin..: Control de un servo del SD20 con un potencimetro
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ********************************** Directivas de Preprocesado *************************************
#include <16F876A.h>
#device adc=8

// Conversor Analgico Digital de 10 bit el PIC 16F876A


// puede trabajar con 8 o 10 bit de resolucion

#fuses XT,NOWDT,PUT,NOWRT
#use delay(clock= 4000000)
#use i2c(Master, force_hw, slow, sda=PIN_C4, scl=PIN_C3)

// Configuracin de I2C
// Definimos el PIC como maestro
// Forzamos a trabajar con su hardware
// interno.(Asociado a I2C)
// Trabajamos a velocidad baja 100 Kbps
// Elegimos sda=PIN_C4 como patilla de datos.
// Elegimos scl=PIN_C3 como patilla de reloj.

/* ******************************************* Declaracin de funciones *********************************************************/


void Sd20_ini (void);
void Sd20(int8,int8);

/* **************************** Funcin principal o programa principal *************************** */


void main()
{
int8 q=0;
Sd20_ini();

// Fijamos los niveles mximos y minimos de TH

setup_adc_ports(0);
setup_adc(ADC_CLOCK_INTERNAL);

// Seleccionamos el Puerto A como entradas Analgicas.


// Mirar ADCON1
// Fuente de reloj RC interno.

set_adc_channel(3);

// Habilitacin canal 3 "AN3"

While(1)
{
q = read_adc();

// Lectura canal 0 "AN3"

Sd20(1,q);
delay_ms(5);

// Posicionamos el Servo3 del SD20 en funcin de q.


// Retardo de 5 mS.

}
}
/* *************************************************** Funcin Sd20_ini ********************************************************** */
void Sd20_ini (void)
{
// Fijamos el rango de trabajo de los servor desde THmin= 0,480 mS hasta THmax= 2,520 mS.
// THmin = Reg22,Reg23 + 20uS
// THmax =(256x255)/Reg21 +(Reg22,Reg23+20)=
// THmin = Reg22,Reg23 +20 uS = 460uS + 20uS = 480 uS ( 460d --> 1CCH )
// THmax =(256x255)/32 +(460+20)= 2520 uS
i2c_start();
i2c_write(0xC2);
i2c_write(21);
i2c_write(32);
i2c_stop();

Microcontroladores

// Inicializa la transmisin
// Seleccionamos el SD20
// Registro de configuracin extandar o control modo expandido.
// Finalizacin de la transmisin.

IES Joan Mir

Pgina 187

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


i2c_start();
i2c_write(0xC2);
i2c_write(22);
i2c_write(0x1);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Direccin 22H del SD20 Modo expansor de offset(Parte Alta)
// 460D -->01CCH (Se introduce la parte alta 01H)
// Finalizacin de la transmisin.

i2c_start();
i2c_write(0xC2);
i2c_write(23);
i2c_write(0xCC);
i2c_stop();

// Inicializa la transmisin
// Seleccionamos el SD20
// Direccin 23H del SD20 Modo expansor de offset(Parte Baja)
// 460D -->01CCH (Se introduce la parte baja CCH)
// Finalizacin de la transmisin.

}
/* ************************************************** Funcin Sd20(int8,int8) *************************************************** */
void Sd20(int8 servo, int8 posicion)
{
i2c_start();
i2c_write(0xC2);
i2c_write(servo);
i2c_write(posicion);
i2c_stop();
}

// Inicializa la transmisin
// Seleccionamos el SD20
// Seleccionamos el Servo1
// Posicionamos el Servo en el extremo A
// Finalizacin de la transmisin.

5.3.9.6.- Puentes en H.
Un Puente H o Puente en H es un circuito electrnico que permite a un motor elctrico
DC girar en ambos sentidos, avance y retroceso. Son ampliamente usados en robtica y como
convertidores de potencia. Los puentes H estn disponibles como circuitos integrados, pero
tambin pueden construirse a partir de componentes discretos.

Estructura de un puente H (marcado en rojo).

Los 2 estados bsicos del circuito.

El trmino "puente H" proviene de la tpica representacin grfica del circuito. Un


puente H se construye con 4 interruptores (mecnicos o mediante transistores). Cuando los
interruptores S1 y S4 (ver primera figura) estn cerrados (y S2 y S3 abiertos) se aplica una
tensin positiva en el motor, hacindolo girar en un sentido. Abriendo los interruptores S1 y S4
(y cerrando S2 y S3), el voltaje se invierte, permitiendo el giro en sentido inverso del motor.
Con la nomenclatura que estamos usando, los interruptores S1 y S2 nunca podrn
estar cerrados al mismo tiempo, porque esto cortocircuitara la fuente de tensin. Lo mismo
Aplicaciones:
Como hemos dicho el puente H se usa para
invertir el giro de un motor, pero tambin puede usarse
para frenarlo (de manera brusca), al hacer un corto entre
las bornas del motor, o incluso puede usarse para
permitir que el motor frene bajo su propia inercia, cuando
desconectamos el motor de la fuente que lo alimenta. En
el siguiente cuadro se resumen las diferentes acciones.

Microcontroladores

S1 S2 S3 S4

Resultado

El motor gira en retroceso

El motor se detiene bajo su inercia

El motor frena (fast-stop)

IES Joan Mir

El motor gira en avance

Pgina 188

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


Montaje
Lo ms habitual en este tipo de circuitos es emplear interruptores de estado slido
(como Transistores), puesto que sus tiempos de vida y frecuencias de conmutacin son mucho
ms altas. En convertidores de potencia es impensable usar interruptores mecnicos, dado su
bajo nmero de conmutaciones de vida til y las altas frecuencias que se suelen emplear.
Adems los interruptores se acompaan de diodos (conectados a ellos en paralelo) que
permitan a las corrientes circular en sentido inverso al previsto cada vez que se conmute la
tensin, puesto que el motor est compuesto por bobinados que durante breves perodos de
tiempo se opondrn a que la corriente vare.

5.3.9.6.1.- L293B y L298.


Dos integrados clsicos utilizados son L293B y el L298, capaces de proporcionar una
corriente elevada I en su salida. Se controlan con lgica digital, adems podemos controlar la
cantidad y el sentido de la corriente.
Caracteristicas del L293B:

Imax=1A por canal


Ipico max (no repetitiva)= 2A por canal.
V max (Salida) = 36V
Control digital. (TTL)
Alta inmunidad al ruido.
Separacin entre alimentaciones de control y de potencia.
Proteccin a temperaturas altas.

Caracteristicas del L298:

Imax=4A.
V max (Salida) = 46V
Control digital. (TTL)
Alta inmunidad al ruido.
Separacin entre
alimentaciones de control y
de potencia.
Proteccin a temperaturas
altas.

Microcontroladores

IES Joan Mir

Pgina 189

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

Para ver el funcionamiento de estos integrados, utilizaremos el entrenador Simulacin


del L298-L293B.DSN contenido en la carpeta de Sensores y Hardware \ Puentes en H \
L298-L293B.
Tabla de la Verdad:
Entradas
ENA IN1 IN2
0
x
x
1
0
0
1
0
1
1
1
0
1
1
1

Microcontroladores

Salidas
OUT1 OUT2
5v
5v
0v
0v
0v
9v
9v
0v
9v
0v

Efectos sobre un Motor


Parado
Parado
Giro a Izquierdas
Giro a Derechas
Parado

IES Joan Mir

Pgina 190

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa

Si queremo realizar un control de velocidad sobre un motor, tendremos que generar


una seal pulsante (Modulacin por Anchura de Pulso, PWM) sobre la patilla EN.
Ver el circuito L293B_PWM.DSN contenido en la carpeta de Sensores y Hardware \
Puentes en H \ L298-L293B.

Microcontroladores

IES Joan Mir

Pgina 191

Curso de Robtica y otras aplicaciones en el Aula de Tecnologa


5.3.9.6.2.- Puente en H con TRT.
Si necesitamos corrientes y tensiones superiores, se pueden utilizar transistores.

Microcontroladores

IES Joan Mir

Pgina 192

You might also like