Club Saber Electrónica Nro. 97: Todo sobre microcontroladores

Portada club 97.qxd:Maquetación 1 05/04/13 14:38 Página 1
2ª de forros.qxd:club 05/03/13 16:29 Página 2ªFo1
suma edi Club 97.qxd:*Cap 4 - telefonia 05/04/13 14:55 Página 1
B ases
de los
M iCroControladores
Editorial
Director
Ing. Horacio D. Vallejo
Producción
José María Nieves (Grupo Quark SRL)
autor:
Varios (ver Editorial)
Selección y Coordinación:
Ing. Horacio Daniel Vallejo
Editorial QUarK S.r.l.
Propietaria de los derechos en castellano de la publicación mensual SabEr ElEctrónica - San Ricardo
2072 (1273) - Capital Federal - Buenos Aires Argentina - T.E. 4301-8804
administración y Negocios
Teresa C. Jara (Grupo Quark SRL)
Patricia Rivero Rivero (SISA SA de CV)
Margarita Rivero Rivero (SISA SA de CV)
Staff
Liliana Teresa Vallejo
Mariela Vallejo
Diego Vallejo
Luis Alberto Castro Regalado (SISA SA de CV)
José Luis Paredes Flores (SISA SA de CV)
Sistemas: Paula Mariana Vidal
red y Computadoras: Raúl Romero
Video y animaciones: Fernando Fernández
legales: Fernando Flores
Contaduría: Fernando Ducach
Técnica y Desarrollo de Prototipos:
Alfredo Armando Flores
atención al Cliente
Alejandro Vallejo
[email protected]
Internet: www.webelectronica.com.mx
Publicidad:
Rafael Morales
[email protected]
Club Se:
grupo Quark Srl
[email protected]
editorial Quark Srl
San Ricardo 2072 (1273) - Capital Federal
www.webelectronica.com.ar
La Editorial no se responsabiliza por el contenido de
las notas firmadas. Todos los productos o marcas
que se mencionan son a los efectos de prestar un
servicio al lector, y no entrañan responsabilidad de
nuestra parte. Está prohibida la reproducción total o
parcial del material contenido en esta revista, así como la industrialización y/o comercialización de los
aparatos o ideas que aparecen en los mencionados
textos, bajo pena de sanciones legales, salvo mediante autorización por escrito de la Editorial.
Impresión: Talleres Babieca - México
Del Editor al Lector
La colección Club Saber Electrónica fue pensada como una obra de 12 tomos de edición
mensual en la que se tratarán los temas más significativos de la electrónica. Rápidamente comprendimos que esta serie estaba llenando un vacío en la información y por ello decidimos continuarla. Ya llevamos más de 8 años (97 tomos de colección) y pensamos que su vida aún está en
pañales.
En diversos tomos nos hemos referido a los microcontroladores pero hasta la fecha poco
hemos hablado de lenguajes de programación de alto nivel, es por ello que este libro y la siguiente edición tratará este tema de una forma sencilla y con gran contenido práctico.
Un microcontrolador es un circuito integrado o chip que incluye en su interior las tres unidades funcionales de una computadora: CPU, Memoria y Unidades de E/S, es decir, se trata de
una computadora completa en un solo circuito integrado.
Son diseñados para disminuir el costo económico y el consumo de energía de un sistema en
particular. Por eso el tamaño de la CPU, la cantidad de memoria y los periféricos incluidos dependerán de la aplicación. El control de un electrodoméstico sencillo como una batidora, utilizará un
procesador muy pequeño (4 u 8 bit) por que sustituirá a un autómata pequeño; en cambio un
reproductor de música y/o vídeo digital (mp3 o mp4) requerirá de un procesador de 32 bit o de 64
bit y de uno o mas códec de señal digital (audio y/o vídeo). El control de un sistema de frenos
ABS (Antilock Brake System) se basa normalmente en un microcontrolador de 16 bit, al igual que
el sistema de control electrónico del motor en un automóvil.
Los microcontroladores representan la inmensa mayoría de los chips de computadoras vendidos, un 50% son controladores "simples" y el resto corresponde a procesadores más especializados. Un microcontrolador difiere de una CPU normal, en que es más fácil convertirlo en una
computadora en funcionamiento, con un mínimo de chips externos de apoyo.
Un microcontrolador típico tendrá un generador de reloj integrado y una pequeña cantidad
de memoria RAM y ROM/EPROM/EEPROM/FLASH, significando que para hacerlo funcionar,
todo lo que se necesita son unos pocos programas de control y un cristal de sincronización. Los
microcontroladores disponen generalmente también de una gran variedad de dispositivos de
entrada/salida, como convertidores de analógico a digital, temporizadores, UARTs y buses de
interfaz serie especializados, como I2C y CAN. Frecuentemente, estos dispositivos integrados
pueden ser controlados por instrucciones de procesadores especializados. Los modernos microcontroladores frecuentemente incluyen un lenguaje de programación integrado, como el BASIC
que se utiliza bastante con este propósito.
Esperamos que esta breve introducción le sirva como “disparador” para estudiar el contenido en la espera del próximo texto.
¡Hasta el mes próximo!
Sobre loS 2 CDS y Su DeSCarga
Ud. podrá descargar de nuestra web 2 CDs: “Microcontroladores vol. 1 y 2”
con gran cantidad de circuitos para armar y sistemas para experimentar. Todos los
CDs son productos multimedia completos con un costo de mercado equivalente a 8
dólares americanos cada uno y Ud. los puede descargar GRATIS con su número de
serie por ser comprador de este libro. Para realizar la descarga deberá ingresar a
nuestra web: www.webelectronica.com.mx, tendrá que hacer clic en el ícono password e ingresar la clave “MICro97”. Tenga este texto cerca suyo ya que se le hará
una pregunta aleatoria sobre el contenido para que pueda iniciar la descarga.
Capítulo 1
1
suma edi Club 97.qxd:*Cap 4 - telefonia 05/04/13 14:55 Página 2
El Mundo de los Microcontroladores
EL MunDo
DE Los
MicrocontroLaDorEs
suMario
Capítulo 1
los sistemas de NumeraCióN . . . . . . . . . . . . . . . .3
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3
Qué Pueden Hacer los Microcontroladores . . . . . . . . . . . . .4
Números, Números, Números... . . . . . . . . . . . . . . . . . . . . . .6
Sistema de Numeración Binario . . . . . . . . . . . . . . . . . . . . . .6
Sistema de Numeración Exadecimal . . . . . . . . . . . . . . . . . .7
Conversión de Sistemas de Numeración . . . . . . . . . . . . . . .8
Conversión de Números Binarios a Decimales . . . . . . . . . .8
Conversión de Números Hexadecimales a Decimales . . . . .9
Conversión de Números Hexadecimales a Binarios . . . . . . .9
Marcar los Números . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9
Números Negativos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9
BIT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10
BYTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10
Detalles Importantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11
Componentes Básicos de la Lógica Digital . . . . . . . . . . . . .11
Registros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12
Puertos de Entrada / Salida (E/S) . . . . . . . . . . . . . . . . . . . .13
Unidad de Memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14
Interrupciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16
Unidad Central de Procesamiento
(CENTRAL PROCESSOR UNIT - CPU) . . . . . . . . . . . . . . .17
Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17
Comunicación en Serie . . . . . . . . . . . . . . . . . . . . . . . . . . . .17
Velocidad de Transmisión Serial . . . . . . . . . . . . . . . . . . . . .18
I2C Circuito Inter- Integrado
(INTER INTEGRATED CIRCUIT) . . . . . . . . . . . . . . . . . . .18
SPI - Bus Serial de Interfaz de Periféricos
(SERIAL PERIPHERAL INTERFACE BUS . . . . . . . . . . . . .18
Oscilador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19
Circuito de Alimentación . Fuente de Alimentación . . . . . . .19
Temporizadores – Contadores . . . . . . . . . . . . . . . . . . . . . .20
¿Cómo Funcionan los Temporizadores? . . . . . . . . . . . . . .20
Utilizando un Preescalador en el
Funcionamiento del Temporizador . . . . . . . . . . . . . . . . . . .21
Utilizando una Interrupción en el
Funcionamiento del Temporizador . . . . . . . . . . . . . . . . . . .21
Contadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .21
Temporizador Perro Guardián. WATCHDOG . . . . . . . . . . .22
Convertidor Digital – Analógico (D/A) . . . . . . . . . . . . . . . . .22
Arquitectura Interna de un Microcontrolador . . . . . . . . . . . .23
2
Club saber electrónica nº 97
Juego de Instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . .24
¿Cómo se Debe Elegir un Microcontrolador? . . . . . . . . . . .25
Capítulo 2
sistemas de programaCióN:
leNguaje mikroC . . . . . . . . . . . . . . . . . . . . . . . .27
Lenguajes de Programación . . . . . . . . . . . . . . . . . . . . . . . .27
Lenguaje Ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . .28
Ventajas de los Lenguajes de Programación
de Alto Nivel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .28
Lenguaje C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .29
Características de el Lenguaje mikroC . . . . . . . . . . . . . . . .30
Fases de la Compilación . . . . . . . . . . . . . . . . . . . . . . . . . . .31
Estructura del Programa . . . . . . . . . . . . . . . . . . . . . . . . . . .31
Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .33
Tipos de Datos en mikroC . . . . . . . . . . . . . . . . . . . . . . . . . .34
Variables y Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . .35
Ámbito de Variables y Constantes . . . . . . . . . . . . . . . . . . .39
Clases de Almacenamiento . . . . . . . . . . . . . . . . . . . . . . . . .40
Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40
Conversión de Tipos de Datos . . . . . . . . . . . . . . . . . . . . . .44
Estructuras de Control . . . . . . . . . . . . . . . . . . . . . . . . . . . .45
Bucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .47
Sentencias de Salto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .49
Tipos de Datos Avanzados . . . . . . . . . . . . . . . . . . . . . . . . .50
Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .54
Capítulo 3
los miCroCoNtroladores piC . . . . . . . . . . . . . .63
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .63
La Memoria de Programa . . . . . . . . . . . . . . . . . . . . . . . . . .67
La Memoria de Datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67
Los Puertos del PIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .68
El Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69
El Reset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .69
Primeras Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . .70
GPIC USB: Programador de Microcontroladores
PIC y Memorias Eeprom por Puerto USB . . . . . . . . . . . . .70
Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .70
Descripción del Circuito Electrónico . . . . . . . . . . . . . . . . . .70
El Programador Quark Pro 2 . . . . . . . . . . . . . . . . . . . . . . .77
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 3
Capítulo 1
eL muNdo de Los microcoNtroLadores
“Los sistemas de NumeracióN”
Prácticamente desde su aparición, allá por el año 1986, en Saber Electrónica destacamos la importancia de los microcontroladores en el mundo de la electrónica.
Hemos escrito más de 50 artículos, 10 libros de texto y varios cursos sobre componentes de distintas familias. Sin embargo, el tema nunca se agota y siempre se puede
dar una nueva vista que nos permita conocer cada vez mejor a estos procesadores
en un solo chip con los que podemos aprender y capacitarnos en nuestra vida profesional. A partir de este número comenzamos con la edición de un curso de microcontroladores de MicroElectronika (www.mikroe.com) a quienes agradecemos por
permitirnos compartir este importantísimo material, invitando a todos los lectores a
que visiten la página de referencia para obtener importante material de apoyo.
www.mikroe.com
IntroduccIón
La situación actual en el campo de los microcontroladores se ha producido gracias al desarrollo de la tecnología de fabricación de los cir-
cuitos integrados. Este desarrollo ha permitido
construir las centenas de miles de transistores
en un chip. Esto fue una condición previa para la
fabricación de un microprocesador. Las primeras microcomputadoras se fabricaron al añadir-
Capítulo 1
3
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 4
El Mundo de los Microcontroladores
les periféricos externos, tales como memoria,
líneas de entrada/salida, temporizadores u
otros. El incremento posterior de la densidad de
integración permitió crear un circuito integrado
que contenía tanto al procesador como periféricos. Así es cómo fue desarrollada la primera
microcomputadora en un solo chip, denominada
más tarde microcontrolador.
Los principiantes en electrónica creen que un
microcontrolador es igual a un microprocesador.
Esto no es cierto. Difieren uno del otro en
muchos sentidos. La primera y la más importante diferencia es su funcionalidad. Para utilizar al
microprocesador en una aplicación real, se debe
de conectar con componentes tales como
memoria o componentes buses de transmisión
de datos. Aunque el microprocesador se considera una máquina de computación poderosa, no
está preparado para la comunicación con los
dispositivos periféricos que se le conectan. Para
que el microprocesador se comunique con algún
periférico, se deben utilizar los circuitos especiales. Así era en el principio y esta práctica sigue
vigente en la actualidad.
Por otro lado, al microcontrolador se le diseña de tal manera que tenga todas las componentes integradas en el mismo chip. No necesita de otros componentes especializados para su
aplicación, porque todos los circuitos necesarios, que de otra manera correspondan a los
periféricos, ya se encuentran incorporados. Así
se ahorra tiempo y espacio necesario para construir un dispositivo.
Qué Pueden Hacer los MIcrocontroladores
Para entender con más facilidad las razones
del éxito tan grande de los microcontroladores,
vamos a prestar atención al siguiente ejemplo.
Hace unos 10 años, diseñar un dispositivo electrónico de control de un ascensor de un edificio
de varios pisos era muy difícil, incluso para un
equipo de expertos.
¿Ha pensado alguna vez en qué requisitos
debe cumplir un simple ascensor? ¿Cómo lidiar
con la situación cuando dos o más personas lla-
4
Club Saber Electrónica Nº 97
man al ascensor al mismo tiempo? ¿Cuál llamada tiene la prioridad? ¿Cómo solucionar las
cuestiones de seguridad, de pérdida de electricidad, de fallos, de uso indebido?
Lo que sucede después de resolver estos
problemas básicos es un proceso meticuloso de
diseñar los dispositivos adecuados utilizando un
gran número de los chips especializados. Este
proceso puede tardar semanas o meses, dependiendo de la complejidad del dispositivo.
Cuando haya terminado el proceso, llega la hora
de diseñar una placa de circuito impreso y de
montar el dispositivo. ¡Un dispositivo enorme! Es
otro trabajo difícil y tardado. Por último, cuando
todo está terminado y probado adecuadamente,
pasamos al momento crucial y es cuando uno se
concentra, respira profundamente y enciende la
fuente de alimentación.
Esto suele ser el punto en el que la fiesta se
convierte en un verdadero trabajo puesto que
los dispositivos electrónicos casi nunca funcionan apropiadamente desde el inicio. Prepárese
para muchas noches sin dormir, correcciones,
mejoras... y no se olvide de que todavía estamos
hablando de cómo poner en marcha un simple
ascensor.
Cuando el dispositivo finalmente empiece a
funcionar perfectamente y todo el mundo esté
satisfecho, y le paguen por el trabajo que ha
hecho, muchas compañías de desarrollo estarán interesadas en su trabajo. Por supuesto, si
tiene suerte, cada día le traerá una oferta de trabajo de un nuevo inversionista. Sin embargo, si
lo requieren para trabajar en el control de los
elevadores de un nuevo edificio que tiene cuatro
pisos más de los que ya maneja su sistema de
control.
¿Sabe cómo proceder? ¿Cree acaso que se
pueden controlar las demandas de sus clientes?
Pensamos que usted va a construir un dispositivo universal que se puede utilizar en los edificios de 4 a 40 pisos, una obra maestra de electrónica. Bueno, incluso si usted consigue construir una joya electrónica, su inversionista le
esperará delante de la puerta pidiendo una
cámara en el ascensor o una música relajante
en caso de fallo de ascensor. O un ascensor con
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 5
B aSES
dos puertas. De todos modos, la ley de Murphy
es inexorable y sin duda usted no podrá tomar
ventaja a pesar de todos los esfuerzos que ha
hecho. Por desgracia, todo lo que se ha dicho
hasta ahora sucede en la realidad. Esto es lo
que “dedicarse a la ingeniería electrónica” real-
dE loS
M iCroCoNtroladorES
mente significa. Es así como se hacían las
cosas hasta aparición de los microcontroladores
diseñados - pequeños, potentes y baratos.
Desde ese momento su programación dejó de
ser una ciencia, y todo tomó otra dirección ...
El dispositivo electrónico capaz de controlar
Figura 1
Capítulo 1
5
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 6
El Mundo de los Microcontroladores
un pequeño submarino, una grúa o un ascensor
como el anteriormente mencionado, ahora está
incorporado en un sólo chip. Los microcontroladores ofrecen una amplia gama de aplicaciones y
sólo algunas se exploran normalmente. Le toca a
usted decidir qué quiere que haga el microcontrolador y cargar un programa en él con las instrucciones apropiadas. Antes de encender el dispositivo es recomendable verificar su funcionamiento
con ayuda de un simulador. Si todo funciona
como es debido, incorpore el microcontrolador en
el sistema. Si alguna vez necesita cambiar, mejorar o actualizar el programa, hágalo.
¿Hasta cuándo se deben hacer modificaciones?
Hasta quedar satisfecho. Eso puede realizarse sin ningún problema. Vea en la figura 1 una
caracterización sobre los pasos que debe seguir
un principiante para la programación.
Sabía usted que todas las personas pueden
ser clasificadas en uno de 10 grupos, en los que
están familiarizados con el sistema de numeración binario y en los que no están familiarizados
con él. Si no entendió lo anterior significa que
todavía pertenece al segundo grupo. Si desea
cambiar su estado, lea el siguiente
texto que describe brevemente algunos
de los conceptos básicos utilizados
más tarde en este libro (sólo para estar
seguro de que estamos hablando en
los mismos términos).
¡Muy simple!
¿Se podría expresar de una forma más desarrollada?
Por supuesto que sí:
764 = 4 + 60 + 700
¿Aún más desarrollado?
Sí:
764 = 4*1 + 6*10 + 7*100
¿Podría este número parecer un poco más
“científico”?
La respuesta es sí otra vez:
764= 4*100 + 6*101 + 7*102.
¿Qué significa esto realmente? ¿Por qué utilizamos exactamente estos números 100, 101 y
102 ? ¿Por qué es siempre el número 10?
Es porque utilizamos 10 dígitos diferentes (0,
1, 2...8, 9). En otras palabras, es porque utilizamos el sistema de numeración en base 10, es
decir el sistema de numeración decimal, figura
2.
núMeros, núMeros, núMeros...
¡La matemática es una gran ciencia!
Todo es tan lógico y simple... El universo de los números se puede describir
con sólo diez dígitos.
¿Realmente tiene que ser así?
¿Necesitamos exactamente esos 10 dígitos?
Por supuesto que no, es sólo cuestión del
hábito. Acuérdese de las lecciones de la escuela. Por ejemplo, ¿qué significa el número 764?
Cuatro unidades, seis decenas y siete centenas.
6
Club Saber Electrónica Nº 97
Figura 2
sIsteMa de nuMeracIón BInarIo
¿Qué pasaría si utilizáramos sólo dos números 0 y 1?
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 7
B aSES
Si sólo pudiéramos afirmar (1) o negar (0)
que algo existe. La respuesta es “nada especial”, seguiríamos utilizando los mismos números de la misma manera que utilizamos hoy en
día, no obstante ellos parecerían un poco diferentes. Por ejemplo: 11011010.
¿Cuántas son realmente 11011010 páginas
de un libro?
Para entenderlo, siga la misma lógica como
en el ejemplo anterior, pero en el orden invertido. Tenga en cuenta que se trata de aritmética
con sólo dos dígitos 0 y 1, es decir, del sistema
de numeración en base 2 (sistema de numeración binario). Vea la figura 3.
Evidentemente, se trata del mismo número
representado en dos sistemas de numeración
diferentes. La única diferencia entre estas dos
representaciones yace en el número de dígitos
necesarios para escribir un número. Un dígito
(2) se utiliza para escribir el número 2 en el sistema decimal, mientras que dos dígitos (1 y 0)
se utilizan para escribir aquel número en el sistema binario.
¿Ahora está de acuerdo que hay 10 grupos
de gente?
¡Bienvenido al mundo de la aritmética binaria! ¿Tiene alguna idea de dónde se utiliza?
Excepto en las condiciones de laboratorio
estrictamente controladas, los circuitos electrónicos más complicados no pueden especificar
con exactitud la diferencia entre dos magnitudes
(dos valores de voltaje, por ejemplo), si son
demasiado pequeños (más pequeños que unos
dE loS
M iCroCoNtroladorES
pocos voltios). La razón son los ruidos eléctricos
y fenómenos que se presentan dentro de lo que
llamamos “entorno de trabajo real” (algunos
ejemplos de estos fenómenos son los cambios
imprevisibles de la tensión de alimentación,
cambios de temperatura, tolerancia a los valores
de los componentes etc...). Imagínese una computadora que opera sobre números decimales al
tratarlos de la siguiente manera: 0=0V, 1=5V,
2=10V, 3=15V, 4=20V... 9=45V
¿Alguien dijo baterías?
Una solución mucho más fácil es una lógica
binaria donde 0 indica la ausencia de voltaje,
mientras que 1 indica la presencia de voltaje.
Simplemente, es fácil de
Figura 3 escribir 0 o 1 en vez de “no
hay voltaje” o “ hay voltaje”.
Mediante el cero lógico (0) y
uno lógico (1) la electrónica
se enfrenta perfectamente y
realiza con facilidad todas
las operaciones aritméticas.
Evidentemente, se trata de
electrónica que en realidad
aplica aritmética en la que
todos los números son
representados con sólo dos
dígitos y donde sólo es importante saber si hay
voltaje o no. Por supuesto, estamos hablando de
electrónica digital.
sIsteMa de nuMeracIón exadecIMal
En el principio del desarrollo de las computadoras era evidente que a la gente le costaba
mucho trabajar con números binarios. Por eso,
se estableció un nuevo sistema de numeración,
que utilizaba 16 símbolos diferentes. Es llamado
el sistema de numeración hexadecimal. Este
sistema está compuesto de 10 dígitos a los que
estamos acostumbrados (0, 1, 2, 3,... 9) y de
seis letras del alfabeto A, B, C, D, E y F.
¿Cuál es el propósito de esta combinación
aparentemente extraña?
Basta con mirar cómo todo en la historia de
Capítulo 1
7
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 8
El Mundo de los Microcontroladores
los números binarios encaja perfectamente para
lograr una mejor comprensión del tema. Vea la
figura 4.
Figura 4
El mayor número que puede ser representado con 4 dígitos binarios es el número 1111.
Corresponde al número 15 en el sistema decimal. En el sistema hexadecimal ese número se
representa con sólo un dígito F. Es el mayor
número de un dígito en el sistema hexadecimal.
¿Se da cuenta de la gran utilidad de estas
equivalencias?
El mayor número escrito con ocho dígitos
binarios es a la vez el mayor número de dos
dígitos en el sistema hexadecimal. Tenga en
cuenta que una computadora utiliza números
binarios de 8 dígitos. ¿Acaso se trata de una
casualidad?
códIgo Bcd
El código BCD (Binary-Coded Decimal Código binario decimal)
es un código binario utilizado para representar a
los números decimales.
Se utiliza para que los circuitos electrónicos puedan comunicarse con los periféricos utilizando el
sistema de numeración decimal o bien utilizando
el sistema binario dentro de “su propio mundo”.
Consiste en números binarios de 4 dígitos que
representan los primeros diez dígitos (0, 1, 2,
3...8, 9). Aunque cuatro dígitos pueden hacer 16
combinaciones posibles en total, el código BCD
normalmente utiliza a las primeras diez.
conversIón de sIsteMas de nuMeracIón
El sistema de numeración binario es el que
utilizan los microcontroladores, el sistema deci-
8
Club Saber Electrónica Nº 97
mal es el que nos resulta más comprensible,
mientras que el sistema hexadecimal presenta
un balance entre los dos. Por eso, es muy
importante aprender cómo
convertir los números de
un sistema de numeración
a otro, por ejemplo, cómo
convertir una serie de
ceros y unos a una forma de representación
comprensible para nosotros.
conversIón de núMeros BInarIos
a decIMales
Los dígitos en un número binario tienen ponderaciones diferentes lo que depende de sus
posiciones dentro del número que están representando. Además, cada dígito puede ser 1 o 0,
y su ponderación se puede determinar con facilidad al contar su posición empezando por la
derecha. Para hacer una conversión de un
número binario a decimal es necesario multiplicar las ponderaciones con los dígitos correspondientes (0 o 1) y sumar todos los resultados. La
magia de la conversión de un número binario a
decimal funciona de maravilla... ¿Tiene dudas?
Vea el ejemplo de la figura 5.
Figura 5
Cabe destacar que es necesario utilizar sólo
dos dígitos binarios para representar a todos los
números decimales de 0 a 3.
Por consiguiente, para representar los números de 0 a 7 es necesario utilizar tres dígitos
binarios, para representar los números de 0 a 15
- cuatro dígitos etc.
Dicho de manera sencilla, el mayor número
binario que se puede representar utilizando n
dígitos se obtiene al elevar la base 2 a la potencia n. Luego, al resultado se le resta 1. Por ejemplo, si n=4:
24 - 1 = 16 - 1 = 15
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 9
B aSES
Por consiguiente, al utilizar 4 dígitos binarios,
es posible representar los números decimales
de 0 a 15, que son 16 valores diferentes en total.
conversIón de núMeros HexadecIMales
a decIMales
Para realizar una conversión de un número
hexadecimal a decimal, cada dígito hexadecimal
debe ser multiplicado con el número 16 elevado
al valor de su posición. Como ejemplo, vea la
representación de la figura 6.
dE loS
M iCroCoNtroladorES
je”? Dependiendo del sistema en cuestión (binario, decimal o hexadecimal), el resultado podría
ser 6, 110 o 272 productos, respectivamente.
Por consiguiente, para evitar equivocaciones,
diferentes prefijos y sufijos se añaden directamente a los números. El prefijo $ o 0x así como
el sufijo h marca los números en el sistema
hexadecimal. Por ejemplo, el número hexadecimal 10AF se puede escribir así: $10AF, 0x10AF
o 10AFh. De manera similar, los números binarios normalmente obtienen el sufijo % o 0B. Si
un número no tiene ni sufijo ni prefijo se considera decimal. Desafortunadamente, esta forma
de marcar los números no es
Figura 6 estandarizada, por consiguiente
depende de la aplicación concreta. La mostrada en la figura 8
es tabla comparativa que contiene los valores de números 0255 representados en tres sistemas de numeración diferentes.
conversIón de núMeros HexadecIMales
BInarIos
a
No es necesario realizar ningún cálculo para
convertir un número hexadecimal a binario. Los
dígitos hexadecimales se reemplazan simplemente por los cuatro dígitos binarios apropiados.
Ya que el dígito hexadecimal máximo es equivalente al número decimal 15, es necesario utilizar
cuatro dígitos binarios para representar un dígito hexadecimal. Vea la figura 7.
Figura 7
Figura 8
Marcar los núMeros
El sistema de numeración hexadecimal, junto
con los sistemas binario y decimal, se consideran los más importantes para nosotros. Es fácil
realizar una conversión de cualquier número
hexadecimal a binario, además es fácil de recordarlo. Sin obstante, estas conversiones pueden
provocar una confusión. Por ejemplo, ¿qué significa en realidad la sentencia: “Es necesario
contar 110 productos en una cadena de monta-
núMeros negatIvos
Como ya hemos visto, para escribir un número negativo en matemáticas, basta con añadirle
el prefijo “-” (signo menos). Sin embargo, en la
programación, al acabarse el proceso de la compilación, se quedan sólo los números binarios,
Capítulo 1
9
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 10
El Mundo de los Microcontroladores
volviéndose las cosas más complicadas. Se utilizan sólo dos dígitos - 0 y 1, mientras que todos
los demás números, símbolos y signos se forman por medio de las combinaciones de estos
dos dígitos. En el caso de los números negativos, la solución es la siguiente:
“En los números negativos, el bit más significativo (el bit del extremo izquierdo) representa el
signo del número (donde 0 será positivo y 1
negativo)”.
En el caso de un número de 8 bits, para
representar un valor numérico sólo quedan 7
bits. De acuerdo a este tipo de codificación el
número +127 es el mayor número positivo con
signo que se puede representar con 8 bits.
Asimismo, hay cero (0) positivo y negativo (refiérase a la siguiente tabla).
el número 444 son los mismos pero tienen los
valores diferentes), el “significado” de un bit
depende de la posición que tiene en número
binario. En los números binarios, sus dígitos se
denominan el bit cero (el primer bit a la derecha), el primer bit (el segundo bit a la derecha)
etc. Además, ya que el sistema binario utiliza
solamente dos dígitos (0 y 1), el valor de un bit
puede ser 0 o 1.
No se confunda si se encuentra con un bit
que tiene el valor 4, 16 o 64. Son los valores
representados en el sistema decimal.
Simplemente, nos hemos acostumbrado tanto a
utilizar los números decimales que estas expresiones llegaron a ser comunes. Sería correcto
decir por ejemplo, “el valor del sexto bit en cualquier número binario equivale al número decimal
64”. Pero todos somos humanos y los viejos
hábitos mueren difícilmente. Además, ¿cómo le
suena “número uno-uno-cero-uno-cero...”?
BYte
¿Se puede saber de qué número se trata?
Por ejemplo, si ponemos el número
10000001, ¿es -1 o 129? No se preocupe, de
eso se encarga el compilador. Ésta es la razón
por la que se declaran variables al escribir el
programa, mientras tanto, mire la tabla 1 para
interpretar lo que estamos diciendo. Bueno, de
eso vamos a hablar a continuación.
BIt
La teoría dice que un bit es la unidad básica
de información...
Vamos a olvidarlo por un momento y demostrar qué es eso en la práctica. La respuesta es nada especial- un bit es un sólo dígito binario.
Similar a un sistema de numeración decimal en
el que los dígitos de un número no tienen la
misma ponderación (por ejemplo, los dígitos en
10
Club Saber Electrónica Nº 97
Un byte consiste en 8 bits colocados uno
junto al otro. Si un bit es un dígito, es lógico que
los bytes representen los números. Todas las
operaciones matemáticas se pueden realizar
por medio de ellos, como por medio de los
números decimales comunes. Similar a los dígitos de cualquier número, los dígitos de un byte
no tienen el mismo significado. El bit del extremo
izquierdo tiene la mayor ponderación, por eso es
denominado el bit más significativo (MSB). El bit
del extremo derecho tiene la menor ponderación, por eso es denominado el bit menos significativo (LSB). Puesto que los 8 dígitos de un
byte se pueden combinar de 256 maneras diferentes, el mayor número decimal que se puede
representar con un byte es 255 (una combinación representa un cero).
Un nibble o un cuarteto representa una
mitad de byte. Dependiendo de la mitad del
número en cuestión (izquierda o derecha), se
les denomina nibbles “altos” o “bajos”, respectivamente (figura 9).
Usted seguramente ha pensado alguna vez
en cómo es la electrónica dentro de un circuito
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 11
B aSES
Figura 9
integrado digital, un microcontrolador o un
microprocesador.
¿Cómo son los circuitos que realizan las operaciones matemáticas complicadas y toman
decisiones? ¿Sabía que sus esquemas, aparentemente complicadas consisten en sólo unos
pocos elementos diferentes, denominados circuitos lógicos o compuertas lógicas?
detalles IMPortantes
El funcionamiento de estos elementos es
basado en los principios establecidos por el
matemático británico George Boole en la mitad
del siglo 19 - es decir, ¡antes de la invención de
la primera bombilla! En breve, la idea principal
era de expresar las formas lógicas por medio de
las funciones algebraicas. Tal idea pronto se
transformó en un producto práctico que se convirtió más tarde en lo que hoy en día conocemos
como circuitos lógicos Y (AND), O (OR) o NO
(NOT). El principio de su funcionamiento es
conocido como algebra de Boole.
coMPonentes BásIcos de la lógIca dIgItal
Algunas instrucciones de programa utilizadas
por un microcontrolador funcionan de la misma
manera que las compuertas lógicas, pero en
forma de comandos. A continuación vamos a
explicar el principio de su funcionamiento.
compuerta Y (and)
Una compuerta lógica “Y” dispone de dos o
más entradas y de una salida. En este caso la
compuerta utilizada dispone de sólo dos entradas. Un uno lógico (1) aparecerá en su salida
dE loS
M iCroCoNtroladorES
sólo en caso de que ambas entradas (A Y B) sean llevadas a alto
(1). La tabla a la derecha de la
figura 10 (en la que también se
muestra el símbolo de esta compuerta) es la tabla de verdad que
muestra la relación entre las
entradas y salidas de la compuerta. El principio de funcionamiento es el mismo
cuando la compuerta disponga de más de dos
entradas: la salida proporciona un uno lógico (1)
sólo si todas las entradas son llevadas a alto (1).
Vea la figura 11.
Figura 10
Figura 11
Cualquier otra combinación de voltajes de
entrada proporcionará un cero lógico (0) en su
salida. Utilizada en el programa, la operación Y
lógico es realizada por una instrucción de programa, de la que vamos a hablar más tarde. Por
ahora basta con conocer que Y lógico en un programa se refiere a la realización de este tipo de
operación sobre los bits correspondientes de
dos registros diferentes.
compuerta o (or)
De manera similar, la compuerta O, cuyo
símbolo se observa en la figura 12, también dispone de dos o más entradas y de una salida. Si
la compuerta dispone de sólo dos entradas, es
aplicable lo siguiente: la salida proporciona un
uno lógico (1) si una u otra entrada (A o B) es llevada a alto (1). En caso de que la compuerta O
Capítulo 1
11
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:50 Página 12
El Mundo de los Microcontroladores
disponga de más de dos entradas, es aplicable
lo siguiente: La salida proporciona un uno lógico
(1) si por lo menos una entrada es llevada a alto
(1). Si todas las entradas están a cero lógico (0),
la salida estará a cero lógico (0) también. Vea la
figura 13.
Figura 12
Figura 13
En un programa, la operación O lógico se
realiza de la misma manera que la operación Y.
compuerta no (not)
La compuerta lógica NO dispone de una sola
entrada y una sola salida, por lo que funciona
muy simplemente, figura 14. Cuando un cero lógico (0) aparezca en su entrada, la salida proporciona un uno lógico (1) y viceversa. Esto significa
que esta compuerta invierte las señales por sí
mismas y por eso es denominada inversor.
En el programa la operación lógica NO se
realiza sobre un byte. El resultado es un byte
con los bits invertidos, figura 15. Si los bits de un
byte se consideran número, el valor invertido es
un complemento a ese número.
El complemento de un número es el valor
que se añade al número hasta llegar al mayor
número binario de 8 dígitos. En otras palabras,
la suma de un dígito de 8 números y de su complemento es siempre 255.
compuerta xor (o exclusiva)
La compuerta XOR (O EXCLUSIVA) es un
poco complicada en comparación con las
demás. Representa una combinación de todas
las compuertas anteriormente descritas y su
símbolo se puede ver en la figura 16. La salida
proporciona un uno lógico (1) sólo si sus entradas están en estados lógicos diferentes.
En el programa, esta operación se utiliza con
frecuencia para comparar dos bytes. La resta se
puede utilizar con el mismo propósito (si el resultado es 0, los bytes son iguales). A diferencia de
la resta, la ventaja de esta operación lógica es
que no es posible obtener los resultados negativos. En la figura 17 puede apreciar cómo es la
correspondencia entre entradas y salidas.
Figura 16
Figura 17
Figura 14
Figura 15
regIstros
Un registro o una celda de memoria es un circuito electrónico que puede memorizar el estado
de un byte.
12
Club Saber Electrónica Nº 97
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 13
B aSES
M iCroCoNtroladorES
dE loS
En otras palabras, el estado
de los bits de registros se fija
dentro de programa, los
registros SFR dirigen los
pequeños circuitos dentro
del microcontrolador, estos
circuitos se conectan por los
pines del microcontrolador a
un dispositivo periférico utilizado para... bueno, depende
de usted.
Figura 18
En la figura 18 tenemos un esquena que
ejemplifica el funcionamiento de un registro.
Puertos de entrada / salIda (e/s)
registros sFr
A diferencia de los registros que no tienen
ninguna función especial y predeterminada,
cada microcontrolador dispone de un número de
Para hacer útil un microcontrolador, hay que
conectarlo a un dispositivo externo, o sea, a un
periférico. Cada microcontrolador tiene uno o
más registros (denominados puertos) conectados a los pines en el microcontrolador, figura 20.
¿Por qué se denominan puertos
de entrada/salida?
Porque usted puede cambiar la
función de cada pin como quiera.
Por ejemplo, usted desea que su
dispositivo encienda y apague los
tres señales LEDs y que simultáneamente monitoree el estado
lógico de 5 sensores o botones de
Figura 19 presión. Uno de los puertos debe
estar configurado de tal manera
que haya tres salidas (conectadas a los LEDs) y
cinco entradas (conectadas a los sensores). Eso
se realiza simplemente por medio de software,
lo que significa que la función de algún pin
registros de funciones especiales (SFR), con la
función predeterminada por el fabricante. Sus
bits están conectados a los circuitos internos del
microcontrolador tales como temporizadores,
convertidores A/D, osciladores entre
otros, lo que significa que directamente
manejan el funcionamiento de estos
circuitos, o sea del microcontrolador.
Imagínese ocho interruptores que
manejan el funcionamiento de un circuito pequeño dentro del microcontrolador. Los registros SFR hacen exactamente lo mismo. Vea en la figura 19 un
diagrama en bloques de aplicación de
estos registros.
Figura 20
Capítulo 1
13
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 14
El Mundo de los Microcontroladores
puede ser cambiada durante el funcionamiento.
Una de las características más importantes
de los pines de entrada/salida (E/S) es la
corriente máxima que pueden entregar/recibir.
En la mayoría de los microcontroladores la
corriente obtenida de un pin es suficiente para
activar un LED u otro dispositivo de baja corriente (10-20mA).
Mientras más pines de E/S haya, más baja
es la corriente máxima de un pin. En otras palabras, todos los puertos de E/S comparten la
corriente máxima declarada en la hoja de especificación técnica del microprocesador.
Otra característica importante de los pines es
que pueden disponer de los resistores pull-up.
Estos resistores conectan los pines al polo positivo del voltaje de la fuente de alimentación y su
efecto se puede ver al configurar el pin como
una entrada conectada a un interruptor mecánico o a un botón de presión. Las últimas versiones de los microcontroladores tienen las resistencias pull-up configurables por software.
Cada puerto de E/S normalmente está bajo
el control de un registro SFR especializado, lo
que significa que cada bit de ese registro determina el estado del pin correspondiente en el
microcontrolador. Por ejemplo, al escribir un uno
lógico (1) a un bit del registro de control (SFR),
el pin apropiado del puerto se configura automáticamente como salida.
Eso significa que el voltaje llevado a ese pin
se puede leer como 0 o 1 lógico. En caso contrario, al escribir 0 al registro SFR, el pin apropiado del puerto se configura como salida. Su
voltaje (0V o 5V) corresponde al estado del bit
apropiado del registro del puerto.
Figura 21
De manera similar, cada dirección de memoria corresponde a una localidad de memoria. El
contenido de cualquier localidad se puede leer y
se le puede acceder al direccionarla. La memoria se puede escribir en la localidad o leer.
Hay varios tipos de memoria dentro del
microcontrolador:
Memoria roM – Memoria de sólo lectura
ROM: Read Only Memory. La memoria ROM
se utiliza para guardar permanentemente el programa que se está ejecutando. El tamaño de
programa que se puede escribir depende del
tamaño de esta memoria. Los microcontroladores actuales normalmente utilizan el direccionamiento de 16 bits, que significa que son capaces
de direccionar hasta 64 Kb de memoria, o sea
65535 localidades. Por ejemplo, si usted es principiante, su programa excederá pocas veces el
límite de varios cientos de instrucciones. Hay
varios tipos de memoria ROM:
unIdad de MeMorIa
La unidad de memoria es una parte del
microcontrolador utilizada para almacenar los
datos, figura 21. La manera más fácil de explicarlo es compararlo con un armario grande con
muchos cajones. Si marcamos los cajones claramente, será fácil acceder a cualquiera de sus
contenidos al leer la etiqueta en la parte delantera del cajón.
14
Club Saber Electrónica Nº 97
rom de Máscara (enmascarada) - MroM
La ROM enmascarada es un tipo de ROM
cuyo contenido es programado por el fabricante.
El término “de máscara” viene del proceso de
fabricación, donde las partes del chip se plasman en las mascaras utilizadas durante el proceso de fotolitografía. En caso de fabricación de
grandes series, el precio es muy bajo. Olvide la
idea de modificarla...
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 15
B aSES
otP roM (one time Programmable roM)
roM programable una sola vez
La memoria programable una sola vez permite descargar un programa en el chip, pero
como dice su nombre, una sola vez. Si se detecta un error después de descargarlo, lo único que
se puede hacer es descargar el programa
correcto en otro chip.
Figura 22
uv eProM (uv erasable Programmable
roM) - roM programable borrable
por rayos ultravioleta
El encapsulado de esta memoria, figura 22,
tiene una “ventana” reconocible en la parte alta.
Eso permite exponer la superficie del chip de silicio a la luz de ultravioleta y borrar el programa
completamente en varios minutos. Luego es
posible descargar un nuevo programa en él.
La instalación de esta ventana es complicada, lo que por supuesto afecta al precio. Desde
nuestro punto de vista, desgraciadamente, de
manera negativa...
dE loS
M iCroCoNtroladorES
pequeña escala. Por la gran popularidad de esta
memoria, la mayoría de los microcontroladores
se fabrican con tecnología flash hoy en día. Si
usted va a comprar un microcontrolador, ¡éste
es en definitiva la opción perfecta!
Memoria raM – Memoria
de acceso aleatorio
RAM: Random Access Memory. Al apagar la
fuente de alimentación, se pierde el contenido
de la memoria RAM. Se utiliza para almacenar
temporalmente los datos y los resultados inmediatos creados y utilizados durante el funcionamiento del microcontrolador. Por ejemplo, si el
programa ejecuta la adición (de cualquier cosa)
es necesario tener un registro que representa lo
que se llama “suma” en vida cotidiana. Con tal
propósito, uno de los registros de la RAM es
denominado “suma” y se utiliza para almacenar
los resultados de la adición.
Memoria eeProM – roM Programable
y Borrable eléctricamente
EEPROM:
Electricall
y
Erasable
Programmable ROM. El contenido de la
EEPROM se puede cambiar durante el funcionamiento (similar a la RAM), pero se queda permanentemente guardado después de la pérdida
de la fuente de alimentación (similar a la ROM).
Por lo tanto, la EEPROM se utiliza con frecuencia para almacenar los valores creados durante
el funcionamiento, que tienen que estar permanentemente guardados. Por ejemplo, si usted ha
Memoria Flash
Este tipo de memoria se inventó en los años
80 en los laboratorios de la compañía INTEL,
como forma desarrollada de la memoria UV
EPROM. Ya que es posible escribir y borrar el
contenido de esta memoria prácticamente un
número ilimitado de veces, los microcontroladores con memoria Flash son perfectos para estudiar, experimentar y para la fabricación en
Capítulo 1
15
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 16
El Mundo de los Microcontroladores
diseñado una llave electrónica
o un alarma, sería estupendo
permitir al usuario crear e introducir una contraseña por su
cuenta. Por supuesto, la nueva
contraseña tiene que estar
guardada al apagar la fuente
de alimentación. En tal caso
una solución perfecta es el
microcontrolador con una
EEPROM embebida.
InterruPcIones
La mayoría de programas utilizan interrupciones durante ejecución de programa regular. El
propósito del microcontrolador generalmente
consiste en reaccionar a los cambios en su
entorno. En otras palabras, cuando ocurre algo,
el microcontrolador reacciona de alguna manera... Por ejemplo, al apretar el botón del mando
a distancia, el microcontrolador lo registra y responde al comando cambiando de canal, subiendo o bajando el volumen etc. Si el microcontrolador pasará la mayoría del tiempo comproban-
16
Club Saber Electrónica Nº 97
do varios botones sin parar - las horas, los días,
esto no sería nada práctico.
Por lo tanto, el microcontrolador “aprendió un
truco” durante su evolución. En vez de seguir
comprobando algún pin o bit, el microconrolador
deja su “trabajo de esperar” a un “experto” que
reaccionará sólo en caso de que suceda algo
digno de atención.
La señal que informa al procesador central
acerca de tal acontecimiento se denomina
INTERRUPCIÓN.
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 17
B aSES
unIdad central de ProcesaMIento
(central Processor unIt - cPu)
Como indica su nombre, esto es una unidad
que controla todos los procesos dentro del
microcontrolador.
dE loS
direccionar la memoria. Se utiliza para transmitir
la dirección de la CPU a la memoria. El bus de
datos es tan ancho como los datos, en este caso
es de 8 bits o líneas de ancho. Se utiliza para
conectar todos los circuitos dentro del microcontrolador.
Figura 23
Consiste en varias unidades más pequeñas,
figura 23, de las que las más importantes son:
•
Decodificador de instrucciones es la
parte que descodifica las instrucciones del programa y acciona otros circuitos basándose en
esto. El “conjunto de instrucciones” que es diferente para cada familia de microcontrolador
expresa las capacidades de este circuito;
•
Unidad lógica aritmética (Arithmetical
Logical Unit - ALU) realiza todas las operaciones
matemáticas y lógicas sobre datos; y
•
Acumulador o registro de trabajo. Es un
registro SFR estrechamente relacionado con el
funcionamiento de la ALU. Es utilizado para
almacenar todos los datos sobre los que se
debe realizar alguna operación (sumar, mover).
También almacena los resultados preparados
para el procesamiento futuro. Uno de los registros SFR, denominado Registro Status (PSW),
está estrechamente relacionado con el acumulador. Muestra el “estado” de un número almacenado en el acumulador (el número es mayor o
menor que cero etc.) en cualquier instante dado.
Bus
El bus está formado por 8, 16 o más cables.
Hay dos tipos de buses: el bus de direcciones y
el bus de datos. El bus de direcciones consiste
en tantas líneas como sean necesarias para
M iCroCoNtroladorES
coMunIcacIón en serIe
La conexión paralela entre el
microcontrolador y los periféricos a través de los puertos de
entrada/salida es una solución
perfecta para las distancias
cortas “hasta varios metros”,
figura 24. No obstante, en otros casos cuando
es necesario establecer comunicación entre dos
dispositivos a largas distancias no es posible utilizar la conexión paralela. En vez de eso, se utiliza la conexión en serie.
Figura 24
Hoy en día, la mayoría de los microcontroladores llevan incorporados varios sistemas diferentes para la comunicación en serie, como un
equipo estándar. Cuál de estos sistemas se utilizará en un caso concreto, depende de muchos
factores, de los que más importantes son:
•
¿Con cuántos dispositivos el microcontrolador tiene que intercambiar los datos?
•
¿Cuál es la velocidad del intercambio de
datos obligatoria?
Capítulo 1
17
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 18
El Mundo de los Microcontroladores
•
¿Cuál es la distancia entre los dispositivos?
•
¿Es necesario transmitir y recibir los
datos simultáneamente?
Una de las cosas más importantes en cuanto
a la comunicación en serie es el “Protocolo” que
debe ser estrictamente observado. Es un conjunto de reglas que se aplican obligatoriamente
para que los dispositivos puedan interpretar
correctamente los datos que intercambian
mutuamente. Afortunadamente, los microcontroladores se encargan de eso automáticamente,
así que el trabajo de programador/usuario es
reducido a la escritura y lectura de datos.
velocIdad de transMIsIón serIal
La velocidad de transmisión serial (baud
rate) es el término utilizado para denotar el
número de bits transmitidos por segundo (bps).
Figura 25
entre ellos es corta (el receptor y el transmisor
están normalmente en la misma placa de circuito impreso). La conexión se establece por medio
de dos líneas - una se utiliza para transmitir los
datos, mientras que la otra se utiliza para la sincronización (la señal de reloj).
Como se muestra en la figura 25, un dispositivo es siempre el principal (master - maestro), el
que realiza el direccionamiento de un chip
subordinado (slave - esclavo) antes de que se
inicie la comunicación. De esta manera un
microcontrolador puede comunicarse con 112
dispositivos diferentes. La velocidad de transmisión serial es normalmente 100 kb/seg (el modo
estándar) o 10 Kb/seg (modo de velocidad de
transmisión baja).
Recientemente han aparecido los sistemas
con la velocidad de transmisión serial 3.4
Mb/sec. La distancia entre los dispositivos que
se comunican por el bus I2C está limitada a
unos metros.
¡Fíjese que este término se refiere a bits, y
no a bytes!
El protocolo normalmente requiere que
cada byte se transmita
junto con varios bits de
control. Eso quiere decir que un byte en un flujo
de datos serial puede consistir en 11 bits. Por
ejemplo, si velocidad de transmisión serial es
300 bps un máximo de 37 y un mínimo de 27
bytes se pueden transmitir por segundo.
Los sistemas de comunicación serial más utilizados son:
I2c cIrcuIto Inter- Integrado
(Inter Integrated cIrcuIt)
Circuito inter-integrado es un sistema para el
intercambio de datos serial entre los microcontroladores y los circuitos integrados especializados de generación. Se utiliza cuando la distancia
18
Club Saber Electrónica Nº 97
sPI - Bus serIal de InterFase de PerIFérIcos
(serIal PerIPHeral InterFace Bus)
Un bus serial de interfase de periféricos es
un sistema para la comunicación serial que utiliza hasta cuatro líneas (normalmente solo son
necesarias tres) para recibir los datos, para
transmitir los datos, para sincronizar y (opcional)
para seleccionar el dispositivo con el que se
comunica, figura 26.
Esto es la conexión full duplex, lo que significa que los datos se envían y se reciben simultáneamente.
La velocidad de transmisión máxima es
mayor que en el sistema de conexión I2C.
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 19
B aSES
Figura 26
uart – transMIsor – recePtor asIncrónIco
unIversal (unIversal asYncHronous
receIver/transMItter) - transMIsorEste tipo de conexión es asincrónica o asíncrona, lo que significa que no se utiliza una línea
especial para transmitir la señal de reloj. En
algunas aplicaciones este rasgo es crucial (por
ejemplo, en mandar datos a distancia por RF o
por luz infrarroja). Puesto que se utiliza sólo una
línea de comunicación, tanto el receptor como el
transmisor reciben y envían los datos a velocidad misma que ha sido predefinida para mantener la sincronización necesaria. Esto es una
manera simple de transmitir datos puesto que
básicamente representa una conversión de
datos de 8 bits de paralelo a serial. La velocidad
de transmisión no es alta, es hasta 1 Mbit/sec.
dE loS
M iCroCoNtroladorES
lador (figura 27) permiten el funcionamiento
armónico y síncrono de
todos los circuitos del
microcontrolador.
El oscilador se configura
normalmente de tal
manera que utilice un
cristal de cuarzo o resonador cerámico para
estabilización de frecuencia. Además, puede
funcionar como un circuito autónomo (como
oscilador RC). Es importante decir que las instrucciones del programa no se ejecutan a la
velocidad impuesta por el mismo oscilador sino
varias veces más despacio. Eso ocurre porque
cada instrucción se ejecuta en varios ciclos del
oscilador.
En algunos microcontroladores se necesita el
mismo número de ciclos para ejecutar todas las
instrucciones, mientras que en otros el tiempo
de ejecución no es el mismo para todas las instrucciones.
Por consiguiente, si el sistema utiliza el cristal de cuarzo con una frecuencia de 20MHZ, el
tiempo de ejecución de una instrucción de programa no es 50 nS, sino 200, 400 o 800 nS
dependiendo del tipo del microcontrolador.
oscIlador
cIrcuIto de alIMentacIón
Fuente de alIMenta cIón
Los pulsos uniformes generados por el osciFigura 27
Hay que mencionar dos cosas dignas de
atención con relación al circuito de la fuente
de alimentación de microcontroladores:
•
Brown out es un estado potencialmente peligroso que ocurre al apagar el microcontrolador o en caso de que el voltaje de la
fuente de alimentación salga de unos márgenes debido al ruido eléctrico.
Como el microcontrolador dispone de varios
circuitos que funcionan a niveles de voltaje
diferentes, ese estado puede causar un comportamiento descontrolado.
Para evitarlo, el microcontrolador normalmente tiene un circuito incorporado para el
Capítulo 1
19
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 20
El Mundo de los Microcontroladores
brown out reset. El circuito reinicia inmediatamente el microcontrolador si el voltaje de alimentación cae por debajo del límite.
•
el pin de reset (reinicio), marcado frecuentemente con MCLR (Master Clear Reset),
sirve para el reinicio externo del microcontrolador al aplicar un cero (0) o un uno (1) lógico
dependiendo del tipo del microcontrolador. En
caso de que el circuito brown out no esté incorporado, un simple circuito externo para el brown
out reset se puede conectar al pin MCLR.
teMPorIzadores – contadores
El oscilador del microcontrolador utiliza cristal de cuarzo para su funcionamiento. Aunque
no se trata de la solución más simple, hay
muchas razones para utilizarlo. La frecuencia
del oscilador es definida con precisión y muy
estable, así que siempre genera los pulsos del
mismo ancho, lo que los hace perfectos para
medición de tiempo. Tales osciladores se utilizan
en los relojes de cuarzo. Si es necesario medir
el tiempo transcurrido entre dos eventos, basta
con contar los pulsos generados por este oscilador. Esto es exactamente lo que hace el temporizador y su representación la podemos observar en la figura 28.
Figura 28
20
Club Saber Electrónica Nº 97
La mayoría de los programas utiliza estos
cronómetros electrónicos en miniatura.
Generalmente son registros SFR de 8 o 16 bits
cuyo contenido se aumenta automáticamente
con cada pulso.
¡Una vez que se llena el registro, se genera
una interrupción!
Si el temporizador utiliza el oscilador de cuarzo interno para su funcionamiento, es posible
medir el tiempo entre dos eventos (el valor de
registro en el momento de iniciar la medición es
T1, en el momento de finalizar la medición es
T2, el tiempo transcurrido es igual al resultado
de la resta T2 - T1).
Si los registros se aumentan con los pulsos
que vienen de la fuente externa, tal temporizador se convierte en un contador.
Esto es una explicación simple de su funcionamiento. Es un poco más complicado en práctica.
¿cóMo FuncIonan los teMPorIzadores?
En la práctica los pulsos generados por el
oscilador de cuarzo son llevados al circuito una
vez por cada ciclo de máquina directamente o
por el pre-escalador, lo que aumenta el número
en el registro del temporizador.
Si una instrucción (un ciclo de máquina generalmente) dura cuatro períodos del oscilador de
cuarzo, este número será cambiado un millón de
veces por segundo (cada microsegundo) al
incorporar al cuarzo que oscila con una frecuencia de 4MHz.
Es fácil de medir los intervalos de tiempo cortos de la manera descrita anteriormente (hasta
256 microsegundos porque es el mayor número
que un registro puede contener).
Esta obvia desventaja se puede superar de
varias maneras: al utilizar el oscilador más lento,
por medio de registros con más bits, del preescalador o de la interrupción. Las primeras dos
soluciones tienen algunas debilidades así que
se recomienda utilizar el pre-escalador y/o la
interrupción.
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 21
B aSES
utIlIzando un Preescalador
FuncIonaMIento del teMPorIzador
en el
Un pre-escalador es un dispositivo electrónico utilizado para dividir la frecuencia por un factor predeterminado. Esto quiere decir que se
necesita llevar 1, 2, 4 o más pulsos a su entrada
para generar un pulso a la salida. La mayoría de
los microcontroladores disponen de uno o más
pre-escaladores incorporados y su tasa de división puede ser cambiada dentro del programa.
El pre-escalador se utiliza cuando es necesario
medir los períodos de tiempo más largos, figura
29.
Figura 29
Si el temporizador y el temporizador perro
guardián comparten un pre-escalador, éste no
se puede utilizar por los dos simultáneamente.
utIlIzando una InterruPcIón
FuncIonaMIento del teMPorIzador
dE loS
M iCroCoNtroladorES
mayor número que se puede escribir en él es
255 (en los registros de 16 bits es el número
65.535). Si se excede este número, el temporizador se reinicia automáticamente y el conteo
comienza de nuevo en cero.
Esto es denominado desbordamiento o
sobreflujo (overflow). Permitido por el programa,
el desbordamiento puede provocar una interrupción, lo que abre completamente nuevas posibilidades.
Por ejemplo, el estado de registros utilizados
para contar segundos, minutos o días puede ser
implementado en una rutina de interrupción. El
proceso entero (excepto la rutina de interrupción) se lleva a
cabo internamente,
lo que permite que
los circuitos principales del microcontrolador funcionen regularmente.
La figura 30 describe el uso de una
interrupción en el
funcionamiento del
temporizador. Al asignarle un pre-escalador al
temporizador, se producen retrasos de duración
arbitraria con mínima interferencia en la ejecución del programa principal.
contadores
en el
Si el registro del temporizador es de 8 bits, el
Si un temporizador se suministra por los pulsos ingresados por el pin de entrada en el micro-
Fifura 30
Capítulo 1
21
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 22
El Mundo de los Microcontroladores
controlador, se produce un contador. Evidentemente, es el
mismo circuito electrónico. La
única diferencia es que los pulsos para contar se ingresan por
el pin de entrada y que su duración (anchura) no es definida.
Por eso, no se pueden utilizar
para medición de tiempo, sino
que se utilizan para otros propósitos, por ejemplo: contar los
productos en la cadena de montaje, número de rotaciones del
eje de un motor, pasajeros etc.
(dependiendo del sensor utilizado).
Figura 31
convertIdor dIgItal – analógIco (d/a)
teMPorIzador Perro guardIán
WatcHdog
El perro guardián es un temporizador conectado a un oscilador RC completamente independiente dentro del microcontrolador.
Si el perro guardián está habilitado, cada vez
que cuenta hasta el máximo valor en el que ocurre el desbordamiento del registro se genera una
señal de reinicio del microcontrolador y la ejecución de programa inicia en la primera instrucción.
El punto es evitar que eso ocurra al utilizar el
comando adecuado.
La idea se basa en el hecho de que cada programa se ejecuta en varios bucles, más largos o
cortos.
Si las instrucciones que reinician el temporizador perro guardián se colocan en lugares
estratégicos del programa, aparte los comandos
que se ejecutan regularmente, el funcionamiento del perro guardián no afectará a la ejecución
del programa, figura 31.
Si por cualquier razón (ruidos eléctricos frecuentes en la industria) el contador de programa
“se queda atrapado” dentro de un bucle infinito,
el valor del registro continuará aumentado, el
temporizador perro guardián alcanzará el máximo valor, el registro se desbordará y, ¡aleluya!
¡Ocurre el reinicio!
22
Club Saber Electrónica Nº 97
Las señales del mundo real son muy diferentes de las que “entiende” el microcontrolador
(ceros y unos), así que deben ser convertidas
para que el microcontrolador pueda entenderlas.
Figura 32
En la figura 32 podemos observar que entre “0”
(0V) y “1” (5V) hay varios niveles de tensión
intermedios. Un convertidor analógico-digital es
un circuito electrónico encargado de convertir
las señales continuas en números digitales discretos.
En otras palabras, este circuito convierte un
número real en un número binario y se lo envía
a la CPU para ser procesado. Este módulo, figura 33, se utiliza para medir el voltaje en el pin de
entrada.
El resultado de esta medición es un número
(el valor digital) utilizado y procesado más tarde
en el programa.
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 23
B aSES
Figura 33
arQuItectura Interna
MIcrocontrolador
de un
Todos los microcontroladores actuales utilizan uno de dos modelos básicos de arquitectura denominados Harvard y Von-Neumann.
Son dos maneras diferentes del intercambio
de datos entre la CPU y la memoria:
arquitectura de von-neumann
Los microcontroladores que utilizan la arquitectura Von- Neumann disponen de un solo bloque de memoria y de un bus de datos de 8 bits,
figura 34.
Figura 34
Como todos los datos se intercambian por
medio de estas 8 líneas, este bus está sobrecargado, y la comunicación por si misma es muy
lenta e ineficaz.
La CPU puede leer una instrucción o
leer/escribir datos de/en la memoria.
Los dos procesos no pueden ocurrir a la vez
puesto que las instrucciones y los datos utilizan
dE loS
M iCroCoNtroladorES
el mismo bus. Por ejemplo, si alguna
línea de programa dice que el registro de la memoria RAM llamado
“SUM” debe ser aumentado por uno
(instrucción: incf SUMA), el microcontrolador hará lo siguiente:
1. Leer la parte de la instrucción
de programa que especifica QUÉ es
lo que debe realizar (en este caso es
la instrucción para incrementar “incf”)
2. Seguir leyendo la misma instrucción que especifica sobre CUÁL
dato lo debe realizar (en este caso es
el contenido del registro “SUMA”)
3. Después de haber sido incrementado, el
contenido de este registro se debe escribir en el
registro del que fue leído (dirección del registro
“SUMA”).
El mismo bus de datos se utiliza para todas
estas operaciones intermedias.
arquitectura Harvard
Los microcontroladores que utilizan esta
arquitectura disponen de dos buses de datos
diferentes, figura 35.
Figura 35
Uno es de 8 bits de ancho y conecta la CPU
con la memoria RAM. El otro consiste en varias
líneas (12, 14 o 16) y conecta a la CPU y la
memoria ROM. Por consiguiente, la CPU puede
leer las instrucciones y realizar el acceso a la
memoria de datos a la vez.
Puesto que todos los registros de la memoria
RAM son de 8 bits de ancho, todos los datos
Capítulo 1
23
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 24
El Mundo de los Microcontroladores
dentro del microcontrolador que se intercambian
son de la misma anchura. Durante el proceso de
la escritura de programa, sólo se manejan los
datos de 8 bits.
En otras palabras, todo lo que usted podrá
cambiar en el programa y a lo que podrá afectar
será de 8 bits de ancho. Todos los programas
escritos para estos microcontroladores serán
almacenados en la memoria ROM interna del
microcontrolador después de haber sido compilados a código máquina.
No obstante, estas localidades de memoria
ROM no tienen 8, sino 12, 14 o 16 bits. 4, 6 o 8
bits adicionales representan una instrucción que
especifica a la CPU qué hacer con los datos de
8 bits.
Las ventajas de este diseño son las siguientes:
•
Todos los datos en el programa son de
un byte (8 bits) de ancho. Como un bus de datos
utilizado para lectura de programa tiene unas
líneas más (12, 14 o 16), tanto la instrucción
como el dato se pueden leer simultáneamente al
utilizar estos bits adicionales. Por eso, todas las
instrucciones se ejecutan en un ciclo salvo las
instrucciones de salto que son de dos ciclos.
•
El hecho de que un programa (la ROM)
y los datos temporales (la RAM) estén separados, permite a la CPU poder ejecutar dos instrucciones simultáneamente. Dicho de manera
sencilla, mientras que se realiza la lectura o
escritura de la RAM (que marca el fin de una instrucción), la siguiente instrucción se lee por
medio de otro bus.
•
En los microcontroladores que utilizan la
arquitectura de von-Neumann, nunca se sabe
cuánta memoria ocupará algún programa.
Generalmente, la mayoría de las instrucciones
de programa ocupan dos localidades de memoria (una contiene información sobre QUÉ se
debe realizar, mientras que la otra contiene
información sobre CUÁL dato se debe realizar).
Sin embargo, esto no es una fórmula rígida, sino
el caso más frecuente. En los microcontroladores que utilizan una arquitectura Harvard, el bus
de la palabra de programa es más ancho que un
byte, lo que permite que cada palabra de pro-
24
Club Saber Electrónica Nº 97
grama esté compuesto por una instrucción y un
dato. En otras palabras, una localidad de memoria - una instrucción de programa.
Juego de InstruccIones
El nombre colectivo de todas las instrucciones que puede entender el microcontrolador es
llamado Juego de Instrucciones, figura 36.
Figura 36
Cuando se escribe un programa en ensamblador, en realidad se especifican instrucciones en
el orden en el que deben ser ejecutadas. La restricción principal es el número de instrucciones
disponibles. Los fabricantes aceptan cualquiera
de los dos enfoques descritos a continuación:
rIsc (reduced Instruction set computer)
- computadora con Juego de Instrucciones
reducidas
En este caso la idea es que el microcontrolador reconoce y ejecuta sólo operaciones básicas
(sumar, restar, copiar etc.) Las operaciones más
complicadas se realizan al combinar éstas (por
ejemplo, multiplicación se lleva a cabo al realizar
adición sucesiva).
Es como intentar explicarle a alguien con
pocas palabras cómo llegar al aeropuerto en
una nueva ciudad. Sin embargo, no todo es tan
oscuro. Además, el microcontrolador es muy
rápido así que no es posible ver todas las “acrobacias” aritméticas que realiza.
El usuario sólo puede ver el resultado final de
todas las operaciones. Por último, no es tan difí-
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 25
B aSES
cil explicar dónde está el aeropuerto si se utilizan las palabras adecuadas tales como: a la
derecha, a la izquierda, el kilómetro etc.
cIsc (complex Instruction set computer)
- computadoras con un juego de instrucciones complejo
¡CISC es opuesto a RISC! Los microcontroladores diseñados para reconocer más de 200
instrucciones diferentes realmente pueden realizar muchas cosas a alta velocidad. No obstante,
uno debe saber cómo utilizar todas las posibilidades que ofrece un lenguaje tan rico, lo que no
es siempre tan fácil.
¿cóMo se deBe elegIr
MIcrocontrolador?
un
Si usted es principiante y ha tomado decisión
de trabajar con los microcontroladores. ¡felicitaciones por la elección! No obstante, a primera
vista, no es fácil la elección del microcontrolador
más adecuado como parece a la primera vista.
¡El problema no es el pequeño rango de dispositivos a elegir, sino todo lo contrario!
Antes de empezar a diseñar un dispositivo
basado en un microcontrolador, tome en cuenta
dE loS
M iCroCoNtroladorES
lo siguiente: cuántas entradas/líneas son necesarias para su funcionamiento, realizaría el dispositivo
otras
operaciones
además
encender/apagar un relé, necesita algún modulo
especializado tal como el de comunicación en
serie, convertidor A/D etc. Cuando usted tiene
una clara imagen de lo que quiere, el rango de
selección se reduce considerablemente, y le
queda pensar en el precio. ¿Va a tener varios
dispositivos? ¿Varios cientos? ¿Un millón? De
todos modos ahora es más claro.
Si está pensando en todas estas cosas por
primera vez, todo le parecerá un poco confuso.
Por esa razón, vaya paso a paso. Antes que
nada, seleccione al fabricante, es decir, la familia de microcontroladores que ofrece. Luego,
aprenda a trabajar con un modelo particular.
Sólo aprenda lo que necesite aprender, no entre
demasiado en detalles. Resuelva el problema
específico y le pasará una cosa increíble - será
capaz de manejar cualquier modelo del mismo
fabricante...
Más o menos, todo se parece a montar en
bicicleta: después de varias caídas inevitables en
el principio, será capaz de mantener el equilibrio
y montar en cualquier otra bicicleta. ¡Por supuesto, nunca se olvida tanto de montar en bicicleta,
como de la destreza de programación! J
Capítulo 1
25
Cap 1 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:51 Página 26
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 27
Capítulo 2
eL mundo de LoS microcontroLadoreS
SiStemaS de Programación:
Lenguaje mikroc
Usted seguramente sabe que no es suficiente sólo conectar el microcontrolador a los
otros componentes y encender una fuente de alimentación para hacerlo funcionar,
¿verdad? Hay que hacer algo más. Se necesita programar el microcontrolador. Si cree
que esto es complicado, está equivocado. Todo el procedimiento es muy simple.
Basta con leer el texto para entender de lo que estamos hablando.
www.mikroe.com
Lenguajes de Programación
El microcontrolador ejecuta el programa cargado en la memoria flash. Esto se denomina el
código ejecutable y está compuesto por una
serie de ceros y unos, aparentemente sin significado. Dependiendo de la arquitectura del
microcontrolador, el código binario está compuesto por palabras de 12, 14 o 16 bits de
ancho. Cada palabra se interpreta por la CPU
como una instrucción a ser ejecutada durante el
funcionamiento del microcontrolador. Todas las
instrucciones que el microcontrolador puede
reconocer y ejecutar se les denominan colectivamente Conjunto de instrucciones. Como es
más fácil trabajar con el sistema de numeración
hexadecimal, el código ejecutable se representa
con frecuencia como una serie de los números
Capítulo 2
27
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 28
El Mundo de los Microcontroladores
hexadecimales denominada código Hex. En los
microcontroladores PIC con las palabras de programa de 14 bits de anchura, el conjunto de instrucciones tiene 35 instrucciones diferentes.
Lenguaje ensambLador
Como el proceso de escribir un código ejecutable era considerablemente arduo, en consecuencia fue creado el primer lenguaje de programación denominado ensamblador (ASM).
Siguiendo la sintaxis básica del ensamblador,
era más fácil escribir y comprender el código.
Las instrucciones en ensamblador consisten en
las abreviaturas con significado y a cada instrucción corresponde una localidad de memoria.
Un programa denominado ensamblador compila
(traduce) las instrucciones del lenguaje ensamblador a código máquina (código binario). Vea la
figura 1. Este programa compila instrucción a
instrucción sin optimización. Como permite controlar en detalle todos los procesos puestos en
marcha dentro del chip, este lenguaje de programación todavía sigue siendo popular.
Ventajas de Los Lenguajes
de Programación de aLto niVeL
A pesar de la gran cantidad de beneficios, el
Figura 1
28
Club Saber Electrónica Nº 97
lenguaje ensamblador tiene algunas desventajas a saber:
* Incluso una sola operación en el programa
escrito en ensamblador consiste en muchas instrucciones, haciéndolo muy largo y difícil de
manejar.
* Cada tipo de microcontrolador tiene su propio conjunto de instrucciones que un programador tiene que conocer para escribir un programa
* Un programador tiene que conocer el hardware del microcontrolador para escribir un programa
En la figura 2 podemos observar un programa escrito en C y el mismo programa compilado
al código ensamblador.
Los lenguajes de programación de alto nivel
(Basic, Pascal, C etc.) fueron creados con el
propósito de superar las desventajas del ensamblador.
En lenguajes de programación de alto nivel
varias instrucciones en ensamblador se sustituyen por una sentencia. El programador ya no
tiene que conocer el conjunto de instrucciones o
características del hardware del microcontrolador utilizado. Ya no es posible conocer exactamente cómo se ejecuta cada sentencia, de
todas formas ya no importa. Aunque siempre se
puede insertar en el programa una secuencia
escrita en ensamblador.
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 29
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
Figura 2
Si alguna vez ha escrito un programa para un
microcontrolador PIC en lenguaje ensamblador,
probablemente sepa que la arquitectura RISC
carece de algunas instrucciones. Por ejemplo,
no hay instrucción apropiada para multiplicar
dos números.
Por supuesto, para cada problema hay una
solución y éste no es una excepción gracias a la
aritmética que permite realizar las operaciones
complejas al descomponerlas en un gran número operaciones más simples. En este caso, la
multiplicación se puede sustituir con facilidad
por adición sucesiva (a x b = a + a + a + ... + a).
Ya estamos en el comienzo de una historia
muy larga...
No hay que preocuparse al utilizar uno de
estos lenguajes de programación de alto nivel
como es C, porque el compilador encontrará
automáticamente la solución a éste problema y
otros similares. Para multiplicar los números a y
b, basta con escribir a*b ó axb.
Lenguaje c
El lenguaje C dispone de todas las ventajas
de un lenguaje de programación de alto nivel
(anteriormente descritas) y le permite realizar
algunas operaciones tanto sobre los bytes como
sobre los bits (operaciones lógicas, desplazamiento etc.).
Las características de C pueden ser muy útiles al programar los microcontroladores.
Además, C está estandarizado (el estándar
ANSI), es muy portable, así que el mismo código se puede utilizar muchas veces en diferentes
proyectos.
Lo que lo hace accesible para cualquiera que
conozca este lenguaje sin reparar en el propósito de uso del microcontrolador. C es un lenguaje compilado, lo que significa que los archivos
fuentes que contienen el código C se traducen a
lenguaje máquina por el compilador. Todas
estas características hicieron al C uno de los
lenguajes de programación más populares.
Capítulo 2
29
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 30
El Mundo de los Microcontroladores
Figura 3
La figura 3 es un ejemplo general de lo que
sucede durante la compilación de programa de
un lenguaje de programación de alto nivel a bajo
nivel.
caracteríSticaS deL Lenguaje mikroc
A continuación vamos a presentar a los elementos principales del lenguaje mikroC
desarrollado por Mikroelektronika.
Este lenguaje es muy similar al C estándar, no obstante en determinados aspectos difiere del
ANSI estándar en algunas características, figura 4. Algunas de estas diferencias se refieren a las
mejoras, destinadas a facilitar la programación de los microcontroladores PIC, mientras que las
demás son la consecuencia de la limitación de la arquitectura del hardware de los PIC. Aquí vamos
a presentar características específicas del lenguaje mikroC en la programación de los microcontroladores PIC.
Figura 4
30
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 31
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
El término C se utilizará para referirse a las características comunes de los lenguajes C y mikroC.
Este libro describe una aplicación muy concreta del lenguaje de programación C utilizado en el compilador “mikroc Pro for Pic”. En este caso, el compilador se utiliza para la programación de los
microcontroladores PIC. Cabe destacar que el lector no necesariamente precisará este compilador
pero creemos oportuno utilizarlo dado que sus ventajas son enormes. De todos modos, en el próximo capítulo, veremos otras formas de trabajar con microcontroladores PIC.
Fases de La comPiLación
El proceso de compilación consiste en varios pasos y se ejecuta automáticamente por el compilador, figura 5. Por consiguiente, un conocimiento básico del funcionamiento puede ser útil para
entender el concepto del lenguaje mikroC.
Figura 5
El archivo fuente contiene el código en mikroC que usted escribe para programar el microcontrolador. El preprocesador se utiliza automáticamente por el compilador al iniciarse el proceso de la
compilación. El compilador busca las directivas del preprocesador (que siempre empiezan por ‘#’)
dentro del código y modifica el código fuente de acuerdo con las directivas.
En esta fase se llevan a cabo inclusión de archivos, definición de constantes y macros etc., lo
que facilita el proceso.
Más tarde vamos a describir estas directivas en detalle. El analizador sintáctico (parser) elimina toda la información inútil del código (comentarios, espacios en blanco). Luego, el compilador
traduce el código a un archivo binario denominado archivo .mcl. El enlazador (linker) recupera toda
la información requerida para ejecutar el programa de los archivos externos y la agrupa en un solo
archivo (.dbg).
Además, un proyecto puede contener más de un archivo fuente y el programador puede utilizar
funciones predefinidas y agrupadas dentro de los archivos denominados librerías. Por último, el
generador “.hex” produce un archivo .hex. Es el archivo que se va a cargar en el microcontrolador.
El proceso entero de la compilación que incluye todos los pasos anteriormente descritos se le
denomina “building”.
estructura deL Programa
La idea principal de escribir un programa en C es de “romper” un problema mayor en varios trozos más pequeños. Supongamos que es necesario escribir un programa para el microcontrolador
para medir la temperatura y visualizar los resultados en un LCD. El proceso de medición se realiza
por un sensor que convierte temperatura en voltaje. El microcontrolador utiliza el convertidor A/D
para convertir este voltaje (valor analógico) en un número (valor digital) que luego se envía al LCD
Capítulo 2
31
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 32
El Mundo de los Microcontroladores
por medio de varios conductores. En consecuencia, el programa se divide en cuatro partes, de las
que cada una corresponde a una acción específica:
Activar y configurar el convertidor A/D incorporado;
Medir el valor analógico;
Calcular temperatura; y
Enviar los datos en el formato apropiado al LCD.
Los lenguajes de programación de alto nivel
como es C le permiten solucionar este problema con facilidad al escribir cuatro funciones
que se ejecutarán cíclicamente sin parar, tal
como se deduce de la figura 6.
La idea general es de dividir el problema en
varios trozos, de los que cada uno se puede
escribir como una sola función. Todos los programas escritos en mikroC contienen por lo
menos una función llamada main() que encierra entre llaves {} las sentencias a ser ejecutadas. Esto es la primera función a ser ejecutada
al iniciarse la ejecución de programa. Las otras
funciones se pueden llamar dentro de la función main. En otras palabras, podemos decir
Figura 6
que la función main() es obligatoria, mientras
que las demás son opcionales. Si todavía no ha escrito un programa en C, es probable que todo le
resulte confuso. No se preocupe, acéptelo tal como es por el momento y más tarde entenderá la
sintaxis.
¡Y ahora, haga su primer programa ‘real’!
La figura 7 muestra la estructura de un programa, señalando las partes en las que consiste.
Figura 7
32
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 33
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
La manera de escribir el código en C es muy importante. Por ejemplo, C difiere entre minúsculas y mayúsculas, así que la función main() no se puede escribir MAIN() o Main(). Además, note
que dos líneas del código dentro de la función terminan con un punto y coma. En C todas las sentencias deben terminar con un punto y coma ‘;’, así el compilador puede aislarlas y traducirlas a
código máquina.
Para comprender mejor esta estructura mire la figura 8 en la que se expresan diferentes observaciones dentro del programa.
Figura 8
comentarios
Los comentarios son las partes del programa utilizados para aclarar las instrucciones de programa o para proporcionar más información al respecto. El compilador no hace caso a los comentarios y no los compila al código ejecutable.
Dicho de manera sencilla, el compilador es capaz de reconocer los caracteres especiales utilizados para designar dónde los comentarios comienzan y terminan y no hace nada de caso al texto
entre ellos durante la compilación. Hay dos tipos de tales caracteres. Unos designan los comentarios largos que ocupan varias líneas de programa marcados por la secuencia especial /*...*/, mientras que otros designan los comentarios cortos que caben en una sola línea //. Aunque los comentarios no pueden afectar a la ejecución de programa, son tan importantes como cualquier otra parte
de programa.
Aquí está el porqué... con frecuencia es necesario mejorar, modificar, actualizar, simplificar un
programa... No es posible interpretar incluso los programas simples sin utilizar los comentarios.
Capítulo 2
33
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 34
El Mundo de los Microcontroladores
tiPos de datos en mikroc
En el lenguaje C, los datos tienen un tipo, o sea, cada dato utilizado en el programa debe tener
su tipo especificado. Esto permite al compilador conocer el tamaño de dato (número de bytes requerido en la memoria) y su representación. Hay varios tipos de datos que se pueden utilizar en el lenguaje de programación mikroc dependiendo del tamaño de dato y del rango de valores. La tabla 1
muestra el rango de valores que los datos pueden tener cuando se utilizan en su forma básica.
Tabla 1
Al añadir un prefijo (calificador) a cualquier tipo de dato entero o carácter, el rango de sus posibles valores cambia así como el número de los bytes de memoria necesarios. Por defecto, los datos
de tipo int son con signo, mientras que los de tipo char son sin signo. El calificador signed (con
signo) indica que el dato puede ser positivo o negativo. El prefijo unsigned indica que el dato puede
ser sólo positivo. Note en la tabla 2 que el prefijo es opcional.
Tabla 2
tipo entero (int)
Un entero es un número sin parte fraccionaria que puede estar expresado en los siguientes formatos, a saber:
Hexadecimal (base 16): el número empieza con 0x (o 0X). Los enteros hexadecimales consisten en los dígitos (de 0 a 9) y/o las letras (A, B, C,D, E, F). Por ejemplo: ‘0x1A’.
Decimal (base 10): el número consiste en los dígitos (de 0 a 9). El primer dígito no puede ser
0. En este formato, se puede introducir el signo de número (‘+’ o ‘-’). Por ejemplo: 569, -25, +1500.
Octal (base 8): los números se representan a base 8 utilizando sólo 8 dígitos (de 0 a 7). Los
enteros octales empiezan con 0. Por ejemplo: ‘056’.
Binario (base 2): cuando un entero empieza con 0b (o 0B) se representan como una serie de
bits (‘0’ y ‘1’). Por ejemplo: 0B10011111.
Vea a continuación un juego de sentencias que pueden corresponder a una parte de un programa en la que se muestran los diferentes formatos:
34
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 35
S iStEmaS
0x11
11
-152
011
0b11
dE
P rogramaCióN : L ENguajE
mikro C
// formato hexadecimal equivale a decimal 17
// formato decimal
// formato decimal
// formato octal equivale a decimal 9
// formato binario equivale a decimal 3
tipo punto flotante (float)
El tipo punto flotante (float) se utiliza para los números reales con el punto decimal. Los datos
de tipo float se pueden representar de varias maneras.
Un dato float es siempre con signo (signed):
0.
-1.23
23.45e6
2e-5
3E+10
.09E34
// = 0.0
// = -1.23
// = 23.45 * 10^6
// = 2.0 * 10^-5
// = 3.0 * 10^10
// = 0.09 * 10^34
tipo carácter (char)
El tipo char es considerado como un entero por el compilador. No obstante, se utiliza normalmente para los datos de tipo carácter. Un dato de tipo carácter está encerrado entre comillas y codificado en un carácter ASCII:
59
'p'
// entero
// carácter ASCII 'p'
Una secuencia de caracteres es denominada cadena (string). Las cadenas están encerradas
entre comillas dobles:
"Presione el botón RA0"
VariabLes y constantes
definiciones
Una variable es un objeto nombrado capaz de contener un dato que puede ser modificado durante la ejecución de programa. En C, las variables tienen tipo, que significa que es necesario especificar el tipo de dato que se le asigna a una variable (int, float etc.). Las variables se almacenan en
la memoria RAM y el espacio de memoria que ocupan (en bytes) depende de su tipo, figura 13.
/* dos líneas de programa consecutivas. En la primera línea del programa
se define el tipo de variable */
int a = 1000;
a = 15;
// Variable a es de tipo int y equivale a 1000
// a equivale a 15
Capítulo 2
35
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 36
El Mundo de los Microcontroladores
Una constante tiene las mismas características que una variable excepto el hecho de que su
valor asignado no puede ser cambiado durante la ejecución de programa. A diferencia de las variables, las constantes se almacenan en la memoria Flash del microcontrolador para guardar el mayor
espacio posible de memoria RAM.
El compilador las reconoce por el nombre y el prefijo const. En mikroC, el compilador reconoce
automáticamente el tipo de dato de una constante, así que no es necesario especificar el tipo adicionalmente.
/* dos líneas de programa consecutivas */
const A = 1000
A = 15;
// el valor de la constante A está definido
// ¡ERROR! no se puede modificar el valor de la constante
Cada variable o constante debe tener un identificador que lo distingue de otras variables y constantes. Refiérase a los ejemplos anteriores, a y a son identificadores.
reglas para nombrar
En mikroC los identificadores pueden ser tan largos como quiera. Sin embargo, hay varias restricciones a saber:
* Los identificadores pueden incluir cualquiera de los caracteres alfabéticos A-Z (a-z), los dígitos
0-9 y el carácter subrayado ‘_’. El compilador es sensible a la diferencia entre minúsculas y mayúsculas. Los nombres de funciones y variables se escriben con frecuencia con minúsculas, mientras
que los nombres de constantes se escriben con mayúsculas.
* Los identificadores no pueden empezar con un dígito.
* Los identificadores no pueden coincidir con las palabras clave del lenguaje mikroC, porque son
las palabras reservadas del compilador.
El compilador mikroC reconoce 33 palabras clave que se muestran en la tabla 3.
Tabla 3
Ejemplos de los identificadores válidos e inválidos los puede ver a continuación:
36
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 37
S iStEmaS
temperatura_V1
Presión
no_corresponder
dat2string
SuM3
_vtexto
7temp
%más_alto
if
j23.07.04
nombre de variable
dE
P rogramaCióN : L ENguajE
mikro C
// OK
// OK
// OK
// OK
// OK
// OK
// NO -- no puede empezar con un número
// NO -- no pueden contener caracteres especiales
// NO -- no puede coincidir con una palabra reservada
// NO -- no puede contener caracteres especiales (punto)
// NO -- no puede contener espacio en blanco
declaración de Variables
Cada variable debe ser declarada antes de ser utilizada en el programa. Como las variables se
almacenan en la memoria RAM, es necesario reservar el espacio para ellas (uno, dos o más bytes).
Al escribir un programa, usted sabe qué tipo de datos quiere utilizar y qué tipo de datos espera como
resultado de una operación, mientras que el compilador no lo sabe. No se olvide de que el programa maneja las variables con los nombres asignados. El compilador las reconoce como números en
la memoria RAM sin conocer su tamaño y formato. Para mejorar la legibilidad de código, las variables se declaran con frecuencia al principio de las funciones:
<tipo> variable;
Es posible declarar más de una variable de una vez si tienen el mismo tipo:
<tipo> variable1, variable2, variable3;
Aparte del nombre y del tipo, a las variables se les asignan con frecuencia los valores iniciales
justamente enseguida de su declaración. Esto no es un paso obligatorio, sino ‘una cuestión de buenas costumbres’. Se parece a lo siguiente:
unsigned int peso;
peso = 20;
// Declarar una variable llamada peso
// Asignar el valor 20 a la variable peso
Un método más rápido se le denomina declaración con inicialización (asignación de los valores
iniciales):
unsigned int peso = 20;
// peso está declarado y su valor es 20
Si hay varias variables con el mismo valor inicial asignado, el proceso se puede simplificar:
unsigned int peso1 = peso2 = peso3 = 20;
int valor_inicial = un_mínimo_de_petróleo = 0;
Tenga cuidado de no declarar la misma variable otra vez dentro de la misma función. Puede
modificar el contenido de una variable al asignarle un nuevo valor tantas veces que quiera.
Al declarar una variable, siempre piense en los valores que la variable tendrá que contener
durante la ejecución de programa.
Capítulo 2
37
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 38
El Mundo de los Microcontroladores
En el ejemplo anterior, peso1 no se puede representar con un número con punto decimal o un
número con valor negativo.
declaración de constantes
Similar a las variables, las constantes deben ser declaradas antes de ser utilizadas en el programa. En mikroC, no es obligatorio especificar el tipo de constante al declararla. Por otra parte, las
constantes deben ser inicializadas a la vez que se declaran. El compilador reconoce las constantes
por su prefijo const utilizado en la declaración. Dos siguientes declaraciones son equivalentes:
const int MINIMUM = -100;
const MINIMUM = -100;
// Declarar constante MINIMUM
// Declarar constante MINIMUM
Las constantes pueden ser de cualquier tipo, incluyendo cadenas:
const T_MAX = 3.260E1;
const I_CLASS = ‘A’;
const Mensaje = “Presione el botón IZQUIERDA”;
// constante de punto flotante T_MAX
// constante carácter I_CLASS
// constante de cadena Mensaje
Las constantes de enumeración son un tipo especial de constantes enteras que hace un programa más comprensible al asignar los números ordinales a las constantes. Por defecto, el valor 0
se asigna automáticamente a la primera constante entre llaves, el valor 1 a la segunda, el valor 2 a
la tercera etc.
enum surtidores {AGUA,GASÓLEO,CLORO};
// AGUA = 0; GASÓLEO = 1; CLORO = 2
Es posible introducir directamente el valor de una constante dentro de la lista de enumeraciones.
El incremento se detiene al asignar un valor a un elemento de matriz, después se reinicia a partir
del valor asignado. Vea el siguiente ejemplo:
enum surtidores {AGUA,GASÓLEO=0,CLORO};
// AGUA = 0; GÁSOLEO = 0; CLORO = 1
Las constantes de enumeración se utilizan de la siguiente manera:
int Velocidad_de_ascensor
enum motor_de_ascensor {PARADA,INICIO,NORMAL,MÁXIMO};
Velocidad_de_ascensor = NORMAL;
// Velocidad_de_ascensor = 2
definir los nuevos tipos de datos
La palabra clave typedef le permite crear con facilidad los nuevos tipos de datos, así, por ejemplo, podemos escribir la siguiente sentencia:
typedef unsigned int positivo;
positivo a,b;
a = 10;
b = 5;
38
Club Saber Electrónica Nº 97
// positivo es un sinónimo para el tipo sin signo int
// Variables a y b son de tipo positivo
// Variable a equivale a 10
// Variable b equivale a 5
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 39
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
Ámbito de VariabLes y constantes
Una variable o una constante es reconocida por el compilador en base de su identificador. Un
identificador tiene significado si el compilador lo puede reconocer. El ámbito de una variable o una
constante es el rango de programa en el que su identificador tiene significado. El ámbito es determinado por el lugar en el que se declara una variable o una constante. Intentar acceder a una variable o una constante fuera de su ámbito resulta en un error. Una variable o una constante es invisible fuera de su ámbito.
Todas las variables y constantes que pensamos utilizar en un programa deben ser declaradas
anteriormente en el código. Las variables y constantes pueden ser globales o locales. Una variable
global se declara en el código fuente, fuera de todas las funciones, mientras que una variable local
se declara dentro del cuerpo de la función o dentro de un bloque anidado en una función. Vea la
figura 9.
Figura 9
A las variables globales se les puede acceder de cualquier parte en el código, aún dentro de las
funciones con tal de que sean declaradas. El ámbito de una variable global está limitado por el fin
del archivo fuente en el que ha sido declarado.
El ámbito de variables locales está limitado por el bloque encerrado entre llaves {} en el que han
sido declaradas.
Por ejemplo, si están declaradas en el principio del cuerpo de función (igual que en la función
main) su ámbito está entre el punto de declaración y el fin de esa función. Refiérase al ejemplo
anterior. A las variables locales declaradas en main() no se les puede acceder desde la Función_1
y al revés.
Un bloque compuesto es un grupo de declaraciones y sentencias (que pueden ser bloques también) encerradas entre llaves. Un bloque puede ser una función, una estructura de control etc. Una
variable declarada dentro de un bloque se considera local, o sea, ‘existe’ sólo dentro del bloque. Sin
embargo, las variables declaradas fuera del ámbito todavía son visibles.
Aunque las constantes no pueden ser modificadas en el programa, siguen las mismas reglas que
las variables.
Esto significa que son visibles dentro de su bloque a excepción de las constantes globales
(declaradas fuera de cualquier función). Las constantes se declaran normalmente en el inicio del
código fuera de cualquier función (como variables globales).
Capítulo 2
39
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 40
El Mundo de los Microcontroladores
cLases de aLmacenamiento
Las clases de almacenamiento se utilizan para definir el ámbito y la vida de variables, constantes y funciones dentro de un programa. En mikroC se pueden utilizar diferentes clases de almacenamiento:
auto es una clase de almacenamiento por
defecto para las variables locales, así que se
utiliza raramente. Se utiliza para definir que
una variable local tiene duración local. La
clase de almacenamiento auto no se puede
utilizar con variables globales, figura 10.
Figura 10
static es una clase de almacenamiento por defecto para las variables globales. Especifica que
una variable es visible dentro del archivo. A las variables locales declaradas con el prefijo static se
les puede acceder dentro del archivo fuente (o sea se comportan como variables globales).
extern: la palabra clave extern se utiliza cuando el programa está compuesto por diferentes
archivos fuente. Esto le permite utilizar una variable, una constante o una función declarada en otro
archivo. Por supuesto, para compilar y enlazar este archivo correctamente, el mismo debe ser incluido en su proyecto. Vea un ejemplo de un programa que consiste en dos archivos: File_1 y File_2.
File_1 utiliza una variable y una función declaradas se usa en File_2.
File 1:
extern int cnt;
extern void hello();
// Variable cnt es visible en File_1
// Función hello()se puede utilizar en File_1
void main(){
PORTA = cnt++;
hello();
}
// Cualquier modificación de cnt en File_1 será visible en File_2
// Función hello()se puede llamar desde aquí
File 2:
int cnt = 0;
void hello();
void hello(){
.
.
}
// Modificaciones que afectan a la
// cnt en File_1 son visibles aquí
oPeradores
Un operador es un símbolo que denota una operación aritmética, lógica u otra operación particular. Dicho de manera sencilla, varias operaciones aritméticas y lógicas se realizan por medio de
40
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 41
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
los operadores. Hay más de 40 operaciones disponibles en el lenguaje C, pero se utiliza un máximo de 10 a 15 de ellas en la práctica. Cada operación se realiza sobre uno o más operandos que
pueden ser variables o constantes. Además, cada operación se caracteriza por la prioridad de ejecución y por la asociatividad.
operadores aritméticos
Los operadores aritméticos se utilizan en las operaciones aritméticas y siempre devuelven resultados numéricos. Hay dos tipos de operadores, los unitarios y los binarios. A diferencia de las operaciones unitarias que se realizan sobre un operando, las operaciones binarias se realizan sobre
dos operandos. En otras palabras, se requieren dos números para ejecutar una operación binaria.
Por ejemplo: a+b o a/b. Vea en la tabla 4 cuáles son los operadores aritméticos:
Tabla 4
int a,b,c;
a = 5;
b = 4;
c = a + b;
c = c%2;
// Declarar 3 enteros a, b, c
// Inicializar a
// Inicializar b
// c = 9
// c = 1. Esta operación se utiliza con frecuencia
// para comprobar la paridad. En este caso, el
// resultado es 1 lo que significa que la variable
// es un número imparo
operadores de asignación
Hay dos tipos de asignación en el lenguaje C:
* Los operadores simples asignan los valores a las variables utilizando el carácter común ‘=’. Por
ejemplo: a =8
* Las asignaciones compuestas son específicas para el lenguaje C. Consisten en dos caracteres como se muestra en la tabla 5.
Tabla 5
int a = 5; // Declarar e inicializar la variable a
a += 10; // a = a + 10 = 15
Capítulo 2
41
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 42
El Mundo de los Microcontroladores
Se utilizan para simplificar la sintaxis y habilitar la ejecución más rápida. Debajo de la tabla se
puede observar un ejemplo de uso en lenguaje C.
operadores de incremento y decremento
Las operaciones de incremento y decremento por 1 se denotan con “++” y “—”. Estos caracteres pueden preceder o seguir a una variable.
En primer caso (++x), la variable x será incrementada por 1 antes de ser utilizada en la expresión. De lo contrario, la variable se utilizará en la expresión antes de ser aumentada por 1. Lo mismo
se aplica a la operación de decremento, tabla 6.
Tabla 6
int a, b, c;
a = b = 5;
c = 1 + a++;
b = ++c + a
// c = 6
// b = 7 + 6 = 13
operadores relacionales
Los operadores relacionales se utilizan en comparaciones con el propósito de comparar dos
valores, tabla 7.
Tabla 7
int prop;
int var = 5;
prop = var < 10; // Expresión es evaluada como verdadera, prop = 1
En mikroC, si una expresión es evaluada como falsa (false), el operador devuelve 0, mientras
que si una oración es evaluada como verdadera (true), devuelve 1. Esto se utiliza en expresiones
tales como ‘si la expresión es evaluada como verdadera, entonces...’
operadores Lógicos
Hay tres tipos de operaciones lógicas en el lenguaje C: y (and) lógico, o (or) lógico y negación - no (not) lógico. Los operadores lógicos devuelven verdadero (1 lógico) si la expresión evaluada es distinta de cero. En caso contrario, devuelve falso (0 lógico) si la expresión evaluada equivale a cero. Esto es muy importante porque las operaciones lógicas se realizan generalmente sobre
42
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 43
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
las expresiones, y no sobre las variables (números) particulares en el programa. Por lo tanto, las
operaciones lógicas se refieren a la veracidad de toda la expresión.
Por ejemplo: 1 && 0 es igual a (expresión verdadera) && (expresión falsa)
El resultado 0, o sea - Falso en ambos casos. En la tabla 8 tiene la correspondencia de estos
operadores lógicos.
Tabla 8
operadores de manejo de bits
A diferencia de las operaciones lógicas que se realizan sobre los valores o expresiones, las operaciones de manejo de bits se realizan sobre los bits de un operando. Se enumeran en la tabla 9.
Tabla 9
¿cómo utilizar los operadores?
Aparte de los operadores de asignación, dos operadores no deben estar escritos uno junto al
otro, por ejemplo:
x*%12;
// esta expresión generará un error
Cada operador tiene su prioridad y asociatividad como se muestra en la tabla 10.
Similar a las expresiones aritméticas, los operadores se agrupan juntos por medio de paréntesis
como se puede observar a continuación:
int a, b, res;
a = 10;
b = 100;
res = a*(a + b); // resultado = 1100
res = a*a + b; // resultado = 200
Primero se calculan las expresiones encerradas entre paréntesis. Si es necesario, se pueden utilizar los paréntesis múltiples (anidados).
Capítulo 2
43
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 44
El Mundo de los Microcontroladores
Tabla 10
conVersión de tiPos de datos
Algunas operaciones implican conversión de datos. Por ejemplo, si divide dos valores enteros,
hay una alta posibilidad de que el resultado no sea un entero.
El mikroC realiza una conversión automática cuando se requiera. Si dos operandos de tipo diferente se utilizan en una operación aritmética, el tipo de operando de la prioridad más baja se convierte automáticamente en el tipo de operando de la prioridad más alta. Los tipos de datos principales se colocan según el orden jerárquico mostrado en la figura 11.
La autoconversión se realiza asimismo en las operaciones de asignación. El resultado de la
expresión de la derecha del operador de la asignación siempre se convierte en el tipo de la variable de la izquierda del operador. Si el resultado es de tipo de la prioridad más alta, se descarta o se
redondea para coincidir con el tipo de la variable. Al convertir un dato real en un entero, siempre se
descartan los números que siguen al punto decimal:
int x;
x = 3;
x+ = 3.14;
// A la variable x se le asigna el tipo integer (un entero)
// A la variable x se le asigna el valor 3
// El valor 3.14 se agrega a la variable x al
// realizar la operación de asignación
/* El resultado de la adición es 6 en vez de 6.14, como era de esperar.
Para obtener el resultado esperado sin descartar los números que siguen al
punto decimal, se debe declarar x como un punto flotante. */
44
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 45
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
Para realizar una conversión explícita, antes de escribir una expresión o una variable hay que
especificar el tipo de resultado de operación entre paréntesis:
double distancia, tiempo, velocidad;
distancia = 0.89;
tiempo = 0.1;
velocidad = (int)(a/b);
// c = (int)8.9 = 8.0
velocidad = ((int)a)/b;
// c = 0/0.1 = 0.0
estructuras de controL
estructuras condicionales
Las condiciones son ingredientes comunes de un programa. Las condiciones permiten ejecutar
una o varias sentencias dependiendo de validez de una expresión. En otras palabras, ‘Si se cumple la condición (...), se debe hacer (...). De lo contrario, si la condición no se cumple, se debe hacer
(...)’.
Los operandos condicionales if-else y switch se utilizan en las operaciones condicionales. Una
sentencia condicional puede ser seguida por una sola sentencia o por un bloque de sentencias a
ser ejecutadas.
operador condicional if-else
El operador if se puede utilizar solo o asociado al operador else (if-else).
Ejemplo del operador if:
if(expresión) operación;
Si el resultado de la expresión encerrada entre paréntesis es verdadero (distinto de 0) la operación se realiza y el programa continúa con la ejecución. Si el resultado de la expresión es falso (0),
la operación no se realiza y el programa continúa inmediatamente con la ejecución.
Como hemos mencionado, la otra forma combina tanto el operador if como el else:
if(expresión) operación1 else operación2;
Si el resultado de la expresión es verdadero (distinto de 0), se realiza operación1, de lo contrario se realiza la operación2. Después de realizar una de las operaciones, el programa continúa con
la ejecución.
La sentencia if-else se parece a lo siguiente:
if(expresión)
operación1
else
operación2
Si operación1 u operación2 está compuesta, escriba una lista de sentencias encerradas entre
llaves. Por ejemplo:
Capítulo 2
45
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 46
El Mundo de los Microcontroladores
if(expresión) {
...
...
...}
else
operación2
//
// operación1
//
El operador if-else se puede sustituir por el operador condicional ‘?:’:
(expresión1)? expresión2 : expresión3
Si el valor de la expresión1 es distinto de 0 (verdadero), el resultado de la expresión entera será
equivalente al resultado obtenido de la expresión2. De lo contrario, si la expresión1 es 0 (falso), el
resultado de la expresión entera será equivalente al resultado obtenido de la expresión3. Por ejemplo:
maximum = (a>b)? a : b
// A la variable maximum se le asigna el
// valor de la variable mayor(a o b)
operador switch
A diferencia de la sentencia if-else que selecciona entre dos opciones en el programa, el operador switch permite elegir entre varias opciones. La sintaxis de la sentencia switch es:
switch (selector)
{
case constante1:
operación1
...
// Selector es de tipo char o int
// El grupo de operadores que se ejecutan si
// el selector y la constante1 son equivalentes
break;
case constante2:
operación2
...
// El grupo de operadores se ejecuta si
// el selector y la constante2 son equivalentes
break;
...
default:
operación_esperada
...
break;
// El grupo de operadores que se ejecuta si
// ninguna constante equivale al selector
}
La operación switch se ejecuta de la siguiente manera: primero se ejecuta el selector y se compara con la constante1. Si coinciden, las sentencias que pertenecen a ese bloque se ejecutan hasta
llegar a la palabra clave break o hasta el final de la operación switch. Si no coinciden, el selector se
46
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 47
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
compara con la constante2. Si coinciden, las sentencias que pertenecen a ese bloque se ejecutan
hasta llegar a la palabra clave break etc. Si el selector no coincide con ninguna constante, se ejecutarán las operaciones que siguen al operador default.
También es posible comparar una expresión con un grupo de constantes. Si coincide con alguna de ellas, se ejecutarán las operaciones apropiadas:
switch (días)
// La variable días representa un día de la semana.
{
// Es necesario determinar si es un día laborable o no lo es
case1:case2:case3:case4:case5: LCD_message = ‘Día laborable’; break;
case6:case7: LCD_message = ‘Fin de semana’; break;
default:LCD_message_1 = ‘Elija un día de la semana’; break;
}
La palabra clave de C ‘break’ se puede utilizar en cualquier tipo de bloques.
Al utilizar ‘break’, es posible salir de un bloque aunque la condición para su final no se haya cumplido.
Se puede utilizar para terminar un bucle infinito, o para forzar un bucle a terminar antes de lo
normal.
bucLes
A menudo es necesario repetir una cierta operación un par de veces en el programa. Un conjunto de comandos que se repiten es denominado un bucle de programa. Cuántas veces se ejecutará, es decir cuánto tiempo el programa se quedará en el bucle, depende de las condiciones de
salir del bucle.
bucle While
El bucle while se parece a lo siguiente:
while(expresión){
comandos
...
}
Los comandos se ejecutan repetidamente (el programa se queda en el bucle) hasta que la expresión llegue a ser falsa.
Si la expresión es falsa en la entrada del bucle, entonces el bucle no se ejecutará y el programa
continuará desde el fin del bucle while.
Un tipo especial del bucle de programa es un bucle infinito. Se forma si la condición sigue sin
cambios dentro del bucle. La ejecución es simple en este caso ya que el resultado entre llaves es
siempre verdadero (1=verdadero), lo que significa que el programa se queda en el mismo bucle:
while(1){
...
...
}
// En vez de “while(1)”, se puede escribir “while(true)”
// Expresiones encerradas entre llaves se ejecutarán
// repetidamente (bucle infinito)
Capítulo 2
47
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 48
El Mundo de los Microcontroladores
bucle For
El bucle for se parece a lo siguiente:
for(expresión_inicial; expresión_de_condición; cambiar_expresión) {
operaciones
...
}
La ejecución de esta secuencia de programa es similar al bucle while, salvo que en este caso el
proceso de especificar el valor inicial (inicialización) se realice en la declaración. La expresión_ inicial especifica la variable inicial del bucle, que más tarde se compara con la expresión_ de_condición antes de entrar al bucle. Las operaciones dentro del bucle se ejecutan repetidamente y después de cada iteración el valor de la expresión_inicial se incrementa de acuerdo con la regla cambiar_expresión. La iteración continúa hasta que la expresión_de_condición llegue a ser falsa.
for(k=0; k<5; k++)
operación
...
// La variable k se incrementa 5 veces (de 1 a 4) y
// cada vez se repite la expresión operación
La operación se ejecutará cinco veces. Luego, al comprobar se valida que la expresión k<5 sea
falsa (después de 5 iteraciones k=5) y el programa saldrá del bucle for.
bucle do-while
El bucle do-while se parece a lo siguiente:
do
operación
while (cambiar_condición);
La expresión cambiar_condición se ejecuta al final del bucle, que significa que operación se ejecuta como mínimo una vez sin reparar en que si la condición es verdadera o falsa. Si el resultado
es distinto de 0 (verdadero), el procedimiento se repite.
Todos los siguientes ejemplos son equivalentes. Esta parte del código visualiza “hello” en un
LCD 10 veces con un retardo de un segundo. Note que en este ejemplo se utilizan funciones predefinidas, que se encuentran en las librerías del compilador mikroC PRO for PIC. No obstante le
aconsejamos que no trate de entenderlas en detalle. Su comportamiento general dentro del bucle
se explica por medio de los comentarios.
i = 0;
// Inicialización del contador
while (i<10) {
Lcd_Out(1,3,”hello”);
Delay_ms(1000);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);
i++;
}
// Condición
// Visualizar “hello” en el LCD
// Retardo de 1000 ms
// Borrar el LCD
// Retardo de 500ms
// Contador se incrementa
48
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 49
S iStEmaS
for(i=0; i<10; i++) {
Lcd_Out(1,3,”hello”);
Delay_ms(1000);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);
}
i = 0;
dE
P rogramaCióN : L ENguajE
mikro C
// Inicialización, condición, incremento
// Visualizar “hello” en el LCD
// Retardo de 1000 ms
// Borrar el LCD
// Retardo de 500ms
// Inicialización del contador
do {
Lcd_Out(1,3,”hello”);
Delay_ms(1000);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);
i++;
}
while (i<10);
// Visualizar “hello” en el LCD
// Retardo de 1000 ms
// Borrar LCD
// Retardo de 500ms
// Contador se incrementa
// Condición
sentencias de saLto
sentencia break
A veces es necesario detener y salir de un bucle dentro de su cuerpo. La sentencia break se
puede utilizar dentro de cualquier bucle (while, for, do while) y en las sentencias switch también. En
éstas la sentencia break se utiliza para salir de las sentencias switch si la condición case es verdadera. En este ejemplo, “Esperar” está parpadeando en la pantalla LCD hasta que el programa detecte un uno lógico en el pin 0 del puerto PORTA.
while(1){
if(PORTA.F0 == 1)
break;
Lcd_Out(1,3,”Esperar”);
Delay_ms(1000);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(500);
}
// Bucle infinito
// Probar si el estado lógico del pin 0 del puerto
// PORTA es 1; si equivale, salir del bucle
// Visualizar “Esperar” en el LCD
// Retardo de 1000 ms
// Borrar LCD
// Retardo de 500ms
sentencia continue
La sentencia continue colocada dentro de un bucle se utiliza para saltar una iteración. A diferencia de la sentencia break, el programa se queda dentro del bucle y las iteraciones continúan.
// Si x=7, puede ocurrir una división por 0.
// continue se utiliza aquí para evitar esta situación.
x=1;
while (x<=10) {
if (x == 7) {
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,3,”Division by 0”);
// saltar x=7 para evitar división por 0
Capítulo 2
49
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 50
El Mundo de los Microcontroladores
Delay_ms(1000);
x++;
continue;
// Después de esta línea, saltar a la sentencia while con x=8
}
a = 1/(x-7);
// Esta división generará un error si x=7
/* Muchas operaciones pueden ocurrir aquí */
Lcd_Out(1,3,”Division is OK”);
Delay_ms(1000);
x++;
// Poner este mensaje en el LCD
}
sentencia goto
La sentencia goto le permite hacer un salto absoluto al otro punto en el programa. Esta característica se debe utilizar con precaución ya que su ejecución puede causar un salto incondicional sin
hacer caso a todos los tipos de limitaciones de anidación. El punto destino es identificado por una
etiqueta, utilizada como un argumento para la sentencia goto. Una etiqueta consiste en un identificador válido seguido por un colon (:).
...
if(CO2_sensor) goto aire acondicionado; // Si se consta que el valor
...
// de la variable CO2_sensor =1
// hacer salto a la línea de programa
// Aire acondicionado
...
Aire acondicionado:
// Desde aquí sigue la parte del código que se ejecutará
// en caso de una concentración de CO2 demasiado alta
...
// en el ambiente
tiPos de datos aVanzados
matrices
Una matriz es una lista de elementos del mismo tipo colocados en localidades de memoria contiguas. Cada elemento es referenciado por un índice. Para declarar una matriz, es necesario especificar el tipo de sus elementos (denominado tipo de matriz), su nombre y el número de sus elementos encerrados entre corchetes. Todos los elementos de una matriz tienen el mismo tipo.
tipo_de_matriz nombre_de_matriz [nº_de_elementos];
Los elementos de una matriz se identifican por su posición. En C, el índice va desde 0 (el primer
elemento de una matriz) a N-1 (N es el número de elementos contenidos en una matriz). El compilador tiene que “saber” cuántas localidades de memoria debe alojar al declarar una matriz.
50
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 51
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
El tamaño de una matriz no puede ser una variable. Por eso, se pueden utilizar dos métodos:
// método 1
// Declaración de la matriz display capaz de contener 3 enteros
// método 2
int display [3];
const DÍGITOS = 5;
char Matriz_nueva[DÍGITOS];
// Declaración de la matriz Matriz_nueva
// capaz de contener 5 enteros
Una matriz se puede inicializar a la vez que se
declara, o más tarde en el programa. En ambos
casos, este paso se realiza al utilizar llaves:
int array_1[3] = {10,1,100};
Para leer o modificar un elemento de matriz del ejemplo anterior, basta con introducir su índice
encerrado entre corchetes:
/* Se supone que a ha sido declarado anteriormente como un entero */
a = array_1[0];
// A la variable a se le asigna el valor del miembro de matriz
// con índice 0 (a = 10)
array_1[2] = 20;
// Miembro de matriz array_1[2] es modificado (nuevo valor es 20)
El siguiente programa cambia el orden de los elementos de una matriz. Note que el índice se
puede expresar mediante variables y operaciones básicas.
void main() {
// Valor de la constante MUESTRAS_DE_AGUA es 4
const MUESTRAS_DE_AGUA = 4;
int i, temp;
// Variables i y temp son de tipo int
int profunidad_de_sonda [MUESTRAS_DE_AGUA] = {24,25,1,1987};
// Todos
// los miembros de la matriz profundidad
// de sonda son de tipo int
for(i=0;i<(MUESTRAS_DE_AGUA/2);i++){ // Bucle se ejecuta 2 veces
temp = profundiad_de_sonda [i];
// temp se utiliza para guardar un valor
// temporalmente
profundiad_de_sonda [i] = profundiad_de_sonda [MUESTRAS_DE_AGUA-1-i];
profundiad_de_sonda [MUESTRAS_DE_AGUA-1-i] = temp;
}
// Aquí tenemos: profundidad_de_sonda [MUESTRAS_DE_AGUA] = {1987,1,25,24}
}
matrices bidimensionales
Aparte de las matrices unidimensionales que se pueden interpretar como una lista de valores, el
lenguaje C le permite declarar matrices multidimensionales.
Capítulo 2
51
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 52
El Mundo de los Microcontroladores
En esta parte vamos a describir sólo las matrices bidimensionales, también denominadas tablas
o matrices. Una matriz bidimensional se declara al especificar el tipo de dato de matriz, el nombre
de matriz y el tamaño de cada dimensión.
tipo_de_matriz nombre_de_matriz [número_de_filas] [número_de_columnas];
En la declaración de esta matriz número_de_filas y número_de_columnas representan el número de filas y columnas en las que consiste una tabla, respectivamente. Vea la siguiente matriz bidimensional:
int Tabla [3][4]; // Tabla se define de modo que tenga 3 filas y 4 columnas
Esta matriz se puede representar en la forma de una tabla:
______________________________________________
tabla[0][0] tabla[0][1]
tabla[0][2]
tabla[0][3]
tabla[1][0] tabla[1][1]
tabla[1][2]
tabla[1][3]
tabla[2][0] tabla[2][1]
tabla[2][2]
tabla[2][3]
––––––––––––––––––––––––––––––––––––––––––––––
Similar a las matrices unidimesionales, es posible asignar los valores a los elementos de una
tabla en la línea de declaración. La asignación debe ser realizada línea a línea como en el siguiente ejemplo. Como hemos visto anteriormente, esta matriz tiene dos filas y tres columnas:
int Tabla [2][3]= { {3,42,1},{7,7,19} };
La matriz anterior se puede representar también en la forma de una tabla de valores:
___________________________
3
42
1
7
7
19
–––––––––––––––––––––––––––
Punteros
Un puntero es una variable destinada a recibir una dirección. Un puntero “apunta” a una localidad de memoria, referenciada por una dirección. En C, la dirección de un objeto se puede obtener
por medio un operador unitario &. Para acceder al contenido de la memoria en una dirección específica (también llamado objeto apuntado), se utiliza un operador de indirección (*).
‘&n’ es la dirección de la localidad de memoria ‘n’.
‘*(&n)’ es el contenido de la dirección ‘(&n)’, o sea de ‘n’.
Para declarar un puntero, se debe que especificar el tipo de la variable apuntada:
tipo_de_variable *puntero;
52
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 53
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
En esta etapa, el puntero mi_puntero apunta al valor almacenado en esta localidad de memoria,
o sea, a un valor desconocido. Así que, una inicialización es muy recomendable:
puntero = &variable;
Ahora, puntero contiene la dirección de variable.
Para acceder al contenido de la variable apuntada, debe utilizar ‘*’.
El siguiente ejemplo muestra el contenido de memoria dependiendo de la acción realizada por
medio del puntero.
Los punteros son muy útiles para manejar las matrices. En este caso, un puntero se utilizará para
apuntar al primer elemento de una matriz.
Debido al hecho de que es posible realizar operaciones básicas sobre los punteros (aritmética
de punteros), es fácil manejar los elementos de una matriz.
Fíjese en la diferencia entre ‘*v+1’ y ‘*(v+1)’ en el siguiente ejemplo:
short int voltio[3] = {0,5,10};
short int *v;
v = &(voltio[0]);
*(v+1) = 2;
voltio[2] = *v+1;
*(v+2) = *(v+1);
v++;
*v = 1;
// v contiene la dirección de voltio[0]
// voltio[1] = 2
// tab[2] = 1 (tab[0] + 1)
// voltio[2] = 2
// v contiene la dirección de voltio[1]
// voltio[1] = 1
Los punteros también pueden ser declarados con el prefijo ‘const’. En este caso, su valor no
puede ser modificado después de la inicialización, similar a una constante.
A diferencia de C, el mikroC no admite alojamiento dinámico.
estructuras
Ya hemos visto cómo agrupar los elementos dentro de matrices. No obstante, al utilizar este
método todos los elementos deben ser del mismo tipo.
Al utilizar estructuras, es posible agrupar diferentes tipos de variables bajo el mismo nombre. Las
variables dentro de una estructura se le denominan los miembros de la estructura. Las estructuras
de datos se declaran al utilizar la siguiente sintaxis:
Capítulo 2
53
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 54
El Mundo de los Microcontroladores
struct nombre_de_estructura {
tipo1_de_miembro1 miembro1;
tipo2_de_miembro2 miembro2;
tipo3_de_miembro3 miembro3;
..
};
No es posible inicializar variables dentro de la declaración de la estructura de datos:
struct generador {
int voltaje;
char corriente;
};
Entonces, podrá definir los objetos denominados ‘turbina’ en el código. A cada uno de estos tres
objetos (turbinas) se le asignan las variables ‘corriente’ y ‘voltaje’.
struct generadores turbina_1, turbina_2, turbina_3;
Para acceder a las variables, es preciso utilizar el operador ‘.’
turbina_3.voltaje = 150;
turbina_3.corriente = 12;
Por supuesto, igual que al utilizar los punteros, todavía se le permite realizar operaciones por
medio de operadores y sentencias definidos en las partes anteriores.
Si está familiarizado con el lenguaje C, recuerde que mikroC no admite la inicialización de los
miembros de estructura por medio de las llaves. Por ejemplo, ‘conjunto_1 ={15,‘m’};’ devuelve un
error en mikroC.
Funciones
Una función es una subrutina que contiene una lista de sentencias a realizar. La idea principal
es dividir un programa en varias partes utilizando estas funciones para resolver el problema inicial
con más facilidad. Además, las funciones nos permiten utilizar las destrezas y el conocimiento de
otros programadores. Una función se ejecuta cada vez que se llame dentro de otra función. En C,
un programa contiene como mínimo una función, la función main(), aunque el número de funciones
es normalmente mayor. Al utilizar funciones el código se hace más corto ya que es posible llamar
una función tantas veces como se necesite. En C, el código normalmente consiste en muchas funciones. No obstante, en caso de que su programa sea muy corto y simple, puede escribir todas las
sentencias dentro de la función principal.
Función Principal
La función principal main() es una función particular puesto que es la que se ejecuta al iniciar el
programa. Además, el programa termina una vez completada la ejecución de esta función. El compilador reconoce automáticamente esta función y no es posible llamarla por otra función. La sintaxis de esta función es la siguiente:
54
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 55
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
void main (void) {
/* el primer ‘void’ significa que main no devuelve ningún valor. El segundo
‘void’ significa que no recibe ningún valor. Note que el compilador
también admite la siguiente sintaxis: ‘main()’ o ‘void main()’ o
‘main(void)’ */
..
/* —- Introduzca su programa aquí —- */
.
};
Esto significa que f es una función que recibe un número real x como parámetro y devuelve 2*xy. La misma función en C se parece a lo siguiente:
float f (float x, float y)
{
float r;
r = 2*x - y;
return r;
}
// variables flotantes x y y se pueden utilizar en f
// declarar r para almacenar el resultado
// almacenar el resultado del cálculo en r
// devolver el valor de r
Cada función debe ser declarada apropiadamente para poder interpretarla correctamente durante el proceso de compilación. La declaración contiene los siguientes elementos:
* Tipo de resultado (valor devuelto): tipo de dato del valor devuelto
* Nombre de función: es un identificador que hace posible llamar a una función.
* Declaración de parámetros: se parece a la declaración de variable regular (por ejemplo: float
x). Cada parámetro consiste en una variable, constante, puntero o matriz, precedidos por la etiqueta de tipo de dato. Se utilizan para pasar la información a la función al llamarla. Los parámetros diferentes están delimitados por comas.
* Cuerpo de función: bloque de sentencias dentro de llaves.
Una función se parece a lo siguiente:
tipo_de_resultado nombre_de_función (tipo argumento1, tipo argumento2,...)
{
Sentencia;
Sentencia;
...
return ...
}
Note que una función no necesita parámetros (función main() por ejemplo), pero debe estar entre
paréntesis. En caso contrario, el compilador malinterpretaría la función. Para hacerlo más claro, puede
sustituir el espacio en blanco encerrado entre paréntesis por la palabra clave void: main (void).
Capítulo 2
55
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 56
El Mundo de los Microcontroladores
Valor devuelto
Una función puede devolver un valor (esto no es obligatorio) por medio de la palabra clave
return. Al llegar a return, la función evalúa un valor (puede ser una expresión) y lo devuelve a la línea
de programa desde la que fue llamada.
return r;
return (2*x - y);
// Devolver el valor contenido en r
// Devolver el valor de la expresión 2*x-y
Una función no puede devolver más de un valor, pero puede devolver un puntero o una estructura. Tenga cuidado al utilizar matrices y punteros. El siguiente ejemplo es un error típico:
int *reverse(int *tab)
{
int r[DIM];
int i;
for(i=0;i<DIM;i++)
r[i] = tab[DIM-1-i];
return r;
// Esta función debe devolver una matriz r
// cuyo contenido está en orden inverso con
// respecto a la matriz tab
// Declaración de una nueva matriz denominada r
// Bucle que copia el contenido de tab en r
// al invertir el orden
// Devolver el valor r
}
En realidad, el compilador reserva memoria para el almacenamiento de variables de la función
reverse sólo durante su ejecución. Una vez completada la ejecución de reverse, la localidad de
memoria para la variable i o para la matriz r ya no está reservada. Esto significa que la dirección
que contiene los valores de i o r[] está libre para introducir datos nuevos. Concretamente, la función
devuelve sólo el valor &r[0], así que sólo el primer elemento de la matriz tab será almacenado en la
memoria. Las demás localidades de memoria, tales como &tab[1], &tab[2], etc. serán consideradas
por el compilador como espacios en blanco, o sea, estarán listas para recibir los nuevos valores.
Para escribir esta función es necesario pasar la matriz r [] como parámetro (vea la subsección
Pasar los parámetros).
La función puede contener más de una sentencia return. En este caso, al ejecutar la primera sentencia return, la función devuelve el valor correspondiente y se detiene la ejecución de la función.
float abs (float x, float y) // Devolver el valor absoluto de 2*x-y
{
if ((2*x - y) >= 0)
return (2*x - y);
else
return (-2*x + y);
}
Si la función no devuelve ningún valor, la palabra void debe ser utilizada como un tipo de resultado en la declaración. En este caso, la sentencia return no debe ser seguida por ninguna expresión. Puede ser omitida como en el siguiente ejemplo:
void wait_1 (unsigned int a)
{
56
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 57
S iStEmaS
cnt ++;
Delay_ms(a) ;
}
dE
P rogramaCióN : L ENguajE
mikro C
// Incremento de una variable global cnt
// Ejecución de la función Delay_ms
// Note que Delay_ms no devuelve nada
declarar Prototipos de Funciones
Para utilizar una función, el compilador debe ser consciente de su presencia en el programa. En
la programación en C, los programadores normalmente primero escriben la función main() y luego
las funciones adicionales. Para avisar al compilador de la presencia de las funciones adicionales,
se requiere declarar los prototipos de funciones en el principio de programa antes de la función
main(). Un prototipo de función está compuesto por:
tipo de resultado
nombre de función
tipos de parámetros
un punto y coma (;)
El prototipo de la función main no necesita ser declarado.
float f (float, float);
/* no es obligatorio escribir los nombres de los parámetros. Este prototipo
informa al compilador: en el programa se utilizará la función f,
que utiliza dos parámetros de tipo float y devuelve el resultado del tipo
float. */
Llamar a una Función
Mientras una función es definida y su prototipo declarado, se puede utilizar en cualquier parte de
programa. Sin embargo, como la función main es ‘raiz’ del programa, no puede ser llamada de ninguna parte de programa. Para ejecutar una función, es necesario escribir su nombre y los parámetros asociados. Vea los siguientes ejemplos:
float resultado,a,b;
int time = 100;
a = 10.54;
b = 5.2;
resultado = f(a,b);
pausa_1(tiempo);
funciónX();
// resultado,a,b,time deben coincidir con los tipos
// definidos
// en la declaración de las funciones f y wait_1
// Ejecutar la función f por medio de los parámetros a y b
// El valor devuelto se le asigna a la variable resultado
// Ejecutar la función pausa_1 por medio de la variable tiempo
// Ejecutar la función funciónX (sin parámetros)
Cuando se llama una función, el programa salta a la función llamada, la ejecuta, después vuelve a la línea desde la que fue llamada.
Pasar los Parámetros
Al llamar una función, se le pasan los parámetros. En C existen dos formas diferentes para pasar
parámetros a una función.
Capítulo 2
57
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 58
El Mundo de los Microcontroladores
El primer método, denominado ‘paso por valor’, es el más fácil. En este caso, los parámetros se
pueden considerar como variables locales de la función. Cuando se llama una función, el valor de
cada parámetro se copia a un nuevo espacio de memoria reservado durante la ejecución de la función. Como los parámetros se consideran como variables locales por el compilador, sus valores
pueden ser modificados dentro de la función, pero sus modificaciones no se quedan en la memoria
una vez completada la ejecución de la función.
Tenga en cuenta de que la función devuelve un valor, y no una variable. Además, se crean copias
de los valores de los parámetros, por lo que sus nombres en la función f pueden ser diferentes de
los parámetros utilizados en la main(). La mayor desventaja del ‘paso por el valor’ es que la única
interacción que una función tiene con el resto del programa es el valor devuelto de un solo resultado (o la modificación de las variables globales).
El otro método, denominado ‘paso por dirección’ le permite sobrepasar este problema. En vez de
enviar el valor de una variable al llamar a función, se debe enviar la dirección de memoria del valor.
Entonces, la función llamada será capaz de modificar el contenido de esta localidad de memoria.
// Función ‘sort’ordena los miembros de la matriz por valor ascendente
// y devuelve el miembro con máximo valor
int sort(int *);
const SIZE = 5;
// Prototipo de función
// Número de miembros a ordenar
void main() {
int maximum, input[SIZE] = {5,10,3,12,0}; // Declaración de variables en la matriz
maximum = sort(input);
// Llamar a función y asignarle el máximo
// valor a la variable maximum
}
int sort(int *sequence) {
int i, temp, permut;
permut = 1;
while(permut!=0) {
permut = 0;
for(i=0;i<SIZE-1;i++) {
// Declaración de variables
// Bandera de bit indica que se ha hecho una permutación
// Quedarse en el bucle hasta reiniciar la bandera
// Bandera reiniciada
// Comparar y ordenar los miembros de la
// matriz (dos a dos)
if(sequence [i] > sequence[i+1]){
temp = sequence [i];
sequence[i] = sequence[i+1];
sequence[i+1] = temp;
permut = 1;
// Se ha hecho una permutación, bandera de bit
//se pone a uno
}
}
}
return sequence[SIZE-1];
}
58
// Devolver el valor del último miembro
// que es al mismo tiempo el miembro con el máximo valor
Club Saber Electrónica Nº 97
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 59
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
En este ejemplo, por medio de una función se realizan dos operaciones: ordena los miembros
de la matriz por valor asdendente y devuelve el máximo valor.
Para utilizar una matriz en una función es necesario asignar la dirección a la matriz (o a su primer miembro). Vea el siguiente ejemplo:
float método_1(int[]);
float método_2(int*);
// Declaración de prototipo de la función Método_1
// Declaración de prototipo de la función Método_2
const NÚMERO_DE_MEDICIONES = 7;
// Número de los miembros de la matriz
void main()
{
double promedio1, promedio2;
// Declaración de las variables promedio1
// y promedio2
int voltaje [NÚMERO_DE_MEDICIONES] = {7,8,3,5,6,1,9};
// Declaración de la
// matriz voltaje
promedio1 = método_1(&voltaje[0]);
// Parámetro de la función es la dirección
// del primer miembro
promedio2 = método_2(voltaje);
// Parámetro de la función es la dirección de
// la matriz
}
//××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
float método_1(int voltaje[])
// Inicio de la función método_1
{
int i, suma;
// Declaración de las variables locales i y suma
for(i=0;i<NÚMERO_DE_MEDICIONES;i++)
suma += voltaje[i];
// Cálculo del valor promedio de voltaje
// Es posible utilizar *(voltaje+i)en vez de voltaje[i]
return(suma/NÚMERO_DE_MEDICIONES);
}
//××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
float método_2 (int *voltaje)
//Inicio de la función método_2
{
int i, suma;
// Declaración de las variables locales i y suma
for(i=0;i<NÚMERO_DE_MEDICIONES;i++)
suma += *(voltaje+i);
// Cálculo del valor promedio de voltaje
// Es posible utilizar voltaje[i] en vez de *(voltaje+i)
return(suma/NÚMERO_DE_MEDICIONES);
}
Las funciones ‘método_1’ y ‘método_2’ son completamente equivalentes. Las dos devuelven el
valor promedio de la matriz ‘voltaje[]’.
Después de declararla, la dirección del primer miembro se puede escribir como ‘voltaje’ o ‘&voltaje[0]’.
Capítulo 2
59
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 60
El Mundo de los Microcontroladores
características PrinciPaLes deL Procesador
El preprocesador es un programa que procesa el código antes de que pase por el compilador.
Funciona bajo el control de las líneas de comando del preprocesador denominadas directivas. Las
directivas del preprocesador se colocan en el código fuente, normalmente en el principio del archivo.
Antes de pasar por el compilador, el código fuente se examina por el preprocesador que detecta y ejecuta todas las directivas del preprocesador. Las directivas del preprocesador siguen a una regla de la
sintaxis especial, empiezan por un símbolo ‘#’ y no requieren ningún punto y coma al final (;).
directivas del Procesador
La tabla 11 contiene un conjunto de directivas del preprocesador frecuentemente utilizadas:
Tabla 11
Las directivas del preprocesador se pueden dividir en tres categorías:
* Definiciones de macro
* Inclusiones de archivos
* Control de compilación
Ahora, vamos a presentar sólo las directivas del preprocesador utilizadas con más frecuencia.
Sin embargo, no es necesario saber todas ellas para programar microcontroladores. Sólo tenga en
cuenta que el preprocesador es una herramienta muy poderosa para los programadores avanzados
en C, especialmente para el control de compilación.
directivas del Procesador para definir marcos
Por medio de los macros es posible definir las constantes y ejecutar funciones básicas. Una sustitución de macro es un proceso en el que un identificador del programa se sustituye por una cadena predefinida. El preprocesador sustituye cada ocurrencia del identificador en el código fuente por
una cadena. Después de la sustitución, el código será compilado normalmente.
Esto significa que el código sustituido debe respetar la sintaxis del mikroC. La acción se realiza
por medio de la directiva ‘#define’.
#define PI 3.14159
// Sustitución simple, PI será sustituido por
// el valor 3.14159 en todas las partes del programa
También puede utilizar los parámetros para realizar substituciones más complejas:
#define VOLUMEN (D,H) (((D/2)*(D/2)*PI))*H
60
Club Saber Electrónica Nº 97
// Macro con parámetros
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 61
S iStEmaS
dE
P rogramaCióN : L ENguajE
mikro C
Entonces, en el código, la siguiente sentencia:
Tanque_1 = VOLUMEN (Diámetro,altura);
Será sustituida por:
Tanque_1 = (((Diámetro/2)*(Diámetro/2)*PI)*altura;
Por medio de la directiva #undef es posible quitar una definición de nombre de macro. Así se
especifica que la substitución que se ha definido anteriormente ya no va ocurrir en el siguiente código. Esto es útil cuando usted quiere restringir la definición sólo a una parte particular del programa.
#undef TANQUE
// Quitar la definición del macro VOLUMEN
inclusión de archivos
La directiva de preprocesador #include copia un archivo específico en el código fuente. El código incluido debe observar la sintaxis de C para ser compilado correctamente.
Hay dos formas de escribir estas directivas. En el primer ejemplo, sólo el nombre de archivo se
especifica, así que el preprocesador lo buscará dentro del archivo include. En el segundo ejemplo,
se especifica la ruta entera, así que el archivo estará directamente incluido (este método es más
rápido).
#include <nombre_de_archivo>
#include “C:\Ruta\nombre_de_archivo.h”
// Se especifica sólo el nombre del archivo
// Se especifica la localidad exacta del archivo
Lo dados hasta aquí es una “base” para que pueda aprender a programar en lenguaje.
Como ya hemos visto, hay varias divergencias entre los lenguajes mikroC y ANSI C. En el próximo tomo de colección del Club Saber Electrónica vamos a presentar las características específicas del mikroC con el propósito de facilitar la programación de los microcontroladores PIC. J
Capítulo 2
61
Cap 2 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:53 Página 62
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 63
Capítulo 3
eL Mundo de Los MicrocontroLadores
“Los MicrocontroLadores Pic”
Los circuitos integrados programables (Programmable Integrated Circuits = PIC) son
componentes sumamente útiles en la Electrónica de Consumo. Aun cuando son
conocidos desde hace más de veinte años, existen en la actualidad nuevos tipos que
cumplen con una serie de requisitos y características sumamente útiles. Como una
primera aproximación podemos definir a un PIC como “un chip que permite obtener
un circuito integrado a mi medida”, es decir, puedo hacer que el PIC se comporte
como un procesador de luminancia, un temporizador o cualquier otro sistema
mediante un programa que le grabo en una memoria ROM interna. Los microcontroladores PIC son, en el fondo, procesadores similares a otros tipos, como por ejemplo
la familia de los microprocesadores X86, 80486, Pentium y muchos otros pero con
capacidades limitadas. En este capítulo veremos en qué consiste un PIC y cuáles son
los tipos más comunes, lo que nos permitirá abordar el tema de su programación, lo
cual se desarrollará en el próximo tomo de la colección Club Saber Electrónica.
IntroduccIón
En realidad, un microprocesador y un microcontrolador no son la misma cosa. Los PICs son
microcontroladores, es decir, una unidad que
posee en su interior al microprocesador y a los
elementos indispensables para que pueda funcionar como una minicomputadora en un solo
chip.
Un microprocesador es solamente la unidad
central de procesos o CPU, la memoria, los
Capítulo 3
63
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 64
El Mundo de los Microcontroladores
puertos y todos los demás periféricos son exteriores. La programación de un microprocesador
es, por lo tanto, una tarea compleja porque deben controlarse todos estos dispositivos externos.
Un microcontrolador integra la CPU y todos
los periféricos en un mismo chip. El programador se desentiende de una gran cantidad de dispositivos y se concentra en el programa de trabajo. Esta circunstancia da lugar a una gran pérdida de tiempo porque los datos tienen que ser
retirados de la memoria y llevados a la CPU
(Central Processor Unit) y viceversa. Esto significa que la computadora dedica la mayor parte
del tiempo al transporte de datos de ida o de
vuelta, en lugar de usar este tiempo para trabajar sobre los datos.
Los PICs emplean un conjunto de instrucciones del tipo RISC (Reduced Instruction Set
Computer). Con el RISC se suele ejecutar la mayoría de las instrucciones con un solo pulso del
clock. Con las instrucciones que se usan en
otros equipos del tipo CISC (Complex Instruction
Set Computer), se logran instrucciones más poderosas, pero a costa de varios ciclos del clock.
En el bien conocido procesador 68HC11 de Motorola se requieren, a veces, hasta 5 ciclos del
clock para ejecutar una instrucción.
A los fines prácticos, nos vamos a referir a los
microcontroladores como bloques que poseen
una memoria de programa, que es el lugar donde deben alojarse los datos que le indiquen al
chip qué es lo que debe hacer; una memoria de
datos donde ingresen las señales que debe procesar el programa, una unidad aritmética y lógica donde se desarrollen todas las tareas, una
unidad de control que se encargue de supervisar
todos los procesos y puertos de entrada y salida
para que el PIC tenga contacto con el exterior
(figura 1).
Un microcontrolador, como cualquier circuito
integrado analógico, tiene entradas, salidas y algunos componentes exteriores necesarios para
procesar las señales de entrada y convertirlas
en las señales de salida (figura 2). El 16C54
(con memoria tipo OTP) y su similar 16F84 (con
memoria EEPROM tipo flash) requieren un cristal con dos capacitores y como mínimo un resis-
64
Club Saber Electrónica Nº 97
Figura 1
tor para el reset. Por supuesto necesita una tensión de fuente de 5V (VDD) aplicada con respecto al terminal de masa (VSS). Posee dos puertos
de salida, el A y el B, cuyos terminales son marcados RA0 al RA4 y RB0 al RB7. Estos puertos
pueden ser programados como de entrada o de
salida. El terminal 4 opera como reset pero también cumple funciones de carga de memoria de
programa cuando es excitado con pulsos de
15V. El terminal RA4 (pata 3) también tiene funciones como entrada de un temporizador y RBO
(pata 6) cumple también funciones como entrada de interrupción.
Vamos a realizar la explicación de este capítulo en base al microcontrolador 16F84 por ser
uno de los PICs de mayor renombre y por existir abundante bibliografía y proyectos disponibles gratuitamente en Internet. Sin embargo, debemos aclarar que existen otros chips como el
16F628, que son similares a éste, más económicos y de mejores prestaciones. Oportunamente
veremos cómo “migrar” de uno a otro sin mayores complicaciones.
Figura 2
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 65
LoS M iCroCoNtroLadorES PiC
También aclaramos que en el próximo tomo
de la colección Club Saber Electrónica
analizaremos a un PIC de mejores características como el PIC 16F887.
Ahora bien, la mayoría de los microcontroladores (sean de Microchip, o de National, Motorola, Philips, etc.) se comportan de forma similar,
por ello nos vamos a referir a los microcontroladores PIC16F84 cuya arquitectura interna puede observarse en la figura 3.
Observe primero los bloques externos. Existe un cristal que se conecta en OSC1 y OSC2
para generar el CLOCK del sistema. Luego una
señal de entrada llamada MCLR negada, que es
un nombre de fantasía para nuestro conocido
RESET (debido a que esa pata tiene un doble
uso) y, por último, dos puertos paralelos de I/O
(entrada o salida) llamados puerto A y puerto B.
Una de las patas del puerto A puede ser utilizada como entrada de interrupciones (esta pata
especial hace que el microprocesador deje de
realizar la tarea que estaba ejecutando y pase a
realizar otra tarea alternativa; cuando la termina
vuelve a su programa original).
Analicemos el bloque más grande (temporizadores), en éste observamos un grupo de bloques dedicados a mejorar el funcionamiento pero sin influir directamente en el flujo de señales.
Vemos un temporizador de encendido, un temporizador de arranque del oscilador de CLOCK,
un circuito de reset y un circuito llamado de vigilancia o WATCHDOG. Los dos primeros bloques
procuran un arranque ordenado para no producir una carga al mismo tiempo sobre la fuente.
Por último, existe un circuito con un nombre curioso: “perro guardián”. Su función es estar vigilante el máximo de tiempo que tarda el microprocesador en completar su programa (o mejor sería decir, la derivación más larga de su programa) y en caso de superarse ese tiempo, provocar un reset automático porque el microprocesador se quedó trabado en alguna parte de su programa. También se dice que el microprocesador
se quedó colgado o congelado.
Este bloque de circuitos no trabaja indepen-
Figura 3
Capítulo 3
65
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 66
El Mundo de los Microcontroladores
dientemente sino que requiere conexiones al exterior y al interior del dispositivo. Por ejemplo, no
siempre son utilizados y es el programa quien
determina su utilización y además ajusta sus parámetros. Esto se realiza a través del bloque de
control o decodificador de instrucciones.
Analicemos ahora la sección de arriba a la izquierda en donde observamos la memoria de
programa, el contador de programa, el registro
de instrucciones y la pila o STACK de 8 niveles.
Cuando hablamos de registros nos referimos a
pequeñas unidades de memoria transitoria,
construida por lo general, con un registro de
desplazamiento. Son memorias volátiles que se
utilizan para guardar información por un tiempo
mínimo, con el fin de realizar una operación
compleja de varios pasos.
El contador de programa es el responsable
de que el microprocesador vaya analizando las
instrucciones en orden ascendente. Este guarda
el número de instrucción en el STACK y la instrucción misma la pasa al registro de instrucciones desde donde se envía al resto del microprocesador. El STACK es, en realidad, una pila de
registros (en nuestro ejemplo hay 8), debido a
que el programa puede tener derivaciones (en la
jerga LOOPS, rulos o subprogramas). Cuando
se termina de ejecutar un loop se debe volver al
mismo punto del programa en donde se había
producido la bifurcación y eso es posible porque
ese número de instrucción quedó guardado en
uno de los registros de la pila. Es común que un
loop tenga, a su vez, un loop secundario y cuando se ejecuta ese loop secundario se debe volver al mismo punto del loop primario, eso se
consigue con guardar ese número de instrucción
del loop secundario en otro registro de la pila.
Analicemos ahora la sección inferior derecha. En ese sector se ubican los bloques responsables de efectuar operaciones matemáticas
y lógicas binarias; recordemos que el nombre
ALU proviene de Aritmetic Logic Unite (unidad
arimética y lógica). En este sector es imprescindible utilizar un registro ya que una operación
aritmética o lógica siempre se efectúa entre dos
números. Los números binarios que deben procesarse se toman de la memoria de datos, el primero se acumula en el registro de trabajo o re-
66
Club Saber Electrónica Nº 97
gistro W (de Work = trabajo) el segundo es el
presente en el instante en que se invoca la memoria de datos. Como las operaciones pueden
ser encadenadas (cuando el resultado sirve como operando de la siguiente operación, tal como
el caso de un producto) el registro W tiene un retorno a la ALU. Vemos además que la ALU está
comandada por el bloque MUX (MUltipleXador).
En efecto, la ALU requiere que se le envíen números para procesar que le lleguen desde la
memoria de datos, pero antes se la debe predisponer para que efectúe la operación requerida
(comparación, rotación de dígitos, etc.).
El registro de estado o estatus colabora durante las operaciones matemáticas. Piense cómo opera Ud. para realizar una resta: primero
ubica el primer número, luego el segundo y después comienza a analizar los bits menos significativos (las unidades), pero si el número de arriba es menor que el número de abajo, entonces
toma prestado de la columna de las decenas,
luego debe recordar esto porque el número de
arriba en la columna de las decenas se redujo
en una unidad. En realidad, aunque se trate de
una operación entre dos números su ejecución
requiere guardar lo que se llama acarreo en otro
registro y éste no es otra cosa más que el registro STATUS.
El PIC16F84 contiene además de todo lo visto, una memoria RAM de registros que puede
ser llamada desde el registro de instrucción a
través de un multiplexador de direcciones. Esta
sección sólo se utiliza en desarrollos avanzados.
Ahora bien, un microcontrolador sin programa
no sabe hacer nada, es como un niño recién nacido; tiene algunos reflejos condicionados como
el de succión que le permite alimentarse pero no
sabe hacer más que eso. Nosotros deberemos
enseñarle a realizar acciones y lo vamos a hacer
como a un bebé, paso a paso. Su capacidad de
aprendizaje es enorme y sumamente variada.
Le vamos a enseñar a llorar a intervalos regulares, a encender luces, a sumar, a restar, etc.
Enseñarle significa programarlo y eso se realiza con una plaqueta de programación que depende de cada marca y modelo de microcontrolador. Antiguamente los microprocesadores tenían una ventanita transparente y era necesario
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 67
LoS M iCroCoNtroLadorES PiC
Figura 4
exponerlos a la luz ultravioleta para borrar su
memoria e introducir un programa nuevo. Actualmente cuentan con memorias que no tienen
este requisito. Basta con cargarlos con un programa para que se borre el anterior. Esto significa que, con el mismo integrado, podremos construir diferentes dispositivos que realicen funciones totalmente distintas unas de otras.
La MeMorIa de PrograMa
La memoria del PIC16F84 es una EEPROM,
es decir, de lectura solamente (ROM = Read
Only Memory) que se programa por tensión (no
necesita luz ultravioleta); es decir que basta con
introducir los datos con cierto nivel de tensión
para que éstos borren el programa anterior y
graben uno nuevo.
¿Por qué esta memoria se llama ROM, si se
pueden grabar datos sobre ella?
Se llama ROM porque para grabarla se debe
conectar el PIC al programador;
luego de que el PIC coloca estos
datos en la plaqueta del dispositivo,
sólo pueden ser leídos, ya que entonces forman el programa del PIC.
Esta memoria (figura 4) tiene una
longitud de 1 Kbyte con palabras de
14 bits. Digamos que tiene un ancho de 14 bits y una altura de 1.000
Bytes o que es una memoria de
1.000 x 14. Observe que los números de instrucción en hexadecimal van desde el 000 al
3FF, lo cual implica que existen 1.040 posiciones
de memoria, valor obtenido empleando la fórmula:
3 x 162+16 x 161+16 x 160
Observe que dos de las posiciones de memoria tienen las indicaciones “vector de reset” y
“vector de interrupción”.
Eso significa que, cuando se provoca un reset, el microprocesador vuelve a la posición 000
del programa y cuando se produce una interrupción, a la posición 004. Estos retornos forzados
deben ser considerados al diseñar el programa
del microprocesador; es decir que el reset se
produce porque la señal externa pone el contador de programa en 000 y todo el programa se
reinicia. En cambio, cuando ingresa una señal
por la pata de interrupción el contador de programa va a 004 y la acción que, en general ocurre,
es que se comienza a leer un subprograma particular. Cuando este
subprograma termina,
Figura 5 el contador de programa recupera el número
que tenía en el momento de arribar la interrupción.
La MeMorIa de datos
La RAM (Random Access Memory = memoria de acceso aleatorio,
figura 5) es una memo-
Capítulo 3
67
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 68
El Mundo de los Microcontroladores
Figura 6
ria de lectura y escritura de 64. De estos 64 registros, los primeros 12 son fijos y cumplen un
propósito determinado, en tanto que desde el 13
hasta el 64 son registros de propósito general,
en donde el programa puede indicar que se almacene un dato para ser tomado más tarde.
Además, posee un conjunto de memoria SRAM
de 36 posiciones con los que se pueden construir registros de 8 bits con características
EEPROM. En lo personal, prefiero designar a
este conjunto de registros como “memoria libre”.
Los Puertos deL PIc
El PIC16C84 tiene dos puertos paralelos de
entrada o salida: el puerto “A” de 8 patas y el “B”
de 5 patas. Cada pata puede ser predispuesta
por el programa para operar como de entrada o
de salida.
Cada pata tiene un resistor de pull-up (resistor conectado a fuente) interno que puede ser
desconectado mediante el programa. Estos resistores se desconectan automáticamente si
una pata se predispone como pata de salida debido a que las salidas ya tienen posibilidad de
entregar corriente desde fuente con un transistor. Todos los resistores de pull-up se conectan
o desconectan al mismo tiempo (no existe un
comando que los conecte independientemen-
68
Club Saber Electrónica Nº 97
te). Como puerto de salida, una pata puede tomar 25mA del circuito o entregar 20mA al mismo, sin embargo, en el puerto “A” sólo se pueden consumir 80mA en total o entregar 50mA,
esto significa que sólo algunas patas pueden
trabajar al máximo porque si todas lo hicieran (y
son 8) el consumo total sería de 25 x 8 = 200mA.
El puerto “B” tiene otras características máximas, ya que en total puede tomar 150mA o entregar 100mA. Como vemos, las salidas admiten
suficiente carga como para alimentar directamente a un led (figura 6). Los puertos no utilizados siempre se deben conectar a la fuente de
5V a través de un resistor de 10kΩ debido a que
se trata de un dispositivo CMOS que, de otro
modo, podría deteriorarse por captación electrostática (figura 7).
La pata 3 perteneciente al puerto “A” puede
ser configurada como de entrada/salida o como
Figura 7
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 69
LoS M iCroCoNtroLadorES PiC
Para circuitos que requieran una gran
precisión se puede trabajar con un cristal
de frecuencia baja, media o alta (figura
10). Como máximo el PIC16F84 puede
trabajar con un cristal de 10MHz. Internamente la frecuencia del cristal se divide por 4, por lo tanto, es muy común la
utilización de un cristal de 4MHz para obtener un CLOCK interno de 1MHz que
garantiza que cada instrucción dure
exactamente 1mS. Para temporizadores
de período largo se utilizan cristales de
baja frecuencia.
Figura 8
de arranque de un temporizador/contador (figura 8). Cuando se programa como entrada esta
pata funciona como un disparador de SCHMITT
o Schmitt trigger, ideal para reconocer señales
distorsionadas o con crecimiento lento. Esta
misma pata también tiene una característica distinta cuando opera como salida. Ella es la única
que trabaja a colector abierto, es decir, que no
puede emplearse como fuente, en este caso
siempre se utilizará un resistor externo.
eL reset
El PIC “se resetea” cuando la pata 4 (MCLR
negada) se pone a potencial bajo. Para simplificar el circuito de reset, el PIC posee un temporizador interno que permite realizar un reset automático cuando se aplica tensión de 5V. En estos
casos el circuito externo de reset sólo implica el
Figura 11
eL cLock
Figura 9
Figura 10
Los PICs poseen un
oscilador configurable por programa de
características muy
amplias. Cuando no
se requiere mucha
precisión se puede
trabajar con un oscilador a RC conectado según la figura 9.
uso de un resistor de 10kΩ entre la pata 4 y
fuente tal como se muestra en la figura 11.
En muchos circuitos es necesario realizar un
reset manual y para ello existen dos posibilidades, una es utilizar sólo el temporizador interno
(por programa) y la otra es agregar una constante de tiempo exterior como se muestra en la figura 12. En el segundo circuito C1 provee un retardo al encendido o posterior al pulsado de reset porque C1 se cargará lentamente a través de
R1 con una constante de tiempo de 22kΩ x
10µF = 220mS.
Capítulo 3
69
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 70
El Mundo de los Microcontroladores
El resistor R3 limita la corriente de descarga
de C1 a valores compatibles con sus características de corriente de pico máxima.
D1 descarga a C1 cuando la tensión de fuente decae para permitir un reset inmediato cuando la fuente se apaga y se enciende en rápida
sucesión. R2 limita la corriente de reset, tomada
desde el microprocesador. Este segundo sistema se suele utilizar cuando se requiere un reseteado remoto a través de varios metros de cable
que podrían captar zumbido (C1 reduce la impedancia del circuito de reset).
PrIMeras concLusIones
El PIC es un microcontrolador, una especie
de "ordenador en miniatura" (con muchas comillas) que podremos programar. Hay muchos tipos de microcontroladores PIC, los hay de 8 patas con 6 terminales para intercambio de datos
(6 terminales de entrada / salida de datos), pero
también existen dispositivos más poderosos de
80 patas con 40 pines I/O (de entrada y salida
de datos).
El PIC16F84 posee en su interior un microprocesador, una memoria RAM (volátil) donde
guardaremos las variables, una memoria EEPROM (no volátil) donde guardaremos nuestro
programa, un timer o contador que nos facilitará
algunas tareas, y otros bloques de control y apoyo. Algunas características más representativas
del PIC16F84 son:
Opera a una frecuencia máxima de
10MHz (excepto el PIC16F84A que puede operar a 20MHz).
1kbyte de memoria EEPROM para
nuestro programa (1024 posiciones).
68 bytes (de 8 bits) de memoria RAM
64 bytes de memoria EEPROM para datos (no volátiles)
Programable con sólo 35 instrucciones
Posee 13 pines de entrada/salida (un
puerto de 8 bits + otro de 5 bits)
Tiene un timer/contador de 8 bits
También posee una serie de registros y temporizadores, cuyo estudio no realizaremos en
esta obra.
GPIC USB:
ProGramador de mICroControladoreS PIC y
memorIaS eeProm Por PUerto USB
IntroduccIón
Este proyecto comenzó a principios del
2008 cuando inicié la escritura del código
fuente para el firmware de un 18F2550 y la
elaboración del Software correspondiente a
la interfaz de usuario para la PC de un programador de microcontroladores Pic por
puerto USB. Anteriormente ya había estado interesado en los procesos de programación de los Pic por lo tanto, basado en
esas experiencias y en el estudio de los
Data Sheets referentes a las especificaciones de programación de los microcontrola-
70
Club Saber Electrónica Nº 97
dores, surgió el GPIC USB como una aplicación totalmente funcional hacia finales
de Octubre del 2008.
A la fecha ha sufrido algunas modificaciones que permite mejorar su funcionamiento y ampliar la cantidad de componentes soportados.
descrIPcIón
deL
cIrcuIto eLectrónIco
El esquema de la figura 1 corresponde al
programador de microcontroladores PIC
por puerto USB, su diseño es simple y sen-
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 71
LoS M iCroCoNtroLadorES PiC
Figura 1
cillo. Lo podemos dividir en tres bloques
fundamentales bien definidos, tal como
muestra la figura 2.
Bloque 1: Microcontrolador
El primero y más importante está constituido por el microcontrolador 18F2550
(IC2), es el encargado de la comunicación
por el puerto USB con la PC por intermedio
Figura 2
de la interfaz de programación, establece la
transferencia de datos con los microcontroladores soportados y activa las tensiones
de VDD y VPP, figura 3.
Los pines 15 y 16 (RC4 - RC5) del puerto C del PIC conectan con la ficha correspondiente para la transmisión y recepción
de los datos vía USB.
Los pines 2 y 3 (RA0 - RA1) del puerto A
se destinan como interfaz
de comunicación del protocolo ICSP entre el programador y los microcontroladores soportados por éste,
a través del conector ICSP
(terminales 1 y 2, figura 1).
Los datos por el pin 2 son
bidireccionales, sincronizados por una señal de reloj
con salida por el pin 3.
Capítulo 3
71
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 72
El Mundo de los Microcontroladores
Figura 3
Los pines 23, 24 y 25 (RB2 - RB3 - RB4)
del puerto B los utilizamos para el control
de la tensión VPP de programación. Según
el estado de estas salidas obtenemos diferentes tensiones en la salida VPP del
conector ICSP (terminal 3, figura 1).
El pin 26 (RB5) del PIC lo utilizamos
como una salida para controlar los estados
de la tensión VDD.
Continuamos con los pines 11, 12 y 13
(RC0 - RC1 - RC2) del puerto C, son utilizados como salidas para los LEDs de
visualización del funcionamiento del programador.
Comenzando con el LED denominado
"VDD", este se encenderá con el suministro
de esta tensión.
Tenemos tres estados posibles, según la
72
Club Saber Electrónica Nº 97
configuración establecida desde la interfaz
de usuario en la PC:
A- Sólo se suministra tensión VDD a
los microcontroladores soportados durante
los procesos de lectura, grabación, verificación y borrado.
B- Suministro de tensión constante,
para poder alimentar a los circuitos durante
las pruebas (sólo circuitos con bajo consumo).
C- No se suministra tensión VDD hacia
los microcontroladores soportados, una
fuente externa debe proveer la alimentación.
El LED denominado VPP, se enciende
durante el suministro de dicha tensión
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 73
LoS M iCroCoNtroLadorES PiC
durante todos los procesos. Desde la interfaz de programación en la PC podemos
configurar el suministro de esta tensión de
dos formas:
A- Sólo se suministra tensión VPP a
los microcontroladores soportados durante
todos los procesos.
B- Suministro de tensión MCLR postprocesos, para "arrancar" al microcontrolador sin tener que desconectar la ficha ICSP.
Por último el LED denominado USB, se
enciende cuando se establece la comunicación con el puerto USB y es reconocido
el programador. Volviendo sobre el PIC
18F2550, éste debe ser grabado en un
principio para su funcionamiento.
El programa para este microcontrolador
podemos dividirlo en dos partes: un programa residente en un bloque de memoria del
PIC, comúnmente llamado bootloader,
encargado de "chequear" la existencia del
firmware correspondiente al conectar el
programador al puerto USB.
En caso de no encontrarse, el LED
denominado USB comenzará una secuencia de encendido en forma intermitente. En
caso contrario, el firmware tomará el control
y el LED quedará encendido en forma continua.
La gran ventaja de utilizar este sistema
se debe a que sólo una vez debemos programar el microcontrolador 18F2550, en lo
sucesivo los cambios y actualizaciones del
firmware se podrán realizar directamente
desde la interfaz de usuario en la PC. Para
finalizar este bloque, el pin 17 (RC6) del
puerto C, lo utilizamos para generar una
señal que, junto con el buzzer BZ1 emite
unos "beeps" cada vez que pulsamos los
botones de comando para lectura, grabación, verificación y borrado desde la interfaz
de programación. Es opcional su implementación y puede ser activado o desactivado desde la misma interfaz.
Bloque 2: conversor dc - dc
En un comienzo me planteé qué diseño
usar para el conversor de tensión, si implementarlo de forma totalmente independiente o utilizar el PIC para esta tarea generando un PWM por software, más los componentes externos necesarios. Me decidí por
la primera opción por varios motivos: el circuito integrado utilizado MC34093, figura 4,
es un conversor especializado para esta
función, de muy bajo costo, ampliamente
difundido, que figura en las listas de componentes de casi todos los comercios de
electrónica. Es autónomo, no depende del
firmware grabado en el 18F2550, quiero
decir con esto que podemos chequear su
funcionamiento y la tensión de salida del
conversor (en las pruebas) sin necesidad
de tener el PIC en la placa del programador
ya que no depende de éste. Además nos
permite, si fuera necesario, regular la tensión de salida con sólo variar el valor de
una resistencia: R3 o R4.
El valor del choque L1 no es crítico,
puede estar comprendido entre 220µH y
680µH sin ningún tipo de
inconveniente.
Figura 4
El circuito se alimenta con 5
volt suministrados por el puerto
USB y a la salida de TP2 obtenemos una tensión continua de
aproximadamente 14V a 14.5V
necesarios para alimentar el
bloque 3 de la figura 2.
Las resistencias R3, R4 junto
con R5 forman un divisor resistivo conectado al pin 5 del
Capítulo 3
73
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 74
El Mundo de los Microcontroladores
MC34093, este lazo de realimentación
estabiliza la tensión de salida ya que es
comparada con una tensión de referencia interna, como podemos observar en
la figura 5. En la salida del integrado pin
1, obtenemos una onda variable en
ancho de pulso (PWM) en relación al
consumo exigido luego de la rectificación, lógicamente dentro de unos límites. Los estados de conmutación On-Off
en el pin 1 del MC34093 junto con L1
producen la elevación de la tensión, el
diodo D1 y los capacitares C3, C4 se
encargan de la rectificación. El capacitor
C2 establece la frecuencia del oscilador
interno.
Bloque 3: tensiones VPP y Vdd
Podría haber utilizado un solo transistor
para tratar la tensión de programación VPP,
pero estaríamos bastante limitados. La idea
era tener una salida Vpp única y más flexible, que proporcionara la tensión normal de
programación, la opción de una tensión
MCLR post programación y por último que
ya estuviera pensada para los microcontroladores que trabajan con 3.3 volt que serán
incorporados en el futuro. Esto lo podía
obtener utilizando un amplificador operacional, precisamente el CA3140 con entradas
MOSFET y salida bipolar, que trabaja bien
con alimentación de simple vía, pero lo más
importante en cuanto a la elección es que
está preparado para obtener una tensión
de salida diferente independientemente a la
tensión suministrada sobre el pin 7.
Con un diodo Zener sobre el pin 8
(STROBE) se consigue de forma simple y
práctica modificar el valor de la tensión de
salida por el pin 6. En la figura 7 podemos
ver la información que brinda el fabricante
del CA3140 para adaptar la salida a niveles
compatibles TTL independientemente de la
tensión V+ en el pin 7.
En el programador he adaptado el circuito para manejar las tensiones de 3.3 volt
para esta gama de PICs que se irán incorporando en próximas actualizaciones.
74
Club Saber Electrónica Nº 97
Figura 5
Figura 6
Figura 7
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 75
LoS M iCroCoNtroLadorES PiC
Listado de Materiales
IC1 = MC34063
IC2 = PIC 18F2550
IC3 = CA 3140
Q1 = BC327
Q2 = BC547
Vpp, Vdd, Usb = LEDs de 3 mm
D1 = 1N4148
R1 = 0.22 a 0.47 Ohm
R2 = 180 Ohm
R3 = R4 = 12kΩ
R5 = 2.2kΩ
R6, R7 - R8 = 33 Ohm
R9, R10, R11= 10kΩ
R12 = 33kΩ
R13, R14, R15, R21, R22 = 4.7kΩ
R16, R17, R18 = 470 Ohm
Está conformada, como podemos observar en la figura 6, por el Zener Z1 conectado al pin 8 del CA3140 en serie con el transistor NPN Q2 que trabaja como llave electrónica On-Off, de acuerdo a los niveles alto
o bajo en la base. Con un nivel bajo sobre
la base de este transistor el circuito está
desconectado, por lo tanto la tensión VPP
será la normal de 12.30V a 13V; por otro
lado, con un nivel alto proporcionado por
RB4 del 18F2550 a través de R13 el circuito se conecta, la tensión VPP en este caso
será de 3.3 volt.
De esta forma queda totalmente automatizado el suministro de VPP de acuerdo
a los dispositivos seleccionados desde la
interfaz de usuario en la PC.
Por el momento no es necesario implementar Z1, Q2 y R13, ya que es la primera
versión base del programador y dicha gama
de dispositivos aún no están incorporados.
En este caso el pin 8 debe quedar sin conexión. Como pueden ver, la electrónica del
programador ya está pensada para soportar de forma práctica a estos microcontroladores a medida que sean agregados.
Continuando con esta etapa, las entradas inversora y no inversora del amplificador operacional se conectan con RB3 y
RB2 del microcontrolador; de acuerdo a los
C1, C4 = 100µF x 16V, electrolítico
C2 = 390pF, cerámico
C3, C5 = 0,1µF, cerámico
C6 = 10µF x 16V, electrolítico
C7, C8 = 15pF, cerámico
C9 = 0,47µF, cerámico
C10 = 1nF, cerámico
C11 = 1µF x 16V, electrolítico
L1 = choque de 330µH a 680µH
Xtal = cristal de 20MHz
Bz1 = (opcional) buzzer sin oscilador interno
F1 = Fusible de 250mA, requiere puente o portafusible
Varios:
Placa de circuito impreso, gabinete para montaje, conector USB, conector ICSP, cables,
estaño, etc.
niveles detectados por las entradas del
CA3140 la salida de éste conmutará entre
un estado próximo a masa (0.3 volt) y Vpp,
al finalizar proveerá una tensión adecuada
al caso, si se eligió la opción "suministrar
MCLR" desde la interfaz de programación.
Todas las señales para la activación de las
tensiones están sincronizadas desde el
firmware del microcontrolador Pic.
Las resistencias R9 y R10 conectadas a
masa evitan que queden al "aire" las entradas del operacional en caso que el microcontrolador 18F2550 no esté presente en
su zócalo, de lo contrario tendríamos un
estado de indeterminación a la salida. El
capacitor C10 limita la banda pasante del
operacional, es obligatorio junto con R11 y
R12.
El pin 7 del CA3140 recibe la tensión de
alimentación para su funcionamiento, proporcionada por el conversor Dc-Dc. El pin 4
se conecta a masa.
La tensión máxima en la salida del operacional pin 6 es aproximadamente 2 volts
menor a la tensión de alimentación sobre el
pin 7 (en caso que no se encuentre activado Q2, Z1).
Para finalizar la descripción y resumiendo, el terminal 3 del conector ICSP (figura
1) puede manejar cuatro estados de VPP:
Capítulo 3
75
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 76
El Mundo de los Microcontroladores
1- Una tensión próxima a masa (0.3
volt).
2- Una tensión Vpp de aproximadamente 12.30 - 13 volt.
3- Una tensión post programación
MCLR.
4- Una tensión Vpp baja de 3.3 volt.
Por último el transistor Q1 se encarga
del manejo de la tensión Vdd, se encuentra
conectado con la salida RB5 del microcontrolador. Un nivel alto en la base de Q1 lo
mantiene bloqueado y un nivel bajo lo coloca en estado de conducción con salida por
colector; el emisor de dicho transistor se
conecta a +5 volt suministrados por el puerto USB.
extensión 3.3 Volt Vdd2
Opcionalmente podemos anexar una
línea auxiliar de 3.3 volt en el conector
ICSP (ya está
contemplado en
Figura 8
el circuito general de la figura 1).
Con
un
simple circuito (figura 8) obtenemos una
tensión de
salida de
3.3 volts en
el emisor
de Q3, con las mismas características de control que VDD. La entrada
de tensión se produce por el colector
de Q3, conectado a VDD, colector de
Q2.
En la figura 9 se puede ver la imagen de la placa de circuito impreso
con su máscara de componentes.
Desde la página del autor puede descargar tanto la interfaz gráfica para
programación (figura 10) como el
firmware para el PIC del programador. La versión 2.1 de dicho firmware
soporta los siguientes componentes:
76
Club Saber Electrónica Nº 97
PIC18F67J93 PIC18F87J93 PIC18F67J90
PIC18F87J90 PIC18F67J50 PIC18F87J72
PIC18F67J11 PIC18F87J50 PIC18F67J10
PIC18F87J11 PIC18F66J93 PIC18F87J10
PIC18F66J90 PIC18F86J93 PIC18F66J55
PIC18F86J90 PIC18F66J50 PIC18F86J72
PIC18F66J16 PIC18F86J55 PIC18F66J15
PIC18F86J50 PIC18F66J11 PIC18F86J16
PIC18F66J10 PIC18F86J15 PIC18F65J90
PIC18F86J11 PIC18F65J50 PIC18F86J10
PIC18F65J15 PIC18F85J90 PIC18F65J11
PIC18F85J50 PIC18F65J10 PIC18F85J15
PIC18F64J90 PIC18F85J11 PIC18F64J11
PIC18F85J10 PIC18F63J90 PIC18F84J90
PIC18F63J11 PIC18F84J11 PIC18F83J90
PIC18F83J11 PIC18F66J60 PIC18F66J65
PIC18F67J60 PIC18F86J60 PIC18F86J65
PIC18F87J60 PIC18F96J60 PIC18F96J65
PIC18F97J60 PIC18F24J10 PIC18LF24J10
PIC18F25J10 PIC18LF25J10 PIC18F44J10
PIC18LF44J10 PIC18F45J10 PIC18LF45J10
PIC18F24J11 PIC18LF24J11 PIC18F25J11
PIC18LF25J11 PIC18F26J11 PIC18LF26J11
PIC18F44J11 PIC18LF44J11 PIC18F45J11
PIC18LF45J11 PIC18F46J11 PIC18LF46J11
Figura 9
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 77
LoS M iCroCoNtroLadorES PiC
Figura 10
PIC18F26J13 PIC18LF26J13 PIC18F27J13
PIC18LF27J13 PIC18F46J13 PIC18LF46J13
PIC18F47J13 PIC18LF47J13 PIC18F24J50
PIC18LF24J50 PIC18F25J50 PIC18LF25J50
PIC18F26J50 PIC18LF26J50 PIC18F44J50
PIC18LF44J50 PIC18F45J50 PIC18LF45J50
PIC18F46J50 PIC18LF46J50 PIC18F26J53
PIC18LF26J53 PIC18F27J53 PIC18LF27J53
PIC18F46J53 PIC18LF46J53 PIC18F47J53
eL PrograMador Quark Pro 2
Para cargar un programa en un microcontrolador PIC se requiere de una serie de
parámetros básicos a saber:
VDD = Voltaje de alimentación de 5V
VSS = Referencia de tierra del circuito
VPP = Voltaje de programación de 14V
PGD = Datos de programación
PGC = Pulsos de reloj para la sincronización
El primer cargador desarrollado por
nuestro equipo y publicado en Saber
Electrónica en 1998, utilizaba el puerto
paralelo de una computadora, precisaba
una fuente externa y estaba basado en un
circuito de David Tate. Posteriormente
desarrollamos varios cargadores usando el
puerto serie con y sin fuente de alimentación, muchos de ellos basados en un diseño denominado “JDM” y que emplean como
interfaz gráfica al programa IC-Prog. El programador más completo lo hemos denominado Quark Pro 2 y se publicó en Saber
Electrónica Nº 200. Aquí una breve descripción.
En la figura 11 se muestra el circuito
eléctrico del programador QUARK-PRO 2.
Como puede observar no existe ninguna
fuente de alimentación externa. El circuito
se alimenta del puerto serial de la PC a través del conector DB9. El voltaje de alimentación VDD se obtiene de los mismos pulsos de reloj (pin 7 del DB9), los cuales son
Capítulo 3
77
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 78
El Mundo de los Microcontroladores
Figura 11
Figura 12
78
Club Saber Electrónica Nº 97
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 79
LoS M iCroCoNtroLadorES PiC
Figura 13
rectificados por los diodos D3 y D4 y estabilizado a 5 volt mediante el diodo zener D5
(5.1V) y el capacitor C1. De la misma
manera, se obtiene el voltaje de programación VPP, cargando el capacitor C2 y estabilizando con el diodo zener D6 (8.2V) el
cual se suma al voltaje del zener D5 (5,1V),
obteniéndose así 13.3 Volt suficientes para
realizar la programación del PIC. Se han
adicionado el LED L1 para visualizar el proceso de grabación o lectura del PIC, así
como el LED L2 para indicar que el circuito
se encuentra alimentado, además, si se
colocara un PIC en corto, este LED se apagará o bajará significativamente su intensidad. En la figura 12 se muestra el circuito
impreso sugerido para nuestro prototipo.
¿Por qué utilizar el programa IC-PROG?
Con el mismo criterio que seleccionamos el hardware (programador JDM),
seleccionamos el software (IC-PROG),
basados en el que fuera más compatible. El
IC-PROG ofrece varias ventajas: La primera es que dentro de su menú ofrece opciones importantes como la posibilidad de
seleccionar el puerto a utilizar, así como el
prototipo de programador a utilizar; la
segunda es que el programa ofrece un
ambiente de trabajo muy amigable, ya que
este programa y gracias a las aportaciones
de muchos colaboradores de todo el
mundo, está traducido a varios idiomas y
tercero es que es compatible con la mayoría de los sistemas operativos de la PC,
además que con frecuencia están disponibles de manera gratuita versiones actualizadas (véase www.ic-prog.com). En la figura 13 se muestra el ambiente de trabajo de
este programa.
Si usted ha trabajado con ambientes de
programas diferentes, podrá observar que
el ambiente del IC-Prog dispone de herramientas de trabajo muy completas. J
Capítulo 3
79
Cap 3 - Microcont.qxd:*Cap 4 - telefonia 05/04/13 14:54 Página 80
3ª de forros.qxd:club 05/03/13 16:31 Página 3ªFo1
4ª de forros.qxd:Club 05/03/13 16:33 Página 4ªFo1