Manipulación directa de puertos. Usando los puertos digitales. (Segunda traducción al castellano de los artículos escritos aqui: http://hekilledmywire.wordpress.com/ http://hekilledmywire.wo rdpress.com/2011/02/ 2011/02/2/! 2/! "ola amigos lectores# hoy $oy a escri%ir un poco acerca de los pines digitales y cómo leer y escri%ir $alores digitales para esto# es un tema sencillo pero de gran importancia# porque casi todo lo que nuestros microcontroladores microcontroladores hacen es utili&ar sus entradas y salidas para ha%lar con leds# los dri$ers del motores# ')# registros de despla&amiento# despla&amiento# para leer los datos de los sensores digitales y un monton de otros usos# así que $amos a empe&ar a leer acerca de cómo hacerlo. *uestro microcontrolador# el +,mega2-p tiene registros# estos registros estn relacionados con los puertos de entrada/salida# cada puerto tiene un nom%re especíico y sus registros asociados# asociados# de hecho# nuestro +tmega tiene el puerto # y )# y cada puerto un dierente nmero de pines (sta es una restricción del paquete de 2- pines 3)43 y no desde el microcontrolador# microcontrolador# ya que un 3)43 50 pines# por e6emplo# tiene 5 puertos con los - %its cada uno!# el nico puerto que tiene el total de sus - pines de entradas/salidas es 378,). 378,). omo usted ya sa%e# cada pin puede tener mltiples unciones# como la generación de 39# o las capacidades de +)# los pines ; y < del 378, 378, son los pines de entrada para el oscilador de cristal# y pin ; del 378, 378, le corresponde corresponde al %otón de reinicio. n esta imagen se puede $er todas las unciones alternati$as que cada pin puede tener en el chip en cuestión que es el +,mega2-3.
= aquí est la asignación asignación entre los nom%res nom%res de los puertos +rduino y su su $erdadero nom%re:
ntonces# >cómo podemos interactuar con n uestros pines digitales? ueno# para empe&ar hay un registro dedicado para cada puerto que deine si cada pin es una entrada o una salida# que es el registro de ))8@# donde A es la letra del puerto que queremos conigurar# en el caso de la +rduino hay ))8# ))8 y ))8). omo toda $aria%le lógica# cada %it en los registros ))8@ puede ser 1 ó 0# es que poner un %it especíicos de ))8@ a 1 conigura el pin como salida y ponerla a 0 conigura el pin como una entrada# $amos a $er un pequeBo e6emplo que conigura pines 0#1#2# como entradas digitales y los pines 5#C#;#< como salidas digitales: DDRD = 0b11110000;
= quiero todos los pin como salidas: DDRD = 0b11111111;
= si usted necesita todas las salidas? ompruD%alo por ti mismo# o espera unos días que $oy a li%erar mi tutorial de de manipulación de %its. )e%e ha%er algn tipo de atención cuando se utili&a 378,) y Serial / ES+8, porque los pines 0 y 1 del 378,) son los utili&ados por la ES+8, y si pones estos dos como entradas o salidas# la ES+8, sera incapa& de leer o escri%ir datos en los pines. =a podemos decir al +tmega cómo sern utili&ados sus pines# pero queremos sa%er cómo leer y escri%ir datos en dichos pines# de modo que para escri%ir datos en un determinado puerto# se utili&a el registro 378,A# Dste es cil de recordar# donde A es el nom%re del puerto# y despuDs de la coniguración de un pin como salida es sólo una cuestión de poner 0 o 1 en el registro 378,A para controlar que el pin de este en estado alta o %a6a# respecti$amente# $amos a $er algo de código para esto: DDRD = 0b11111111; PORTD = 0b11111111;
// Todos los pines de PORTD son salidas. // Todos los pines de PORTD están en estado alto.
DDRD = 0b11111111; PORTD = 0b00000000;
// Todos los pines de PORTD son salidas. // Todos los pines de PORTD están estado bajo.
>= quD tal un patrón de encendido# apagado# encendido# ..? DDRD = 0b11111111; PORTD = 0b10101010;
// Todos los pines de PORTD son salidas. // Un patrón de encendido, apagado, encendido, etc.
+hora# lo nico que queda es leer en el pin para poder leer los datos de los sensores o incluso cuando se pulsa un %otón# para leer el estado de un pin digital conigurado como entrada# $amos a utili&ar un tercer registro llamado 34*@# donde de nue$o A es el nom%re del puerto donde se encuentra el pin# así que primero con ))8@ decimos a la microFcontrolador que queremos algunos pines como entradas digitales# y luego usando 34 *@ leemos sus $alores# parece cil# por lo que permite proundi&ar en el código: DDRD = 0b00000000; car !"#$ar = 0; !"#$ar = P)*D;
// Todos los pines del PORTD son entradas // %rea!os &na $ariable para g&ardar la in'or!ación le(da en PORTD // +ee PORTD " pone la in'or!ación en la $ariable
s tan cil como puede ser# y en comparación con el digital9rite de +rduino y las unciones de leer# con acceso directo al puerto puede ahorrar espacio en el la memoria lash y tam%iDn puede ganar mucha $elocidad# porque las unciones +rduino puede tomar ms de 50 ciclos de relo6 para leer o escri%ir un solo %it en un puerto y al mismo tiempo para leer otra de un solo %it el código es %astante comple6o con un montón de líneas que ocupan por lo menos unos 50 %ytes# que podría ser un pequeBo ahorro en lash# pero es un gran paso para acelerar cualquier programa# pero estos son ciles de usar por las personas que no entienden mucho acerca de la programación/microcontroladores# por lo que cada aplicación tiene sus $enta6as y des$enta6as# pero le permite continuar. s un poco raro que usted necesite leer o escri%ir en un puerto completo en cada momento# por e6emplo# si usted quiere encender un ')# o leer un %otón sólo tendr que utili&ar un pin# y escri%ir todos los %its uno a uno cada $e& que queremos cam%iar un $alor en un puerto# es una tarea a%urrida# pero li%rería de +G8 tiene algunas pocas pala%ras deinidas como 3A0..<# donde A es de nue$o el puerto que desea utili&ar y 0..< es el $alor del pin indi$idual de dicho puerto# por lo que para iluminar un ') de%emos hacer algo como esto: DDRD = 1--PD; PORTD = 1--PD;
// %on'ig&ra el pin de PORTD co!o salida. // l pin de PORTD tiene aora &n $alor lógico 1.
7 para leer el estado de un %otón: DDRD = 0b11111101;
/ car !"#$ar = 0; / !"#$ar = P)*D 2 1--PD1; /
%on'ig&ra el pin 1 de PORTD co!o estrada " el resto co!o salida. / %rea &na $ariable para g&ardar la in'or!ación le(da en PORTD. / +e el pin 1 de PORTD " lo coloca en la $ariable. /
,am%iDn puede utili&ar la macro 3A0..< $arias $eces en una misma instrucción# por e6emplo# en este código# se e6ectutara algo de código sólo si se pulsa dos %otones al mismo tiempo: DDRD = 0b11111100; // +os pines 0 " 1 de PORTD son entradas, " el resto salidas. i'P)*D 2 1--PD0 3 1--PD1 4 / 5lg6n código dentro del i' 7&e se ejec&tara solo si los dos botones se enc&entran acti$ados. / 8
reo que $as a encontrar el punto# pero el tutorial de manipulación de %its ayudar un poco so%re esto temas. "ay toda$ía algunas cosas ms que podemos hacer con nuestra entrada y salida de los pines/puertos que sera muy til para usar las interaces 42 y por e6emplo# para utili&ar los %otones# estoy ha%lando de los pullFups que nuestros microcontroladores tienen en su interior y te mostrarD cómo se pueden ha%ilitar y por quD de%es utili&arlos cuando se utili&an los pulsadores. uando usted tiene un %otón que puede tener dos estados# uno es desconectado# y cuando usted lo presiona har una coneAión entre los pines del microcontrolador y permite por e6emplo# conectarse a tierra# pero cuando se desconecta# no hay nada que uerce un $alor esta%le en el pin de entrada# para el o6o ineAperto es acepta%le suponer que el pin $a a leer un 1# porque cuando se pulsa el %otón lee 0# pero la realidad es que el pin puede leer 1 ó 0 ya que el pin es muy sensi%le al ruido electromagnDtico# como una pequeBa antena# por lo que puede resol$er este pro%lema de dos maneras similares# una es para conectar una resistencia de 10Hohms o ms entre el Gcc (IC $! y el pin de entrada# o sólo tienes que ahorrar algunas
monedas de un centa$o con el uso de los pullFups que nuestros microFcontrolador que tienen integrados# tam%iDn hace que nuestros circuitos un poco ms simple y esto tam%iDn es una %uena idea. 3ara ha%ilitar las resistencias pullFups tenemos que hacer algo que puede resultar un poco eAtraBo a primera $ista# porque no eAiste un registro dedicado para acti$ar o desacti$ar el pullFups# estos son acti$ados o desacti$ados escri%iendo# 1 o 0 respecti$amente en el registro 378,A cuando el registro ))8@ se coniguran como entradas# $amos a $er algo de código para clariicar esto: DDRD = 0b00000000; PORTD = 0b00001111; car !"#$ar = 0; !"#$ar = P)*D;
// / // //
Todos los pines de PORTD son entradas. 9abilito las P&ll:&ps de los pines 0,1, " " lo desabilito en los pines <,,> " ?. %reo &na $ariable para g&ardar la in'or!ación le(da en PORTD. +eo PORTD " coloco la in'or!ación en la $ariable.
Si e6ecuta este código# sin tener nada conectado a 378,)# los cuatro %its mas altos de la $aria%le myJ$ar puede ser 0 ó 1# cualquier com%inación posi%le de ellos porque son lotantes (actan como pequeBas antenas!# pero los cuatro %its ms %a6os leer todos un 1 de%ido a que el pullFups imponen una seBal de CG dD%il que se lee como un $alor lógico 1. n un sentido %sico esto es todo lo que necesita sa%er para dominar la manipulación directa de los puertos# pero el tutorial de manipulación de %its le enseBar cosas mas ingeniosas como las mscara de %its# las operaciones +*)# 78# *7, y @78 y cómo conigurar y limpiar los %its en un registro y algunos %uenos trucos con los operaciones de despla&amiento derecho e i&quierdo# todas cosas %ueno a sa%er# ya que puede acelerar su programa y son muy tiles cuando se utili&an los puertos digitales. 3ermitanme ahora hacer un pequeBo programa de prue%a que pueda hacer uso de las entradas y salidas digitales# así como el pullFups# porque este tutorial a sido muy teórico y es agrada%le llegar al inal haciendo parpadear algunos ledsK. ste es el pseudoFcódigo de nuestro programa# su intención es la de leer un interruptor y cada $e& que el interruptor es leído# se conmutara el estado de un ')# por lo que cuando se presione el interruptor el ') se iluminara# pulse de nue$o y el led se apagara# y de nue$o desde el principio# esto se podría hacer usando $arias condicionales i(!# pero se puede hacer en una sola línea usando el poderoso operador @78(L! @ain 4 %on'ig&ración del p&erto, en este código de eje!plo &sar PORTD. b&cle in'inito 4 +eo el $alor del botón Ai el led esta encendido " el botón ==1B 5paga el led. Ai el led esta apagado " el botón==1 enciende el led. 8 8
Sólo una cosa ms (sD que siempre $oy un poco oFtopic# pero este es importante! cuando se utili&a un %otón conectado a una entrada digital# de%emos ser conscientes de que un %otón no da una %uena y transición limpia entre 0 a 1 o de 1 a 0# pero en su lugar la seBal puede tener pro%lemas de re%ote# esto es de%ido a las propiedades mecnicas del %otón y no un deecto de diseBo. omo el %otón tiene una pequeBo conector en el interior# y cuando presiona el conector se cierra y se cierra el circuito entre su entrada y salida# pero esta pata suele a oscilar un poco hasta que quede irme en su parada# lo que de%emos tener cuidado de esto# y como siempre hay dos maneras# mediante un condensador pequeBo cerca de la %otón para el re%ote del $alor# o que esta eliminación de re%otes en el mismo código# que es ms cil de hacer cuando tenemos un montón de %otones y de nue$o es ms %arato que la adición de una gran cantidad de componentes a nuestro circuito. Si %uscas en Moogle el termino N%utton de%ouncingO encontrara una gran $ariedad de ormas para e$itar el re%ote de los %otones usando código# la orma que $oy a utili&ar aquí es la ms simple de todos# es sólo insertar un pequeBo retraso entre las consecuti$as lecturas de un %otón# esto es de por supuesto# un mDtodo de %loqueo# porque nuestro microcontrolador se detendr por algunos milisegundos# hay otras ormas mas inteligentes que usar tempori&adores# pero para proyectos de 2 ó %otones que no requieren una sincroni&ación super precisa se trata de una mDtodo de uso comn. 3ara hacer este retraso $oy a utili&ar el incorporado en las rutinas de retraso proporcionado por +G8 li%Fc.
+sí que $amos a empe&ar a programar# todo el código es muy sencillo si usted entendió todo lo que ue escrito anteriormente. Cincl&de -a$r/io.
/ Esta cabecera incluye las definiciones para todas las
* direcciones do los registros y otras cosas, casi siempre * deberá incluirse. */ #define F_CPU !""""""U
/* F_CPU le dice al compilador $ue usas un cristal de !%&' * y asi puede generar los delay e(actos, entonces debe ser * declarado. */
#include )util/delay.&
/* Contiene las funciones de delay $ue pueden generar delays * e(actos de ms o u+. */
&intE#t readF&tton$oid;
// Declaración de la '&nción readF&tton.
int !ain$oid 4 DDRD 2= G1--PD; PORTD 3= 1--PD; DDRF 3= 1--PF;
// // /
%on'ig&ra el pin del PORTD co!o &na entrada. 5cti$a el p&ll:&ps en el pin del PORTD. %on'ig&ra el pin del PORTF co!o salida, este es el pin digital 1 en la placa 5rd&ino 7&e tiene el led integrado. /
Hile1 4 // )n'inite loop i'readF&tton==1 4 // Ieri'ica el estado del botón. PORTF J=1--PF; / sta es la linea de código 7&e !encione anterior!ente para interca!biar el estado del led. / 8 #dela"#!s0; // Dela" entre consec&ti$as lect&ras. 8 8 &intE#t readF&tton$oid 4 i'P)*D 2 1--PD == #dela"#!s; 8 i'P)*D 2 1--PD == Ret&rn 1; // Ai 8 else 4 ret&rn 0; // Ai 8 8
0 4 // Ai el botón esta presionado. // Retardo de entrada para el $alor le(do. 0 4 // Ieri'ica 7&e la la lect&ra sea correcta. toda$(a es 0 es por7&e si ten(a!os p&lsado el botón
el $alor ca!bio la lect&ra es incorrecta.
reo que no hay necesidad de mostrar cómo crear el proyecto en +$rStudio en este punto# pero si usted tiene cualquier duda consulte los otros tutoriales o de6e un comentario# y no se ol$ide de presionar el %otón de reinicio cuando se quiere su%ir su código. ,ampoco tiene un esquema del circuito# pero puedo conseguir uno si alguien lo solicite# o cuando tengo el tiempo para hacer uno# el ') usado en es el ') incorporado que +rduino como en el pin digital 1# y el %otón es tam%iDn es cil# se conecta una de las patas del %otón situado a la pin 378,)2# que es el pin digital 2 de arduino y la otra pierna del interruptor de%e conectarse a masa. "ay aquí un pequeBo $ideo que muestra que este código en acción# el led no siempre cam%ia# pero esto es PnormalP porque mi %otón como ya se ha surido un poco en su $ida y tam%iDn puede pulsar el %otón cuando el retraso de los 2C0 ms se est e6ecutando# pero unciona y aquí est la prue%a: http://www.youtu%e.com/watch?eatureQplayerJem%eddedR$Qku4&0dlrn0 "e hecho algunas correcciones al teAto# y aquí est el código en un proyecto de +G8 Studio listo para compilar y cargar: http://code.google.com/p/a$rFtutorials/downloads/detail?nameQport.&ip Mracias por leer y no te ol$ides de comentar cualquier cosa que desee# y una %uena programaciónK