tag:blogger.com,1999:blog-49456806084713352802024-03-13T03:58:06.214+01:00Tutoriales PICFundamentos de microcontroladores aplicados a la familia PIC de Microchip.
Proyectos y Aplicaciones.Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-4945680608471335280.post-20898247985881039992013-11-29T18:45:00.001+01:002013-11-30T19:36:47.614+01:00Control de múltiples servos con un único TIMER.<div class="MsoNormal">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUX502PS1i5nYsboQvFa8IxzDXiULvHlU7YeEw1qVPdSJ2FlzBySrdXKpDPZYnqxJ-ksuV1msCOLjqg7Y8mvxRd_N10YpzDUgfJj1xB2RJhyL2_gOtkT9pcZNLPOL18hebucjSfMEo/s1600/img_servo.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUX502PS1i5nYsboQvFa8IxzDXiULvHlU7YeEw1qVPdSJ2FlzBySrdXKpDPZYnqxJ-ksuV1msCOLjqg7Y8mvxRd_N10YpzDUgfJj1xB2RJhyL2_gOtkT9pcZNLPOL18hebucjSfMEo/s1600/img_servo.jpg" /></a><span style="font-family: Verdana;"></span><br />
<span style="font-family: Verdana;">En esta
entrada vamos a ver como conectar nuestro microcontrolador con otro dispositivo muy
popular, </span><span style="font-family: Verdana;">un
servomotor. Un servomotor es un motor DC, similar a los usados en las entradas
que dedicamos </span><span style="font-family: Verdana;">al control
de motores. Sin embargo, al contrario que los motores que manejamos allí, los
servomotores </span><span style="font-family: Verdana;">incluyen
su propio hardware de control, por lo que no tendremos que preocuparnos de esa parte.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En la
primera parte de esta entrada describiremos los fundamentos de cómo controlar
un servo </span><span style="font-family: Verdana;">con un
microcontrolador, con una mínima sobrecarga para el PIC mediante el uso de un timer y sus interrupción asociada.</span></div>
<div class="MsoNormal">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En la
segunda parte extenderemos este enfoque para el caso de que necesitemos controlar </span><span style="font-family: Verdana;">muchos
servos con un único PIC. Veremos como podemos controlar hasta 8/10 servos dedicando
sólo un TIMER </span><span style="font-family: Verdana;">del
microcontrolador.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span>
<div class="MsoNormal" style="background-color: white; line-height: 10pt;">
<span lang="PT-BR" style="color: #111111;"><span style="font-family: Verdana, sans-serif;">Archivos de código asociados a esta entrada:</span></span><span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/servo_calib.c">servo_calib.c</a></span><span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"> </span><span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;">y </span><span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"> </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/servo_n.c" style="font-family: Verdana, sans-serif; line-height: 10pt;">servo_n.c</a></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">--------------------------------------------------------------------------------------</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<a name='more'></a><div class="MsoNormal">
<b><span lang="PT-BR" style="font-family: Verdana;">Hardware :</span></b><span lang="PT-BR" style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<b><span lang="PT-BR" style="font-family: Verdana;"><br /></span></b></div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600"
o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f"
stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1028" type="#_x0000_t75" style='position:absolute;
margin-left:372.6pt;margin-top:5.25pt;width:108pt;height:101pt;z-index:3;
mso-position-horizontal:absolute;mso-position-horizontal-relative:text;
mso-position-vertical:absolute;mso-position-vertical-relative:text'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.jpg"
o:title="interior_servo"/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><span lang="PT-BR" style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj87CeCT8N7viEDCOZDzVki-F8h8MTjOKkaStN1DF5_4mFNDzYvHXLcJIp1myEbIUSr9e4Tfffl9UXUv67_9Fu_rrdKmBo0AApObvBmmNbdOnlWyF0k68soly_AU_DFYWW2loOx-Nm7/s1600/interior_servo.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj87CeCT8N7viEDCOZDzVki-F8h8MTjOKkaStN1DF5_4mFNDzYvHXLcJIp1myEbIUSr9e4Tfffl9UXUv67_9Fu_rrdKmBo0AApObvBmmNbdOnlWyF0k68soly_AU_DFYWW2loOx-Nm7/s200/interior_servo.jpg" width="200" /></a><span style="font-family: Verdana;">Como hemos
comentado, un servo (ver figura adjunta) es un simple motor DC con su propia
electrónica de control. Normalmente el parámetro controlado es la posición: una
orden nuestra hace que el servo vaya hasta una cierta posición y permanezca en
ella. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Aunque
menos comunes, podemos encontrarnos servos cuyo parámetro controlado es la
velocidad. En este caso, nuestras ordenes causan que el servo gire
uniformemente a la velocidad indicada.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En esta
entrada nos centraremos en los servos de posición. Típicamente constan de un
motor DC normal con una gran reductora entre el eje del motor y el eje de
salida. A este eje de salida está conectado algún tipo de sensor (normalmente
un potenciómetro) a través de cuya medida el servo conoce que ha llegado a la
posición deseada y puede detener el motor.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La mayoría
de los servos están limitados a moverse dentro de una fracción de vuelta, por
lo que en vez de posiciones hablaremos del ángulo del servo. Un parámetro
importante de un servo es el rango máximo que puede girar ("throw" en
ingles). Así tendremos servos de media vuelta (180º), una vuelta completa
(360º) o incluso un cuarto (90º) de vuelta. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Los servos
de media vuelta, con un rango máximo de 180º, son muy comunes y en ellos basaré
la explicación de los </span><span style="font-family: Verdana;">conceptos
básicos.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Un servo
suele contar con 3 hilos. Dos de ellos, típicamente rojo (V+) y negro (GND), le
proporcionan la alimentación requerida, así como un nivel de referencia común
(masa) con el micro. </span><span style="font-family: Verdana;">El tercer
hilo (naranja es una opción muy usada para este hilo) es el que el micro usará
para control, es decir, para decirle al servo a que posición (ángulo) debe
girar.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La forma de
enviar esa información en muy sencilla. Técnicamente se denomina modulación por
ancho de pulso y consiste en que el PIC debe mandar una serie de pulsos al
servo con una frecuencia constante (del orden de 50 Hz). </span><span style="font-family: Verdana;">La
separación entre pulsos por lo tanto es siempre de unos 20 msec. Las ordenes se
las damos a través del ancho de los pulsos, que suele oscilar entre 1 y 2
milisegundos.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En la
figura adjunta podemos ver gráficamente esta situación:</span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6q-2WLScNcbu2yjzCpPKZwrYYj6QqTQ53UG3XGWj-AGJVCUdN6zPMItnp9FJyVNXiOToO1IeDl5TaIvddPy__kDK3Og5mrxmXUwSi3wLUUYhXs8yMNJgqbbr6_dj6jIngF8Jehk_K/s1600/control-de-giro-del-servomotor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="329" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6q-2WLScNcbu2yjzCpPKZwrYYj6QqTQ53UG3XGWj-AGJVCUdN6zPMItnp9FJyVNXiOToO1IeDl5TaIvddPy__kDK3Og5mrxmXUwSi3wLUUYhXs8yMNJgqbbr6_dj6jIngF8Jehk_K/s640/control-de-giro-del-servomotor.jpg" width="640" /></a></div>
<br />
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><!--[if gte vml 1]><v:shape id="_x0000_i1025"
type="#_x0000_t75" style='width:336.75pt;height:174.75pt'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image003.jpg"
o:title="control-de-giro-del-servomotor"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El caso
ilustrado corresponde a un servo con un rango de ½ vuelta o 180º. Un ancho del
pulso de 1.5 milisegundos </span><span style="font-family: Verdana;">le dice al
servo que debe ir a su posición central o neutra. Si acortamos o alargamos el
pulso giraremos a la izquierda o a la derecha. En el ejemplo mostrado el servo
alcanza sus extremos (0 y 180º) para 1 y 2 milisegundos.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como se
observa, independientemente del ancho de los pulsos, la separación entre pulsos
es constante y debe ser </span><span style="font-family: Verdana;">del orden
de 20 milisegundos, lo que corresponde a la frecuencia antes mencionada de 50
Hz. Esta frecuencia no es crítica: frecuencias entre 40 y 65 Hz funcionarán
posiblemente (periodos entre 15-25 msec).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Es
importante resaltar que los valores anteriores son aproximados y deben
considerarse un punto de partida.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Es
fundamental no sobrepasar los valores máximo y mínimo, porque el servo
intentará ir más allá y sus "topes" se lo impedirán. El resultado,
dependiendo de la fuerza del servo y la calidad de los engranajes podría ser un
servo quemado o con sus engranajes "pulidos" (sobre todo si son de plástico,
como ocurre en muchos servos baratos).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Debido a
esto, es muy importante verificar los servos con los que vamos a trabajar antes
de usarlos en nuestra aplicación. Para ello podemos ir
incrementando/decrementando el ancho del pulso hasta encontrar sus límites. El
punto de partida será la posición neutra "nominal": un ancho de 1.5
msec. Puede que no corresponda al punto central exactamente pero seguro que cae
en la zona permitida.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shape id="_x0000_s1026" type="#_x0000_t75"
style='position:absolute;margin-left:318.6pt;margin-top:.75pt;width:2in;
height:103.05pt;z-index:1;mso-position-horizontal:absolute;
mso-position-horizontal-relative:text;mso-position-vertical:absolute;
mso-position-vertical-relative:text'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image005.jpg"
o:title="esq1"/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQtADHsmWjKZSnewvJ1XZ3elbMUXQlCMI8F07VnGkn9Kx-HmePv2BG94HJcAu3pQ6AZu57Fc1QgEwYI8z5VTOjWBGfsaq04P0tClXpY0HulQIA5s74v9FYbDd6DwSxATugRQA5pvjR/s1600/esq1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="142" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQtADHsmWjKZSnewvJ1XZ3elbMUXQlCMI8F07VnGkn9Kx-HmePv2BG94HJcAu3pQ6AZu57Fc1QgEwYI8z5VTOjWBGfsaq04P0tClXpY0HulQIA5s74v9FYbDd6DwSxATugRQA5pvjR/s200/esq1.jpg" width="200" /></a><span style="font-family: Verdana;">El siguiente esquema refleja las conexiones entre el
micro y el servo. El hilo de control (naranja?) se conecta directamente a
cualquier pin (modo salida digital) del PIC. En nuestro primer ejemplo hemos
usado RC0, pero cualquier otro valdría. Los otros dos hilos del servo se
conectan a la alimentación (rojo?) y a masa (negro/marrón?).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Recalcar
que es necesario que la masa del PIC y la del servo estén conectadas para que
tengan una referencia común de voltaje.</span><span style="font-family: Verdana;"> </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Respecto
al voltaje de alimentación para el servo habrá que consultar las especificaciones, pero muchos de ellos
funcionarán razonablemente con una alimentación entre 4 y 8V. Si nos quedamos
cortos lo único que puede pasar es que el servo no se mueva o gire más
lentamente.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como 5V es
un voltaje adecuado para muchos servos podríamos estar tentados de usar la
misma alimentación para el servo y el PIC. Esto es una mala idea, ya que las
demandas de corriente del servo al moverse pueden hacer caer el voltaje de la
alimentación, con el consiguiente riesgo de reseteo del PIC.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHKw-JOtcdWQ9jzk55ygskssoQZlw-aA5c-57mXugm_FLRCCIlzIWL7Hv8dX6Z-Babx-032POwMNVXKMkyMIMQxhyphenhyphenEsA-Ykyukb3WmvvWRYgJ_xOMUgr6ditN1Z9fzbWnt4lS6RvD4/s1600/esq_pulsar2.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHKw-JOtcdWQ9jzk55ygskssoQZlw-aA5c-57mXugm_FLRCCIlzIWL7Hv8dX6Z-Babx-032POwMNVXKMkyMIMQxhyphenhyphenEsA-Ykyukb3WmvvWRYgJ_xOMUgr6ditN1Z9fzbWnt4lS6RvD4/s1600/esq_pulsar2.jpg" /></a><span style="font-family: Verdana;">En mi
montaje uso la placa EasyPIC, alimentada a través del USB (5V) del ordenador.
Sin embargo, uso otra batería independiente (7V) para alimentar al servo.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Finalmente,
en el programa usaremos un par de pulsadores (conectados a RA1 y RA2) para
variar el ancho del pulso (y por lo tanto mover el servo). Vemos en el esquema
adjunto cómo cada pin está atado a tierra con una resistencia de pull-down. Su estado natural es LOW (0). Sólo al pulsar
pasan a un nivel alto.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> </span><b><span style="font-family: Verdana;">Software :</span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Nuestro
principal objetivo es programar una señal de 50 Hz con un ancho de pulso que
podamos variar en el rango indicado. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Lo primero
que podemos pensar es que la señal esperada por el servo (periodo fijo, ancho
del pulsi variable) se </span><span style="font-family: Verdana;">parece
mucho a una señal PWM. De hecho eso es exactamente lo que es (antes la hemos
llamado codificación por ancho de pulso, pero eso en inglés es justamente PWM,
Pulse Width Modulation).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Nuestra
primera idea sería usar una línea PWM para controlar un servo. Se trataría de
conseguir una frecuencia PWM del orden de 50 Hz y variar el ancho del pulso con
el duty_cicle. Esto es factible, pero en mi opinión, no es una buena idea por
varias razones:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana;">1.<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Las
líneas PWM son escasas (típicamente sólo 2 en un PIC). ¿Qué pasa si queremos
controlar más servos? Además, las líneas PWM tienen otras funciones (modo de
CAPTURE o COMPARE) y pueden no estar disponibles.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana;">2.<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Aunque
no hubiese problemas de disponibilidad, las características del PWM de un PIC
no se prestan a su uso como control de un servo. Veamos las razones.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si
recordamos la entrada de introducción al PWM la frecuencia PWM que puede
obtenerse para una cierta frecuencia del oscilador es: <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> Fpwm (mínima) = Fosc / 16384<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Para poder
llegar a la frecuencia deseada de 50 Hz deberíamos bajar a un oscilador de 1
MHz o menor, lo que posiblemente haga muy lento el sistema para otras tareas. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Además PWM
está diseñado para variar el ciclo de trabajo (% on) entre 0 y 100%. En cambio,
para controlar un servo el tiempo on (ancho del pulso) oscila como hemos visto entre
1 y 2 msec dentro del periodo de 20 msec. Traducido a ciclo de trabajo
correspondería a movernos entre un 5% (1/20) y un 10% (2/20). Perderemos mucha
"resolución" si estamos limitados a un intervalo tan pequeño.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En vez de usar
el módulo PWM es mucho mejor usar un simple TIMER (y su correspondiente
interrupción) para crear la señal de control. Se nos puede criticar que estamos
cambiando un recurso (PWM) por otro (TIMER) pero eso no sería correcto, ya que
usar el PWM conlleva también el gasto del timer asociado (TMR2). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Otra
posible crítica es que si necesitamos controlar muchos servos se nos acabarán
los timers. Lo bueno de este enfoque es que, como explicaremos en esta entrada,
podemos controlar hasta 8 servos con un único
timer (el número exacto depende de las características de los servos
usados, podrían ser alguno más o menos).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En esta entrada veremos dos programas: en el primero presentaremos los fundamentos de la interfaz con el servo usando un timer. En el segundo ampliaremos el concepto al uso de múltiples servos sin que necesitemos más recursos del PIC.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<u><b><span style="font-family: Verdana;">PROGRAMA1 (servo_calib.c):</span></b><span style="font-family: Verdana;"> </span></u></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Ilustrará los conceptos básicos sobre como configurar un TIMER para generar la señal de control sin apenas sobrecarga para el PIC. Usaremos un par de pulsadores para aumentar/reducir el ancho del pulso.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Este programa también puede servirnos como calibración de un servo cuyas especificaciones detalladas desconozcamos. Podemos partir de un ancho medio (1500 msec) correspondiente a la posición neutra e ir subiendo/bajando hasta notar (chirridos, vibraciones) que hemos alcanzado el tope. De esta forma podemos obtener el ancho mínimo y máximo del pulso para ese servo y su posición neutra. Nos vendrá bien además para verificar el verdadero rango del servo (su movimiento en grados). Es fácil adquirir servos baratos supuestamente con un rango de 180º, cuyo verdadero rango está más cerca de ¼ de vuelta (90º).<o:p></o:p></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El
programa es muy sencillo. Veamos el código de la rutina principal. <span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> main() </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{ </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> T0CON = 0b00000000; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> enable_global_ints; enable_TMR0_int;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> start_TMR0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> ADCON1=0x0F;
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// No PORTS used as AD </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> TRISA=0b00000110; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// RA1,RA2 inputs</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> TRISB=0; PORTB=0; TRISC=0; PORTC=0; TRISD=0; PORTD=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// All pins down to 0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">while</span><span lang="EN-GB" style="font-family: 'Courier New';">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTAbits.RA1==1) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pulse<2100) pulse++; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Increments pulse (max 2.1 msec)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTAbits.RA2==1) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pulse>500) pulse--; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Decrements
pulse (min 0.5 msec) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> PORTB = pulse/10; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Show
current pulse in PORTB</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> Delay10TCYx(100); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Wait
a while <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">}
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Algunos
comentarios:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<ul>
<li><span style="font-family: Verdana; text-indent: -18pt;">La
inicialización a 0 de T0CON pone al timer TMR0 en modo de 16 bits, contando
ciclos de instrucción y con un pre-scaler 1:2. En este proyecto estoy usando un
cristal de 8 MHz, por lo que la frecuencia de instrucción es de Fosc/4 = 2 MHz.
Con un preescaler 1:2 hago que el contador del TMR0 se incremente cada
microsegundo, lo que resulta muy conveniente para "traducir" los
delay programados.</span></li>
<li><span style="font-family: Verdana; text-indent: -18pt;">Habilitamos
las interrupciones globales y la interrupción asociada a TMR0.</span></li>
<li><span style="font-family: Verdana; text-indent: -18pt;">Usaremos
todos los pines como de entrada/salida digital (ADCON1=0x0F)</span></li>
<li><span style="font-family: Verdana; text-indent: -18pt;">Declaramos
RA1 y RA2 entradas (bits correspondientes de TRISA = 1).</span></li>
</ul>
<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Previamente
hemos declarado un par de macros para arrancar el timer TMR0 y resetera su
contador (16 bits):<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> set_TMR0(x) {TMR0H=(x>>8);
TMR0L=(x&0x00FF);}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> start_TMR0 T0CONbits.TMR0ON=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El resto
del main() es simplemente un bucle infinito donde monitorizamos si se han
pulsado los pulsadores asociados a RA1 y RA2. Si es así se incrementa o
decrementa la variable pulse (uint16) que gobernará el ancho del pulso de
control. El valor de dicha variable puede variar entre 0.5 y 2.1 milisegundos,
que son los extremos que he detectado para el servo usado.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Evidentemente
toda la acción sucede durante la interrupción del TMR0. Veamos su código:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> SERVO_LINE LATCbits.LATC0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint16 TMR0_ini,pulse=1325; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//
in microsec</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// High priority
interruption </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New';"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// ISR de la interrupcion de TMR0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> SERVO_LINE=1-SERVO_LINE;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (SERVO_LINE) TMR0_ini= 25-pulse; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//65536-(pulse-25); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="DA" style="font-family: 'Courier New';"> </span><span lang="DA" style="color: blue; font-family: 'Courier New';">else</span><span lang="DA" style="font-family: 'Courier New';"> TMR0_ini= 45536+pulse+25; </span><span lang="DA" style="color: forestgreen; font-family: 'Courier New';">//65536-(20000-(pulse-25))</span><span lang="DA" style="font-family: "Courier New"; mso-ansi-language: DA; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="DA" style="font-family: 'Courier New';">
set_TMR0(TMR0_ini);</span><span lang="DA" style="font-family: "Courier New"; mso-ansi-language: DA; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="DA" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">TMR0_flag=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<ul>
<li><span style="font-family: Verdana; text-indent: -18pt;">Con
el define #SERVO_LINE indico que pin voy a usar para controlar el servo. En
este caso es RC0.</span></li>
<li><span style="font-family: Verdana; text-indent: -18pt;">Declaro
la variable pulse (uint16) que guardará el ancho del pulso deseado, y la
inicializo con 1325, que corresponde a 1.325 milisegundos (que resulta ser la
posición neutra de mi servo).</span><span style="font-family: Verdana; font-size: 8pt;"> </span></li>
</ul>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana;">Examinemos
ahora con más detalle el código de la interrupción:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l2 level1 lfo4; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana;">1.<span style="font-family: 'Times New Roman';"> </span></span><!--[endif]--><span style="font-family: Verdana;">Lo
primero que hacemos es cambiar el estado de la línea. Si estaba baja se levanta
y viceversa.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l2 level1 lfo4; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana;">2.<span style="font-family: 'Times New Roman';"> </span></span><!--[endif]--><span style="font-family: Verdana;">Si
la línea está alta (tras la operación anterior) es que estamos en la fase del
pulso, que debe durar el ancho del pulso (valor de pulse en microsegundos).
Como los contadores de los timers en los PIC se incrementan siempre y la
interrupción se producirá al llegar a 65536, debo programar un valor nominal
inicial para TMR0:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> TMR0_ini
= 65536 – pulse<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;">para que
pasados pulse microsegundos rebose el contador y se produzca la siguiente
interrupción (donde se cambiará el
estado de la línea, acabándose el pulso.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;">Sin embargo,
debido a los retrasos introducidos en la llamada a la interrupción y a los
cálculos previos he comprobado que
es más exacto inicializar el contador un poco más adelante de su valor nominal. </span><span style="font-family: Verdana;">En particular, una corrección de
25 ciclos es muy adecuada:</span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> TMR0_ini
= 65536 – pulse + 25 = (para un uint16) = 25 - pulse<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> y ese es el
valor que introduzco en la variable TMR0_ini.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l2 level1 lfo4; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana;">3.<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Si
tras el cambio la línea esta baja es que estamos en la fase de
"descanso" hasta el siguiente pulso. La duración de esa fase será de
20 msec – ancho_pulso = 20000 – pulse. Inicializaremos TMR0_ini con su <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> complementario:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> TMR0_ini = 65536 – 20000 +
pulse = 45536 + pulse. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> Al igual que
antes para compensar retrasos en la ejecución podemos adelantar un poco dicho
contador. Si introducimos la misma
corrección de antes tendremos:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> TMR0_ini = 45536 + pulse + 25 <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l2 level1 lfo4; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana;">4.<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Tras
hacer los cálculos anteriores pongo en hora el contador TMR0 con set_TMR0(TMR0_ini).<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Y ya está
todo. La interrupción saltará alternadamente cada pulse (en msec) y cada
20-pulse (msec). Trás el intervalo largo (20-pulso) se subirá la línea y tras
el corto (pulse) se bajará, obteniéndose así la señal de control deseada. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como pulse
es una variable puede cambiarse en cualquier momento (en nuestro caso a través
de los pulsadores en el bucle principal) modificando el ancho del pulso y la
posición del servo.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En el video adjunto se muestra el resultado cuando conectamos RC0 a la línea de control de un servo:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzkKkGSCShTcOGU4ofS0M3qhePBoFQM4hV7sNO4G4Hk4PJnm-4F74DrUzVngUnwr3zPtrQjHDGr1JZc6dGUwA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez entendidos los fundamentos para controlar un servo, ampliaremos el concepto al caso d</span><span style="font-family: Verdana;">e
querer gobernar múltiples servos.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><u><b>PROGRAMA 2 (servo_n.c)</b></u><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En este segundo ejemplo ilustraremos como usar múltiples servos con un único TIMER del PIC.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Además del usoi de un timer necesitaremos (en principio) 8 líneas de control, una para cada servo. </span><span style="font-family: Verdana;">Sin embargo veremos que con este enfoque en cada instante sólo tenemos activa una línea de un servo, por lo </span><span style="font-family: Verdana;">que sería posible usar un demultiplexador (tipo 74HC237) para gobernar 8 servos con sólo 3 pines del PIC. En este código no se ha usado esta opción pero sería fácil de adaptar. </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Podemos controlar varios servos sin usar timers adicionales porque el tiempo que cada servo esta alto (1-2 msec) es muy pequeño
comparado con el periodo (20 msec). La idea es aprovechar el tiempo en que la
línea de un servo está baja para dedicarnos al resto de los servos.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Veamos el código, que está escrito suponiendo 5 servos a controlar, aunque es fácilmente modificable para potro número. </span><span style="font-family: Verdana;">Empezaremos con la declaración
de los defines y variables globales a usar:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> </span><span style="font-family: Verdana; font-size: 8pt;"> </span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="PT-BR" style="font-family: 'Courier New';"> N_SERVO 5</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_0 LATCbits.LATC0</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_1 LATCbits.LATC1</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_2 LATCbits.LATC2</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_3 LATCbits.LATC3</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_4 LATCbits.LATC4</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';">uint8 servo_active=0;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';">uint16
pulse[N_SERVO]={600,900,1200,1500,1800};
</span><span lang="PT-BR" style="color: forestgreen; font-family: 'Courier New';">// in microsec</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">uint16 TMR0_ini;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Muy similar
al caso anterior, solo que ahora tenemos 5 servos (N_SERVO) a controlar, por lo que tenemos que declarar no 1 sino 5 pines de control, desde RC0 a RC4.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Tenemos que tener también una nueva variable (servo_activo) que nos indicará de que servo se está
ocupando el timer. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Finalmente
tenemos nuestras conocidas variables TMR0_ini y pulse, solo que ahora pulse es
un array de tamaño 5, ya que tenemos 5 servos y cada uno puede tener un ancho
de pulso (posción) diferente. Los pulsos para los cinco servos se inicializan a
0.6, 0.9 , 1.2, 1.5 y 1.8 msec.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Dentro de
la función main() tenemos un sistema
parecido al anterior para poder cambiar los anchos de los pulsos:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">ADCON1=0x0F; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// No PORTS used as AD</span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New';">TRISA=0b00000111;</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">while</span><span lang="EN-GB" style="font-family: 'Courier New';">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTAbits.RA0==1) {k++; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (k==N_SERVO) k=0; PORTB=k;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTAbits.RA1==1) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pulse[k]<2100) pulse[k]++; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTAbits.RA2==1) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pulse[k]>500) pulse[k]--; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> Delay10TCYx(100);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Además de
los pulsadores RA1 y RA2 de antes para cambiar el tamaño de un pulso, tengo que tener una variable (k, inicializada a 0) que me indica cuál de los servos estoy modificando. Dicha variable cambia al pulsar RA0, por lo que puedo modificar el ancho de pulso de cualquiera de las
señales de control. Para saber qué servo estoy modificando el programa me
muestra el valor actual de k en PORTB.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Ya sólo
queda ver el código de la interrupción donde se hace el trabajo:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> slot
(20000/N_SERVO) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Time slot allocated to each servo</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> c_slot (65536-slot+30) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Complementary
(16 bits) of c_slot</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// High priority
interruption </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New';"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> PORTDbits.RD0=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//
ISR de la interrupcion de TMR1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">switch</span><span lang="EN-GB" style="font-family: 'Courier New';"> (servo_active)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">case</span><span lang="EN-GB" style="font-family: 'Courier New';"> 0: </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" name="OLE_LINK1"><span lang="EN-GB" style="font-family: 'Courier New';"> SERVO_0=1-SERVO_0; </span></a><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Changes
states of SERVO_0<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';"> // if HIGH program pulse[0]
delay, else // else (slot-pulse[0]) delay</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (SERVO_0)
TMR0_ini= 25-pulse[0]; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> {TMR0_ini=
c_slot+pulse[0]; servo_active++;} </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">break</span><span lang="EN-GB" style="font-family: 'Courier New';">;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">case</span><span lang="EN-GB" style="font-family: 'Courier New';"> 1: </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="font-family: 'Courier New';">SERVO_1=1-SERVO_1;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">if</span><span lang="PT-BR" style="font-family: 'Courier New';"> (SERVO_1) TMR0_ini= 25-pulse[1];</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">else</span><span lang="PT-BR" style="font-family: 'Courier New';"> {TMR0_ini=
c_slot+pulse[1]; servo_active++; }</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">break</span><span lang="PT-BR" style="font-family: 'Courier New';">;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">case</span><span lang="PT-BR" style="font-family: 'Courier New';"> 2: </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_2=1-SERVO_2;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">if</span><span lang="PT-BR" style="font-family: 'Courier New';"> (SERVO_2) TMR0_ini= 25-pulse[2];</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">else</span><span lang="PT-BR" style="font-family: 'Courier New';"> {TMR0_ini= c_slot+pulse[2];
servo_active++; }</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">break</span><span lang="PT-BR" style="font-family: 'Courier New';">;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">case</span><span lang="PT-BR" style="font-family: 'Courier New';"> 3: </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_3=1-SERVO_3;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">if</span><span lang="PT-BR" style="font-family: 'Courier New';"> (SERVO_3) TMR0_ini= 25-pulse[3];</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">else</span><span lang="PT-BR" style="font-family: 'Courier New';"> {TMR0_ini= c_slot+pulse[3];
servo_active++; }</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">break</span><span lang="PT-BR" style="font-family: 'Courier New';">;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">case</span><span lang="PT-BR" style="font-family: 'Courier New';"> 4: </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> SERVO_4=1-SERVO_4;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">if</span><span lang="PT-BR" style="font-family: 'Courier New';"> (SERVO_4) TMR0_ini= 25-pulse[4];</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">else</span><span lang="PT-BR" style="font-family: 'Courier New';"> {TMR0_ini= c_slot+pulse[4]; servo_active=0;
}</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New';">break</span><span lang="PT-BR" style="font-family: 'Courier New';">; </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> }</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> set_TMR0(TMR0_ini);</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> TMR0_flag=0;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> }</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><span lang="PT-BR" style="font-family: 'Courier New';"> PORTDbits.RD0=0;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';">}</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: Verdana;">A través de servo_active podemos ver que servo está
"activo". </span><span style="font-family: Verdana;">Dentro
de cada servo, el código es muy similar al de antes:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New';"> <span lang="EN-GB"> SERVO_0=1-SERVO_0; </span></span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Changes states of SERVO_0<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';"> // if
HIGH program delay = pulse[0] else =(slot-pulse[0])</span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (SERVO_0)
TMR0_ini= 25-pulse[0]; <o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> {TMR0_ini=
c_slot+pulse[0]; servo_active++;} </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">break</span><span lang="EN-GB" style="font-family: 'Courier New';">;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana;">Como antes cambiamos el estado de la línea. </span><span style="font-family: Verdana;">Si tras el cambio está
alta es que estamos en el periodo del pulso y programamos el timer para que salte dentro de pulse[0]
microsegundos. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La
diferencia es que ahora, si la línea está baja en vez de esperar 20 msec (–
pulso), esperamos 20 msec/5 (- pulso). Es lo que en el programa defino como un
slot. La idea es que ahora los N servos deben repartirse los 20 milisegundos de
los que disponemos, por lo que cada uno sólo cuenta con 20/5 = 4 msec antes de
ceder el paso al siguiente pulso.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Eso se
hace incrementando la variable servo_active, salvo en el último caso (case 4:)
donde se resetea a 0 para volver a empezar el ciclo.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si
conectasemos la salida de las 5 líneas a un analizador lógico veríamos algo así
como lo mostrado en la figura adjunta. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOeC1fWElTiAKor6MNamaKXeF1fBC07W7OZWqlXkntzutwCIHglG3Giof_TCGJobQnQzImCWNSaUP_ua8Ip6eMgTz5kM82Ze6ozP_Ir0ivkW1UESitN5FfyAUDu0ludJaPiFMaHPo9/s1600/cronograma.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOeC1fWElTiAKor6MNamaKXeF1fBC07W7OZWqlXkntzutwCIHglG3Giof_TCGJobQnQzImCWNSaUP_ua8Ip6eMgTz5kM82Ze6ozP_Ir0ivkW1UESitN5FfyAUDu0ludJaPiFMaHPo9/s320/cronograma.jpg" width="285" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En cada segmento de 20/5 = 4 msec la
variable servo_active toma un valor distinto y los comandos de levantar/bajar
la línea afectan a distintos pines. Una vez que ha acabado el pulso y el pin ha vuelto
a su nivel bajo no hay nada más que hacer para ese servo (hasta dentro de 20 msec), por lo que puedo
dedicarme al siguiente.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Solo falta
ver cuantos servos podríamos llegar a manejar. La respuesta es sencilla. El
problema de tener muchos servos es que puede que todavía estuviesemos haciendo
la ronda cuando se cumplieran los 20 milisegundos. En ese momento tendríamos
que volver a ocuparnos de preparar el pulso del 1er servo.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si
nuestros servos tienen un ancho máximo de unos 2 msec con asignar un slot de
2.5 msec a cada servo tendríamos suficiente. 20 msec entre 2.5msec dan un total
de 8 slots. Incluso podríamos acomodar alguno más usando el hecho de que la
frecuencia de 50 Hz no es crítica. De ser necesario podríamos seguramente
incrementar el periodo de los pulsos a 25 msec (40 Hz), lo que nos daría
espacio para 2 slots adicionales.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Otro
consideración es que % del PIC queda libre para otras tareas. Y la respuesta es
que prácticamente todo. Si monitorizamos cuanto nos demoramos en la
interrupción veremos que es del orden de 25 usec (justo la compensación que
tuvimos que usar para ajustar más exactamente los timings).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Por cada
timer que tengamos TMR0 salta 2 veces, una para subir y otra para bajar la
línea. En el caso máximo de tener 8 timers tendríamos 8 x 2 = 16 interrupciones
durante el periodo de 20 msec. 16 interrupciones nos ocuparán <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">16 x 25 = 400
usec = 0.4 msec. El tanto por ciento que se come la interrupción es por lo
tanto de:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> 0.4/20 = 2%<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Luego el
PIC tiene libre un 98% de sus ciclos para dedicarlos a sus otras tareas.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com13tag:blogger.com,1999:blog-4945680608471335280.post-32473349703456157532013-09-30T19:04:00.000+02:002013-09-30T19:16:47.162+02:00Monitor del ritmo cardíaco<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: #111111;">Vamos a volver a usar el sensor de luz
TSL235 en una aplicación más interesante: monitorizar nuestro ritmo cardíaco. </span></span><span style="color: #111111; font-family: Verdana, sans-serif;">¿Cómo hacerlo con un sensor de luz?</span><span style="color: #111111; font-family: Verdana, sans-serif;"> </span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: #111111;"><br /></span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: #111111;">La idea viene explicada en </span></span><span style="font-family: Verdana, sans-serif;">una "application note" dedicada a estos sensores:</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><a href="http://smartdata.usbid.com/datasheets/usbid/2000/2000-q2/230evm2taos.pdf">http://smartdata.usbid.com/datasheets/usbid/2000/2000-q2/230evm2taos.pdf</a></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDRvfqxioC0hE8gsuyCb7jPRL-zxnN7gg6OBuzOJ5QJSzNMCRU7EChT5rY7nox4HIdveURqnJoXB0iwmRCG4KaeIGk8PhCOUYvJ69-SO2jorHvLaMH_V3-oCZ1Ah5-A0zHuxdH477T/s1600/dedo_1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDRvfqxioC0hE8gsuyCb7jPRL-zxnN7gg6OBuzOJ5QJSzNMCRU7EChT5rY7nox4HIdveURqnJoXB0iwmRCG4KaeIGk8PhCOUYvJ69-SO2jorHvLaMH_V3-oCZ1Ah5-A0zHuxdH477T/s200/dedo_1.jpg" width="200" /></a><span style="font-family: Verdana, sans-serif;">La configuración propuesta se muestra
en la imagen adjunta. Un LED (u otra fuente de luz) ilumina un dedo, detrás del
cuál se encuentra nuestro sensor. A cada pulsación del corazón, un nuevo flujo
de sangre llega al dedo, cambiando su "opacidad" a la luz. El
objetivo es detectar dichas oscilaciones, determinar su frecuencia fundamental
y a partir de ahí el ritmo cardíaco en pulsaciones por minuto (ppm).<span style="color: #111111;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 12pt;">En la aplicación citada antes, el microcontrolador solo recoge los datos
del sensor y los manda al PC para su proceso. La principal mejora de mi proyecto es que el PIC no sólo captura la
señal, sino que la procesa y obtiene el ritmo cardíaco. </span><span style="color: #111111; font-family: Verdana, sans-serif; line-height: 12pt;">De esta forma tenemos un sistema autónomo.</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111;"><span style="font-family: Verdana, sans-serif;">Al igual que en otras
entradas el código del PIC se complementa con un programa MATLAB que nos
permite ver gráficamente los datos sobre los que trabajamos y los
resultados obtenidos. Recalcar que el programa MATLAB sólo visualiza los datos:
todos los cálculos se llevan a cabo en el PIC.<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111;"><span style="font-family: Verdana, sans-serif;">En este corto video
podemos visualizar los datos obtenidos tras un pre-proceso de los datos del
sensor. Es sobre esta señal sobre la que el PIC trabaja para estima su periodo:<o:p></o:p></span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111;"><span style="font-family: Verdana, sans-serif;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dwNjVkHU0mhYokduAGE6yHd_98acRgn0eu_uA-VAHZ-7vXQxB9yCx0qkeXL_9-qLtK67kYwFLHaMUUmZaiDKQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<br />
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span lang="PT-BR" style="color: #111111;"><span style="font-family: Verdana, sans-serif;">Archivos de código asociados a esta entrada:</span></span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"> PIC: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/pulse_monitor2.c">pulse_monitor2.c</a></span><span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"> </span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"> MATLAB: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/heart_monitor.m">heart_monitor.m</a></span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<span style="color: #111111; font-family: Verdana, sans-serif; line-height: 10pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
</div>
<a name='more'></a><br />
<br />
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
<br /></div>
<h3>
<b><u><span style="color: #111111; font-family: Verdana;">Hardware (TSL235R):</span></u></b></h3>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOEfV10s-duTfbJBgDpk4ouno7ct9Xd1MGrT7mZw-Drc9FId8CCLkMGFQlON2EYhDs350qqyiBm9kkjDGTdut3fexgWQivrZkcV03g9Rn_WG5pgmSFyJ8hqfcTAyXa4gTk_LBQ187V/s1600/esquema_tsl235_bis.JPG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOEfV10s-duTfbJBgDpk4ouno7ct9Xd1MGrT7mZw-Drc9FId8CCLkMGFQlON2EYhDs350qqyiBm9kkjDGTdut3fexgWQivrZkcV03g9Rn_WG5pgmSFyJ8hqfcTAyXa4gTk_LBQ187V/s320/esquema_tsl235_bis.JPG" width="320" /></a><span style="color: #111111; font-family: Verdana;">Vamos a usar el mismo sensor de luz (TSL235R)
que presentamos en la entrada anterior. Entonces usábamos el modo
CAPTURE para medir la duración de un periodo (frecuencia instantánea). En este proyecto, para evitar los efectos de aliasing que vimos
entonces vamos a usar el otro enfoque. En vez de medir la duración de un
periodo, vamos a contar el número de pulsos en recibidos en un intervalo más
grande. Obtendremos así la frecuencia media y por lo tanto la luminosidad media
durante el intervalo. </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">Para
contar los pulsos usaremos la interrupción INT0 (igual que con los codificadores
en cuadratura). Para poder usar INTO conectaremos la salida del sensor al pin
RB0 (ver figura).</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk9vYOSvHoCHasc7pssh9VZWzXwzLx6zrCM8zoE15eO6kVcI7bPTZs_UDHiV-SBbZLnzeIc5IZGe_xQ83WZdtRQ4sPNUJt7abml4VF9PyGQ3B8qjjx9xo9dRtLnV4QrwGj2bUqPLj1/s1600/dedo_3.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk9vYOSvHoCHasc7pssh9VZWzXwzLx6zrCM8zoE15eO6kVcI7bPTZs_UDHiV-SBbZLnzeIc5IZGe_xQ83WZdtRQ4sPNUJt7abml4VF9PyGQ3B8qjjx9xo9dRtLnV4QrwGj2bUqPLj1/s200/dedo_3.jpg" width="160" /></a><span style="color: #111111; font-family: Verdana;">Respecto
a la configuración LUZ / DEDO / SENSOR, he decidido no usar un LED sino la fuente
de luz (natural o artificial) de la habitación (ver figura adjunta). Obviamente esto requiere
que haya suficiente luz ambiente para que llegue algo de luz al sensor.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">La
opción del LED es preferible si se desea construir un dispositivo (por ejemplo
para fijarlo en un dedo) y que no dependa del nivel de luz ambiente. La ventaja
de mi enfoque es simplemente que es más sencillo de usar en las pruebas: basta
tapar el sensor (colocado plano sobre una breadboard) con el dedo.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 10.0pt;">
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">De todas
formas, de cara al software, ambas configuraciones pueden usarse de forma
similar.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<h3>
<u><span style="color: #111111; font-family: Verdana;"><b>Software:</b></span></u></h3>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Como hemos descrito el hardware empleado se reduce al sensor, por lo que el grueso del trabajo recaerá en el programa.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En
primer lugar debemos contar con una ISR para la interrupción INT0 que se
incremente cada vez que se reciba un pulso:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">uint16 pulsos=0; </span><span style="color: forestgreen; font-family: 'Courier New';">// Pulse
counter</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; border: none; line-height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// High priority
interruption </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New';"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (INT0_flag)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> pulsos++;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> INT0_flag=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Code @ 0x0008 ->
Jump to ISR for high priority ints</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New';"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_interrupt (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">){_asm </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">goto</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_ISR _endasm}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: 'Courier New';">#pragma</span><span style="font-family: 'Courier New';"> code</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">La
variable pulsos (uint16) acumula los pulsos recibidos. Cada cierto tiempo (usando
timer TMR3) consulto el número de pulsos recibidos. Programaré el contador del
timer TMR3 para saltar cada 50 milisegundos. La elección de dicho espaciado se
basa en varios criterios:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">1.<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">Como la frecuencia máxima del sensor es de 1 MHz podríamos
llegar a tener un máximo de 50000 pulsos durante esos 50 msec. Eso asegura que
el contador de pulsos no se desborda.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 21.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">2.<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">Un periodo de 50 mseg es un tiempo suficientemente largo para no
ver efectos de aliasing si usamos luz artificial. Estamos midiendo la "luz
media" durante 5 ciclos de encendido-apagado.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 21.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">3.<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">Un espaciado de 50 msec corresponde a una frecuencia de muestreo
de (1000/50) 20 muestras por segundo. Valores "normales" del ritmo
cardíaco oscilan entre 30 y 150 pulsaciones por minuto. Dividiendo por 60 (pulsaciones
por segundo) corresponden a un rango entre 0.5 y 2.5 Hz. Una frecuencia de
muestreo de 20 Hz es más que suficiente para captarlas adecuadamente.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En la
interrupción del TMR3 consultamos el número de pulsos recibidos y reseteamos el
contador. El número de pulsos recibidos constituye nuestra medida del sensor. A partir de ahí pasamos a procesar los datos.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
</div>
<h4>
<span style="color: #111111; font-family: Verdana;"> </span><b style="line-height: 12pt;"><u><span style="color: #111111; font-family: Verdana;">Procesado de señal:</span></u></b></h4>
<div>
<b style="line-height: 12pt;"><u><span style="color: #111111; font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Nuestro objetivo en el proyecto es detectar y medir una oscilación regular con una frecuencia de entre 0.5 y 3 Hz
(si tu pulso está por debajo de 30 ppm o por encima de 180 ppm deberías hacertelo
mirar).<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">La señal
medida (luz transmitida a través del dedo) además de esa oscilación fundamental
tendrá otras componentes:</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
</div>
<ul>
<li><span style="color: #111111; font-family: Verdana; line-height: 12pt;">frecuencias bajas, oscilaciones lentas del
nivel de luz, tal vez causadas por un pequeño movimiento del dedo) </span></li>
<li><span style="color: #111111; font-family: Verdana; line-height: 12pt;">frecuencias más altas (ruido en la medida del sensor).</span></li>
</ul>
<br />
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Para
mejorar los resultados posteriores vamos a hacer un preproceso inicial de los datos,
consistente en un filtrado paso-banda, ajustado para tratar de eliminar
frecuencias fuera de la zona de interés (0.5-3 Hz = 30-180 ppm). <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Por
simplicidad se ha implementado con un filtro FIR (Finite Impulse Response) con
coeficientes enteros. Esencialmente un filtro FIR consiste en que la salida
y[n] es combinación de unas cuantas entradas anteriores. En este caso he usado las
8 entradas anteriores:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="PT-BR" style="color: #111111; font-family: Verdana;"> y[n] = sum_k {b(k) x[n-k]} k=0,1,...,7<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Los coeficientes
usados son b(k) = {1 2 2 1 -1 -2 -2 -1}. Por eficiencia (para poder usar
aritmética entera) hemos usado coeficientes enteros. De todas formas, la
función de transferencia de este filtro se corresponde bastante con lo que
quiero:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuMdRi9-b7m-Z0L68hVR7TYTwcIThdHdexWDUA-qPZu55DOqCHhqj8XnaTFeFBa7UvVjyL0WldDZx5Qfd-EF7uEVZokyVPvyq7ExvtMGAs5t1VZCcIZRKQ9f6ONKymqEQhsw5Rh31W/s1600/paso_banda.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuMdRi9-b7m-Z0L68hVR7TYTwcIThdHdexWDUA-qPZu55DOqCHhqj8XnaTFeFBa7UvVjyL0WldDZx5Qfd-EF7uEVZokyVPvyq7ExvtMGAs5t1VZCcIZRKQ9f6ONKymqEQhsw5Rh31W/s400/paso_banda.jpg" width="400" /></a></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">Se
observa que en el intervalo [1,3] Hz = [60,180] ppm la atenuación es pequeña. Por
el contrario, frecuencias fuera de esa banda son notablemente atenuadas.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Para
implementar el filtrado anterior en el PIC uso un buffer circular last_x[], con
las últimas 8 medidas. En cada paso combino los resultados del buffer para
obtener la salida y[n]<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-size: x-small;"><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//
Band-pass filtering b(k) = [1 2 2 1 -1 -2 -2 -1]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> next_x++; next_x&=7; last_x[next_x]=res;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x+1; p&=7; res-=last_x[p];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x-1; p&=7; res+=(last_x[p]<<1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x+2; p&=7; res-=(last_x[p]<<1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x-2; p&=7; res+=(last_x[p]<<1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x+3; p&=7; res-=(last_x[p]<<1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x-3; p&=7; res+=last_x[p];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> p=next_x+4; p&=7; res-=last_x[p];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Al final
en la variable res está el valor de la salida y[n]. En la figura adjunta se
muestran ambas señales (x[n] e y[n]) tomadas durante un periodo de 8 segundos:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl6f5FZQmQ45ge-3M_ZsXmY3Aad-eVNVaqvJuEj1nZaun2E-JY72r0f449UDg5cdTustSn1XDkiqGK2VRIxfVZ_3J1h8n3fM9G4fgGgOqLkGip8w7yVCDeHY1HqO2Cm0jxZXlt8zvs/s1600/filtrado.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl6f5FZQmQ45ge-3M_ZsXmY3Aad-eVNVaqvJuEj1nZaun2E-JY72r0f449UDg5cdTustSn1XDkiqGK2VRIxfVZ_3J1h8n3fM9G4fgGgOqLkGip8w7yVCDeHY1HqO2Cm0jxZXlt8zvs/s400/filtrado.jpg" width="400" /></a></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En la
parte de arriba tenemos los datos obtenidos directamente del sensor (x[n]). Se
observa la oscilación principal (unos 8 ciclos en esos 8 segundos), pero
también la contaminación con oscilaciones lentas de luz (caída) más un ruido de
alta frecuencia (pequeños picos).<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En la
parte de abajo tenemos la salida del filtro paso-banda, y[n]. La oscilación en
la que estamos interesados queda claramente resaltada. Sobre esta señal será
mucho más sencillo medir la duración de un periodo.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<b><u><span style="color: #111111; font-family: Verdana;">Detección del ritmo cardíaco<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Si
mandamos los datos (filtrados) al PC sería fácil en MATLAB (analizando cierto
número de muestras) detectar la frecuencia predominante. Por ejemplo podríamos
usar análisis de Fourier, a través de la conocida FFT (Fast Fourier Transform).
<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Sin
embargo estoy interesado en que sea el PIC quien haga los cálculos. Aunque
sería posible programar una FFT en el PIC, veremos que no es necesario, ya que
puede hacerse de una forma más sencilla de programar y computacionalmente menos
costosa.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En este
proyecto voy a usar la auto-correlación. La auto-correlación de una señal (o correlación consigo misma) se define como:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"> C[n] =
sum_k {y[k] y[k-n]}<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">C[n]
mide la similitud de las muestras de una señal separadas por n muestras. La
idea es que si y[k] e y[k-n] son similares su producto será siempre positivo (+
x + o – x - = +) y la suma de dichos valores tenderá a ser alta. Si y[k] e
y[k-n] no están relacionadas, su
producto será unas veces positivo y otras negativo y su suma tenderá a
cancelarse.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600"
o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f"
stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
left:0;text-align:left;margin-left:3.6pt;margin-top:7.75pt;width:210.6pt;
height:147.6pt;z-index:1'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJMoJ5_y4lGQWWWsXRPLG2NHBz-acnIFOeMglFpo3MQ50YBrcJVyyiqXkQ3z0nTapGeXOp61dTy6ulPNc2D-PH3IoUs_g6WKDVxAfIlwti4zaFyZorfLKTgtRu04xYMBTv0ZYUHu_g/s1600/corr.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJMoJ5_y4lGQWWWsXRPLG2NHBz-acnIFOeMglFpo3MQ50YBrcJVyyiqXkQ3z0nTapGeXOp61dTy6ulPNc2D-PH3IoUs_g6WKDVxAfIlwti4zaFyZorfLKTgtRu04xYMBTv0ZYUHu_g/s320/corr.jpg" width="320" /></a><span style="color: #111111; font-family: Verdana;">En la imagen adjunta tenemos la señal recogida
por el sensor y su autocorrelación (abajo) desde n=0 hasta n=100. <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">El máximo
de la autocorrelación lo encontramos para n=0, ya que nada se parece más a una
señal que ella misma. En el caso de señales cuasi-periódicas como las que nos ocupan, también
encontraremos un máximo (un poco menor) para n = T (periodo de la señal). La idea es que pasadas T muestras la
señal se repite.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">En este caso se puede observar que T es del orden de 18-19 muestras.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">Hay que
tener en cuenta que la correlación también muestra máximos en 2T, 3T, etc. Tendremos que tener
cuidado con esto.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Para
calcular la autocorrelación necesito guardar unas cuantas muestras del pasado y[k-n],
para "comparar" con la muestra más reciente y[n]. Iré guardando en un buffer las muestras
obtenidas. En cada paso descartaré la más antigua y guardaré la más reciente,
teniendo siempre disponibles los N últimos valores:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El
tamaño de este buffer debe ser el suficiente para capturar la correlación del T
más grande en el que pudiera estar interesado. He usado N_past=32 muestras que
permiten detectar una correlación con T = 32 muestras = 32/20 = 1.6 sec. Esto corresponde a f = 1/1.6 = 0.625 Hz = 37 ppm.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Esta
vez, en vez de un buffer circular uso un buffer de desplazamiento. A cada paso
corro las N-1 muestras y hago hueco para guradar la última recibida en la
posición [0]:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(p=N_past;p>=1;p--) past[p]=past[p-1]; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//
shift buffer</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">past[0]=res; </span><span style="color: forestgreen; font-family: 'Courier New';">// last sample</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Esto es
poco eficaz, pero al ritmo de muestras recibidas (20 por segundo) no tengo
problemas. La ventaja es que, al no ser circular, será más fácil (más legible
en el código) direccionar las muestras pasadas:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"> past[0] = y[k] (última) past[1]=y[k-1] , . . . , past[n]=y[k-n]<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<b><u><span style="color: #111111; font-family: Verdana;">Busqueda inicial:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En un
primer momento (fase de búsqueda) no tenemos ni idea de nuestro ritmo cardíaco,
por lo que debemos calcular todas las correlaciones en un cierto margen. Los
resultados se guardan en la variable corr[]. <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Debo
decidir que rango de correlaciones (n) debo calcular. No necesito calcular
correlaciones muy próximas porque no me interesa el máximo que se que existe
para n=0. He decidido buscar entre n=5 y
n=30 muestras, correspondientes a ritmos entre 240 ppm (T=5/20) y 40 ppm
(T=30/20). <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En el
programa un par de #defines determinan esta elección:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-size: x-small;"><span style="color: forestgreen; font-family: 'Courier New';">// Mem for complete correlation lag=delta,delta+1, ...,
delta+N_lag-1</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: 'Courier New';">#define</span><span style="font-family: 'Courier New';"> N_lag 25</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: 'Courier New';">#define</span><span style="font-family: 'Courier New';"> delta 5</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">int16
corr[N_lag]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">N_lag
indica el número de correlaciones a estimar (25) y delta el punto de inicio (5)<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Si tu
pulso está por debajo de 40 ppm deberías extender el tamaño de Na (p.e a 30). Si
está por encima de 240 deberías acudir a un hospital (y solo después, disminuir
delta).<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Durante
un cierto número de muestras (N_corr=30) se van acumulando en corr[] los
valores de la auto-correlación. Al cumplirse el tiempo, una bandera
(corr_ready) se pone a 1 para indicar al programa principal que las
correlaciones ya están calculadas.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: forestgreen; font-family: 'Courier New';">// Accumulate correlations</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"><span lang="EN-GB" style="color: blue;">for</span><span lang="EN-GB">(i=0,p=delta;i<N_lag;i++,p++) corr[i]+= (res*past[p]); </span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"><span lang="EN-GB"><br /></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (n_sample==NT_corr) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="FR" style="font-family: 'Courier New';">{</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';"> T
= center; T*=FRAC_SCALE; T+=frac; </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="color: #b28c00; font-family: 'Courier New';">#ifdef</span><span lang="FR" style="font-family: 'Courier New';"> MATLAB_MODE</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';"> send_msg(T,254); </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: 'Courier New';">#endif</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> n_sample=0;
corr_ready=1;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 18.0pt; text-align: justify;">
<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 18.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Verdana;">En este código:</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">1. </span><span style="color: #111111; font-family: Verdana;">Se calculan las correlaciones desde p=delta a delta+N_lag sumando
y[n]*y[n-p] a los correladores.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; margin-left: 54pt; text-align: justify; text-indent: -18pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana; line-height: 12pt;">2.</span><span style="color: #111111;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">Cuando llevamos acumuladas NT_corr (por defecto 30) muestras,
ponemos corr_ready a 1, para indicar que la correlación está lista y podemos
pasar a calcular su máximo, etc. (en programa principal). En su caso, también enviamos el
periodo hallado al PC a través del puerto serie. <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En el
programa principal, si las correlaciones están listas pasamos a buscar su
máximo y a tomar algunas decisiones:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (corr_ready==1) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> { </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> M=find_max(); cont++;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> ( (M>0) && (abs8(M-last_max)<=1))
aciertos++; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> last_max=M;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';">(M>0) center=M+delta; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> center=0; frac=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (cont==3)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (aciertos==3) tracking=1; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> cont=0; aciertos=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> } <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> corr_ready=0; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<N_lag;k++)
corr[k]=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">}
</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El
código anterior realiza las siguientes funciones:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">1.<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">Halla el máximo más cercano a cero de las correlaciones y (caso
de encontrarlo) lo guarda en la variable center. Si no lo encuentra devuelve 0.
Un máximo se define como un punto que supera un cierto umbral y que es mayor
que sus 4 vecinos (dos a cada lado)<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 18.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">2.<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">Se verifica si el máximo encontrado no se ha movido mucho respecto
al anterior (aciertos++). Si eso pasa varias veces seguidas, confiamos en que
hemos encontrado un un pico de correlación fiable. En ese caso se declara
tracking=1 y entramos en la fase de tracking.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 18.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Verdana;">3.<span style="font-family: 'Times New Roman'; line-height: normal;"> S</span></span><span style="color: #111111; font-family: Verdana;">e pone corr_ready a 0 y se resetean las correlaciones para
volver a calcularlas.<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; font-size: 9.0pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; font-size: 9.0pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<b><u><span style="color: #111111; font-family: Verdana;">Tracking:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Si
sistemáticamente encontramos el máximo de correlaciones en la misma muestra
pasamos a la siguiente fase: el seguimiento fino o tracking. La idea es que
partimos de una buena idea inicial para el periodo T (el valor estimado en la
fase de búsqueda). La precisión de esta aproximación es de aproximadamente 1
muestra.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Imaginad
una situación con un pulso de 80 ppm. Para esa frecuencia el periodo es de 0.75
segundos, o lo que es lo mismo, 15 muestras. En ese caso el error causado por 1
muestra correspondería a <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="FR" style="color: #111111; font-family: Verdana;">T = 14 -> f = 85.7 ppm
<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="FR" style="color: #111111; font-family: Verdana;">T = 16 -> f = 75
ppm <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Tenemos
saltos del orden de 5 ppm en la estimación del ritmo cardíaco, lo que
claramente es mucho.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El
objetivo en esta fase de tracking es mejorar la estimación del ritmo cardíaco y
permitir un rápido seguimiento de posibles cambios.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El
sistema que vamos a usar y que describo a continuación es similar al usado en
un receptor GPS cuando está midiendo la distancia a los satélites.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En esta
fase se calcularan únicamente tres correlaciones (durante NT_track= unas 10
muestras):<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">corr[0], correspondiente al periodo ideal T <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana;">corr[1] y corr[2], correspondiente a T+1 y T-1 muestras
respectivamente.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600"
o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f"
stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
left:0;text-align:left;margin-left:-5.4pt;margin-top:8.35pt;width:137.4pt;
height:123pt;z-index:1'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidNXm5MF5ZM7HAY1f4o0Upp0OmTtQ8yHry2QlyfjDJj369j5R3o4kx45DFLlYUOrPa21TQbzQSvxHGswHTUY5z8SoBiOOYbgwPPMkm9JzQiID8gjitF6zCeQK1jkQp8XpdzGce48xF/s1600/maximo_corr.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidNXm5MF5ZM7HAY1f4o0Upp0OmTtQ8yHry2QlyfjDJj369j5R3o4kx45DFLlYUOrPa21TQbzQSvxHGswHTUY5z8SoBiOOYbgwPPMkm9JzQiID8gjitF6zCeQK1jkQp8XpdzGce48xF/s1600/maximo_corr.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidNXm5MF5ZM7HAY1f4o0Upp0OmTtQ8yHry2QlyfjDJj369j5R3o4kx45DFLlYUOrPa21TQbzQSvxHGswHTUY5z8SoBiOOYbgwPPMkm9JzQiID8gjitF6zCeQK1jkQp8XpdzGce48xF/s1600/maximo_corr.jpg" /></a><span style="color: #111111; font-family: Verdana;"></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="line-height: 12pt;">La idea es que si la correlación
máxima se da en T los valores de correlación en T-1 y T+1 deberían ser iguales. </span></div>
<br />
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En la gráfica adjunta se ve que el máximo está en T=18. Se aprecia que los valores de
correlación en T-1=17 y T+1=19 son muy parecidos entre sí, lo que indica que
T=18 es una buena estimación del máximo. <o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">Sin
embargo, si nos fijamos con cuidado vemos que corr[17] un poco mayor que
corr[19], indicando que el máximo de correlación deberíamos moverlo un poco a la
izquierda. </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">La idea es que si las
correlaciones en T-1 y T+1 no son iguales, moveremos ligeramente el periodo
ideal T hacia el lado que muestra una correlación mayor que el otro.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En
principio podría parecer que mover T supondría añadir o restar una muestra. Sin
embargo, como queremos tener más precisión que la que nos da 1 muestra, vamos a
permitir que T tome valores fraccionarios. El valor de T se codificará con dos
variables de tipo uint8. L</span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">a primera (center) contendrá la parte entera y la segunda (frac) la parte fraccionaria (escalada por un factor FRAC_SCALE=32). </span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">Por ejemplo, si </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">center=17 y frac = 7 el periodo de correlación
es:</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"> T = center + (frac/32) = 17 + 7/32 = 17.22
muestras<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Con este
enfoque la precisión con la que podemos especificar el periodo es de 1/FRAC_SCALE = 1/32 muestras, lo que (para un T del orden de 15)
no da una precisión de unos 0.2 ppm, más que suficiente en nuestra
aplicación.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Al usar
valores de T no enteros nos surge otro problema. Para calcular la correlación
tendría que comparar la muestra recibida y[k] con p.e. y[k-17.22]. Obviamente
yo no puedo preguntar por past[17.22]. La solución es usar una simple
interpolación lineal y estimar past[17.22] en función de past[17] y past[18]. </span><span lang="EN-GB" style="color: #111111; font-family: Verdana;">De forma general:<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="EN-GB" style="color: #111111; font-family: Verdana;">y[n-T]=past[T]= past[center+frac/32]</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="EN-GB" style="color: #111111; font-family: Verdana;"> </span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="EN-GB" style="color: #111111; font-family: Verdana;"> = past[center]*(1-frac/32)
+ past[center+1](frac/32) </span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="EN-GB" style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span lang="EN-GB" style="color: #111111; font-family: Verdana;"> =</span><span style="color: #111111; font-family: Verdana; line-height: 12pt;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">( past[center]*(32-frac)
+</span><span style="color: #111111; font-family: Verdana; line-height: 12pt;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">past[center+1]*frac )/32</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">De esta
forma podemos hacer los cálculos en aritmética
entera.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">La
función interp_past interpola el array past[] para el retraso T determinado por
(center,frac):<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Interpolates data @
c+f/FRAC_SCALE using past[c] y past[c+1]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">int16 interp_past(uint8
c,uint8 f)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> int16 temp;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> temp=past[c]*(FRAC_SCALE-f)+past[c+1]*f;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> temp/=FRAC_SCALE;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> temp; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El
código, dentro de la interrupción del timer, para el caso de que tracking=1 es:<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">corr[0]+=
res*interp_past(center,frac);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">corr[1]+=
res*interp_past(center+1,frac);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">corr[2]+=
res*interp_past(center-1,frac);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Steers tracking
based on acums</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(n_sample==NT_track) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> tracking=steer_tracking();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> n_sample=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Se
calculan las tres correlaciones y cada cierto tiempo (NT_track muestras) se
usan para modificar la estimación del máximo de correlación T (que está codificado
en center + frac). La función steer_tracking se encarga de ello:<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">uint8 steer_tracking(</span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">void</span><span style="font-family: 'Courier New'; font-size: 9pt;">)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">{</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR;">float</span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> c;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint8
res=1;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> int16
T;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> c = (abs16(corr[1])+ abs16(corr[2])); </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (c==0) res=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> c = (corr[1]-corr[2])/c; c*=FACTOR_STEERING;
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (c>0) c+=0.5; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(c<0) c-=0.5; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Rounding</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac+=(int8)c;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> T=(int16)c; send_msg(T,250); </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">send_msg(corr[0],0);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_msg(corr[1],1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">send_msg(corr[2],2);</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR;">while</span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">(frac>=FRAC_SCALE) { frac-=FRAC_SCALE;
center++; }</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR;">while</span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">(frac<0)
{ frac+=FRAC_SCALE; center--; }</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (
(center>=N_lag) || (center<8) ) res=0;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Lost tracking</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// checks
if tracking is able to follow changes</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ( (corr[0]>corr[1]) &&
(corr[0]>corr[2]) ) bad=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> bad++; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> PORTD=bad;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//if (bad==6) res=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> corr[0]=0;corr[1]=0;corr[2]=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Reset acums</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">La corrección
usada es: </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;"> </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">(corr(T+1)
– corr(T-1))/(|corr(T+1)|+ |corr(T-1)|).</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Este
valor está normalizado entre [-1 1] y se multiplica por FACTOR_STEERING para
obtener el cambio que aplicaremos a la parte fraccionaria del periodo (frac).
FACTOR_STEERING es un #define que marca el máximo cambio que es capaz de hacer
el algoritmo sobre frac (estamos usando un valor 8).</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Dentro
de la función también comprobamos si hay problemas para seguir la señal. La
función devuelve 0 si detecta que se ha perdido el tracking. En ese caso se
vuelve a la fase anterior de búsqueda, basada en encontrar máximo de la función
de correlación.<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<br /></div>
<h4>
<u><span style="font-family: Verdana;">Resultados:</span></u></h4>
<div>
<u><span style="font-family: Verdana;"><br /></span></u></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Como en proyectos
anteriores los datos se comunican al PC a través del puerto serie. </span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Se puede
elegir entre una interfaz de texto (</span><span style="color: #b28c00; font-family: 'Courier New';">#define</span><span style="font-family: 'Courier New';"> TEXT_MODE</span><span style="color: #111111; font-family: Verdana;">) o a través de un
programa de MATLAB (</span><span style="color: #b28c00; font-family: 'Courier New';">#define</span><span style="font-family: 'Courier New';"> MATLAB_MODE</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";">)</span><span style="font-family: Verdana, sans-serif;">para visualizar datos<span style="color: #111111;">.</span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En el modo texto
simplemente se vuelca el status (NO DATA, SEARCH o TRACK) y en caso de tener
datos la estimación del ritmo cardíaco. El modo NO DATA se define cuando los
valores (número de pulsos) recibidos por el sensor son demasiado altos,
indicando que no hay un dedo encima del sensor:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;"> </span><span style="color: #111111; font-family: Verdana; font-size: 9pt;"> </span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 9pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (res>1000)
res=last_x[next_x]; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 9pt;">// Way too much light: no finger placed on sensor</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Si intentáis hacer este proyecto, dependiendo del nivel de luz con el que esteis trabajando, tendréis que modificar ese valor.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El video final muestra los resultados finales del proyecto usando la interfaz de MATLAB (heart_monitor.m) para
visualizar los datos:<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: #111111; font-family: Verdana; font-size: 9.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/gIDi1aC5kWI?feature=player_embedded' frameborder='0'></iframe></div>
<div class="MsoNormal">
<span style="color: #111111; font-family: Verdana; font-size: 9.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="color: #111111; font-family: Verdana; font-size: 9.0pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">De nuevo, resaltar que el programa MATLAB solo se ocupa de presentar de una forma más vistosa los datos, status y resultados del proceso. Todos los cálculos se hacen en el PIC y podríamos configurarlo como un sistema autónomo volcando los resultados a través de un LCD.</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com7tag:blogger.com,1999:blog-4945680608471335280.post-55502701897556604252013-08-28T13:21:00.002+02:002013-08-28T13:21:21.086+02:00Vuelta de vacaciones He vuelto hoy de vacaciones y me he encontrado con un montón de comentarios nuevos. Desde mi perspectiva norte-céntrica pensaba que agosto sería un mes muy tranquilo, pero veo que no.<br />
<br />
Intentare ponerme al día en los próximos días.<br />
<br />
Un saludo, Antonio.Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com2tag:blogger.com,1999:blog-4945680608471335280.post-74705659976404169222013-07-03T16:18:00.001+02:002013-07-03T16:18:35.383+02:00Aplicación modo CAPTURA: sensor TSL235<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;">En la entrada anterior describimos la funcionalidad del </span><a href="http://picfernalia.blogspot.com.es/2013/07/modo-de-captura-en-el-modulo-ccp.html" style="font-family: Verdana;">modo Captura del módulo CCP</a>.<span style="color: #111111; font-family: Verdana;"> En esta entrada usaremos dicha funcionalidad en una sencilla aplicación. </span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">Vamos a usar el sensor TSL235, que es un medidor de intensidad de luz. Al contrario que otros sensores, cuya salida es un voltaje proporcional a la irradianza recibida, la salida de este sensor es una onda cuadrada, cuya frecuencia es proporcional a la magnitud (luz) medida. </span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111;"><span style="font-family: Verdana;">Usando el módulo de CAPTURA mediremos el periodo de los pulsos emitidos. </span><span style="font-family: Verdana, sans-serif;">A partir de dicho periodo será sencillo deducir su frecuencia y de ahí la irradianza (en W/m2) recibida.</span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Como en entradas anteriores, los datos recibidos se mandan al puerto serie del PC donde usamos un programa MATLAB para ver los resultados.</span></div>
<br />
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span lang="PT-BR" style="color: #111111; font-family: Verdana;">Archivos de código asociados a esta entrada: </span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span><span style="color: #111111; font-family: Verdana;"><span lang="PT-BR" style="color: #ff3700; mso-ansi-language: PT-BR;"> Código para PIC <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/tsl235.c">tls235.c</a> </span></span><br />
<span style="color: #111111; font-family: Verdana;"><span lang="PT-BR" style="color: #ff3700; mso-ansi-language: PT-BR;"><br /></span></span><span style="color: #111111; font-family: Verdana;"><span lang="PT-BR" style="color: #ff3700; mso-ansi-language: PT-BR;"> Programa MATLAB </span></span><span lang="PT-BR" style="color: #111111; font-family: Verdana;"><o:p></o:p></span><span style="color: #111111; font-family: Verdana; line-height: 10pt;"> </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/flicker.m" style="font-family: Verdana; line-height: 10pt;">flicker.m</a><span style="color: #111111; font-family: Verdana; line-height: 10pt;"> </span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;">--------------------------------------------------------------------------------------------</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;"></span></div>
<a name='more'></a><b><u><span style="color: #111111; font-family: Verdana;"><br /></span></u></b>
<h3>
<b><u><span style="color: #111111; font-family: Verdana;">Hardware: (TSL235R)</span></u></b></h3>
<div>
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span>
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">El TSL235R de TAOS (Texas Advanced Optoelectronic Solutions) es un pequeño conversor de luz a frecuencia. Se alimenta entre 3 y 5V y por su pin de salida saca una onda cuadrada con una frecuencia proporcional a la luz (formalmente irradianza en W/m2) que está recibiendo el sensor.</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div class="MsoNormal" style="line-height: 12pt;">
<br /></div>
<div class="MsoNormal" style="line-height: 12pt;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">Yo lo adquirí en </span><span style="font-family: Verdana; line-height: 12pt;"><a href="https://www.sparkfun.com/products/9768">https://www.sparkfun.com/products/9768</a> por unos $3, aunque supongo que se puede conseguir en otros muchos sitios.</span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN1ZpF2Gbct7h9Olo6H_mu7VBMztbKWTgcVx6t1eqqM5HklKESM0_6G1OvRvBz_6T7VAp-AdODdw-e1Q1JgdK0IAbr7qVpCvsXm26IDY0nQLNhWZqqroqvWGJD-bUMdtRBxP33BmS4/s1600/pines_tsl235.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN1ZpF2Gbct7h9Olo6H_mu7VBMztbKWTgcVx6t1eqqM5HklKESM0_6G1OvRvBz_6T7VAp-AdODdw-e1Q1JgdK0IAbr7qVpCvsXm26IDY0nQLNhWZqqroqvWGJD-bUMdtRBxP33BmS4/s200/pines_tsl235.jpg" width="100" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji5b_hrMO9wP8-WkA5_88Lwa20zKveRLamUIBJstSeQaL0mBmQaU9ZdCpS_ugIYn9KI5szsfDomSngkbg6HwE3Zwp1-xdQWp_28_ZgIKevpR1a8xzPg7J5828UJamrE0DzQwgZBwpW/s1600/tama%C3%B1o_tsl.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji5b_hrMO9wP8-WkA5_88Lwa20zKveRLamUIBJstSeQaL0mBmQaU9ZdCpS_ugIYn9KI5szsfDomSngkbg6HwE3Zwp1-xdQWp_28_ZgIKevpR1a8xzPg7J5828UJamrE0DzQwgZBwpW/s1600/tama%C3%B1o_tsl.jpg" /></a></div>
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">Las ventajas de usar frecuencia como salida en vez de un voltaje proporcional son varias: </span><br />
<span style="color: #111111; font-family: Verdana; line-height: 12pt;"><br /></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<ul>
<li><span style="color: #111111; font-family: Verdana;">Mucho mayor rango posible. El TSL235 da una salida desde 1Hz hasta casi 1MHz (en mi muestra el máximo está por 800 KHz). Eso son 6 ordenes de magnitud. Con un voltaje necesitaríamos un conversor AD de 20 bits (log2(10^6)) para obtener una resolución semejante.</span></li>
<li><span style="color: #111111; font-family: Symbol; line-height: 12pt; text-align: justify;"><span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span><span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;">Además la medida de una frecuencia es mucho más resistente al ruido que la medida de la amplitud de un voltaje (pensad en FM vs AM).</span></li>
</ul>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En el datasheet </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">(</span><span style="font-family: Verdana; line-height: 12pt;"><a href="https://www.sparkfun.com/datasheets/Sensors/Imaging/TSL235R-LF.pdf">https://www.sparkfun.com/datasheets/Sensors/Imaging/TSL235R-LF.pdf</a>) vemos que s<span style="color: #111111;">u respuesta es casi lineal en la mayor parte de su rango usando una escala logarítmica tanto para la frecuencia como para la irradianza:</span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana;"><span style="color: #111111;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2uZ0I1TpDVLjWk4ZmivOL-WUN9a17ECZcqbIF6hsAG-NDUtFpA2gZuntMV92wkDqk3la7-mhcdykWfx9Q_tMpNOGS9HZSzOktN4cVTmzLnDMJMDUMg6buYwPDHVMcHJQadeHEwcvL/s1600/TSL235.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2uZ0I1TpDVLjWk4ZmivOL-WUN9a17ECZcqbIF6hsAG-NDUtFpA2gZuntMV92wkDqk3la7-mhcdykWfx9Q_tMpNOGS9HZSzOktN4cVTmzLnDMJMDUMg6buYwPDHVMcHJQadeHEwcvL/s320/TSL235.jpg" width="295" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana;">De la gráfica adjunta vemos que la irradianza recibida (en uW/cm2 para una luz de 635 nano-metros) coincide casi exactamente con la frecuencia (en kHz) de la onda cuadrada a su salida. Siendo más precisos:<span style="color: #111111;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"> log10(irrad) = 0.9871 log10(f) + 0.1579<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span><span style="color: #111111; font-family: Verdana;"> irrad = 1.4385 f^0.9871, (</span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">f en KHz, irrad en uW/cm2)</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span><span style="color: #111111; font-family: Verdana;">Si lo deseamos podemos convertir uW/cm2 a W/m2 (1W/m2 = 100 uW/cm2).<o:p></o:p></span><br />
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Conectando la salida a un osciloscopio se ve la esperada onda cuadrada cuya frecuencia varia en un rango muy amplio según el nivel de luz:<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">Máxima frecuencia de unos 780 kHz, expuesto directamente a la luz solar.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">Frecuencias del orden de 100-300 kHz en pleno día pero con el sensor en la sombra.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">· </span><span style="color: #111111; font-family: Verdana;">Unos 50 kHz en una habitación, de día, pero con las persianas bajadas.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">Unos 20 Hz si tapo el sensor con una vieja caja de película fotográfica.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">Unos 5 Hz en casi total oscuridad.</span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipc2OGOO8Nbf89ze1DacRB2qwpt54KqyD4zcMsdMNDNVYOh9FGHQnvwDBOuAu3VWsHye-fkR8z3Lv44pY873OL2LlqAaU1VEJxyeCbnRpAhGH2MOX0536dtz4KFFeo1AQ57leBgMvz/s370/esquema_tsl235.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipc2OGOO8Nbf89ze1DacRB2qwpt54KqyD4zcMsdMNDNVYOh9FGHQnvwDBOuAu3VWsHye-fkR8z3Lv44pY873OL2LlqAaU1VEJxyeCbnRpAhGH2MOX0536dtz4KFFeo1AQ57leBgMvz/s320/esquema_tsl235.jpg" width="320" /></a><span style="color: #111111; font-family: Verdana;"></span><br />
<span style="color: #111111; font-family: Verdana; line-height: 12pt;">La conexión al micro es inmediata. Se alimenta con los mismos 5V que el PIC (con un condensador de 0.1 uF entre alimentación y tierra). El pin de salida se conecta al correspondiente pin del micro. La elección del pin a usar dependerá del tipo de medida que vayamos a hacer. Para usarlo en modo CAPTURA (como haremos en este post) usaremos RC2 o RC1. Si por el contrario vamos a contar pulsos usaríamos RB0 y la correspondiente interrupción INT0 como hicimos con los codificadores en cuadratura. </span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br />
<br /></div>
<h3>
<b><u><span style="color: #111111; font-family: Verdana;">Software:</span></u></b><span style="background-color: white; color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;"> </span></h3>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span><span style="color: #111111; font-family: Verdana;">Nuestro objetivo es </span><span style="color: #111111; font-family: Verdana;">medir el periodo de la señal de salida. A partir de ahí calculamos su frecuencia y con la fórmula anterior la irradianza recibida por el sensor en W/m2.</span><br />
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Cuando tratamos de estimar el periodo de una señal cuadrada tenemos dos posibilidades:<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Verdana;">1.<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">Podemos <b>medir la duración de 1 periodo</b> (o unos pocos si son demasiado cortos). De esta forma obtenemos una medida de la <b>frecuencia instantánea</b>, adecuada p.e. para monitorizar una iluminación que cambie rápidamente.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; margin-left: 18pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Verdana;">2.<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">Si estamos midiendo una iluminación que cambia poco o nos interesa una media de la iluminación en un cierto periodo de tiempo podemos <b>contar el número de periodos</b> en un tiempo más largo. Obtendremos así la <b>frecuencia media</b> durante la observación.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El enfoque 2) es el que usamos en el tema de los codificadores en cuadratura. Conectaríamos la salida del sensor al pin RB0 y habilitaríamos la interrupción INT0. Con cada subida de la línea, en el código de la interrupción, se incrementaría un contador que representa el número de pulsos recibidos. Cada cierto tiempo un temporizador nos da el número de periodos recibidos en el intervalo (y de ahí sacamos la frecuencia).<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En esta entrada vamos a usar el enfoque 1), basado en medir la duración de un periodo <b>usando el módulo de captura.</b> Para ello conectaremos la salida del sensor al pin RC2 (asociado al módulo CCP1).<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br />
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<b><span style="color: #111111; font-family: Verdana;">Configuración CCP1 y TMR3:</span></b></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">El código de configuración es prácticamente idéntico al que vimos en la entrada anterior. Programamos T3CON para asociar el timer TMR3 al módulo CCP1 en modo CAPTURA. El timer TMR3 se configura en modo 16 bits con un prescaler 1:2 (con ese prescaler @ 8 MHz, cada incremento del timer equivale a 1 usec). Se habilita el modo CAPTURA y declaramos el pin asociado RC2 como entrada. Finalmente se habilita la correspondiente interrupción:</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div class="MsoNormal" style="background-color: white; line-height: 12pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';"> OpenTimer3(TIMER_INT_OFF&T3_16BIT_RW&T3_SOURCE_INT&T3_PS_1_2&T3_SOURCE_CCP);</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> T3CONbits.T3CCP2=1; T3CONbits.T3CCP1=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// TMR3 as source for both CCP1/CCP2</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> TRISCbits.TRISC2=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// RC2 (CCP1 associated pin) is an input</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> CCP1CON=0b00000110; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Modo CAPTURE. Event = x4 rising edges</span></div>
</div>
<div class="MsoNormal" style="background-color: white; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; line-height: 12pt; text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Como los eventos pueden producirse muy rápido (del orden de 1 usec si hay mucha luz) hemos configurado el módulo de captura en modo 4X (capturamos cada 4º pulso)</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<b><span style="color: #111111; font-family: Verdana, sans-serif;">Interrupción CCP1:</span></b><span style="color: #111111; font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">A partir de ese momento, si el sensor TSL235 está conectado al pin RC2, empezarán a producirse eventos y los correspondientes tiempos del timer TMR3 se capturarán en los registros CCPR1H:CCPR1L. Para que no se sobre-escriban debemos habilitar la correspondiente interrupción:</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> enable_priority_levels;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> CCP1_flag=0; enable_CCP1_int; set_CCP1_high;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: Courier New, Courier, monospace;"> enable_high_ints; enable_low_ints;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana, sans-serif;">Hemos declarado la interrupción CCP1 como de alta prioridad. La razón es que luego añadiremos otra interrupción y queremos que CCP1 se ejecute de forma preferentemente (para no perder eventos).<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="color: #111111;">Una vez que habilitamos la interrupción CCP1 hay que escribir el correspondiente código de la ISR para procesar los tiempos de los eventos antes de que se pierdan. La rutina usada es la misma </span>que el explicado en la entrada anterior. Dos variables externas t0 y dt de tipo uint16 guardan, respectivamente, el tiempo del último evento y la separación entre los dos últimos eventos. La variable dt corresponderá por lo tanto a 4 periodos de la señal del sensor.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">Como comentamos en la anterior entrada, si no llevamos la cuenta de los rebosamientos de TMR3, nuestra medida se verá limitada a un máximo de 65536 usec. Eso equivale a un periodo de 65536/4 = 16384 microsegundos, lo que corresponde a una frecuencia de unos 60 Hz en la señal del sensor.</span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En el código de la interrupción hemos añadido un cambio de status en el pin RC1, cuyo objeto es ver si la interrupción entra correctamente. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En el siguiente pantallazo (izquierda) podemos ver (canal 1 amarillo) el ritmo de la interrupción (cambios en RC1) y en el canal 2 (abajo, azul) la salida directa del sensor. Vemos que la interrupción sucede cada 4 pulsos de la señal como habíamos programado. También se aprecia (en el zoom de la derecha) que la entrada de la interrupción está retrasada unos 10 usec con respecto a la subida del 4º pulso que la causa. Esto es debido a que el PIC tarda unos pocos ciclos en guardar su estado, saltar a la rutina de la interrupción, etc. Sin embargo, esto no afecta a la medida porque aunque la ejecución de la interrupción se retrase el instante correcto del evento quedó correctamente guardado en CCPR1L:CCPR1H.</span><span style="font-family: Verdana; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCf8M1ILdCxHR_MravSCqhnIXzYB4t11KlBImOFt_8ci1DntJNZkxZMHfT-V8mNA6CbdOVGvF9cKLYLisg4LrH1L1gXqUNZmtyZizPzUOPH8RP2F7xJ0vItzhZ6TdkPoroEXJkrnkp/s1600/oscope1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"> <img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCf8M1ILdCxHR_MravSCqhnIXzYB4t11KlBImOFt_8ci1DntJNZkxZMHfT-V8mNA6CbdOVGvF9cKLYLisg4LrH1L1gXqUNZmtyZizPzUOPH8RP2F7xJ0vItzhZ6TdkPoroEXJkrnkp/s200/oscope1.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW6pcdYLjvGjZRA3AvX0BzDVHyG8vdy72lsHmFrm8tFrVc9xl3Wkk4nolQ78ceTMpGw1G3y36oICnTbvohSdxk42RDaA8wEeMRl7dIZTv12XfmVsNW9BmwNaWqqHsI7vGYNFnGT7XN/s1600/oscope2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW6pcdYLjvGjZRA3AvX0BzDVHyG8vdy72lsHmFrm8tFrVc9xl3Wkk4nolQ78ceTMpGw1G3y36oICnTbvohSdxk42RDaA8wEeMRl7dIZTv12XfmVsNW9BmwNaWqqHsI7vGYNFnGT7XN/s200/oscope2.jpg" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<b><span style="color: #111111; font-family: Verdana;">Muestreo y envío de datos:</span></b><span style="color: #111111; font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Con el código de la interrupción nos aseguramos de que en la variable dt (uint16) tengamos siempre disponible el valor más reciente de la medida que nos interesa (en este caso, el tiempo de 4 periodos de la señal del sensor).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Se trata ahora de (cada cierto tiempo) consultar dicho valor y volcarlo por un LCD o puerto serie. Siguiendo con el modelo de entradas anteriores voy a usar el puerto serie y mandar los datos (en binario) para que un programa en MATLAB en el PC se ocupe de recibirlos, convertirlos a frecuencia (o irradianza) y graficarlos.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Para implementar esta parte vamos a usar el timer TMR0 para que nos marque el ritmo de muestreo. Programare el timer para que su interrupción salte cada un cierto intervalo (Ts msec). En la interrupción consultaré el valor de dt y lo escribiré en otra variable, levantando una cierta bandera. Este sería el código de la ISR del TMR0:</span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Low priority interruption</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB"> interruptlow low_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span style="color: blue;">void</span> low_ISR (<span style="color: blue;">void</span>)<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;">{<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> <span style="color: blue;">if</span> (TMR0_flag) <span style="color: forestgreen;">// ISR de la interrupcion de TMR3</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> {<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> set_TMR0(contador);<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> PORTCbits.RC0=~PORTCbits.RC0;<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> contador = 65535-TMR0_delay;<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> data=dt; data_ready=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> TMR0_flag=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span>}<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La variable TMR0_delay va a determinar cada cuanto salta la interrupción y se muestrea el valor dt.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el programa principal configuraré el timer TMR0 y habilitaré su interrupción (como de baja prioridad):<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB">OpenTimer0(TIMER_INT_ON&T0_16BIT&T0_SOURCE_INT&T0_PS_1_2); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 16 bit, Prescaler 1:2</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: Courier New, Courier, monospace;">enable_TMR0_int; set_TMR0_low;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El valor de arranque para TMR0_delay es de 10000, que con un prescaler 1:2 para TMR0 y un reloj de 8 MHz corresponde a un intervalo nominal de muestreo Ts = 10000 usec = 10 msec.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Finalmente, en el programa principal (tras la configuración de timers, módulo CCP, etc. ) entraré en un bucle infinito y consultaré la bandera (data_ready). Si me indica que hay datos que mandar me pondré a ello (tendré que controlar que el tiempo para mandar los datos no exceda el intervalo de muestreo Ts):<span style="font-size: 9pt;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB"> (data_ready==1) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Dump msg with dt and TMR0_delay </span><span lang="EN-GB"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> send_byte(</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'A'</span><span lang="EN-GB">); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Message head<o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> send_byte(ptr[0]); send_byte(ptr[1]); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// send bytes in data (dt)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> data = TMR0_delay;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> send_byte(ptr[0]); send_byte(ptr[1]); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// send bytes in data (TMR0_delay)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> send_byte(msg++); send_byte(</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'Z'</span><span lang="EN-GB">); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Message counter and tail </span><span lang="EN-GB"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> data_ready=0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB"> (DataRdyUSART()) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Modify TMR0_delay through serial port</span><span lang="EN-GB"></span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> ch = getcUSART();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">switch</span><span lang="EN-GB">(ch)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">case</span><span lang="EN-GB"> </span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'+'</span><span lang="EN-GB">: TMR0_delay+=2; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">break</span><span lang="EN-GB">;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">case</span><span lang="EN-GB"> </span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'0'</span><span lang="EN-GB">: TMR0_delay=10000; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">break</span><span lang="EN-GB">;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">case</span><span lang="EN-GB"> </span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'-'</span><span lang="EN-GB">: TMR0_delay-=2; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">break</span><span lang="EN-GB">;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> } <span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> }<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Courier New, Courier, monospace;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La segunda parte del código nos permite aumentar ('+) o disminuir ('-') el </span><span style="font-family: Verdana, sans-serif;">intervalo de muestreo a través del puerto serie.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">Como en otras entradas, el código del PIC se acompaña de un programa MATLAB que recibe los datos capturados por el PIC y se encarga de presentarlos gráficamente, etc.</span></div>
<div class="MsoNormal">
<br />
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<b><u><span style="color: #111111; font-family: Verdana;">Resultados:</span></u></b><span style="color: #111111; font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Veamos algunos resultados del programa bajo diferentes condiciones de iluminación. En primer lugar, un vídeo mostrando la salida del sensor (visualizada desde el PC con el programa MATLAB que acompaña a esta entrada) cuando está iluminado por luz natural:</span><br />
<span style="font-family: Verdana;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxKtMmVOz_4ju0S7yQGEnzVDznAHwQ32oUMnOwwodO1isgfI99t-VXDXvzxrpdWohLfM5a10xyswiY-9huYCw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana;">En el caso de iluminación con luz natural (o con luz artificial "continua", como una linterna) no hay ninguna influencia del periodo de muestreo (alrededor de 10 msec) en la luminosidad recibida, ya que esta no cambia con el tiempo.</span></div>
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">Las cosas son diferentes si registramos la salida del sensor bajo condiciones de luz artificial. Debido a la corriente alterna usada en la red, la iluminación artificial oscila con el ciclo de la red. Idealmente la luz se apagará cada vez que el voltaje pase por el 0 (100 veces por segundo si la frecuencia de la red es de 50 Hz, como en España). Dependiendo del tipo de iluminación el efecto es mayor o menor. La oscilación es más fácil de observar con fluorescentes. Las lámparas incandescente, por su mayor "inercia" (no les da tiempo a enfriarse), muestran un menor efecto.</span><br />
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">La idea es que al ser nuestra medida bastante "instantánea" (en nuestro código estamos midiendo 4 pulsos del sensor, lo que a iluminaciones "normales" se traduce a una fracción de milisegundo) vamos a poder "ver" dichas oscilaciones.</span><br />
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">Esta es la principal diferencia entre un enfoque de medición instantánea (capturando la duración de un pulso) y contar los pulsos producidos durante un intervalo grande de tiempo. Si tomásemos la medida contando los pulsos recibidos en 20 milisegundos obtendríamos una medida <b>media</b> de la luminosidad en un periodo de la red y no podríamos apreciar estos efectos.</span><br />
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">Hemos dicho que el periodo de la iluminación con una luz artificial serán 10 milisegundos (la mitad del periodo del voltaje de la red). Nuestro programa está muestreando cada 10 milisegundos (nominales), ¿qué deberiamos ver?</span><br />
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">La respuesta es que deberíamos ver una iluminación constante. La iluminación cambia continuamente, pero como mi periodo de muestreo coincide con el de cambio de la señal, siempre muestreo en el mismo punto del ciclo, obteniendo el mismo valor.</span><br />
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">Esto se ilustra en la siguiente figura (fila 4). Tenemos (azul) una señal (luminosidad) con un periodo de 10 mseg, que se muestrea (puntos rojos) </span><span style="font-family: Verdana, sans-serif;">cada 10 milisegundos exactamente. Lo que obtenemos es un valor constante, mayor o menor dependiendo de en que parte del ciclo acertemos.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">En la práctica será difícil sincronizar perfectamente nuestro muestreo con los 100 Hz de la iluminación. En ese caso se obtienen las otras situaciones ilustradas en la figura. El punto de muestreo se va corriendo en cada muestra y observamos una oscilación en los resultados. Notad que esa oscilación no está realmente en la señal, es un efecto ("aliasing") de intentar muestrear una señal con un ritmo de muestreo incorrecto (demasiado lento).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWOIecEClZ_utJJ5Nk_gKb4GlM-zIXJVwlnoQLG3vM-HajFNoQ1zBInIE41u06sK4IHPjF_QYctgwL3yXGevHaBGXFwA-tn5noRdywgdkYmolHa7ZHsx4opeJ427fRAfIXlYHFxncx/s1018/ex_alias.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="511" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWOIecEClZ_utJJ5Nk_gKb4GlM-zIXJVwlnoQLG3vM-HajFNoQ1zBInIE41u06sK4IHPjF_QYctgwL3yXGevHaBGXFwA-tn5noRdywgdkYmolHa7ZHsx4opeJ427fRAfIXlYHFxncx/s640/ex_alias.jpg" width="640" /></a></div>
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Estas oscilaciones (rojo) son las que esperamos ver con el programa si exponemos el sensor a luz artificial y muestreamos con una frecuencia del orden de 10 mili-segundos. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">Como el programa permite modificar el retraso (TMR0_delay) entre muestras podemos cambiarlo hasta intentar obtener una salida estable. En ese momento nuestro interrupción de muestreo estará perfectamente sincronizada con la red. Esta situación de equilibrio no durará mucho porque tanto nuestro cristal como la red pueden experimentar una deriva (alejamiento de su frecuencia nominal) que hará que se pierda la sincronización y volvamos a ver una oscilación.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">El siguiente vídeo ilustra este comportamiento:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dx8oGovnS2jCqYS9aIbuGQ3_AFmzCDjFZf7bkd4XgXEicUfCBks6i8JN5G8ZNcb-DuZizx7gKftUEwCc3gWNw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: Verdana, sans-serif;">Este fenómeno de aliasing o "interferencia" entre la frecuencia de una señal y la frecuencia de muestreo puede apreciarse en multitud de situaciones. Es la razón de que podamos ver los radios de una rueda "moviéndose" en dirección contraria al desplazamiento del vehículo. También se usaba en los antiguos discos estroboscópicos para ajustar la velocidad de giro de los tocadiscos, etc.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">En el siguiente video (youtube) podéis ver otro ejemplo de aliasing. El concepto es el mismo que el presentado aquí (muestrear una señal periódica con un periodo de muestreo coincidente con el de la señal para verla estacionaria), pero en este caso el resultado es mucho mas llamativo que nuestras gráficas: </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<br /><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/mODqQvlrgIQ?feature=player_embedded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br /></div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com5tag:blogger.com,1999:blog-4945680608471335280.post-55227726101362689162013-07-03T14:05:00.002+02:002013-07-03T14:05:29.496+02:00Modo de Captura en el módulo CCP <div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;">En una entrada anterior (<a href="http://picfernalia.blogspot.com.es/2012/06/modulacion-pwm-pulse-width-modulation.html">PWM</a>) vimos una de las funcionalidades del módulo CCP. En esta entrada describiremos otra de sus funcionalidades, el modo CAPTURE.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;">Como su nombre indica, este modo se usa para capturar eventos. Los eventos serán bajadas o subidas de los pines correspondientes a CCP1 y CCP2 que son, respectivamente, RC2 y RC1 (este último puede cambiarse por RB3 en la configuración inicial). Para la captura se precisa que un timer este corriendo. Este timer será nuestro "reloj": capturar un evento será grabar la "hora" (contador del timer) en que se ha producido. Los timers usados con el módulo de CAPTURA pueden ser tanto el TMR1 como el TMR3.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;">Podríamos conseguir similares resultados usando las interrupciones INTx que vimos en los codificadores en cuadratura. Cada vez que entre la interrupción podríamos guardar el valor de un timer que este corriendo. La diferencia es que con este enfoque, para cuando "miremos la hora" ya habrá pasado un tiempo (mientras el micro termina lo que esté haciendo, pasa el control a la interrupción, etc.) que puede ser del orden de microsegundos.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;">Por el contrario, si se usa el método de captura, en cuanto se produce el evento se copia el valor del timer usado a los registros CCPRxH:CCPRxL. Por supuesto, será nuestra responsabilidad guardar dicho valor en otra variable antes de que se repita el evento y se machaque con otro valor.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt;">
<span style="color: #111111; font-family: Verdana;">En la entrada explicaremos la configuración del modo de CAPTURA y los registros asociados. En la siguiente entrada usaremos el modo de CAPTURA para leer los datos de un sensor de luz (TSL235) cuya salida en una onda cuadrada de frecuencia variable. </span></div>
<br />
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;">--------------------------------------------------------------------------------------------</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
<span style="color: #111111; font-family: Verdana;"></span></div>
<a name='more'></a><br />
<b><u><span style="color: #111111; font-family: Verdana;">Modo de Captura del módulo CCP:</span></u></b><br />
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div style="text-align: left;">
<span style="color: #111111; font-family: Verdana;">Como siempre, la mejor explicación la encontraréis en los datasheets de Microchip. Aquí presentaré un rápido resumen.<o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div style="text-align: left;">
<br /></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div style="text-align: left;">
<span style="color: #111111; font-family: Verdana;">El modo de Captura es una de las tres funciones posibles que puede desempeñar cada módulo CCP (Capture-Compare-PWM) del PIC. Normalmente hay 2 módulos CCP1 y CCP2 con pines asociados RC2 y RC1 (notad la inversión en la asignación de pines). Es posible dedicar cada módulo CCPx a una función distinta. Uno podría estar en modo CAPTURA (usando TMR1) y el otro en modo PWM (usando TMR2). Incluso usando ambos en modo CAPTURA podríamos usar una base de tiempos distinta en cada módulo.</span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">La siguiente tabla del datasheet muestra las posibilidades de combinación:<o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Uo2BrF55luERZkdo_7S6P1gGDqmUvZys_J6EuzTI9gycIcsDBz-M0DvW5qmVvLXBbty22aYpk3JxhJwDm4UNHLCzQ1xoF1QPStrCfvm51lN0MbC_D9RuwJDbmRAxtUwHWiYMOWE2/s1600/combinaciones.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="325" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Uo2BrF55luERZkdo_7S6P1gGDqmUvZys_J6EuzTI9gycIcsDBz-M0DvW5qmVvLXBbty22aYpk3JxhJwDm4UNHLCzQ1xoF1QPStrCfvm51lN0MbC_D9RuwJDbmRAxtUwHWiYMOWE2/s640/combinaciones.jpg" width="640" /></a></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Cada uno de los módulos CCP tiene asociados varios registros (cambiar la x en lo sucesivo por 1 o 2):<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<b><span style="color: #111111; font-family: Verdana;">CCPxCON</span></b><span style="color: #111111; font-family: Verdana;"><b>:</b> con este registro definiremos el tipo de operación (Capture / Compare / PWM) del módulo. </span><span style="color: #111111; font-family: Verdana;">El valor para seleccionar modo de CAPTURA es: </span><br />
<span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: center;"><br /></span>
<span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: center;">0b 000001xx</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"> <o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Los dos últimos bits configuran el tipo de evento a capturar:<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 92.4pt; mso-list: l1 level1 lfo1; tab-stops: list 92.4pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">00: capturar cada caída de la línea.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 92.4pt; mso-list: l1 level1 lfo1; tab-stops: list 92.4pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">01: capturar cada subida de la línea.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 92.4pt; mso-list: l1 level1 lfo1; tab-stops: list 92.4pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">10: capturar cada 4ª subida de línea.<o:p></o:p></span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 92.4pt; mso-list: l1 level1 lfo1; tab-stops: list 92.4pt; text-align: justify; text-indent: -18.0pt;">
<span style="color: #111111; font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="color: #111111; font-family: Verdana;">11: capturar cada 16º subida de línea.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<b><span lang="PT-BR" style="color: #111111; font-family: Verdana;">CCPRxH,CCPRxL</span></b><span lang="PT-BR" style="color: #111111; font-family: Verdana;"><b>:</b> dos registros de 8 bits. </span><span style="color: #111111; font-family: Verdana;">En el modo captura guardan el valor de un timer (TMR0 o TMR3) corriendo en modo 16 bits en el momento de producirse el evento.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">En el caso del modo captura, también tendremos que configurar ciertos bits especiales del registro del timer TMR3 (<b>T3CON</b>) que seleccionan que timer se asocia al módulo de captura. Es posible configurar ambos módulos en modo captura y aún así usar timers distintos (TMR1 o TMR3) en cada uno de ellos (al contrario que lo que vimos en modo PWM, donde los dos módulos compartían el mismo timer (TMR2).</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br />
<ul>
<li><span style="color: #111111; font-family: Verdana;">T3CON.T3CCP2 : bit 6 de T3CON</span></li>
<li><span style="color: #111111; font-family: Verdana;">T3CON.T3CCP1 : bit 3 de T3CON</span></li>
</ul>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Notad que ambos bits no están consecutivos en T3CON. Valores posibles para estos bits:<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">1x --> TMR3 para ambos módulos<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">01 --> TMR3 usado en CCP2, TMR1 usado en CCP1<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">00 --> TMR1 usado en ambos módulos.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Además de los registros anteriores el modo CAPTURE tiene definida una interrupción, que salta (si esta habilitada) cuando se produzca un evento. Esta interrupción se usa a menudo porque lo que se suele querer medir es la separación entre dos eventos (periodo, ancho de un pulso, etc.). Si no hacemos nada, al suceder el segundo evento, el PIC sobre-escribirá el tiempo del primero. La interrupción nos permite guardar el primer tiempo antes de ser sobrescrito.<o:p></o:p></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Si los eventos se suceden muy rápido (p.e. del orden de 1 usec) podría ser que la interrupción no llegue a tiempo de guardar el 1er valor. En ese caso podemos programar un prescaler (modos 10 o 11 en CCPCON) para definir el evento como 1 de cada 4 o 1 de cada 16. De esta forma también mejoraríamos la calidad de la medida al promediar varios periodos.<o:p></o:p></span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;"><br /></span>
<b><u><span style="color: #111111; font-family: Verdana;">Inicialización módulo CCP y timer asociado</span></u></b></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Veamos un ejemplo de los pasos a realizar para usar el modo CAPTURE. Por ejemplo, para usar CCP1 con TMR3 como timer asociado, debemos:</span></div>
<div class="MsoNormal" style="background: white; line-height: 12.0pt; margin-left: 39.0pt; mso-list: l0 level1 lfo2; tab-stops: list 39.0pt; text-align: justify; text-indent: -18.0pt;">
<ol>
<li><span style="color: #111111; font-family: Symbol; line-height: 12pt; text-align: justify;"><span style="font-family: 'Times New Roman'; line-height: normal;">C</span></span><span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;">onfigurar el timer a usar (TMR3) en modo 16 bits, con el prescaler escogido, definiendo así la base de tiempos a usar.</span></li>
<li><span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;">Arrancar el timer (TMR3) a usar.</span><span style="color: #111111; font-family: Symbol; line-height: 12pt; text-align: justify;"><span style="font-family: 'Times New Roman'; line-height: normal;"> </span></span></li>
<li><span style="color: #111111; font-family: Verdana;">Poner los bits T3CCP2 y T3CCP1 de T3CON a 1 para seleccionar el uso de TMR3 como timer asociado a ambos módulos CCP.</span></li>
<li><span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;">Declarar el pin correspondiente (en este caso RC2, asociado a CCP1) como entrada.</span></li>
<li><span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;">Habilitar el módulo CCP1 en modo CAPTURE con la definición de evento que se desee (1x subida, 1x caída, x4, x16)</span></li>
<li><span style="color: #111111; font-family: Verdana; line-height: 12pt; text-align: justify;">Si vamos a usar la interrupción de CCP1, habilitarla y declararla de alta prioridad (aconsejable pues no queremos "saltarnos" un evento).</span></li>
</ol>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;">Veamos el código para llevar a cabo los pasos anteriores.<o:p></o:p></span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">El timer se pondrá </span><span style="color: #111111; font-family: Verdana; line-height: 12pt;">en marcha en modo 16 bits y se dejará en modo "free-running" sin interferencia alguna (no tocaremos el contador del TMR3). En el proyecto estoy usando un cristal de 8 MHz por lo que el ciclo de instrucción es de ½ microsegundo. Por comodidad usare un PRESCALER 1:2 en el timer TMR3, de forma que cada incremento de su contador representará 1 microsegundo. Sería fácil configurar T3CON por nuestra cuenta, pero en este ejemplo usaremos las funciones de C18:</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';"><span style="color: forestgreen;">// Starts TMR3 using OSC as source, 16bit mode,</span></span><br />
<span lang="FR" style="font-family: 'Courier New';"><span style="color: forestgreen;">// with 1:2 prescaler</span></span><span lang="FR" style="font-family: 'Courier New';"><span style="color: forestgreen;"> (1 usec @ 8 MHz)</span></span><span style="font-family: 'Courier New', Courier, monospace;"> </span><span style="font-family: 'Courier New';">OpenTimer3(TIMER_INT_OFF&T3_16BIT_RW&T3_SOURCE_INT&T3_PS_1_2&T3_SOURCE_CCP);</span><br />
<span style="color: forestgreen; font-family: 'Courier New';">// TMR3 as source for both CCP1/CCP2</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> T3CONbits.T3CCP2=1; T3CONbits.T3CCP1=1; </span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">Aquí creo que hay un bug en C18. Según la documentación hay una máscara (T3_SOURCE_CCP) que si se añadiese al argumento de OpenTimer3, pondría los valores adecuados en los bits T3CCP1 y T3CCP2 de forma que TMR3 fuese el timer a usar por ambos módulos. Sin embargo, cuando la uso no se ponen los bits a su valor correcto (1). Es por esto por lo que necesito ponerlos a 1 "manualmente" en la siguiente línea.</span><br />
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">Para que el módulo CCP1 funcione correctamente y detecte los eventos es necesario que su pin asociado (RC2) esté declarado como una entrada:</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><br />
<span lang="EN-GB" style="font-family: 'Courier New';"><br /></span>
<span lang="EN-GB" style="font-family: 'Courier New';">TRISCbits.TRISC2=1; </span><span style="color: forestgreen; font-family: 'Courier New';">// RC2 as input </span><br />
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">Ahora vamos a configurar el módulo CCP1 en modo CAPTURA. Por ejemplo, si deseamos configurar CCP1 en modo 4X (un evento es la llegada de 4º pulsos o más específicamente, la llegada de la 4º subida) basta hacer:</span><br />
<br /></div>
</div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> CCP1CON=0b00000110; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Modo CAPTURE. Event = x4 rising edges</span></div>
</div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="color: #111111; font-family: Verdana;"><br /></span>
<span style="color: #111111; font-family: Verdana;">Para hacer el programa más legible podríamos usar la correspondiente rutina de C18 (en </span><span style="color: #111111; font-family: Verdana;">este caso tendríamos que incluir fichero capture.h):</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: forestgreen; font-family: 'Courier New';">// CCP1CON=0b00000111 Modo CAPTURE. Event = x16 rising edges</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New', Courier, monospace;"> </span><span lang="EN-GB" style="font-family: 'Courier New', Courier, monospace;">OpenCapture1(CAPTURE_INT_OFF,C1_EVERY_4_RISE_EDGE);</span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Finalmente habilitaríamos la interrupción del CCP (alta prioridad):</span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> enable_priority_levels; </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> enable_CCP1_int; set_CCP1_high;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> enable_high_ints; enable_low_ints;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
</div>
</div>
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; margin: 0px; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<span style="font-family: Verdana, sans-serif;">Ese sería el código de inicialización en el programa principal. Como hemos habilitado la interrupción CCP1 debemos escribir una ISR que maneje dicha interrupción. Obviamente lo que hagamos en esa interrupción dependerá de la aplicación en la que estemos pensando. Sin embargo, en muchas ocasiones, lo que si querremos hacer es guardar el tiempo (registros CCPR1H:CCPR1L) del evento que ha provocado la interrupción y calcular la separación con el evento anterior. Veamos como escribir una sencilla ISR para conseguir esos objetivos:</span></div>
<br />
<div class="MsoNormal">
</div>
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="FR">uint16 t0=0;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="FR">uint16 dt=0;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// High priority interruption</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> uint16 t;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB"> (CCP1_flag)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> {</span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> t=CCPR1H; t<<=8; t+=CCPR1L; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Read CCPR1 (time of event that just happened)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> dt = (t-t0); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Interval between events </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> t0 = t; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Keep latest time in t0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> CCP1_flag=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Code @ 0x0008 -> Jump to ISR for high priority ints</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span lang="EN-GB"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB"> high_interrupt (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB">){_asm </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">goto</span><span lang="EN-GB"> high_ISR _endasm}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="margin: 0px;">
<span style="font-family: Courier New, Courier, monospace;"><span style="color: #b28c00;">#pragma</span> code</span><span style="font-family: 'Courier New'; font-size: 9pt;"><o:p></o:p></span></div>
</div>
</div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana;">El código es muy sencillo. Hay dos variables externas t0 y dt de tipo uint16. La ISR lee el momento del último evento (de CCPR1H:CCPR1L) y lo salva en t. Calcula el intervalo con el último evento (t-t0) y lo guarda en dt. Después actualiza t0 (último evento) con el valor de t. </span><br />
<span style="font-family: Verdana; text-align: justify;"><br /></span>
<span style="font-family: Verdana; text-align: justify;">De esta forma en t0 guarda el momento del último evento y en dt tenemos siempre disponible el valor más reciente de la separación de eventos. </span><br />
<span style="font-family: Verdana;"><br /></span>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: Verdana;">La limitación de este enfoque es que si la separación entre eventos supera los 65536 "clocks" del timer TMR3 va a haber un rollover y a la resta (t-t0) le faltará añadirle 65536, 65336x2, etc.</span></div>
<span style="font-family: Verdana; text-align: justify;"><br /></span><span style="font-family: Verdana; text-align: justify;">Una solución sería habilitar la interrupción del TMR3 y llevar la cuenta del número de rebosamientos que tienen lugar entre un evento y el siguiente. En ese caso el intervalo entre eventos sería:</span><br />
<span style="font-family: Verdana; text-align: justify;"><br /></span>
<span style="font-family: Verdana; text-align: justify;"> # rebosamientos x 65536 + dt</span><br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En este caso no lo hemos implementado, por lo que la separación entre eventos no debería exceder los 65536 microsegundos. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana, sans-serif;"> <span style="color: #111111;">Bueno, pues eso es todo lo que necesitabamos saber para usar el modo CAPTURA. En la siguiente entrada vamos a ver como usarlo en una aplicación real, para medir el periodo de un sensor que convierte luz recibida en una frecuencia de salida.</span></span></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 10pt;">
</div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="background-color: white; background-position: initial initial; background-repeat: initial initial; line-height: 12pt; text-align: justify;">
<br /></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com6tag:blogger.com,1999:blog-4945680608471335280.post-52239393266782492542013-06-07T09:54:00.002+02:002013-06-07T10:48:21.792+02:00Proyecto: Medidor de potencia<div class="MsoNormal" style="text-align: justify;">
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 10.0pt;">En este proyecto vamos a construir un medidor de potencia,
un dispositivo que monitoriza la potencia (de la que se puede deducir
fácilmente el consumo) de un electrodoméstico o cualquier otro aparato
conectado a la red. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 10.0pt;">Para obtener la potencia consumida tendremos que
monitorizar (muestrear) la intensidad y el voltaje de la red. Como siempre que
manipulemos la red, debemos ser muy cuidadosos con nuestros montajes. Existen
varias formas de monitorizar el voltaje e intensidad de la red. En este montaje
he escogido la que me ha parecido más segura: un montaje en el que existe un
aislamiento galvánico entre la red y las señales que el micro monitoriza.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 10.0pt;">Una vez que tenemos las medidas de intensidad y voltaje a
lo largo de un ciclo de trabajo (20 milisegundos si nuestra red va a 50 Hz) es
muy sencillo para el micro estimar valores como la intensidad RMS, potencia RMS
y potencia real consumida y volcar los resultados por el puerto serie o (si
queremos un sistema más autónomo) presentarlos en un LCD.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 10.0pt;">Como en proyectos anteriores, se adjunta un programa
MATLAB para visualizar los datos capturados (intensidad, potencia instantánea,
etc.) a lo largo de un ciclo, permitiéndonos ver gráficamente aspectos como el
desfase entre Intensidad y Voltaje, forma de onda de la intensidad, etc. En el video adjunto se muestran los resultados
para el caso de una pequeña batidora, mientras cambiamos su velocidad,
ponemos el "turbo", etc:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 10.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxHXjJg_O8ge_HlJYBdDbgLPxro3RKI6UnKK7tmZZUBfqzLkOu8w2QYpyiIvXGbDByUDY5EVyp9iw_2CeSZwQ' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;"><span style="text-align: start;">Código asociado:</span><span class="apple-converted-space" style="text-align: start;"> </span><span style="text-align: start;"> </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/power_meter.c" style="text-align: start;">power_meter.c</a><span style="text-align: start;"> (código PIC)</span></span><br />
<span lang="PT-BR" style="font-family: Verdana;"><span style="text-align: start;"> </span></span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/18f4520_g_powermeter.lkr" style="font-family: Verdana; text-align: start;">18f4520_g.lkr</a><span style="font-family: Verdana; text-align: start;"> (linker script modificado) </span><br />
<span lang="PT-BR" style="font-family: Verdana;"> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/power_meter.m" style="text-align: start;">power_meter.m</a><span style="text-align: start;"> (programa MATLAB de interfaz con el PC). </span></span><br />
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;"></span></div>
<a name='more'></a><br />
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">---------------------------------------------------------------------------------------------</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">1. Fundamentos (Voltaje, Intensidad, Potencia)<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La potencia consumida por una carga es el producto del
potencial (voltaje) entre sus bornes y la intensidad que la atraviesa:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> <b> P = I V</b><span style="mso-text-raise: -3.0pt; position: relative; top: 3.0pt;"><!--[if gte vml 1]><v:shapetype
id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:45.75pt;
height:14.25pt' o:ole="">
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.wmz"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><!--[if gte mso 9]><xml>
<o:OLEObject Type="Embed" ProgID="Equation.3" ShapeID="_x0000_i1025"
DrawAspect="Content" ObjectID="_1432049509">
</o:OLEObject>
</xml><![endif]--></span><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="MsoNormal">
<span style="font-family: Verdana;">Si estamos manejando corriente continua (donde el voltaje
se mantiene esencialmente constante) no hay mucha más complicación. Sin
embargo, en el caso de cargas conectadas a la red la cosa se complica un poco
(aunque no mucho). En la red tenemos un voltaje alterno, esencialmente una
sinusoide cuya amplitud V0 y frecuencia (f) dependen del país o zona donde nos
encontremos. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En España, por ejemplo, la frecuencia es de 50 Hz y el
voltaje de 230 V (rms). Veis que el voltaje tiene un "adjetivo". Esto
es consecuencia de tener una corriente alterna. Podríamos pensar que el voltaje
declarado corresponde a la amplitud máxima de la sinusoide (sería entonces
V0=230), pero esto no es correcto. El voltaje declarado (rms, o root mean
square) corresponde al voltaje continuo que haría el mismo trabajo que el
voltaje alterno usado.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<span style="font-family: Verdana;">Como el voltaje alterno sube y baja, pasará por el cero de
tanto en tanto (100 veces por segundo) y en esas zonas no hará demasiado trabajo.
Si de media tiene que comportarse como un voltaje de 230V está claro que
durante su máximo tendrá que compensar el poco esfuerzo que hizo cuando estaba
cerca del cero. Eso quiere decir que el</span><span style="font-family: Verdana;">
</span><span style="font-family: Verdana;">máximo (amplitud V0) del voltaje debe ser mayor que el Vrms declarado.
¿Cuánto mayor? El voltaje y la intensidad</span><span style="font-family: Verdana;">
</span><span style="font-family: Verdana;">RMS están definidos como:</span><span style="font-family: Verdana;"> </span><span style="font-family: Verdana;"><span style="mso-text-raise: -13.0pt; position: relative; top: 13.0pt;"></span> </span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"></span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAM3TIKt8uhjREZiX_exp7ZNOCfovPF8eVzOgtW4_4x3JLA_BTPDcwP2dmoXJS5NvhIgcSpW3Lbo9weY32KTBNx8Whmu7XbBRvHSUE92Sbp8hglh63FTyqHwXg_u5U6q3rLxumymjS/s1600/formula1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAM3TIKt8uhjREZiX_exp7ZNOCfovPF8eVzOgtW4_4x3JLA_BTPDcwP2dmoXJS5NvhIgcSpW3Lbo9weY32KTBNx8Whmu7XbBRvHSUE92Sbp8hglh63FTyqHwXg_u5U6q3rLxumymjS/s1600/formula1.jpg" /></a></span></div>
<span style="font-family: Verdana;"><span style="mso-text-raise: -13.0pt; position: relative; top: 13.0pt;"><!--[if gte vml 1]><v:shape
id="_x0000_i1026" type="#_x0000_t75" style='width:95.25pt;height:33.75pt'
o:ole="">
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image005.wmz"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><!--[if gte mso 9]><xml>
<o:OLEObject Type="Embed" ProgID="Equation.3" ShapeID="_x0000_i1026"
DrawAspect="Content" ObjectID="_1432049511">
</o:OLEObject>
</xml><![endif]--></span><b><u><span style="font-family: Verdana;"><o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="MsoNormal">
<span style="font-family: Verdana;">Notad que ahora V(t) e I(t) dependen del tiempo, al
contrario que en la primera ecuación. Los valores rms (al cuadrado) son
esencialmente una media del cuadrado de la señal durante un periodo. De ahí su
nombre: son la raíz (Root) de la media (Mean) del cuadrado (Square) de la
señal. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Consideremos en primer lugar la relación entre V0
(amplitud) y Vrms:</span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeTo8znRREihMK6qFreIvTkcElHistBFGKX3phw8vNXWcqrUfi7z1DAOjN-l0o_oEsZw8jPlpVAGQ4Muyq5fH1u-vyW9ze33nT2QnvH2HNB44JQbheseYVQi3oRnyaztrVXLx2zqQk/s1600/formula2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeTo8znRREihMK6qFreIvTkcElHistBFGKX3phw8vNXWcqrUfi7z1DAOjN-l0o_oEsZw8jPlpVAGQ4Muyq5fH1u-vyW9ze33nT2QnvH2HNB44JQbheseYVQi3oRnyaztrVXLx2zqQk/s1600/formula2.jpg" /></a></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En España (Vrms=230) tendremos un voltaje con una amplitud
máxima (V0) de 325V.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una ve</span><span style="font-family: Verdana;">z que conocemos las especificaciones de nuestro
voltaje, imaginemos una carga puramente resistiva (R) enchufada a la red (una
bombilla incandescente podría ser una buena aproximación). En cada momento la
intensidad que atraviesa la bombilla será I(t) = V(t)/R.</span></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana;">La potencia instantánea consumida será por lo tanto: </span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZu2ayO0mAYlayQCTuibtApaXXt4AmPiiot7Sujvo6JUcHQzmAbWH1wLrNqZ8LmxZ1PtRni7CMhARxoOdrsRPl8n7feivdHKrqMdhcH98lAcKpgBBAB3bpa3FZVs-7KGv7MJh0YR2x/s1600/formula3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZu2ayO0mAYlayQCTuibtApaXXt4AmPiiot7Sujvo6JUcHQzmAbWH1wLrNqZ8LmxZ1PtRni7CMhARxoOdrsRPl8n7feivdHKrqMdhcH98lAcKpgBBAB3bpa3FZVs-7KGv7MJh0YR2x/s1600/formula3.jpg" /></a></div>
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: Verdana;">Notad que en este caso la potencia instantánea siempre es
positiva (una carga resistiva está consumiendo energía durante todo el ciclo).
Veremos que esto no es siempre así.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">¿Cuál es la potencia media durante un ciclo? Basta
promediar P(t) sobre un periodo:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><span style="mso-text-raise: -13.0pt; position: relative; top: 13.0pt;"><!--[if gte vml 1]><v:shape id="_x0000_i1029" type="#_x0000_t75"
style='width:350.25pt;height:35.25pt' o:ole="">
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image011.wmz"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><!--[if gte mso 9]><xml>
<o:OLEObject Type="Embed" ProgID="Equation.3" ShapeID="_x0000_i1029"
DrawAspect="Content" ObjectID="_1432049514">
</o:OLEObject>
</xml><![endif]--></span><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSOcRYM62RtbHh1v7zYQlYeTVM9YXiUJ2EBOO32BnX15K_dU4AXe7klF2AAxm6oR8wa-ktIz5Xb5bgnS81mJsUjWSc5u1g9QqPiIdLepnGDCM4qXxkd0jE8xHNact1FhT8TujKqjB8/s1600/formula4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSOcRYM62RtbHh1v7zYQlYeTVM9YXiUJ2EBOO32BnX15K_dU4AXe7klF2AAxm6oR8wa-ktIz5Xb5bgnS81mJsUjWSc5u1g9QqPiIdLepnGDCM4qXxkd0jE8xHNact1FhT8TujKqjB8/s1600/formula4.jpg" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">A la cantidad anterior se le denomina potencia media o
potencia real consumida. La potencia media se relaciona directamente con la
energía consumida (si no hubiésemos dividido por T en la fórmula anterior
habríamos obtenido la energía consumida en el periodo). Para obtener energía
bastaría volver a multiplicar <P> por el periodo T.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Se observa que la energía consumida en esta situación es
la mitad de la que se consumiría si hubiésemos aplicado un voltaje V0
constante. De ahí que el voltaje alterno equivalente (rms) tuviera ese factor
de raíz de 2 respecto a V0.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si calculamos Vrms e Irms para el caso anterior (carga
resistiva) obtendríamos:</span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJhMHriLJazCpoxQJ7t71PN-37JjnFIvXNMu3go25qT8k-xjLGlOSU_N4kkUJqAu7U7NMqo7d21d9EEp96q07WbPmu66NyfX141BsNGbByHY5V2BBIrDtm4B4zAtJ6aB3C4cpwgIMj/s1600/formula5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJhMHriLJazCpoxQJ7t71PN-37JjnFIvXNMu3go25qT8k-xjLGlOSU_N4kkUJqAu7U7NMqo7d21d9EEp96q07WbPmu66NyfX141BsNGbByHY5V2BBIrDtm4B4zAtJ6aB3C4cpwgIMj/s1600/formula5.jpg" /></a></div>
</div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="mso-text-raise: -14.0pt; position: relative; top: 14.0pt;"><!--[if gte vml 1]><v:shape id="_x0000_i1031"
type="#_x0000_t75" style='width:162pt;height:35.25pt' o:ole="">
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image013.wmz"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><!--[if gte mso 9]><xml>
<o:OLEObject Type="Embed" ProgID="Equation.3" ShapeID="_x0000_i1031"
DrawAspect="Content" ObjectID="_1432049515">
</o:OLEObject>
</xml><![endif]--></span><span lang="PT-BR" style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Al producto de estas dos cantidades se le denomina P_rms:<o:p></o:p></span><br />
<span style="font-family: Verdana;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5UKYkeHV5lgU-CsPEsbcXWkK2BWdcfRbuMu2u3bEAYme_yU9NfdanCDg56f-cpvKp6ogpiAUkDJGcyxtGiNvKlCsqjkLMgfGkXrU6zfSJc4oa6woI_JCErM1WJOuK5XOjAO_NckBk/s1600/formula6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5UKYkeHV5lgU-CsPEsbcXWkK2BWdcfRbuMu2u3bEAYme_yU9NfdanCDg56f-cpvKp6ogpiAUkDJGcyxtGiNvKlCsqjkLMgfGkXrU6zfSJc4oa6woI_JCErM1WJOuK5XOjAO_NckBk/s1600/formula6.jpg" /></a></div>
<span style="font-family: Verdana;">y en este caso verificamos que coincide con la potencia real
consumida.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Cuando usamos un polímetro para medir el voltaje de una
corriente alterna nos da V(rms). Si medimos la intensidad obtenemos I(rms).
Multiplicando ambos obtenemos P(rms). El problema es que P(rms) sólo coincide
con la potencia real <P> para una carga resistiva como hemos visto en el
ejemplo anterior.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Imaginad por ejemplo una carga con un componente inductivo
o capacitivo que cambia la fase de la intensidad respecto al voltaje. En este
caso <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcqp5q_YVSf5wBH6ogweO2ZaPPUzQCtWNx_w9vcu6VjYZCUIM7yL5U0oGmJ8uZh84pc65DCeMYBym-_BTA2uhi-2m5zU-lqJ8gj_74LsSHz1sbqzowTnZXDSIyvIph5TRL4WmyuGx/s1600/formula7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcqp5q_YVSf5wBH6ogweO2ZaPPUzQCtWNx_w9vcu6VjYZCUIM7yL5U0oGmJ8uZh84pc65DCeMYBym-_BTA2uhi-2m5zU-lqJ8gj_74LsSHz1sbqzowTnZXDSIyvIph5TRL4WmyuGx/s1600/formula7.jpg" /></a></div>
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">donde phi es el desfase entre I y V. ¿Cuál es la potencia
real consumida en este caso?</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDe0pY1C2x-0TFazCkPA54fQc8fPyAjdaMTTJVGX-wAoejs-eg9JhM4xXiP0x6vJWk-E1HHg0bf1LDVYCeG0lFhJSu45ziGQ4cFfRGKQhy4niKI9S3SujKHuaIeX4dDwcsTi-U1tvj/s1600/formula8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDe0pY1C2x-0TFazCkPA54fQc8fPyAjdaMTTJVGX-wAoejs-eg9JhM4xXiP0x6vJWk-E1HHg0bf1LDVYCeG0lFhJSu45ziGQ4cFfRGKQhy4niKI9S3SujKHuaIeX4dDwcsTi-U1tvj/s1600/formula8.jpg" /></a></div>
<br /></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="mso-text-raise: -13.0pt; position: relative; top: 13.0pt;"><!--[if gte vml 1]><v:shape id="_x0000_i1033"
type="#_x0000_t75" style='width:432.75pt;height:33.75pt' o:ole="">
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image019.wmz"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><!--[if gte mso 9]><xml>
<o:OLEObject Type="Embed" ProgID="Equation.3" ShapeID="_x0000_i1033"
DrawAspect="Content" ObjectID="_1432049518">
</o:OLEObject>
</xml><![endif]--></span><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En este caso la potencia real es menor que la potencia RMS
por un factor (cos(phi)) que se denomina </span><b style="font-family: Verdana;">factor
de potencia</b><span style="font-family: Verdana;">. Lo que está pasando es que durante una parte del ciclo la
carga está devolviendo energía a la red, por lo que su consumo total es menor
que el de una carga equivalente resistiva.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Otra razón por la que <P> puede ser diferente de
Prms es cuando tengamos un comportamiento no lineal de la carga, lo que hará
que la intensidad se aleje de la forma sinusoidal. <span style="font-size: x-small;"><o:p></o:p></span></span></div>
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;">
</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Con nuestro dispositivo medidor de potencia queremos
conocer la potencia real consumida. Lo que tenemos que hacer es monitorizar
(muestrear) el voltaje y la intensidad en la red. El muestreo tiene que ser lo
suficientemente "fino" para poder ver que está pasando dentro de un
ciclo. Una vez que tengamos dichas muestras podremos aproximar las integrales
anteriores para calcular la potencia media, Irms, factor de potencia, etc.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">2. Hardware, sensores, montaje:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como hemos comentado necesitamos monitorizar la intensidad
y voltaje de la línea. Veamos como hacerlo de la forma más segura y menos
"invasiva" posible.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Medición de la Intensidad:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Para medir la intensidad se ha usado el sensor mostrado en
la figura adjunta. (adquirido en </span><a href="http://www.seeedstudio.com/depot/grove-electricity-sensor-p-777.html?cPath=25_28">http://www.seeedstudio.com/depot/grove-electricity
sensor-p-777.html?cPath=25_28</a><span style="font-family: Verdana;"> por unos $5). <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyv630CKUn7_7Y70F2lNnXHaa0FrVcdHgRTPftIMmpcduHE_jf9q-UhQyhGo5E-L5peS5l7AhDbbpo3WHHt3flDvtWRQ79z-vD9QN3AB-uLpoEoEppOi76_T4qntnbLerlSrqb4v7e/s1600/sensor_Int.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyv630CKUn7_7Y70F2lNnXHaa0FrVcdHgRTPftIMmpcduHE_jf9q-UhQyhGo5E-L5peS5l7AhDbbpo3WHHt3flDvtWRQ79z-vD9QN3AB-uLpoEoEppOi76_T4qntnbLerlSrqb4v7e/s200/sensor_Int.jpg" width="198" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> </span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioNvM2oLaGB08xjgk9duEFtEsQiVvE7IbIRywq1TDSwyYeH-JVY5Dn_sO4BxIPGr5KDmeKB-z1xRz5LRXGO4LLzd8icuc2QcDTwcVCzKPaAN2DPOy38Ywh3mUMWgxNXhF5ozYVXZEN/s1600/esquema1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioNvM2oLaGB08xjgk9duEFtEsQiVvE7IbIRywq1TDSwyYeH-JVY5Dn_sO4BxIPGr5KDmeKB-z1xRz5LRXGO4LLzd8icuc2QcDTwcVCzKPaAN2DPOy38Ywh3mUMWgxNXhF5ozYVXZEN/s320/esquema1.jpg" width="320" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">Un hilo (no los dos, eso cancelaría la medida) de la red
se pasa por el eje de la bobina (roja). Una corriente alterna que circule por
el hilo provocará una corriente proporcional en los bornes de la bobina.
Mirando las especificaciones vemos que la corriente inducida resulta ser 1/2000
veces la intensidad original. La corriente inducida se hace pasar por una
resistencia de 800 ohmios (ver diagrama adjunto), provocando un voltaje:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> V = 800 x (I /
2000) = I / 2.5<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<!--[if gte vml 1]><v:shapetype
id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
left:0;text-align:left;margin-left:273.6pt;margin-top:3.9pt;width:201.35pt;
height:151pt;z-index:1;mso-position-horizontal:absolute;
mso-position-horizontal-relative:text;mso-position-vertical:absolute;
mso-position-vertical-relative:text'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjevXhETa6Tx1fgGjubFOjqVyHkNWuDt6SnIRDj1mFTUJOFmeOx_AyEODgsrzTf_KPIscvT9OYOgotTh__XQWihyphenhyphen5uS9cbS2aDRkEy4f8RUUTfPqlWSpLP4uVbO1UA5ZBYQX0wJQ_nY/s1600/sensor_int_oscope.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjevXhETa6Tx1fgGjubFOjqVyHkNWuDt6SnIRDj1mFTUJOFmeOx_AyEODgsrzTf_KPIscvT9OYOgotTh__XQWihyphenhyphen5uS9cbS2aDRkEy4f8RUUTfPqlWSpLP4uVbO1UA5ZBYQX0wJQ_nY/s1600/sensor_int_oscope.jpg" /></a><span style="font-family: Verdana;">En el pantallazo adjunto se muestra una captura en
el osciloscopio del voltaje observado en la bobina con una bombilla
incandescente de 60W. Vemos que es básicamente una sinusoide pura con un Vrms
de unos 104 mV. Eso equivale a una Irms (según la fórmula anterior) de unos 260
mA. Como la carga es resistiva tenemos que Prms = P = Vrms x Irms = 230 x 0.26 = 59.8 W, lo
que concuerda muy bien con lo esperado. </span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Si bien el voltaje obtenido es proporcional a la
intensidad que circula por el hilo, nada nos garantiza que esté en fase con
dicha intensidad. </span><span style="font-family: Verdana;">Las especificaciones hablan de un desfase de unos 5º. Como
veremos no tendremos que fiarnos de las especificaciones, ya que un proceso de
calibración en software tendrá en cuenta ese factor.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">¿Cuál es la intensidad máxima que podemos medir? La
especificaciones indican un máximo de unos 5/6 A. Con las especificaciones
dadas esos 5 amperios provocarán un voltaje de +/- 2V, lo que corresponde a un
rango de unos 4-5 V, perfecto para ser monitorizado con el ADC de un micro
trabajando a 5V.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En principio la intensidad podría ser mayor, lo único que
el voltaje a monitorizar podría exceder el rango de 5V y tendríamos que usar un
divisor de tensión o similar en la interfaz con el PIC. No se si la
recomendación de no pasar de 5A viene de ahí o si tendríamos algún otro
problema. Incluso si nos vamos a 20A la intensidad inducida no pasaría de 10 mA
que no creo que vaya a quemar la bobina. Podría ser que pasados los 5A se
pierda la linearidad entre corriente de entrada y voltaje de salida.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En cualquier caso no hecho pruebas para verificar los
límites del sensor. En mi caso con un voltaje Vrms de 230V puedo monitorizar
cargas poco más de 1000W (230V x 5A).<span style="font-size: x-small;"><o:p></o:p></span></span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana; font-size: x-small;"><b>Nota: si en alguna otra aplicación estáis interesados en aumentar la sensibilidad de la medida (porque las intensidades a medir son pequeñas) siempre podéis pasar varias vueltas del hilo cuya corriente queremos medir por la bobina. De esta forma multiplicando la intensidad inducida y por lo tanto el voltaje a detectar.</b></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Medición de Voltaje:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La medición de la intensidad anterior tiene la gran
ventaja que aísla galvanicamente el circuito del PIC (que solo está conectado a
la bobina) de la red. Esto lo hace muy seguro.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Para la medición del voltaje me gustaría algo similar. Me
he decidido por una solución de compromiso que me permite contar también con
aislamiento galvánico en la medida del voltaje. Eso me supondrá tener que hacer
ciertas asunciones, pero como veremos en los resultados no parecen funcionar
mal.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr1oB-6jhuuD40G2cNnOPU89xCWgcX509ZZYPyTW-mhEzLKDTo-I7IVuvPcaR0JhsNDBsoNMyqz_hpfCRroIMnzx_4w47ATbfY3cvknCiC-TMwS1HUPT7KbRS7s4liS33c2BB9fMgz/s1600/esquema2.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr1oB-6jhuuD40G2cNnOPU89xCWgcX509ZZYPyTW-mhEzLKDTo-I7IVuvPcaR0JhsNDBsoNMyqz_hpfCRroIMnzx_4w47ATbfY3cvknCiC-TMwS1HUPT7KbRS7s4liS33c2BB9fMgz/s320/esquema2.jpg" width="320" /></a><span style="font-family: Verdana;">La idea es conectar simplemente un pequeño trafo o
transformador a la red y monitorizar el voltaje en el secundario (ver diagrama adjunto).
El trafo usado lo saqué de una vieja radio. Tiene la ventaja de que el voltaje
en el secundario es de unos 1.5 V (rms). Como sabemos ahora eso corresponde a
un voltaje máximo de unos +/- 2 V, de nuevo un rango ideal para monitorizarlo
con el micro sin tener que añadir un divisor de tensión.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El problema obvio es que lo que estaremos viendo no es el
voltaje de la red (primario) sino el del bobinado secundario, con todas las distorsiones
y desfases introducidas por el trafo. En el pantallazo adjunto vemos el
voltaje del trafo al que tendríamos acceso desde el PIC. El rango (+/- 2V) es ideal,
pero la forma no es la sinusoide esperada.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjokT7UzzgC2KmMKptuLq5OTqjWh7EPDeHYboaLfvjyAaNoRptcXHGMLIUIt0fl6KvvqtXmfWKun_r-i764lx467-rowNSw-LapS-QSd2st2gzXkugCyCz8MXADOT-fe8Ll8qqPT_L3/s1600/trafo_oscope.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjokT7UzzgC2KmMKptuLq5OTqjWh7EPDeHYboaLfvjyAaNoRptcXHGMLIUIt0fl6KvvqtXmfWKun_r-i764lx467-rowNSw-LapS-QSd2st2gzXkugCyCz8MXADOT-fe8Ll8qqPT_L3/s320/trafo_oscope.jpg" width="320" /></a><span style="font-family: Verdana;">La idea es que al fin y al cabo el voltaje en la red lo
conozco muy bien: una sinusoide de amplitud 325V (para Vrms=230) y periodo de
20 MSEC (50 Hz). Lo único que me hace falta es conocer su fase, esto es, saber
cuándo arranca un nuevo ciclo de voltaje. Y podemos obtener dicha información a
partir de nuestro trafo. De nuevo, la salida del trafo no estará en fase con el
verdadero voltaje. El pantallazo anterior fue obtenido con el trigger en modo
RED: vemos como la salida del trafo se adelanta al voltaje un poquito (del orden de un milisegundo
aproximadamente). Tendremos que hacer algún proceso de calibración previa para
determinar dicho valor. Veremos los detalles en la parte del software.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Diagrama completo:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;"><br /></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El
esquema adjunto muestra como conectaríamos la salida de ambos sensores con el
micro:</span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiX-j7v2idasKT0pPo3o5kSZzU3Dl4M3w0uEsGsy-l1z1STXVfdOw_jAHvRw1bn3j5vdhzOrrD9pmu9TWnTFy_hzC5hT504sEKoFcWlgPYv_4gSfgHkp1QC49XkqBQnq-GLihZLPsn/s1600/esquema3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiX-j7v2idasKT0pPo3o5kSZzU3Dl4M3w0uEsGsy-l1z1STXVfdOw_jAHvRw1bn3j5vdhzOrrD9pmu9TWnTFy_hzC5hT504sEKoFcWlgPYv_4gSfgHkp1QC49XkqBQnq-GLihZLPsn/s640/esquema3.jpg" width="640" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Hemos unido ambos sensores en un punto común para tener
una referencia común. No hay problema en hacerlo al estar ambos sensores
"en el aire". Como los voltajes a medir son alternos, para poder
medirlos con el ADC del PIC (0-5V) ato el punto común a un divisor de voltaje
con dos resistencias iguales lo que lo pone a 2.5V. A partir de ahí los otros
dos hilos de los sensores van a los canales ADC 0 y 1 del PIC (RA0 y RA1).
También conecto al canal RA2 el punto común para medirlo también (por si no
fuese exactamente 2.5V) y descontarlo de las medidas de RA0 y RA1.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como los voltajes de ambos sensores oscilaban en +/-2V,
sumados a los 2.5V de referencia darán valores cubriendo bastante bien el rango
del ADC.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana; font-size: 9.0pt;">Nota: el esquema
anterior es lo mejor que se me ha ocurrido con mis escasos, tendiendo a nulos, conocimientos de electrónica. Supongo
que hay formas mucho más acertadas, eligiendo R para ajustar impedancias,
metiendo algún condensador por ahí, etc. Si a alguien se le ocurre un montaje mejor (no será
difícil) o simplemente puede decirme por qué el anterior es una malísima idea,
se agradecerán todas las sugerencia</span></b><span style="font-family: Verdana; font-size: 10.0pt;">.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">3. Software:</span></u></b><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El programa es muy sencillo. Programaremos un timer (TMR0)
para que tome muestras de un periodo de la señal (o de varios periodos para
reducir ruido) a intervalos predefinidos. Dentro de la interrupción del timer
se harán sendas capturas del ADC correspondientes al voltaje e intensidad
monitorizados. Los valores leídos del ADC se guardarán en sendos arrays. Cuando
se complete la fase de toma de datos (1
o varios ciclos) se parará el TMR0 (interrumpiendo la toma de datos) y se
pondrá a 1 una bandera. Una vez que detectemos dicha bandera procesaremos los
datos desde el programa principal, calcularemos los resultados y los enviaremos
por el puerto serie (si se desea un medidor más portatil podrían aparecer en un
LCD).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Tras terminar de procesar los datos reactivaremos el timer
TMR0 y volverá a empezar un nuevo ciclo de toma de datos. Dependiendo del
número de periodos que se usen para tomar datos podremos refrescar los
resultados con mayor o menor frecuencia. Con 32 periodos para la medida (32/50 = 0.65 seg), más el tiempo empleado en procesar los datos, actualizaremos los datos cada segundo, aproximadamente.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Ajustar timing del
sampling:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La variable SAMPLES_PERIOD determina el número de muestras
que se toman en un ciclo de la red. He elegido tomar 128 muestras por periodo. Si
solo queremos presentar datos de consumo podría valer con menos, pero como
también quiero presentar algunas gráficas he sobremuestreado los datos.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Para mi frecuencia de 50 Hz un periodo corresponde a 20
msec = 20000 usec. La separación entre muestras será de 20000/128 = 156.25
microsec. En este proyecto estoy usando un cristal de 8 MHz con un
multiplicador PLLx4, lo que equivale a una Fosc = 32 MHz. Eso quiere decir que
un ciclo de instrucción se ejecuta en 1/8 usec, por lo que la separación entre
muestras corresponde a 156.25 x 8 = 1250
ciclos. La fórmula a usar sería:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> delay (ciclos de
instrucción) = (F_osc/4) / (F_red x SAMPLES_PERIOD ) <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Si programamos el TMR0 sin pre-scaler y en modo 16 bits,
debemos programar el contador TMR0 (cada vez que entremos en la interrupción de
reloj) para que vuelva a rebosar en 1250 "clocks" (TMR0 = 65536 –
delay)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En realidad el valor a usar será un poco mayor, ya que
para cuando llegamos a la ISR (y fijamos el siguiente tiempo de re-entrada) ya
ha pasado un tiempo (mientras guardamos datos imprescindibles, saltamos a la
rutina de interrupción, etc). Normalmente eso tarda unos pocos microsegundos,
por lo que deberíamos aumentar la estimación anterior por dicho tiempo (en
ciclos).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En la tabla adjunta se dan varios valores de partida para
varias frecuencias de red y del micro usado (todas ellas para 128 puntos de
muestreo en el ciclo) <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 23.0pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Fosc<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">8<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">10<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">16<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">20<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">32<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">50 Hz<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65410<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65255<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65175<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">64940<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">64785<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">64315<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">60 Hz<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65435<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65305<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65240<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">65245<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">64915<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 60.5pt;" valign="top" width="81"><div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">64525<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Si solo vamos a muestrear 1 periodo la elección del delay
no es demasiado crítica. Sin embargo, para reducir ruido, voy a promediar los
valores tomados en una serie de periodos. En particular por defecto usaré N_PERIOD =
32 periodos. En ese caso si que es más critico determinar exactamente el delay
para que 128 muestras correspondan exactamente a un periodo. En caso contrario
los ciclos se irían "corriendo" respecto a nuestras muestra y terminaría
promediando valores que se han tomado en diferentes instantes del ciclo.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Para ver cual es exactamente el valor más conveniente a
usar como delay voy a generar (usando el timer TMR0) una onda cuadrada,
intentando que esté sincronizada con la red. Para verificarlo iré probando
varios delay (en la vecindad de TMR0=64300) y visualizaré la señal obtenida en
el osciloscopio (usando la RED como trigger). Cuando vea a señal lo más
estacionaria posible será la señal de que el valor que estamos usando es el más
ajustado. En el corto video adjunto se muestra el proceso, donde se observa que
el mejor valor es TMR0=64315. Valores inmediatamente inferiores o superiores
causan una lenta deriva en la señal (hacia uno u otro lado según que el timer
se adelante o retrase respecto a la red.)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxtib9PDO2mdU8ZvdLeHKkjBuMH32ZSiRqwv_zzEv3gPyl0CY5kiRjc8h7G7RgNH5H3ZeEnvEyqsWM1JNAb' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Una vez establecido el timing ideal para el TMR0 este es
el código de la interrupción, donde todo el proceso de toma (ADC) y
almacenamiento de los datos tiene lugar:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> set_TMR0(x) {TMR0H=(x>>8);
TMR0L=(x&0x00FF);}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> start_TMR0 T0CONbits.TMR0ON=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> stop_TMR0 T0CONbits.TMR0ON=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_ADC(ch) { ADCON0 &= 0b11000011; ADCON0 += (ch<<2); }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint16 delay=64315;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// High priority
interruption </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> int16 res,ref;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//ISR
de la interrupcion de TMR0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> set_TMR0(delay);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Reference voltage</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_ADC(2); ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
(ADCON0bits.GO); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ref=ADRESH; ref<<=8; ref+=ADRESL;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Voltage (chan 0) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_ADC(0); ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
(ADCON0bits.GO); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">res=ADRESH;
res<<=8; res+=ADRESL; res-=ref; V[sample]+=res;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Intensity (chan 1)
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_ADC(1); ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
(ADCON0bits.GO); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=ADRESH; res<<=8; res+=ADRESL;
res-=ref; I[sample]+=res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> sample++;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (sample==SAMPLES_PERIOD) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// PERIOD SAMPLED</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> sample=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> period++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (period==N_PERIOD) { data_ready=1;
stop_TMR0; } </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// End of ADQ process</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=~LATBbits.LATB0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> TMR0_flag=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// clear flag</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Nada más entrar en la interrupción reprogramamos el
contador para volver a entrar en el siguiente instante de muestreo.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">A continuación se muestrean los tres canales: primero el
voltaje de referencia y luego el voltaje del trafo y de la bobina del sensor de
intensidad. El voltaje de referencia se resta a las dos mediadas y los
resultados <b>se acumulan</b> en los arrays
V e I. Dichos arrays son de enteros con signo (+/- 32768). Como cada medida
está en el rango +/- 512 podría acumular hasta 64 medidas sin causar un
rollover. Ese será el número máximo de periodos a promediar. En el código uso
N_PERIOD=32 periodos por defecto. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Tras acumular los valores medidos se incrementa una
variable global que indica en que muestra dentro del periodo estamos. Si
llegamos a SAMPLES_PERIOD (128) se resetea a 0 y seguimos acumulando datos
durante otro periodo. Si el indicador de periodo (period) llega a N_PERIOD (32)
se detiene el timer y se pone a 1 la bandera para pasar a procesar los datos
adquiridos. </span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">Los arrays donde se acumulan los datos son de tipo int16 y de tamaño 128 cada uno. Ocupan 128x2x2=512 bytes, por lo que será necesario reservar un par de bancos de la memoria del PIC para guardarlos. Hemos de usar un script del linker modificado como se explicó en entradas anteriores (el script .lkr modificado se enlaza al principio de esta entrada). </span><span style="font-family: Verdana;">En nuestro programa crearemos dos punteros I y V apuntando
a esa zona: </span><br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> udata big </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Memory needed for two int16 arrays (128 elements) <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte tmp[512]; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// located in specific section </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> udata </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">int16*
V=(int16*)&tmp[0]; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Pointer to first array (V measurements)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">int16*
I=(int16*)&tmp[256]; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Pointer
to second array (I measurements)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<br />
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En el programa principal es sólo cuestión de configurar el
ADC, timer TMR0 y la UART para eventualmente enviar datos:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST
& ADC_4_TAD,</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ADC_INT_OFF & ADC_VREFPLUS_VDD
& ADC_VREFMINUS_VSS, 7);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">TMR0L=0;
OpenTimer0(T0_16BIT&T0_SOURCE_INT&T0_PS_1_1); </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">stop_TMR0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">enable_global_ints;
enable_TMR0_int; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">// USART @ 19200
(32MHz)</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">OpenUSART(USART_TX_INT_OFF
& USART_RX_INT_OFF &USART_ASYNCH_MODE </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> & USART_EIGHT_BIT &
USART_BRGH_HIGH,103); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> printf(</span><span lang="EN-GB" style="color: #a020f0; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">"-- Power Meter ------"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">); salto_linea; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> start_TMR0; </span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Luego, entramos en un bucle sin fin:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> { </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> reset_datos(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Resets arrays, initializes samples=period=0, restarts TMR0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(data_ready==0);
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Wait until data is ready (while
capturing data)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> procesar_resultados(); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// Process
captured data</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> Delay10KTCYx(216); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// Delay<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La función reset_data inicializa los contadores sample y
period, pone a cero los arrays donde se acumularan los datos y pone en marcha el
timer TMR0, provocando el inicio de un proceso de captura. El bucle se bloquea
hasta terminar la captura (data_ready=1) y entonces se procesan los resultados. Opcionalmente
se puede añadir un delay entre captura y captura.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> reset_datos(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint8 k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k<SAMPLES_PERIOD) { V[k]=0; I[k]=0; k++;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> period=0; data_ready=0; sample=0; start_TMR0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br />
<br />
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Modo Calibración (determinación del desfase para una carga
resistiva)<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Dentro del procesado podemos hacer dos cosas (dependiendo
de unos #define). Si tenemos:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#define</span><span style="font-family: 'Courier New'; font-size: 9pt;"> CALIB</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">el programa lleva a cabo una calibración previa (necesaria
para compensar los desfases que tanto el voltaje del trafo como el de la bobina
que monitoriza la intensidad pueden tener un desfase con respecto al verdadero
voltaje o intensidad). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La idea es conectar una carga resistiva (bombilla
incandescente) y detectar el paso por cero de la señal procedente del trafo
(esencialmente asociada con el voltaje V) y de la señal de la bobina del sensor
de intensidad. Si no existiesen los desfases de los que hemos hablado ambos
pasos por cero deberían coincidir ya que con una carga resistiva Intensidad y
Voltaje deberían ir en fase. En nuestro caso no coincidirán. Dicho desfase lo
anotaremos y lo codificaremos en la parte del programa que lleve a cabo las
mediciones (cuando ya no estemos seguros de si la carga monitorizada es o no
resistiva). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Veamos el código usado para detectar los pasos por cero:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Detects zero
crossing (index + fraction)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> zero_crossing(int16* data)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint8 k,kk;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; tab-stops: 32.55pt; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0;k<SAMPLES_PERIOD;k++)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> kk=k+1; kk&=(SAMPLES_PERIOD-1); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ( (data[k]<=0) && (data[kk]>0) ) </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">break</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
ZC in [k,k+1]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac = (data[kk]-data[k]); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (frac==0)
frac=0.5; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac = -data[k]/frac; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//Fraction
within interval</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">frac+=k;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 9pt;"> frac;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<br />
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Simplemente se recorre el array data[] buscando un cambio de
signo (de - a +) entre los índices k y k+1. Dentro del intervalo se hace una interpolación
lineal para determinar la fracción dentro del intervalo donde ocurriría el
corte con el cero (que no vemos debido al carácter discreto de los datos).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Dentro de la función procesa_datos llamamos 2 veces a
zero_crossing, una para los datos de V y otra para los de I, calculamos la
diferencia y volcamos los resultados por el puerto serie. <span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shapetype
id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
margin-left:314.2pt;margin-top:5.45pt;width:162.8pt;height:188.45pt;z-index:1;
mso-position-horizontal:absolute;mso-position-horizontal-relative:text;
mso-position-vertical:absolute;mso-position-vertical-relative:text'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFXwu7i7xJrrutZtlGN7MZCtk_jMgvJSZLx93fKHJ6IxzyOAl8hwMHUCuwWYRBPrBZnUSvVtS3PLb1sez-q2tJS5IOQK5vlWiw7p-85sDxzWOyb96eI-zdcgac6fsLUxKlbOe4qcSt/s1600/volcado_delta_zc.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFXwu7i7xJrrutZtlGN7MZCtk_jMgvJSZLx93fKHJ6IxzyOAl8hwMHUCuwWYRBPrBZnUSvVtS3PLb1sez-q2tJS5IOQK5vlWiw7p-85sDxzWOyb96eI-zdcgac6fsLUxKlbOe4qcSt/s1600/volcado_delta_zc.jpg" /></a></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CALIB </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Calibration of initial phase shift</span><br />
<div class="MsoNormal">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">zc1=zero_crossing(V);</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">
zc2=zero_crossing(I);</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">dt = zc2-zc1; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (dt<0)
dt+=SAMPLES_PERIOD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k=float2str(txt,zc1,2);
txt[k++]=32;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k+=float2str(txt+k,zc2,2);
txt[k++]=32;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k+=float2str(txt+k,dt,2);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_txt(txt);
send_CR; send_LF;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 9pt;">;</span></div>
<div class="MsoNormal">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#endif</span><span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">A la izquierda podemos ver un típico volcado de
resultados. Los cruces por el cero no se mantienen de una mediada a otra (el
timer TMR0 está parado entre una serie de medidas y la siguiente y no hay
ninguna garantía de que el siguiente ciclo se empiece a muestrear en el mismo
punto que el anterior). Sin embargo la diferencia entre ambas medidas si que es
consistente, ya que ambas señales están sincronizadas entre ellas (a través de
la red).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Vemos que la intensidad va retrasada 5.33 (de media)
muestras con respecto al voltaje. Y no debería ser así. Lo que haremos cuando
estemos en modo medida es correr las medidas de la intensidad 5.33 muestras
hacia atrás, antes de empezar a operar con ellas de cara a medir potencia, etc.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Este desfase es del orden de 1msec y proviene en su mayor
parte del desfase introducido por el trafo, aunque también el sensor de
intensidad descoloca las cosas un poco.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Modo Medición de
potencia.<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez que hemos averiguado el desfase entre I e V cuando
no debería haber ninguno podemos usarlo para corregir la fase de medida.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En esta fase se vuelve a medir el paso por cero del
voltaje del trafo. Al valor encontrado le sumo el desfase antes encontrado
(p.e. 5.33). En ese punto debería encontrarse el cero de intensidad (y por lo
tanto de voltaje) si tuviésemos una carga resistiva pura:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Measurements</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> zc1=zero_crossing(V); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
zero crossing for V</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> zc1+=5.33; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Add phase found during calibration </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (zc1>=SAMPLES_PERIOD) zc1-=SAMPLES_PERIOD; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Correct for rollover<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ZC = (uint8)zc1; frac = zc1-ZC; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Extracts index and fraction</span><span style="font-family: 'Courier New';"> </span></div>
</div>
<br />
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En ZC guardo la parte entera del desfase detectado y en frac la fracción. </span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">A continuación desplazo (ZC muestras) e
interpolo (por la fracción frac) los datos de intensidad, para colocarlos con
referencia al arranque del ciclo de voltaje. Para hacer dicho reordenamiento
uso el array V[], cuyos valores ya no necesito para nada (solo lo uso como base
de tiempos):<span style="font-size: x-small;"><o:p></o:p></span></span><br />
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Array V
is not needed anymore, will use it to store array I shifted (by ZC) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0,kk=ZC;k<SAMPLES_PERIOD;k++,kk++) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Shift data ZC indexes</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> kk &= (SAMPLES_PERIOD-1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> V[k]=I[kk];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0,kk=1;k<SAMPLES_PERIOD;k++,kk++) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Interpolate I between k,k+1 using frac</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> kk &= (SAMPLES_PERIOD-1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ii = (V[kk]-V[k]); ii*=frac; ii+=V[k];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ii*=0.3815;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// INtensity in mA</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> I[k]=(int16)ii;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">} </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<br />
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El factor <b>0.3815</b> relaciona el valor en el array donde hemos
acumulado las medidas y la intensidad en la red (mA). Sabemos que:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">V_bob = I /2.5 , I = intensidad deseada (en A) , luego I(ma) = 2500 V_bob<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">V_bob está relacionada con el resultado del ADC de la forma
siguiente:</span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;"> V_bob = (ADC/1024)*5V<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Finalmente, el valor contenido en el array I[k] es en
realidad la suma de N_period (32) valores del ADC, por lo que:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana;">I = 2500
V_bob = 2500 (ADC/1024)*5 = 2500
((I[k]/32)/1024)*5 </span><br />
<span lang="EN-GB" style="font-family: Verdana;"> = 0.3815 I[k] (en mA)<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si usais otro voltaje (5V) en el micro, un número diferente
de niveles (1024) o un número distinto de periodos (32) tendréis que cambiar
esta constante. Por supuesto si usáis un sensor de intensidad distinto, la
relación inicial (I = 2500 Vbob) también habrá que cambiarla.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez que tenemos la intensidad medida alineada con el
voltaje es sólo cuestión de hacer unas pocas cuentas para calcular Irms,
<P> real, Prms y factor de potencia. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Las integrales que aparecían antes se aproximan por
sumatorios. La potencia queda p.e.:<o:p></o:p></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3CJRUtYf0TTtnZJVJfgW7CmKm413nMUs88_2fCyaoVxgWIGJMnmIErQ869VNjJzxMvE53q31aIY0IUgn3lvrWNFaspZWE6a0mU1qVL19Ws7xnoBJbvO6PPdB6lrr4uYSoGoe_wGHk/s1600/formula10.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3CJRUtYf0TTtnZJVJfgW7CmKm413nMUs88_2fCyaoVxgWIGJMnmIErQ869VNjJzxMvE53q31aIY0IUgn3lvrWNFaspZWE6a0mU1qVL19Ws7xnoBJbvO6PPdB6lrr4uYSoGoe_wGHk/s1600/formula10.jpg" /></a><span style="font-family: Verdana; font-size: 10pt; text-align: justify;"> </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Los valores del voltaje ideal (para Vrms = 230) han sido
precalculados (en 128 muestras/ciclo) y guardados previamente en un array en
memoria de programa:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Computes <P>
and Irms using measured intensity + ideal voltage </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Preal=0;
Irms=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0;k<SAMPLES_PERIOD;k++)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> vv = Vteo[k]; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Ideal voltage (230 rms) sampled @ 128 samples/cycle</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ii = (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">)I[k]/1000; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// I
measurement (Amps)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Irms
+= (ii*ii); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Computes Irms</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Preal += (ii*vv); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Computes <P></span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Irms=sqrt(Irms/SAMPLES_PERIOD);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Preal=Preal/SAMPLES_PERIOD; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Vrms=230; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Prms = Vrms*Irms; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">factor = Preal/Prms;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Sólo queda volcar los datos por el puerto serie. Si se
define la opción TEXTO los resultados (Irms, Prms, Preal y factor de potencia)
se vuelcan en formato texto usando las rutinas que vimos para formatear números
reales:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#define</span><span style="font-family: 'Courier New'; font-size: 9pt;"> TEXTO</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> TEXTO </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Dumps results as text through the serial port <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> float2str(txt,Irms,3); send_txt(txt);
send_byte(32);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> float2str(txt,Prms,1); send_txt(txt); send_byte(32);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> float2str(txt,Preal,1); send_txt(txt);
send_byte(32);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> float2str(txt,factor+5e-4,3); send_txt(txt); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_CR; send_LF;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Dumps binary data (I) to be used by a MATLAB program (power_meter.m)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">ptr=(uint8*)I;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Pointer to array </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_byte(65); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 'A'</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(temp=0;temp<256;temp++)
send_byte(ptr[temp]);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_byte(msg_cont++);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_byte(90); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 'Z'</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#endif</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El resultado, cuando tenemos conectada la bombilla que
usamos de calibración es:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana;">+0.254
+58.6 +58.6 +1.000<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">obteniendo una intensidad rms de 0.25A y una potencia
medida de unos 59W. El factor de potencia sale justo 1, pero eso se esperaba
puesto que es la bombilla usada en la calibración. Sin embargo los 59W que
vemos nos indica que el factor (0.3815) deducido para la relación entre la
medida tomada del sensor y la verdadera intensidad es correcto.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Programa MATLAB
(gráficos):<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si la opción TEXTO no está definida lo que hace el
programa es mandar (en su formato nativo) los 128 datos de intensidad (en mA)
por el puerto serie. Dichos datos estaban alineados con un ciclo del voltaje.
El programa adjunto (power_meter.m) de MATLAB recibe los datos, y hace unas
gráficas con el voltaje ideal (Vrms=230V), la intensidad medida y la potencia
instantánea en un ciclo. Como tiene todos los datos puede también presentar los
resultados de Irms, Prms, factor de potencia, etc.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En las siguientes gráficas se adjuntan algunos ejemplos: arriba </span><span style="font-family: Verdana;">una lampara incandescente etiquetada como
60W. La medida de potencia son 59W y la intensidad sigue fielmente la forma del
voltaje, por lo que el factor de potencia=1.00</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Abajo una lámpara de tipo CFL etiquetada como 20W. se
observa una gran diferencia entre la Preal y la Prms, debido a que la forma de
onda de la intensidad dista mucho de una sinusoide. En este caso la potencia
declarada (20W) parece estar entre medias de la potencia rms (25W) y la
potencia real (15W).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFBGK0dKazPKk1ClCMq75dVvonOE-l-X5T28EXMSbatRNLHyRdv2XObDIuV-u877PuwRX7AMH8ock6-dtdkZtSndnFf5wsjqIowZ6IrCD9eRd-tdJm6DRG2KG9oF1LeSXJawrjpOkd/s1600/incadescente_60W.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFBGK0dKazPKk1ClCMq75dVvonOE-l-X5T28EXMSbatRNLHyRdv2XObDIuV-u877PuwRX7AMH8ock6-dtdkZtSndnFf5wsjqIowZ6IrCD9eRd-tdJm6DRG2KG9oF1LeSXJawrjpOkd/s320/incadescente_60W.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCJPwSr22r_FNZCJPcws4Bc8Xr_KvreFScnPFtyIzUn8N8gDXJN2nnJHHHg8ajuADCHAGE4jcxW1Vo8neyMzwTWaC3ElgVt60WQpaZAIJEQML5CmT7w7UakT-ejUbWQO-3xWRqgIkE/s1600/captura_CFC_20W.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="239" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCJPwSr22r_FNZCJPcws4Bc8Xr_KvreFScnPFtyIzUn8N8gDXJN2nnJHHHg8ajuADCHAGE4jcxW1Vo8neyMzwTWaC3ElgVt60WQpaZAIJEQML5CmT7w7UakT-ejUbWQO-3xWRqgIkE/s320/captura_CFC_20W.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En las siguientes gráficas se muestra el consumo de una fuente de alimentación de un portatil sin (arriba) y con (abajo) el PC conectado:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijmxuGVr9m7xW-uZrWJBu58kGmAtNhGtoSz5xdAJnrWxxJSbbJY5C51iz0cvwABr9Fh4kE7dO9HsvJenXdrKZDQyPmakzOIO70lXVrRby7mPe_EcmFtxqUn1Lbt6NBLBKIR-gKkNgm/s1600/alimentacion_portatil_65W_sin_conectar.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijmxuGVr9m7xW-uZrWJBu58kGmAtNhGtoSz5xdAJnrWxxJSbbJY5C51iz0cvwABr9Fh4kE7dO9HsvJenXdrKZDQyPmakzOIO70lXVrRby7mPe_EcmFtxqUn1Lbt6NBLBKIR-gKkNgm/s320/alimentacion_portatil_65W_sin_conectar.jpg" width="320" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiV2mcCntmEfJZjryfhYC-zGHkiCoSzauVP8eXoltr9hTQTQBl-erDYxJlZjw6547i0iDx1fnl7Y7XmKghUeOBBAisr4Fx7hsIny1x8fmaBnUpNSKWEQZxgWpIaAGtz-4aj7dvPT5h/s1600/alimentacion_portatil_65W.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiV2mcCntmEfJZjryfhYC-zGHkiCoSzauVP8eXoltr9hTQTQBl-erDYxJlZjw6547i0iDx1fnl7Y7XmKghUeOBBAisr4Fx7hsIny1x8fmaBnUpNSKWEQZxgWpIaAGtz-4aj7dvPT5h/s320/alimentacion_portatil_65W.jpg" width="320" /></a></div>
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<span style="font-family: Verdana;">Se observa que aunque la potencia RMS es de unos 5W en ausencia de carga, la potencia real es mucho menor. Con carga se consumen unos 70W. La fuente de alimentación está etiquetada como de 65W. De nuevo, debido a la fuerte no linealidad de la intensidad con respecto al voltaje el factor de potencia se aleja mucho de la unidad.</span><br />
<br /></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com18tag:blogger.com,1999:blog-4945680608471335280.post-48054292283464288212013-06-04T16:05:00.003+02:002013-06-04T16:05:34.002+02:00Formateo de números en coma flotante<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como comentamos en la entrada anterior, la función sprintf
(y sus variantes) del compilador C18 no tienen soporte para volcar datos de
tipo float en coma flotante (modificador %f en ANSI C). La posible razón es que
interpretar y volcar números en coma flotante no es trivial, por lo que el
código necesario es relativamente grande. La función sprintf ya ocupa bastante
código (alrededor de 2K word) y si incluyese soporte para números reales su
tamaño posiblemente se doblaría. Al ser una función monolítica, dicho coste
adicional lo sufrirían incluso aquellos usuarios que nunca trabajasen con
números en coma flotante.</span><b><span style="font-family: Verdana;"><o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<!--[if gte vml 1]><v:shapetype
id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
left:0;text-align:left;margin-left:318.6pt;margin-top:.1pt;width:156.7pt;
height:121.85pt;z-index:1'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqQ-XaUXH0xex2x22ye6UWto-D4obyroPsOTRGeiTmhe7P4wMr8WII8lLueJQi-3G3XvsHh2cmKiHWPnnNgkUU55xhITFSMz9hhpBvP6fzufCl87vc-gLF8LpQojNXZiBRh6stSCc/s1600/volcado.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZqQ-XaUXH0xex2x22ye6UWto-D4obyroPsOTRGeiTmhe7P4wMr8WII8lLueJQi-3G3XvsHh2cmKiHWPnnNgkUU55xhITFSMz9hhpBvP6fzufCl87vc-gLF8LpQojNXZiBRh6stSCc/s1600/volcado.jpg" /></a><span style="font-family: Verdana;">En esta entrada vamos a describir la representación
de números en coma flotante dentro del PIC para entender como se guarda la
información. A partir de ahí crearemos un par de rutinas que nos permitan
volcar este tipo de datos a una cadena.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El objetivo es poder sacar datos por el LCD o puerto serie
con los formatos mostrados en la figura adjunta, que corresponden a %e
(izquierda) y %f (derecha) del printf definido en ANSI C.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; text-align: start;">Código asociado a esta entrada: </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/float2ascii.c" style="font-family: Verdana; text-align: start;">float2ascii.c</a><span style="font-family: Verdana; text-align: start;"> </span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; text-align: start;"></span></div>
<a name='more'></a><br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">-------------------------------------------------------------------------------------------<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana, sans-serif;">Números reales en coma fija:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Tendemos a asociar los números reales a una
representación de coma flotante porque así es como se manejan en la mayoría de
los ordenadores actuales. Sin embargo una alternativa a usar coma flotante (y
que para ciertas aplicaciones puede ser preferible) es usar una representación
en coma fija.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Una representación en coma fija no es más que el uso de
una representación entera junto con el
acuerdo de que la unidad de dichos enteros no vale 1, sino un cierto valor
acordado de antemano (valor del dígito menos significativo). Por ejemplo
podemos manejar enteros en base diez y decidir que las unidades valen 0.01. El
ordenador guardaría y operaría con enteros pero al final, si el dato almacenado
en memoria fuese el 12345, lo presentaríamos como 123.45, ya que la unida
del dígito menos significativo valer 0.01.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Esencialmente se está usando un tipo entero de datos (con las ventajas que eso conlleva en un micro
que carece de un hardware específico de coma flotante). A la hora de enseñar
los resultados, simplemente colocaríamos el punto decimal en el lugar adecuado.
Como el valor del digito menos significativo está fijado, el puesto del punto
(o coma) decimal será siempre el mismo (2ª posición por la derecha en el caso
anterior). De ahí el nombre de coma fija que recibe esta representación. La
característica principal de una representación en coma fija es que el salto
entre sus números es constante (0.01 en el nuestro ejemplo). <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Si estamos usando base 10 es trivial ir volcando los dígitos
de un número entero y al llegar a la posición de la coma pintar el carácter
"." y terminar de volcar los restantes dígitos. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Al estar usando base 2 es un poco más complicado, pero no
mucho más. En la entrada anterior vimos como convertir un número entero de base
2 a base 10. Ahora nos planteamos convertir una fracción decimal (en base 2) a
base 10. Consideremos un byte compuesto de 8 bits (p.e. 10010101). Obviamente
codifica un número entero desde 0 a 255 (en este caso el 149). Pero si
decidimos que la coma que separa la parte entera de las fracciones la
posicionamos (por ejemplo) separando los 5 primeros bits de los 3 últimos el
número binario quedaría: 10010.101<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La interpretación de dicho número sería:</span><span style="font-family: Verdana; font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 36.5pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 14.0pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.55pt;" valign="top" width="70">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">Valor<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">16<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">8<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">2<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 43.2pt;" valign="top" width="58">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1/2<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 43.2pt;" valign="top" width="58">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1/4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1/8<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.1pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.55pt;" valign="top" width="70">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">Posición<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b(4)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b(3)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b(2)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b(1)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 43.2pt;" valign="top" width="58">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">B(-1)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 43.2pt;" valign="top" width="58">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b(-2)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.1pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">b(-3)<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.75pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.55pt;" valign="top" width="70">
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;"> 1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 43.2pt;" valign="top" width="58">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 43.2pt;" valign="top" width="58">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.95pt;" valign="top" width="57">
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;">1<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La parte entera es 10010 (18 en decimal). En cuanto a la
fracción, cada bit a la derecha de la
coma "decimal" valdrá sucesivamente 1/2, 1/4, etc. de la misma forma
que en base 10 los decimales valen 0.1, 0.01, etc. Por lo tanto, el número
codificado por el byte 10010101 será:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> Parte entera: 1 x 16 + 0 x 8 + 0 x 4 + 1 x 2 + 0 x 1 =
18<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> Fracción :
1 x 1/2 + 0 x 1/4 + 1 x 1/8 =0.5+0.125
= 0.625 <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El resultado es 18.625. Está representación tiene una
resolución (separación entre números sucesivos) de 1/8 = 0.125 (el valor del
dígito menos significativo). Cada bit vale ahora 0.125, en lugar de 1 unidad
(de hecho si hacemos 149 x 0.125 obtenemos 18.625). Obviamente en un byte sigue habiendo espacio para sólo
256 valores, por lo que lo que ganamos en precisión lo perdemos en rango: la
representación sólo puede manejar números desde 0.00 (0/8) hasta 31.875
(255/8). <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Se trata ahora de volcar estos números en base 10. La
parte entera ya sabemos hacerlo. En el ejemplo anterior bastaría quedarnos con
la parte entera (b >> 3) y usar una de las rutinas vistas en la entrada
anterior (o sus equivalentes tipo itoa de C18) para crear una cadena ASCII
conteniendo un 18. Nos falta un poco de código para volcar la parte fraccionaria
(.625).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como ejemplo del algoritmo a usar, el siguiente código
int2frac recibe un entero sin signo de 16 bits (uint16) e interpreta sus 12
bits menos significativos como si fuesen una fracción decimal, volcándola con
ndec decimales (base 10) de la forma '.XXX'.
Como un dígito decimal equivale a algo más de 3 dígitos binarios solo tiene
sentido presentar un máximo de 3 o 4 (12 bits / 3.algo) decimales. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El código ignora cualquier posible contenido de los 4 bits
más significativos. Los pone a 0 al principio y usa ese espacio para ir sacando
los sucesivos decimales:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint8 int2frac(uint16 frac, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ndec, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* dest)<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// The function
decodes the 12 least significant bits of a uint16 as a <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// decimal fraction
and writes it as .xxx in dest[], using ndec decimal figures</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Since one decimal
figure equals log2(10)=3.x binary digits, you'd be getting</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// garbage past the
3th or 4th decimal figure.<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// If ROUNDING is
defined, considers rounding and returns 1 if there is a carryover <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// into the integer
part. Otherwise (or if rounding is not considered) it returns 0. </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dig,i,p=12;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint16 mask;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint8 k=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=46; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// "."</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> mask = 0x0FFF; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(i=0;i<ndec;i++)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac&=mask; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac*=10; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dig = (frac>>p);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=dig+48;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k]=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ROUNDING</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> frac&=mask;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dig=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(frac>=2048) dig=1; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> i=k-1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(dig && (i>0))</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[i]++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (dest[i]==58) dest[i]=48; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dig=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> i--;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dig;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#endif</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> 0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: Verdana;">La
primera parte del código (hasta el </span><span style="color: #b28c00; font-family: 'Courier New';">#ifdef</span><span style="font-family: 'Courier New';"> ROUNDING</span><span style="font-family: Verdana;">) va sacando los sucesivos
decimales. Es más sencillo que el usado para volcar la parte entera. En primer
lugar los decimales se obtienen empezando por el más significativo, por lo que
pueden ser volcados según van saliendo. Además, en vez de tener que ir
dividiendo por 10, lo que se hace a cada paso es multiplicar por 10, una
operación más rápida. </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En la 2ª parte del código, si ROUNDING está definido la
función redondea correctamente para mostrar la fracción más cercana con los decimales
dados. Por ejemplo, con 2 decimales la fracción 0.2785 se vería como 0.28. Si
por el contrario ROUNDING no está definido la fracción se mostraría truncada
como 0.27.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El problema de usar redondeo es a veces no sólo afecta al
último dígito como sucede en el ejemplo anterior. Si tenemos la fracción
0.2985, tras volcarla como ".29" tendríamos que modificarla a ".30"
si se usa redondeo. Mayor problema tendríamos con una fracción como 0.999. Si
la truncamos con 2 decimales tendríamos ".99". Si queremos redondearla
sería ".00" y deberíamos incrementar por 1 la parte entera (que ya
estaba "escrita" en la cadena). Por eso la función anterior devuelve
1 si tras redondear hay un acarreo hacia la parte entera.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En general, salvo que sea imprescindible, se recomienda
truncar y no redondear. Los resultados serán un poco menos precisos, pero nos
evitaremos mucho trabajo. En el caso anterior (acarreo a la parte entera)
tendríamos que sumar uno al número entero. Y eso podría producir sucesivos
acarreos (pensar en 99.99). Truncar nunca nos obligará a modificar el trabajo
ya hecho, por lo que será mucho más rápido.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Limitaciones de las representación
en como fija:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Cualquier intento de representar infinitos números (los
reales) con un número finito de casillas va a tener limitaciones. Las
limitaciones son de dos tipos:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">Rango:
en la representación anterior (un byte) teníamos un rango de 0 a 32 aprox.
Números mayores no podrían manejarse. La solución si necesitamos más rango
es aumentar el número de casillas (a int16 o int32).<o:p></o:p></span></li>
</ul>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">El
otro problema es la resolución o salto entre números. Como hemos comentado
la característica principal de una
representación en coma fija es que el salto entre sus números es constante
(0.01 en el primer ejemplo o 0.125 en el caso de la representación binaria
anterior). <o:p></o:p></span></li>
</ul>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Cuando intentamos meter un número real dentro de una cierta
representación cometeremos un error. Sea la representación binaria (usando 1
byte) anterior y el número real 12.342. Dicho número cae entre: <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 70.8pt; text-align: justify; text-indent: 35.4pt;">
<span style="font-family: Verdana;"> 12.250 (01100.010) <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 70.8pt; text-align: justify; text-indent: 35.4pt;">
<span style="font-family: Verdana;"> 12.375 (01100.011)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Los números anteriores son representados de forma exacta
en la representación dada (es lo que se llama números máquina). Pero 12.342 no
"está" en la representación. Podremos optar por cambiarlo por alguno
de los anteriores (12.250 si truncamos, 12.375 si redondeamos). El caso es que
cometeremos un error. El error máximo (cota) posible corresponde a la mitad (si
hay redondeo previo) o todo (si truncamos) el intervalo entre números. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como dicho intervalo es constante, también lo será nuestra
cota del error absoluto. Por lo tanto, una representación en coma fija mantiene
constante el error absoluto.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El problema es que suele ser más conveniente mantener
constante el error relativo que el absoluto. No es lo mismo error de 0.1 si manejamos
un número como 1232.76 que si el número es el 0.34. En el primer caso el error
relativo cometido al convertirlo a 1234.8 puede ser despreciable (0.003%), pero
el en otro caso (0.34 </span><span style="font-family: Wingdings;">à</span><span style="font-family: Verdana;">
0.3) es del orden de un 15%.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Las representaciones en coma fija son adecuadas cuando los
números que vayamos a manejar no cubran un rango excesivo. Si los números a
usar son más o menos similares, usar errores absolutos o relativos es
equivalente. Si el rango de posibles números a manejar es muy grande, es mejor
abandonar la representación en coma fija
y pasarnos a coma flotante.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La ventaja de una representación en coma flotante es que
mantiene constante el error relativo y puede manejar un rango mucho mayor de
números, manteniendo mejor controlado el error.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Números reales en coma flotante:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La representación de un número en una representación en
coma flotante basada en la base B consiste en:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 106.75pt; mso-list: l2 level1 lfo4; tab-stops: list 106.75pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]--><span style="font-family: Verdana;">Signo
(+/-)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 106.75pt; mso-list: l2 level1 lfo4; tab-stops: list 106.75pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]--><span style="font-family: Verdana;">Mantisa
positiva m, en el intervalo [1,B<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 106.75pt; mso-list: l2 level1 lfo4; tab-stops: list 106.75pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span lang="PT-BR" style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]--><span lang="PT-BR" style="font-family: Verdana;">Exponente e, positivo o negativo. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Con estos datos, el número representado es (+/-) m x B^e<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Una notación en coma flotante es similar a la conocida
representación científica donde números como 123 o 0.057 se expresan como 1.23
10^2 o 5.7 10^-2.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En el caso de la notación científica (destinada a nuestro
uso) estamos usando B=10. Dentro de un ordenador es mucho más común usar B=2.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El PIC no tiene un soporte nativo para coma flotante, por
lo que cada compilador es libre de escoger los parámetros que desee al
implementar (por software) su representación. En el caso del compilador C18 se
ha escogido la misma representación que se usa en la mayoría de los ordenadores
personales, la basada en el standard IEEE 754 cuyos parámetros son:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l3 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">Base
B=2</span></li>
</ul>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l3 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">1
bit dedicado al signo.</span></li>
</ul>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l3 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">8
bits dedicados al exponente. El signo se maneja con un sesgo (127). Eso
quiere decir que al número (sin signo, de 0 a 255) que se guarde en esos
bits debemos restarle 127 para obtener el exponente. De esta forma podemos
manejar exponente positivos (para números mayores que 1) y negativos
(números menores que la unidad).</span></li>
</ul>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l3 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">24
bits dedicados a codificar la mantisa (obviamente en binario)<o:p></o:p></span></li>
</ul>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Un número en coma flotante ocupa por lo tanto (1+8+23 = 32
bits = 4 bytes)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La razón por la que solo cuento 23 bits para la mantisa es
que uno de sus 24 bits no es necesario guardarlo. La mantisa (para garantizar
unicidad) debe estar en el intervalo [1,2). Luego debe ser 1.algo. Por lo tanto
su primer bit siempre será 1 (no puede ser 0 porque 0.xxx es menor que 1). Y si
siempre es 1 no hay que gastar espacio para guardarlo. Es lo que se llama un
bit implícito o bit fantasma. Si los bits almacenados son b1,b2,b3,…,b23, la
mantisa se interpretará como:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> m =
1.b1 b2 b3 . . . b23 = 1 +
b1/2 + b2/4 + . . . + b23 2^-23<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Esto quedará más claro con un ejemplo. El siguiente código
crea una variable float x y le asigna el valor x=5.75. A continuación apunto
con un puntero tipo uint32 (32 bits) a la dirección donde la variable se
almacena (&x) y obtengo el valor almacenado (operador *) en una variable de
tipo uint32. Usando la rutina Long2Bin vuelco los 32 bits que codifican al número
5.75 en una cadena de texto<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">x=5.75; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> l = *(uint32*)&x; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Long2Bin(txt,l); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Si vuelco dicha cadena por el puerto serie o el LCD obtengo
el siguiente resultado:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> 01000000101110000000000000000000<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">que podemos separar en:
0 10000001 01110000000000000000000<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">1
bit de signo: 0 = +<o:p></o:p></span></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">8
bits de exponente: 10000001 =
129 </span><span style="font-family: Wingdings;">à</span><span style="font-family: Verdana;"> e = 129-127 = 2<o:p></o:p></span></li>
<li class="MsoNormal" style="mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">23
bits mantisa: 01110000000000000000000, que interpretaremos (con bit
fantasma)<o:p></o:p></span></li>
</ul>
<div class="MsoNormal" style="margin-left: 18.0pt; text-align: justify;">
<span style="font-family: Verdana;">
<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt; text-align: justify;">
<span style="font-family: Verdana;"> 1.01110000000000000000000 = 1 +
0/2 + 1/4 + 1/8 + 1/16 = 1.4375<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">¿Qué tienen que ver ese exponente y mantisa con el número
original? Podemos ver que: <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> 1.4375 x 2^2 =
1.4375 x 4 = 5.75 = x<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La representación usada por C18 es esencialmente la misma
que la del standard IEEE 754. (aunque tiene algunas carencias, por ejemplo, la
ausencia de números denormalizados). Eso es conveniente porque podemos mandar
datos float en binario a través del puerto serie o grabarlos en una tarjeta de
memoria y serían directamente legibles desde nuestro PC.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Nota:</span></b><span style="font-family: Verdana;"> otros compiladores usan pequeñas
variantes de este esquema. Por ejemplo el compilador de MikroCPro usa también
este reparto de bits (1 signo, 8 exponente, 23 mantisa) pero por conveniencia
altera su orden (8 exp , 1 signo, 23 mantisa). De esta forma el exponente (8
bits) es justo el primer byte de los 4 que forman un float y podemos acceder y
operar con él más eficazmente que antes (donde está repartido entre dos bytes).
En este caso los floats usados por MikroC Pro no serían directamente
exportables a nuestro PC (aunque tienen la misma precisión que el standard,
porque el número de bits y su reparto no ha cambiado). <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">¿Errata en manual
de Microchip?:</span></u></b><span style="font-family: Verdana;">
el manual de las librerías del C18 (funciones matemáticas, capítulo 5) parece indicar
que su compilador usa la misma organización interna que MikroC Pro en sus
variables float: 1er byte dedicado al exponente y 3 bytes dedicados a signo y
mantisa (1+23). Incluso suministra un par de rutinas para cambiar de uno a otro
formato. Sin embargo, con los datos del ejemplo anterior a mi me parece claro
que C18 está usando el orden "correcto" definido por IEEE754.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Todas las rutinas siguientes asumen que C18 usa el orden
definido por el standard IEEE754 y a mi me están funcionando adecuadamente. <b style="font-size: 10pt;"><u><o:p></o:p></u></b></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Volcado de números
reales a ASCII:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">A las complicaciones de manejar coma flotante se le añade
el problema del cambio de base, aunque para ello contamos con la experiencia de
las rutinas que vimos en la entrada anterior.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La primera solución que se nos ocurre si queremos volcar
datos de tipo float en el PIC es separar parte entera y parte fraccionaria. Por
ejemplo, sea el número 1234.5678, que queremos volcar con 2 decimales. El
siguiente código: <span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> x = 1234.56789</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">i = (int16)x;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Integer part = 1234</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">x-= i;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Fraction = 0.5678 </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">x*=100; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Fraction x 100 = 56.78</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">f = (uint16)x;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Force to int = 56</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">extrae la
parte entera (i=1234) y fraccionaria (f=56). Luego podemos usar itoa o Word2Dec
(vista en la entrada anterior) para
volcar ambos números intercalando un punto decimal entre medias obteniendo así "1234.56".<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">¿Qué
posibles problemas tiene este enfoque?<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal"><span style="font-family: Verdana;">No hemos redondeado
correctamente. 1234.5678 con dos decimales debería aparecer como 1234.57.
Esta es un problema menor, que nos perseguirá aunque usemos otros
enfoques. Como hemos visto antes, redondear trae algunas pegas.<o:p></o:p></span></li>
</ul>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal"><span style="font-family: Verdana;">La resta de la parte entera (x-=i)
y la multiplicación por 100 (x*=100) son operaciones con floats y por lo
tanto lentas.<o:p></o:p></span></li>
</ul>
<div class="MsoNormal">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal"><span style="font-family: Verdana;">Una pega importante es que si
el número hubiese sido 1234.0567 habríamos obtenido i=1234 y f=5 y
escribiríamos el resultado como 1234.5 en vez de 1234.05. Se podría
arreglar recordando el número de decimales (2) y rellenando con 0's pero
es un rollo.<o:p></o:p></span></li>
</ul>
<div class="MsoNormal">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal"><span style="font-family: Verdana;">Otro problema aparece cuando
tenemos números muy grandes o muy pequeños. En general no deseo ver cosas
como:<o:p></o:p></span></li>
</ul>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;">
12345678901230000000.000 (mejor
1.234e20)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;">
0.0000000000000000001234 (mejor
1.234e-20)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana;"> En otras palabras, desearía tener la posibilidad de usar notación científica al volcar los resultados.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Rutina float2str: similar a usar
el descriptor %f en printf (ANSI C).<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Nuestro
primer objetivo será escribir una rutina que vuelque un número real con un
cierto número de decimales (el equivalente del modificador %f en la cadena de
formato de printf):<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint8 float2str(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* dest,</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> x, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">short</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dec)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Writes float to
dest[] with a xxx.yyy format with dec decimal digits</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Works if |x| less
than 65535. At most 4 digits after the point.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// For numbers greater
than 65536 or less than 0.0001 use float2exp</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// that writes real
numbers using scientif notation.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Lo primero que tenemos que hacer es acceder al contenido
de x interpretándolo como un entero de 32 bits. Luego (sabiendo donde está cada
cosa) con operaciones de desplazamiento y AND lógico extraemos los bits
correspondientes a signo, exponente y mantisa: <span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">F = *(uint32*)&x;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (F &
0x80000000) s=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Sign bit = MS bit</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> E = ((F>>23)&0xFF); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Exponent bytes (8 bits following sign bit)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> F = F & 0x007FFFFF; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Mantissa<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (E>0) F = F | 0x00800000; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Add phantom bit to mantissa 1.xxxxxxx</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> e = (E-0x7F);
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// non biased exponent</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Las dos últimas líneas añaden el
bit fantasma a la mantisa y corrigen el sesgo (127) del exponente. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como hemos dicho antes con este
formato no me gusta ver números muy grandes ni muy pequeños. Lo primero que
hago es ver el número está en el rango adecuado (observando su exponente):<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Number too large: X</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (e>=16) { dest[0]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'X'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; dest[1]=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> 1;} </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Number too small: 0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (e<=-16) { dest[0]=48; dest[1]=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si el exponente (valor absoluto)
es mayor que 16 el número se considera fuera de rango y no se sigue procesando.
Se muestra un 0 (si |x|<1e-5) o X (|x|>65536) para indicarlo.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si queremos ampliar el rango de
números a mostrar tendríamos que modificar este código. </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez decidido que el número
está en el rango deseado, pasamos a separar su parte entera (I) y los primeros
12 bits de su mantisa (por lo que estaremos limitados a mostrar unos 3 o 4
decimales):<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Extracts integer
part(I) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> p = 23-(int8)e; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//position
of "decimal" point when exponent is taken into account</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p>24) I=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
I=F>>p; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// integer part</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// First
12 bits of fraction (F)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> p -=12; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p>=24) F=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p>=0) F>>=p; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> F<<=(-p); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">F&=0x0FFFL;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez que disponemos de signo
(s), parte entera (I) y fracción (F) es sólo cuestión de volcar dichos
contenidos en la cadena de destino, usando las rutinas Word2Dec (para parte
entera) e int2frac (para la fracción):<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Write float number: sign + integer part + fraction</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[0]=43+(s<<1); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Sign 43 = +, 45 = -</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k=1; k+=Word2Dec(dest+k,(uint16)I,1); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Integer </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> int2frac(F,dec,dest+k); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// sends 12 MS bit to INt2frac </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">k+=(dec+1);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 9pt;">(k);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La
función devuelve el número de caracteres escritos. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En el código suministrado la función se completa con unos
#ifdef que permiten seleccionar si se desea o no redondeo (#define ROUNDING) y
si se está usando el formato de floats del compilador MIKROC Pro (#define
MIKROE). Por defecto se usa el formato de C18 (IEEE 754).<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Descriptor %e en ANSIC
sprintf: función float2exp()<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Vamos a ver una rutina (float2exp) que vuelca un número
real en notación científica, de forma similar al descriptor %e en la función
sprintf de ANSI C. Por ejemplo, el número 1234.5678 se presentaría como: <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> 1.234e+03 1.23e+03, etc. dependiendo del número de decimales de
mantisa elegidos.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Aunque hemos visto que la notación científica y la
representación en coma flotante son esencialmente la misma cosa (mantisa, base,
exponente), la pega principal es que en el PIC la base usada es 2 mientras que
en nuestros volcados querremos usar base 10. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Los parámetros de entrada de la rutina serán el puntero a
la cadena de texto donde volcaremos el número, el número a volcar y el número de
decimales a usar para la mantisa:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint8 float2exp(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* dest, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> x, uint8 dec)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Writes the real
number x in string starting at *dest, </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Uses using
scientific notation: 123456.7890 is written as 1.234e+05. </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// The third argument
dec are the number of decimal digits used in mantissa.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Empezaremos con la versión más simplificada del código y
luego iremos comentaremos algunas complicaciones que podemos considerar (opcionales a través de #defines):<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Al igual que antes, accedemos a los contenidos de x como
un entero de 32 bits (uint32) y de ellos extraemos el signo (bit más
significativo), bits de exponente (8 siguientes bits) y mantisa (23 bits menos
significativos). Los bits de exponente se corrigen por el sesgo para obtener el
verdadero valor del exponente. Con la opción #define MIKROE podemos acceder a
dichos datos en el formato IEEE754 modificado:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">r=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> MIKROE</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (m & 0x00800000) r=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Sign detection (+ -> r=0, - ->
r=1) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> p = (m>>24); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Extract exponent bits </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// C18
format</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (m & 0x80000000) r=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Sign detection (+ -> r=0, - ->
r=1) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> p = ((m>>23)&0xFF); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Extract exponent bits </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#endif</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> m &= 0x007FFFFF; </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// Mantissa</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> e=p; e-=0x7F; </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// corrects exponent bias (127 =
0x7F)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez
que contamos con la mantisa (m) y exponente (e) el siguiente código hace el
trabajo principal de la rutina, pasando de un número representado como:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> m 2^e </span><span lang="EN-GB" style="font-family: Wingdings;">à</span><span style="font-family: Verdana;"> x.yyyy
10^e10 con x un digito entre 1 y 9<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Es decir, pasamos de mantisa (m) y exponente (e) en base 2
a mantisa y exponente (e10) en base 10. Esencialmente el código va
multiplicando/dividiendo por 10 si el número es pequeño/grande hasta conseguir que
la mantisa (en base 10) quede en el intervalo [1, 10). <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El exponente en base 10 se guarda en la variable e10.
Empezamos con e10=0 y se incrementa/decrementa cada vez que se divide o multiplica
por 10 el número original. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código
no se ejecuta si los bits del exponente son 0, ya que ese caso singular representa
una mantisa = 0 (y por lo tanto el número representado es el 0.0):</span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Reduce m 2^e to to
x.yyy 10^e10 with leading digit x = 1, 2, .., 9
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> e10=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p>0) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Non 0 number</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> m |= 0x00800000; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Add phantom bit to mantissa 1.xxxxxxx </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">cont=0;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">while</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">(e<0)</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> { </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> m += (m>>2); e+=3; e10--;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">cont++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (cont==3)
{cont=0; m>>=1; e++;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> cont=0; </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">while</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">(e>=3)</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> m = m<<2; m=m/5; e-=3; e10++;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">cont++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (cont==3)
{cont=0; m<<=1; e--; }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">if</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> (e>0) m<<=e; </span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">else</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">if</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> (e<0) {m>>=(-e);}</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">p =
m>>23; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// check if integer part is within [1,10). Correct if needed.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p>=10)
{m>>=1; m/=5; e10++; } </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// divide by 10, increment e10</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p==0) {m= (m<<1) + (m<<3); e10--; } </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// multiply by 10, decrement e10</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> p = m>>23; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Leading digit (1-9)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> m=m&0x007FFFFFL; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Fraction</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Al final
de este código el primer dígito de la mantisa (1-9) se guarda en p y la
fracción de la mantisa en m. En e10 tenemos el exponente en base 10 (número
entero entre -38 y 38) y en r habíamos previamente extraído el signo (0 para +,
1 para -). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Ahora es
sólo cuestión de volcar dicha información secuencialmente: signo, primer digito
de mantisa, coma decimal, fracción de mantisa, el carácter "e"
para indicar exponente y el valor de e10
(entero con signo volcado con 2 digitos):<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Writes number to dest[]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Start at the beginning of char string </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=43+(r<<1); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// writes sign ('+'=43 '-'=45)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=48+p; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Leading digit of mantissa</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> r=int2frac(m>>11,dec,dest+k); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// write first 12 bits of mantissa as a decimal
fraction</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ROUNDING </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//Correct if using rounding</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (r) { </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p==9) { dest[1]=49; e10++;} </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[1]++;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#endif</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k+=(dec+1);
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// End of string so far</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Write
exponent </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'e'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (e10<0) { dest[k++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'-'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; e10=-e10;} </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'+'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// exponent sign </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
absolute value of exponent (2 digits with leading 0 if needed)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">p=e10/10;
dest[k++]=48+p;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> p*=10; p=e10-p; dest[k++]=48+p;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">dest[k]=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Null-terminate the string</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// return numbers of chars written (length of string) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código
puede complicarse añadiendo una opción de redondeo (con un #define ROUNDING):</span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ROUNDING</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (r) { </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p==9) { dest[1]=49; e10++;} </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[1]++;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#endif</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Este código se ejecutaría tras la llamada a int2frac (que
devuelve r). Si r es 1 ha habido un acarreo que ha llegado a la parte entera.
Si dicha parte entera era menor que 9 simplemente se incrementa. Si era 9,
pasaría a 10, por lo que la mantisa pasa a ser 1.0 y el exponente e10 se
incrementa.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Excepciones: NaN
y Inf:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La representación IEEE754 tiene algunos casos que
codifican excepciones, como Inf (infinito) para operaciones del tipo 1/0 o NaN
(Not a Number) para operaciones no definidas (como 0/0). Dichos "números"
se codifican poniendo a 1 todos los bits del exponente = 0xFF. En ese caso, si
la mantisa es 0, tenemos un Inf y si no lo es, un NaN. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El código anterior interpretaría incorrectamente dichos
números. Si pensamos que podemos obtener este tipo de números (NaN o Inf) y
queremos que aparezcan correctamente, tendríamos que hacer un #define NaN_Inf y
el siguiente código se incorporaría a la función: <span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> NaN_Inf</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p==0xFF) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// </span><st1:place><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">NaN</span></st1:place><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> or Inf</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k=0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (m==0) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// show '+Inf' or '-Inf'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> { <o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=43+(r<<1);
dest[k++]=73; dest[k++]=110; dest[k++]=102;} </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// show
'</span><st1:place><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">NaN</span></st1:place><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> { </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
dest[k++]=78; dest[k++]=97; dest[k++]=78; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> dest[k++]=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#endif</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como
ejemplo del uso de esta opción, el siguiente código (si NaN_Inf está definido):<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 9pt;"> <span lang="EN-GB">x=0.0/0.0; float2exp(txt,x,3); send_txt(txt); send_CR;
send_LF;</span></span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> x=1.0/0.0; float2exp(txt,x,3); send_txt(txt); send_CR;
send_LF;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> x=-1.0/0.0;
float2exp(txt,x,3); send_txt(txt); send_CR; send_LF;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">produce
por el puerto serie la siguiente salida:
</span><b><span style="font-family: 'Courier New';">NaN<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: 'Courier New';"> +Inf<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: 'Courier New';"> -Inf<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><span style="font-family: Verdana;">Tiempos de ejecución
y tamaño del código:<o:p></o:p></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En cuanto
a tiempos y tamaño de código la siguiente tabla recoge el tamaño y tiempo de
ejecución de las dos funciones consideradas:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> </span><span style="font-family: Verdana;"> </span></div>
<table align="left" border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 4.8pt; margin-right: 4.8pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-table-anchor-horizontal: page; mso-table-anchor-vertical: paragraph; mso-table-left: 111.6pt; mso-table-lspace: 7.05pt; mso-table-rspace: 7.05pt; mso-table-top: -1.5pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 13.0pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<span style="font-family: Verdana;">Rutina<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<span style="font-family: Verdana;">Código (words)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<span style="font-family: Verdana;">Tiempo (usec)<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.0pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<b><span style="font-family: Verdana;">float2str<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<b><span style="font-family: Verdana;">470<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<b><span style="font-family: Verdana;">150-300<o:p></o:p></span></b></div>
</td>
</tr>
<tr style="height: 13.6pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<b><span style="font-family: Verdana;">float2exp<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<b><span style="font-family: Verdana;">820<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134">
<div align="center" class="MsoNormal" style="mso-element-anchor-horizontal: page; mso-element-anchor-vertical: paragraph; mso-element-frame-hspace: 7.05pt; mso-element-left: 111.65pt; mso-element-top: -1.5pt; mso-element-wrap: around; mso-element: frame; mso-height-rule: exactly; text-align: center;">
<b><span style="font-family: Verdana;">500<o:p></o:p></span></b></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: 'Courier New';"><br /></span></b></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Ambas funciones usan por debajo la función int2frac, lo
que añade 150 palabras de código en ambos casos. La función float2str usa
además la función Word2Dec (250 palabras más), por lo que el código total
necesario para usar float2str es de unas 870 palabras frente a unas 970 para
float2exp.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El tiempo de ejecución de float2exp es de medio
milisegundo (@ 4x8 = 32 MHz), lo que puede parecer elevado, hasta que
consideramos que el objeto de generar estas cadenas es que un usuario humano
las vea en el LCD o puerto serie. Por ejemplo, la cadena típica generada por
float2exp es de unos 12 caracteres. Incluso a velocidades como 57600 bauds,
tardaríamos unos 2 msec en mandarla por el puerto serie, unas 4 veces el tiempo
empleado en crearla.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como
chequeo final de las rutinas escritas, ejecutamos el siguiente código:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVJJrQbxjf8mTeVN8UEv4V5BmEb1ryT1tCWy1AJHjCDRDp4nMYIh8ijLR740q1TDgedvWmGyARWg6qugIFGgqedXgLSh7e_Jzp8Fs1elZVlOjx07YAtgyE4KPht6js6HJKVu8lbNzR/s1600/volcado_float.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVJJrQbxjf8mTeVN8UEv4V5BmEb1ryT1tCWy1AJHjCDRDp4nMYIh8ijLR740q1TDgedvWmGyARWg6qugIFGgqedXgLSh7e_Jzp8Fs1elZVlOjx07YAtgyE4KPht6js6HJKVu8lbNzR/s400/volcado_float.jpg" width="356" /></a><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> x=3e-38;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <span style="color: blue;">while</span>(x<1e38)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> <span lang="EN-GB">{</span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span lang="EN-GB"><span style="font-family: Courier New, Courier, monospace; font-size: x-small;">
k=Long2Bin(txt,*(uint32*)&x);<o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB"> txt[k++]=32;</span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB">
k+=float2exp(txt+k,x,3); </span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB"> txt[k++]=</span><span lang="EN-GB" style="color: #ff40ff;">' '</span><span lang="EN-GB">; txt[k++]=</span><span lang="EN-GB" style="color: #ff40ff;">'='</span><span lang="EN-GB">; <o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB"> txt[k++]=</span><span lang="EN-GB" style="color: #ff40ff;">' '</span><span lang="EN-GB">; </span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB">
k+=float2str(txt+k,x,3); </span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB">
send_txt(txt); send_CR; send_LF;</span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><span lang="EN-GB"> x*=200;</span><span lang="EN-GB"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span lang="EN-GB"><span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span></span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El código barre el intervalo de los números reales (1e-38 a
1e+38). En cada paso </span><span style="font-family: Verdana;">multiplicamos el número por un factor 200 y mostramos los 32 bits que se guardan en la variable. El número es interpretado con el formato %e
y con %f. El resultado es el mostrado en la figura adjunta.</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Notad el rango mucho más pequeño (de 0.001 a 65535) donde
la función float2str es "operativa", frente al código alternativo de float2exp.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana; font-size: 10.0pt;"><br /></span></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com0tag:blogger.com,1999:blog-4945680608471335280.post-10239879626748101002013-06-03T16:40:00.000+02:002013-06-04T15:48:31.431+02:00Formateo de datos (para LCD o puerto serie)<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En muchos momentos (presentación de resultados, debug)
tendremos que visualizar valores de la variables de nuestro programa por el
LCD, puerto serie o equivalente. Ello conlleva convertir los datos numéricos en
cadenas de texto mostrando sus contenidos, bien sea en formato binario,
hexadecimal, decimal, etc.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El compilador C18 (y otros basados en ANSI C) ya cuentan
con una forma rápida y versatil de hacer dicha conversión: con las rutinas tipo
printf, sprintf o equivalentes. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Estas funciones son muy flexibles y convenientes pero como
veremos pueden ser lentas y ocupar bastante espacio. Son ideales por su
conveniencia en las primeras fases de un desarrollo. Sin embargo, si la aplicación se va complicando y nos acercamos
a los límites del micro usado podemos encontrarnos con que ocupan demasiada
memoria de programa y/o van demasiado lentas. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En esta entrada replicaremos la funcionalidad de sprintf
de forma modular. Escribiremos varias rutinas para volcar diferentes datos
enteros con varios formatos (binario, hexadecimal, decimal con o sin signo, etc).
Estas funciones, al preocuparse de un solo argumento y tipo de formato van a
ser mucho más pequeñas y rápidas que sprintf. Además, muchas veces, dentro de
una aplicación, solo trabajaremos con un cierto tipo de datos, por lo que este
tipo de rutinas pueden ahorrarnos bastante código.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En una entrada posterior trataremos el tema de la
presentación de datos tipo float, del que carecemos por defecto en C18.<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<span style="font-family: Verdana;">Código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/int2ascii.c">int2ascii.c</a> </span><br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: PT-BR;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: PT-BR;"></span></div>
<a name='more'></a><br />
<br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 10.0pt;">---------------------------------------------------------------------------------------------<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Origen de los inconvenientes de
sprintf:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Recordemos el uso de sprintf, cuyo resultado es una cadena
de texto formateada y lista para ser visualizada. Una típica llamada a sprintf
sería:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"> n=sprintf(dest,"format",arg1,arg2,…)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">dest[] puntero a char para almacenar cadena de
carácteres de salida. La cadena obtenida será null-terminated, esto es, el
valor 0 indica su final.<o:p></o:p></span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">"format": Una combinación de texto explicatorio +
descriptores (%d,%u,%b, etc) sobre como sacar los datos, en binario, hex,
decimal, con o sin signo, etc.<o:p></o:p></span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">arg1,
arg2,… datos que se convierten al formato indicado por los correspondiente
descriptores.<o:p></o:p></span></li>
<li class="MsoNormal" style="mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-align: justify;"><span style="font-family: Verdana;">El
argumento de salida n indica la longitud de la cadena creada.</span></li>
</ul>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Los inconvenientes de sprintf y similares residen
precisamente en su flexibilidad:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana; font-size: 10.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">1)<span style="font-family: 'Times New Roman';"> </span></span><!--[endif]--><span style="font-family: Verdana;">Código muy grande: si compilamos
un programa añadiendo sprintf veremos que su tamaño aumenta en unaci</span><span style="font-family: Verdana;">s 2000+ palabras, independientemente del tipo de formateo usado. La razón es que sprintf debe ser capaz de manejar cualquier tipo de formato que el usuario le presente en tiempo de ejecución, por lo que su código debe cubrir todas las posibilidades (volcar digitos binarios, hex, de</span><span style="font-family: Verdana; text-indent: -18pt;">males, con o sin signo, etc)
aunque el usuario solo desee una de ellas.</span></div>
<div class="MsoNormal" style="margin-left: 18.0pt; text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana; font-size: 10.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">2)<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Lento en ejecución por la misma
razón de antes. La rutina debe parsear la cadena de formato y decidir que tipo
de formato desea el usuario antes de ejecutar el código correspondiente. La
forma de especificar el formato es muy abierta y tiene muchas posibilidades
(tipo de datos, número de dígitos, rellenar o no con 0's, etc) por lo que
tardará en parsearla. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-align: justify; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana; font-size: 10.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">3)<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">En el caso de C18 estas funciones
no tienen soporte para volcar datos de tipo float en coma flotante (modificador
%f en ANSI C). La razón enlaza con la pega 1) de antes. Interpretar y volcar
números en coma flotante no es trivial, por lo que el código necesario es
relativamente grande. Al ser sprintf una función monolítica, su tamaño
aumentaría aún más, incluso para aquellos usuarios que nunca trabajan con
números en coma flotante.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Vamos a presentar algunas funciones alternativas a sprinft
que reproducen la mayoría de su funcionalidad con una fracción del coste en
tiempo y memoria. En esta entrada nos centraremos en como presentar enteros
(binario, hexadecimal y decimal con/sin signo) y en la siguiente exploraremos
los números en coma flotante.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Todas las funciones que veremos (igual que el sprintf que
reemplazan) reciben como primer argumento un puntero a carácter. Es
responsabilidad del usuario asegurar que hay espacio suficiente para almacenar
la cadena resultante (incluido el terminador 0). También devuelven la longitud
de la cadena creada.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Enteros sin signo a binario:<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Llamadas equivalente usando sprintf:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 83.45pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 12.45pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 12.45pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 151.25pt;" valign="top" width="202"><div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="font-family: 'Courier New';">Byte2Bin(dest,a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.45pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 151.25pt;" valign="top" width="202"><div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="font-family: 'Courier New';">sprintf(dest,"%b",a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.45pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.45pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 151.25pt;" valign="top" width="202"><div class="MsoNormal" style="mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">Word2Bin(dest,a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.45pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 151.25pt;" valign="top" width="202"><div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="font-family: 'Courier New';">sprintf(dest,"%b",a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.25pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.25pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 151.25pt;" valign="top" width="202"><div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="font-family: 'Courier New';">Long2Bin(dest,a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.25pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 151.25pt;" valign="top" width="202"><div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="font-family: 'Courier New';">sprintf(dest,"%lb",a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La primera rutina Byte2Bin vuelca un byte (uint8) a
binario: se inicializan los 8 caractéres (bits) con 0's (ASCII 48) y se termina
la cadena con 0. A continuación se recorren los bits del 2º argumento: si es 1
se incrementa ('1'=49) la posición correspondiente en la cadena. Para volcar un
uint16 o uint32, apuntamos con un puntero de bytes al inicio de la variable. De
esta forma podemos acceder a los bytes individuales y llamar repetidamente a
Byte2Bin. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// uint8 (byte) to
binary. dest[] must be at least 8+1 chars long</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 Byte2Bin(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest,uint8 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<8;k++) dest[k]=48; dest[8]=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Fill with 0's</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k=7; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New';">(a) { </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (a&0x01) dest[k]++; a>>=1; k--;} </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Add 1 if needed</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: "Courier New";">return</span><span style="font-family: 'Courier New';"> 8;
</span><span style="color: forestgreen; font-family: "Courier New";">// always 8 chars written</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// uint16 to binary.
dest[] must be at least 16+1 chars long</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 Word2Bin(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest,uint16 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">{</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8* ptr=(uint8*)&a; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Access to individual bytes in integer</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<2;k++) Byte2Bin(dest+(k<<3),ptr[1-k]);
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Call Byte2Bin twice</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New';"> 16; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// always
16 chars written</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// uint32 to binary.
dest[] must be at least 32+1 chars long</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 Long2Bin(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest,uint32 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8* ptr=(uint8*)&a; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Access to individual bytes in long</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<4;k++) Byte2Bin(dest+(k<<3),ptr[3-k]);
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: "Courier New";">return</span><span style="font-family: 'Courier New';"> 32; </span><span style="color: forestgreen; font-family: "Courier New";">// always 32 chars written</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En la siguiente tabla comparamos el tamaño del código y
tiempos de ejecución de estas rutinas con las equivalentes usando sprintf.
Recordar que el código para sprintf es siempre de unos 2K words
independientemente del tipo de datos usados.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 24.9pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 13.0pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Rutina<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Código (words)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Tiempo (usec)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 120.8pt;" valign="top" width="161"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Tiempo sprintf<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.0pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Byte2Bin<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">75<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">50<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 120.8pt;" valign="top" width="161"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">1500<o:p></o:p></span></b></div>
</td>
</tr>
<tr style="height: 13.0pt; mso-yfti-irow: 2;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Word2Bin<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">+75<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">100<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 120.8pt;" valign="top" width="161"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">2500<o:p></o:p></span></b></div>
</td>
</tr>
<tr style="height: 13.6pt; mso-yfti-irow: 3; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.85pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Long2Bin<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 108.4pt;" valign="top" width="145"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">+75<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 100.65pt;" valign="top" width="134"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">150-250<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.6pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 120.8pt;" valign="top" width="161"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">6-7 msec<o:p></o:p></span></b></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: PT-BR;">
</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Enteros sin signo a hexadecimal:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><span style="font-family: Verdana, sans-serif;">Llamadas equivalente usando sprintf:</span><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 57.45pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 14.25pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 14.25pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 177.1pt;" valign="top" width="236"><div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">Byte2Hex(dest,a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 14.25pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 177.1pt;" valign="top" width="236"><div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">Sprintf(dest,"%02x",a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 14.25pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 14.25pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 177.1pt;" valign="top" width="236"><div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">Word2Hex(dest,a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 14.25pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 177.1pt;" valign="top" width="236"><div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">Sprintf(dest,"%04x",a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 15.15pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 15.15pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 177.1pt;" valign="top" width="236"><div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">Long2Hex(dest,a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 15.15pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 177.1pt;" valign="top" width="236"><div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New';">Sprintf(dest,"%08x",a)</span><span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El proceso es muy similar al caso binario, ya que cada
dígito en base 16 no es más que un bloque de 4 dígitos binarios. Repetimos el
proceso de antes pero examinando bloques de 4 bits (un AND con 0x0F en vez de
0x01 y un SHIFT de 4 posiciones en vez de 1 a cada paso).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Como antes la función básica corresponde al volcado de un
byte:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: forestgreen; font-family: "Courier New";">// Byte to hex. dest[] must be at least </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">2 chars long</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 Byte2Hex(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest,uint8 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';"> dig,k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dest[0]=48; dest[1]=48; dest[2]=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Fill with 0's and null-terminated </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New';">(a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dig=(a&0x0F); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (dig>9) dig+=7; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dest[k--]+=dig;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> a>>=4;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New';"> 2; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Always two chars written</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La cadena
se inicializa con 00 (ASCII 48) y se va examinando cada dígito hexadecimal (AND
0x0F). Valores entre 0 y 9, incrementan por dicha cantidad el correspondiente
código ASCII. Para valores entre 10 y 15 añadimos 7 para obtener los caracteres
'A','B', etc.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Al igual
que en el caso binario, las rutinas para uint16 y uint32 llaman repetidamente a
la anterior para volcar los 4 u 8 dígitos hexadecimales. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En la
siguiente tabla se compara el tamaño del código y tiempos de ejecución de estas
rutinas con los tiempos para sprintf:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Rutina<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Código (words)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Tiempo (usec)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Tiempo sprintf<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Byte2Hex<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">95<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">20<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">500<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Word2Hex<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">120<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">35<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">500<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Long2Hex<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">140<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">70<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">500<o:p></o:p></span></b></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código
para Byte2Hex son unas 100 palabras. Cada rutina adicional necesita unos 60
palabras (el + indica que también precisan la rutina Byte2Hex). El tiempo de ejecución de estas rutinas es
variable según el tamaño del dato en cuestión (menor cuantos menos dígitos
tiene). Como regla general se requieren unos 15 usec por cada dígito
adicional. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Enteros sin signo a decimal:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Ahora las
cosas se complican un poco. Volcar datos en base 2 o base 16 era relativamente
rápido porque base 2 es la base nativa de los datos en un PIC (y base 16 solo
es cuestión de examinar bloques de 4 bits). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Para
beneficio de los usuarios humanos, en la mayoría de los casos querremos volcar
los datos en base 10. Eso implica un cambio de base, por lo que estas rutinas
serán ligeramente más complicadas y lentas que las anteriores. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Dado un
número a, el algoritmo básico para ir obteniendo sus dígitos (base 10) desde el
menos al más significativo es el siguiente: <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">while(a)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> {<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"> b =
a/10; // Division entera<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"> dig = a – b*10;
// remainder = least significant digit<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"> a=b; // repeat for next digit<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 10.0pt; mso-ansi-language: EN-GB;"> </span><span style="font-family: Verdana;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Se va
dividiendo a por 10 y el resto obtenido es el dígito buscado. El problema es
que se empieza por el menos significativo (unidades) y no se sabe a priori
cuantos tendremos. Por ejemplo un byte puede tener 1 (0-9), 2 (10-99) o 3
dígitos (100-255).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La
solución es reservar el número máximo de dígitos posibles (3 para un byte, 5
para un entero) e ir llenándolos de derecha a izquierda. Al acabar sabremos el
número de dígitos que han salido y podremos justificarlos a la izquierda o
dejarlos tal cual, rellenando con blancos o ceros a la izquierda:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Byte (unsigned
int8) dumped as decimal (right justified and padded with 0's) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 Byte2Dec(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest,uint8 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';">{<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> uint8 k,b,dig;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<3;k++) dest[k]=48; dest[3]=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Fill with 0's and
null-terminate</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k=2; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Starts with LS digit</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New';">(a>=10)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> b=a/10; dig = a-10*b;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dest[k--]+=dig;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> a=b;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dest[k]=a+48;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Leading digit</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: "Courier New";">return</span><span style="font-family: 'Courier New';"> 3; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Always
3 chars long (000, 001, , 255)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En este
caso se ha preferido mantener la justificación a la derecha, por lo que las
posibles salidas siempre tienen 3 digitos, desde 000 hasta 255.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el
siguiente caso (enteros de 16 bits o uint16) se ilustra como justificar a la
izquierda. Un tercer argumento decide si correr el resultado a la izquierda (1)
o dejarlo tal cual (0).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 Word2Dec(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest, uint16
a,uint8 left)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';">{</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> uint8 k,i,dig,n;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';">uint16 b;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k=4; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// At most 5 digits, dest[0],dest[1],..., dest[4]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New';">(a>=10)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> b=a/10; dig = a-10*b;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dest[k--]=dig+48;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> a=b;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> dest[k]=a+48;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> n=5-k; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Number of digits used</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (left)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (n<5) </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(i=0;i<n;i++) dest[i]=dest[i+k]; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Shift number left </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New';"> (i=0;i<k;i++) dest[i]=48; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Right justified, padded with 0's</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="font-family: 'Courier New';">n=5; </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> }</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> dest[n]=0;
</span><span lang="PT-BR" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">//Null terminate</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New';"> </span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">return</span><span lang="PT-BR" style="font-family: 'Courier New';"> n;</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En la segunda parte del código (si se ha elegido
justificación a la izquierda y el número resultante tiene menos de 5 cifras) se
desplazan los dígitos obtenidos hacia la izquierda. En caso contrario se
rellenan las posiciones vacías con 0's (ASCII 48). Cambiándolo por dest[i]=32,
rellenaríamos con espacios. Fijaros que el código de sprintf debe considerar
todas esas posibilidades a través de su cadena de formato, lo que complica su
código.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> </span><b><u><span style="font-family: Verdana;">Enteros con signo a decimal:</span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Remarcar que en este caso, C18 si que tiene unas rutinas
para volcar enteros con signo a decimal sin usar sprintf (btoa, itoa, ltoa). Son
más compactas y tan rápidas como las aquí presentadas, por lo que en este caso
serían preferibles a las mías.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">A pesar de esto, por completitud, presentare las
correspondiente rutinas, que no son más que las usadas en el apartado anterior,
añadiendo el manejo del signo. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">La idea es detectar el signo y obtener el valor absoluto
del entero. Si el signo es negativo añadimos el carácter '-' a la cadena de
salida, para posteriormente volcar el valor absoluto. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">En el PIC, los enteros con signo están codificados en
complemento a dos (ver tabla adjunta):<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 142.0pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 13.3pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Numero binario<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Interpretacion<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.3pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">0000 0000<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">0<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.3pt; mso-yfti-irow: 2;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">0000 0001<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.3pt; mso-yfti-irow: 3;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">. . .<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">. . .<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.5pt; mso-yfti-irow: 4;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.5pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">0111 1111<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.5pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">127<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.5pt; mso-yfti-irow: 5;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.5pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1000 0000<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.5pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">-128<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.3pt; mso-yfti-irow: 6;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1000 0001<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">-127<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.3pt; mso-yfti-irow: 7;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">…<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">…<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.3pt; mso-yfti-irow: 8;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1111 1110<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.3pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">-2<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 14.15pt; mso-yfti-irow: 9; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 14.15pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 95.4pt;" valign="top" width="127"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1111 1111<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 14.15pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 90.0pt;" valign="top" width="120"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">-1<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El bit más significativo nos indica el signo (1 para números
negativos). Para hallar el valor absoluto de un número negativo basta negar el
byte (invertir sus bits) y sumar 1 al resultado. Así por ejemplo vemos que 1000
0001 (-127) sería negativo al ver primer bit = 1. Invirtiéndolo obtenemos 0111 1110 = 126. Sumando 1 tenemos
su valor absoluto (127).<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Aprovechando podemos escribir una rutina (abs) que
devuelva el valor absoluto de un entero y que no encontramos en C18:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint16 abs(int16 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 s;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> s = (a>>15); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (s) {a=~a; a++; }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New';"> a;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">Las rutinas siguiente convierten enteros con signo de 8 y 16
bits (el código para 32 bits es similar). Para valores positivos el signo '+'
se omite. Sería trivial modificar el código para que el carácter del signo (+ o
-) siempre acompañe al número.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// signed int8 to
decimal</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 SignedByte2Dec(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest,int8 a)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k,s;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> s = (a>>7); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (s) { a=~a; a++; dest[k++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'-'</span><span lang="EN-GB" style="font-family: 'Courier New';">; } </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Get sign and absolute value</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k+=Byte2Dec(dest+k,a); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New';"> k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// signed int16 to
decimal (left=1, left justified)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">uint8 SignedWord2Dec(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New';">* dest, int16
a,uint8 left)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k,s;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> s = (a>>15); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (s) { a=~a; a++; dest[k++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'-'</span><span lang="EN-GB" style="font-family: 'Courier New';">; } </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Get sign and absolute value</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> k+=Word2Dec(dest+k,(uint16)a,left); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New';"> k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">El código anterior ilustra también como concatenar varias
cadenas obtenidas sucesivamente con estas rutinas. <o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">El equivalente a: k=sprintf(dest,"%u %x %d",a,b,c);
<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 10.0pt; mso-ansi-language: EN-GB;">sería:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">k=Word2Dec(dest,a);k+=Word2Hex(dest+k,b);k+=SignedWord2Dec(dest+k,c);</span></div>
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;">De nuevo los tiempos dependen del número de digitos (cuanto
antes se "acabe" el número, antes dejaremos de tener que hacer
costosas divisiones). Por ejemplo los tiempos citados para la conversión de
enteros de 16 bits (words) son para 4 o 5 cifras (max):<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div class="MsoNormal">
<span style="font-family: Verdana;">Rutina<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div class="MsoNormal">
<span style="font-family: Verdana;">Código
(words)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div class="MsoNormal">
<span style="font-family: Verdana;">Tiempo
(usec)<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div class="MsoNormal">
<span style="font-family: Verdana;">Tiempo
sprintf<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Byte2Dec<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">200<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">40-60<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">500-700<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">+ signo<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">+75<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">idem<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Idem<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Word2Dec<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">251<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">180-220<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">800-1200<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 104.4pt;" valign="top" width="139"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">+ signo<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 126.0pt;" valign="top" width="168"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">+95<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">idem<o:p></o:p></span></b></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Idem<o:p></o:p></span></b></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br />
<br />
<div class="MsoNormal" style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6XhI3vplvxHvZ0ELEvGwu9q-ZSPx27TY_Y9JL14SEsU25_cDN5qguE1mYdPpyZOcJaVS_2VjhpNX8w06Pn5lZEgDfuhOvTD-Ke2jJpAKN4W1v6Gq_l71hsIkAqYHvsMVvGA3xhOk7/s1600/volcado_ints.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6XhI3vplvxHvZ0ELEvGwu9q-ZSPx27TY_Y9JL14SEsU25_cDN5qguE1mYdPpyZOcJaVS_2VjhpNX8w06Pn5lZEgDfuhOvTD-Ke2jJpAKN4W1v6Gq_l71hsIkAqYHvsMVvGA3xhOk7/s400/volcado_ints.jpg" width="295" /></a><span style="font-family: Verdana;"></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
El siguiente código muestra la funcionalidad de las
rutinas presentadas. Un entero (uint16 sin signo) se va incrementando y a cada
paso se presenta en formato binario, hexadecimal, decimal sin signo y decimal
con signo:</div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">i=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> { </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
k=Word2Bin(txt,i); txt[k++]=32;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
k+=Word2Hex(txt+k,i); txt[k++]=32;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
k+=Word2Dec(txt+k,i,0); txt[k++]=32;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
k+=SignedWord2Dec(txt+k,i,0); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_txt(txt);
send_CR; send_LF;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">i++;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<br />
<div class="MsoNormal" style="text-align: justify;">
<br /></div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com1tag:blogger.com,1999:blog-4945680608471335280.post-32162219292197641732013-04-12T16:19:00.001+02:002013-04-12T16:51:24.899+02:00Tarjetas SD/SDHC (lectura/escritura de datos)<a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><br />
<span style="font-family: Verdana, sans-serif;">Tras aprender como inicializar una tarjeta SD y obtener información sobre su capacidad, etc, es hora de usarlas para lo que sirven: leer/escribir información.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En esta entrada completaremos nuestra introducción a las comunicaciones de bajo nivel entre un PIC y una tarjeta SD viendo las lecturas/escrituras a los sectores de datos de la tarjeta. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Como siempre haremos algunos comentarios sobre como optimizar las rutinas para maximizar la velocidad de transferencia de datos.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Recordar que las rutinas que vamos a usar son de bajo nivel, escribiendo directamente sobre los sectores de la tarjeta. No saben nada del tipo de formato, sistema de archivos, etc, por lo que pueden destruir datos en la tarjeta que usemos. He escogido un número alto de sector (5000) para empezar a escribir por lo que posiblemente no estropearán el formato de la tarjeta pero si machacarán los datos de dichos sectores. No obstante, incluso si se estropea el formato siempre se puede volver a reformatear la tarjeta en el PC sin ningún problema. Obviamente debéis que evitar hacer pruebas con una tarjeta con datos de interés. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Para verificar que las cosas están funcionando es útil contar con un lector de tarjetas para el PC y un software (tipo </span><a href="http://winhex.com/winhex/index-e.html" style="font-family: Verdana, sans-serif;">WINHEX</a> <span style="font-family: Verdana, sans-serif;">o similar) que permita editar los sectores lógicos de un disco para ver si nuestros programas escriben lo que queremos y donde queremos. </span><br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana;">Código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/SPI_sdhc_v2.c">SPI_sdhc_v2.c</a>, </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/18f4520_g.lkr" style="font-family: Verdana;">18f4520_g.lkr</a></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"></span></u></b></div>
<a name='more'></a><b><u><br /></u></b>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana;"><b>--------------------------------------------------------------------</b></span></div>
<div class="MsoNormal">
</div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<b style="font-family: Verdana, sans-serif;"><u>Estrategias de buffering de datos en el PIC:</u></b><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Nuestro objetivo será leer/escribir una gran cantidad de datos entre el PIC y la tarjeta SD. LO primero que hay que decidir es que tipo de estrategia de buffers vamos a usar en el PIC. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Pensad en una típica aplicación: un datalogger. En el PIC se generan datos (p.e. leyendo un sensor) y se desean volcarse a la tarjeta SD para almacenamiento. Podríamos pensar en que cada vez que tengamos un dato nuevo podríamos grabarlo en la tarjeta. Sin embargo esto sería un grave error, porque la lectura/escritura de la tarjeta está optimizada para un acceso por bloques. De hecho en tarjetas SDHC el acceso por bloques (512 bytes) es el único posible, no siendo posible leer/escribir menos de un bloque.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-size: x-small;"><b style="font-family: Verdana, sans-serif;">Nota:</b><span style="font-family: Verdana, sans-serif;"> en las especificaciones SD un bloque de datos (típicamente 512 bytes) es el conjunto de datos a los que puede accederse en una única operación de lectura/escritura y que se corresponde con lo que solemos llamar un sector de un disco. Sin embargo, la especificación reserva el nombre de sector para un conjunto de bloques (entre 1 y 64 normalmente) que son afectados conjuntamente por una operación de borrado. Esto tiene que ver con las peculiaridades de la memoria tipo flash. En esta entrada usaremos bloque o sector para referirnos al conjunto de bytes que será nuestra unidad de lectura/escritura.</span></span><br />
<br />
<span style="font-family: Verdana, sans-serif;">Incluso en tarjetas SDSC donde se permiten accesos a bytes individuales haremos bien en usar un buffer lo más grande posible en el PIC e ir llenándolo con los datos. Cuando el buffer esté lleno se arrancará el proceso de volcado a la tarjeta y se volvera a reusar el buffer para los nuevos datos. Igualmente en las operaciones de lectura leeremos un bloque de datos lo más grande posible y luego iremos "leyendo" los bytes individuales en el PIC.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En cuanto al tamaño del buffer idealmente debería de ser de 512 bytes, el tamaño de un sector típico de las tarjetas SD. Sólo si tenemos problemas de memoria en nuestro dispositivo podríamos hacerlo más pequeño, pero tratando de no bajar de 256 o 128 bytes. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Si se va a usar un buffer de menos de 512 bytes es preciso avisar a la tarjeta del nuevo tamaño de bloque a usar con el comando CMD_SET_BLOCKLEN (que usamos en la inicialización para fijar el bloque a 512 bytes). </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En nuestro caso vamos a usar un buffer de 512 bytes. Como se comento en la entrada del levitador magnético crear un array que atraviese los bancos de memoria (256 bytes) del PIC requiere usar una función modificada del archivo 18f45209_g.lkr con instrucciones sobre el mapa de memoria para el linker:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"></span><br />
<span style="font-family: Verdana, sans-serif;">DATABANK NAME=gpr0 START=0x80 END=0xFF</span><br />
<span style="font-family: Verdana, sans-serif;">DATABANK NAME=gpr1 START=0x100 END=0x1FF</span><br />
<span style="font-family: Verdana, sans-serif;">DATABANK NAME=gpr2 START=0x200 END=0x2FF</span><br />
<span style="font-family: Verdana, sans-serif;">DATABANK NAME=big START=0x300 END=0x4FF PROTECTED</span><br />
<span style="font-family: Verdana, sans-serif;">SECTION NAME=big RAM=big</span><br />
<br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En el código anterior reservamos 2 bancos de memoria (de 0x300 a 0x4FF)</span><br />
<span style="font-family: Verdana, sans-serif;">en una sección a la que llamamos big. En el programa principal usamos #pragma udata para posicionar un array de 512 bytes en dicha sección:</span><br />
<br />
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> udata big</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte tmp[512];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: PT-BR;">#pragma</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;"> udata</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 9pt;">byte *data=&tmp[0];</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><u style="font-weight: bold;">Rutina de lectura de un sector:</u></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Con la rutina </span><span style="font-family: Verdana, sans-serif;">read_data_block</span><span style="font-family: Verdana, sans-serif;"> que escribimos para leer los registro CSD y CID tenemos lo necesario para leer un sector o bloque de datos de la tarjeta, ya que el protocolo es el mismo:</span><br />
<br />
<ol>
<li><span style="font-family: Verdana, sans-serif;">Mandar el comando correspondiente CMD_READ_SECTOR usando como argumento la dirección de la memoria donde iniciar la lectura. </span></li>
<li><span style="font-family: Verdana, sans-serif;">Hacer una lectura de un bloque de 512 bytes.</span></li>
</ol>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: EN-GB;"> <span lang="EN-GB"> </span></span><br />
<span style="font-family: Verdana, sans-serif;">Un comentario muy importante respecto a la dirección de los datos a leer. En las tarjetas SDSC (típicamente hasta 2 Gb de capacidad) la dirección de la memoria de da en bytes. Sin embargo en las memorias SDHC (>2 Gb) dicha dirección se da en bloques (de 512 bytes).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Como nuestra rutina va a ser de lectura de sectores completos le pasaremos siempre como argumento el número de sector a leer. Internamente dicho numero se multiplica por 512 (caso de SDSC) para tener dirección en bytes o se usa tal cual (SDHC). La decisión puede hacerse con un #define si se sabe previamente que tipo de tarjeta usaremos o con una condición. En este último caso podríamos saber el tipo de tarjeta a través de los registros CSD / OCR.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">El código de la rutina de lectura de un sector queda:</span><br />
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte read_sector_sd(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> byte res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SDSC</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s<<=9; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Start address of sector in bytes (sector # x 512)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#endif</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=send_command_R1(CMD_READ_SECTOR,s); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res==0) res=read_data_block(buf,(uint16)512); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Read data block</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> deselect_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<span style="font-family: Verdana, sans-serif;">que es casi idéntico al código para leer los registros CSD/CID. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Si se ha fijado un distinto tamaño de bloque (p.e. 128 bytes) la tarjeta enviará únicamente 128 bytes tras el comando de petición de sector. Para leer todo el bloque (512 bytes) deberemos modificar la rutina anterior para especificar un offset adicional dentro del sector deseado</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"> address = </span><span style="font-family: Verdana, sans-serif;"> </span><span style="font-family: Verdana, sans-serif;">(sector<<9 + offset)</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Así, si quisieramos leer el sector 37 tendriamos que llamar cuatro veces a la rutina con argumentos (37,0) (37,128) (37,256) y (37,384). </span><span style="font-family: Verdana, sans-serif;">Esto sólo sería posible hacerlo con tarjetas de baja capacidad.</span><br />
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><b><u>Escritura de un sector o bloque de datos:</u></b><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Nos falta una rutina de escritura. El esquema de una operación de escritura es el siguiente:</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Gun84ZwjdGnwP3or9B0VrYz6ZHlU2M7JVSpEFt3ZU2dOiuDr5ON4tAQwbkdjxu99HvgiQCb1u8lR6KonrO8hMav3aA8QQPIMaw2UNCwYQTNBYatmUt3tzQtin5Rd5oUT8tyxoA4D/s1600/operacion_escritura.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Gun84ZwjdGnwP3or9B0VrYz6ZHlU2M7JVSpEFt3ZU2dOiuDr5ON4tAQwbkdjxu99HvgiQCb1u8lR6KonrO8hMav3aA8QQPIMaw2UNCwYQTNBYatmUt3tzQtin5Rd5oUT8tyxoA4D/s640/operacion_escritura.png" width="640" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;">Tras el intercambio CMD/R el micro debe transmitir un bloque de datos usando spi_tx. La siguiente rutina es la análoga a read_data_block en escritura:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint8
write_data_block(uint8* buf, uint16 n) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Write data block</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint16
k;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint8
res,crc;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(0xFE); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// SEnd data token</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0;k<n;k++) spi_tx(buf[k]); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// send n bytes</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(0xFF); spi_tx(0xFF); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Dummy CRC (16 bits) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;"> </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_rx(res); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Get answer from card with Write Status</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res = (res>>1)&0b00000111; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Extract status bits </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res!=2) </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Error, data not accepted</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=0x00; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (res!=0xFF) spi_rx(res); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Wait while card BUSY</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(0);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"><br /></span></div>
<br />
<span style="font-family: Verdana, sans-serif;">Al igual que en la lectura el bloque de datos va enmarcado por un DataToken = 0xFE y un CRC de 16 bits (que puede ser cualquier cosa, a menos que tengamos habilitado la verificación de CRCs). La diferencia con la lectura es que ahora la tarjeta mandará una Data Response (1 byte) tras la recepción del bloque de datos, indicando si ha habido algún problema. La estructura de dicha respuesta es:</span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh3YC-SJJPcUyKz8q9vSFy3-KqAMTltYsGoTD0Eq3PZoJxadPAPbARiwCUz4MiqPj1xGVLGEcfa_DhDmr5TJxZTdxrRXZSpUAH9Y5lErVBNPq0ELd2VGMaJ6xUn3Asp410_kWaxZSr/s1600/dta_response.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh3YC-SJJPcUyKz8q9vSFy3-KqAMTltYsGoTD0Eq3PZoJxadPAPbARiwCUz4MiqPj1xGVLGEcfa_DhDmr5TJxZTdxrRXZSpUAH9Y5lErVBNPq0ELd2VGMaJ6xUn3Asp410_kWaxZSr/s320/dta_response.png" width="320" /></span></a></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">donde un valor 010 (2 dec) en status indica que los datos han sido aceptados.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Tras dicha respuesta la tarjeta entra en un estado BUSY hasta terminar de mover procesar los datos recibido (moverlos del buffer de recepción al correspondiente sector de la memoria). Dicho estado BUSY se indica con un nivel BAJO en la línea MISO (de tarjeta a micro). </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Notad que en un comando de lectura no existía dicho estado tras el intercambio porque una vez que mandaba los datos la tarjeta no tiene trabajo pendiente. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El código para la escritura de un sector que usa la rutina anterior será:<o:p></o:p></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte write_sector_sd(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> byte res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SDSC</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s<<=9;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Start address of sector in bytes
(sector # x 512)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#endif</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=send_command_R1(CMD_WRITE_SECTOR,s); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res==0) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_clock();
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 1 byte "margin" before
sending data</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=write_data_block(buf,(uint16)512); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Write data block</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> deselect_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
</div>
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Al igual que antes el argumento que recibe la función es la dirección del sector. Dependiendo del tipo de tarjeta se pasará o no a bytes.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Con esto ya tenemos lo necesario para escribir un programa de usuario que escriba y lea de cualquier sector.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El siguiente bucle barre 1024 sectores (desde el sector 5000 para no interferir con el formato de la tarjeta) llenando cada sector consecutivamente con 00, 01, 02, etc. A continuación se lee el mismo sector y si hay alguna diferencia entre los datos escritos y leídos se incrementa un contador de errores:</span><br />
<br />
<br />
<div class="MsoNormal">
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> start_SEC 5000L</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> NSEC 1024</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0;k<NSEC;k++) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(i=0; i<=511;
i++) data[i] = k&0xFF; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// write buffer in PIC</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res =
write_sector_sd(start_SEC+k,data); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Write buffer to SD card</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(i=0; i<=511; i++) data[i] = 0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Clear PIC buffer</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res = read_sector_sd(start_SEC+k,data); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Read SD sector back to buffer</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Checks for discrepancies</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> difs=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(i=0; i<512; i++) </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
(data[i]!=(k&0xFF)) difs++;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(difs) err++; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// If errors, increment bad_sectors</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> printf(</span><span lang="EN-GB" style="color: #a020f0; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">"Sectors checked: %4d BAD=%02d%c"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">,k+1,err,13);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (err==0) LATD++;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<br />
<br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Los resultados del test se vuelcan por el puerto serie: </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"></span><br />
<span style="font-family: Verdana, sans-serif;">------------------------------------</span><br />
<span style="font-family: Verdana, sans-serif;">init_SD --> OK</span><br />
<span style="font-family: Verdana, sans-serif;">Sectors checked: 1024 Err=00</span><br />
<span style="font-family: Verdana, sans-serif;">End SD test</span><br />
<span style="font-family: Verdana, sans-serif;">------------------------------------</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En el bucle anterior usamos el pin RB0 para mostrar el tiempo que tarda en ejecutarse un comando de escritura / lectura de un sector (512 bytes). En la siguiente imágen tenemos los resultados para una vieja tarjeta SDSC de 32 Mbytes: </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana, sans-serif;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6QTuvv4WPMls7o3Uz9cyOn2LuoB5MF3yvKteS2UEYIK1efXBtMycKIntT4ONpSQBMKLsnQ_3T0OKzWkiqLtbZmmbQp5vHo5kMqXz0WSGx4W5Mx3gVTwYVsUJrShm2j-m2GfYVHjdr/s1600/oscope_pan32.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6QTuvv4WPMls7o3Uz9cyOn2LuoB5MF3yvKteS2UEYIK1efXBtMycKIntT4ONpSQBMKLsnQ_3T0OKzWkiqLtbZmmbQp5vHo5kMqXz0WSGx4W5Mx3gVTwYVsUJrShm2j-m2GfYVHjdr/s640/oscope_pan32.jpg" width="640" /></a></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">La traza superior (amarilla) corresponde a RB0. Valores altos indican que se está ejecutando una escritura (1º pulso) o una lectura (2º pulso). Se observa que la escritura es mucho más lenta que la lectura (especialmente el el caso de la tarjeta de 32 Mb). La lectura son unos 4/5 msec mientras que la escritura son unos 17.5 msec (dependiendo de la tarjeta).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En la traza inferior se monitoriza RB1. En el código, RB1 se pone a 1 estrictamente durante la transferencia de los 512 bytes (dentro de read_data_block y write_data_block), ignorando los tiempos de espera debidos a la tarjeta.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Se observa que ambos tiempos ahora son muy parecidos (se tarda lo mismo en mandar 512 bytes que en recibirlos, unos 4.4 msec). Además, en el caso de la lectura el tiempo para leer un sector es prácticamente el tiempo necesario para transferir los bytes. En cambio para la lectura se observa que la tarjeta pasa mucho tiempo ocupada tras recibir los datos. Esto es debido a las diferencias que comentamos entre la lectura/escritura en una memoria flash.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Los tiempos anteriores nos dan unas velocidades máximas de transferencia de unos 120 Kb/sec de lectura y unos 30 Kb/sec para escritura. Usando una tarjeta más moderna (que previsiblemente es más eficaz grabando los datos) el tiempo de escritura se reduce a unos 8/9 msec (50-60 Kb/sec) pero aún así sigue siendo el doble de lento que la lectura.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><b><u>Optimización (uso de macros para spi_tx, spi_rx, etc):</u></b></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En primer lugar vamos a intentar reducir el tiempo que dedicamos a mover los 512 bytes por el puerto SPI. Obviamente no podemos hacer que el módulo SPI saque los bytes más rápidamente (salvo subiendo el reloj, pero eso sería hacer trampa).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Si que podemos intentar mejorar un poco el rendimiento cambiando las rutinas de transmisión y recepción de datos (spi_tx, spi_rx) por macros, de forma que se evite la sobrecarga de llamar a una función, pasar argumentos, etc.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Las antiguas macros, basadas en la función spi_transfer:</span><br />
<br />
<div class="MsoNormal">
<br /></div>
<span style="font-family: Verdana, sans-serif;">
</span><br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Verdana, sans-serif;"><span style="color: forestgreen; font-family: 'Courier New'; font-size: 9pt;">// SPI functions
aliases</span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Verdana, sans-serif;"><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(x)
spi_transfer(x) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// sends TX data, ignores return value.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Verdana, sans-serif;"><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_rx()
spi_transfer(0xFF) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// sends
dummy data, returns RX data.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Verdana, sans-serif;"><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_clock() spi_transfer(0xFF) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// send 8 clocks (nobody cares about data)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></span></div>
</div>
<span style="font-family: Verdana, sans-serif;">
<div class="MsoNormal">
<br /></div>
<br />
se transforman en las siguientes, que no usan llamadas a funciones.<br />
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(x) { SSPBUF=x; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(SSPSTATbits.BF==0); }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_rx(x) { SSPBUF=0xFF; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(SSPSTATbits.BF==0); x=SSPBUF;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_clock() { SSPBUF=0xFF; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(SSPSTATbits.BF==0); }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
La única pega es que en el caso de la recepción, hay que cambiar los comandos res=spi_rx() por spi_rx(res). No hay que cambiar nada para spi_tx y spi_clock.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKFSeKBcnetfj48yM4vbFvqf7H4_zXRWv9cikGGnj1Ww6JE4ITKvfnxIHA1hdzwNSqPCPueY3TCgJdYu_gYfGsaBMcDv_EEnSB7e_WqEXygAtdRe0ZMVBoYZZZd7q-ZgN0Mw7pmIx/s1600/oscope_pan32_macros.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="162" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkKFSeKBcnetfj48yM4vbFvqf7H4_zXRWv9cikGGnj1Ww6JE4ITKvfnxIHA1hdzwNSqPCPueY3TCgJdYu_gYfGsaBMcDv_EEnSB7e_WqEXygAtdRe0ZMVBoYZZZd7q-ZgN0Mw7pmIx/s400/oscope_pan32_macros.jpg" width="400" /></a></div>
</span><br />
<span style="font-family: Verdana, sans-serif;">En la imagen se observa la mejora en (estrictamente) el tiempo de transferencia de datos. Los pulsos de la traza de abajo son más estrechos. En el detalle de la derecha se ve que el tiempo dedicado a transferir los 512 bytes ha pasado de 4.4 msec a 3.2 msec, un ahorro de un 25%.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Un tiempo de 3.2 msec en la lectura de 512 bytes supone una velocidad de unos 160 Kb/sec. Sin embargo la escritura no ha mejorado apenas, porque aunque hemos ahorrado 1 msec en mandar los datos, la tarjeta sigue tardando el mismo tiempo en procesarlos. En el siguiente apartado veremos como es posible en ciertas circunstancias optimizar la fase de escritura.</span><br />
<br />
<b style="font-family: Verdana, sans-serif;"><u><br /></u></b>
<b style="font-family: Verdana, sans-serif;"><u>Optimización (uso de comandos de lectura/escritura múltiples):</u></b><br />
<b style="font-family: Verdana, sans-serif;"><u><br /></u></b>
<span style="font-family: Verdana, sans-serif;">En muchas aplicaciones (pensar el el datalogger de antes) no se alternan operaciones de lectura/escritura como en el ejemplo anterior, sino que solamente escribimos o leemos datos. En ese caso es posible optimizar la transferencia utilizando los comandos de lectura/escritura de múltiples bloques (0x12=18 y 0x19=25).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">El protocolo de una lectura múltiple es sencillo:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3uj7SeDrCG_HGZQFBq7obY2Saw6zITWgFxSIIcX1gBHyln7CrhF6KWeA-fWoChPYyORy3Oqi5dt_H-Sz9mrq6o6oXG7UJK98tt-fq1M3xKvyzx-4ywWjoNS5V5xWoeBkc4mcJwHUL/s1600/read_mult.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3uj7SeDrCG_HGZQFBq7obY2Saw6zITWgFxSIIcX1gBHyln7CrhF6KWeA-fWoChPYyORy3Oqi5dt_H-Sz9mrq6o6oXG7UJK98tt-fq1M3xKvyzx-4ywWjoNS5V5xWoeBkc4mcJwHUL/s640/read_mult.png" width="640" /></a></div>
<span style="font-family: Verdana, sans-serif;">Tras el comando (0x12=18) y la respuesta de la tarjeta llegan sucesivos bloques de datos (Data TOKEN 0xFE + 512 datos + CRC16). En cualquier momento (incluso en mitad de un paquete de datos) el micro puede interrumpir el flujo de datos con un comando 12. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">La escritura de múltiples bloques es similar. Tras el comando CMD25 (0x19) y su respuesta el micro empieza a mandar bloques de datos (TOKEN+512 bytes + CRC16). A diferencia los demás casos el DATA TOKEN es ahora 0xFC en lugar de 0xFE. Al igual que antes, tras cada paquete la tarjeta hace un acknowlegde y esta BUSY durante un tiempo (linea BAJA). Cuando la línea se libera se pueden seguir mandando paquetes. Cuando el micro ya no desea mandar más bloques, envía un TOKEN de fin de datos (0xFD o Stop Transmission).</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtyDfQPExw2L6QZ1BXw0T1tIN1vuLJicCBUiO5Z41HQDzup5GGC6dcIWS1WiQ4_bnxOa65DpWEItZvQtQe7t5BnpLcfJQ7wAHg1Dx1iHVnQ1RhNE8QULjLAVxp0TQcPftz-2oTZFuI/s1600/mult_write.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtyDfQPExw2L6QZ1BXw0T1tIN1vuLJicCBUiO5Z41HQDzup5GGC6dcIWS1WiQ4_bnxOa65DpWEItZvQtQe7t5BnpLcfJQ7wAHg1Dx1iHVnQ1RhNE8QULjLAVxp0TQcPftz-2oTZFuI/s640/mult_write.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;">Estas dos figuras las he cogido de <a href="http://elm-chan.org/docs/mmc/mmc_e.html">http://elm-chan.org/docs/mmc/mmc_e.html</a> una muy buena referencia que ya he citado en la entrada anterior. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Veamos un ejemplo de aplicación del comando de escritura múltiple (recordad que la escritura era el caso menos eficiente):</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="color: #b28c00; font-size: 9pt;">#define</span><span lang="EN-GB" style="font-size: 9pt;">
DATA_TOKEN_MULT_WRITE 0xFC</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: #b28c00; font-size: 9pt;">#define</span><span style="font-size: 9pt;"> STOP_TRAN 0xFD</span><o:p></o:p></div>
<br />
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"><br /></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte multiple_write_sector(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* buf, uint16 n)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> byte res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">int</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">uint16 ss,err=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SDSC</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> s<<=9;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Start address of sector in bytes
(sector # x 512)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#endif</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> select_SD;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=send_command_R1(CMD_WRITE_MULT,s); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Multiple sector write</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res) {deselect_SD; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res;}
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Error</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_rx(res); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 1 byte "margin" before sending data</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (ss=0;ss<n;ss++) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 12px;">// Envio de n sectores</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">{</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=1; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(DATA_TOKEN_MULT_WRITE); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Sends Data Token</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0;k<512;k++) spi_tx(buf[k]); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Sends data </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">spi_tx(0xFF); spi_tx(0xFF); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// dummy CRC</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> LATBbits.LATB0=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> LATD++;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_rx(res); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Get answer from card with Write Status</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res = (res>>1)&0b00000111; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Extract status bits </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res!=2) err++; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Error, data not accepted</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=0x00; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (res!=0xFF) spi_rx(res); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Wait until line is clear</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> Delay10KTCYx(4); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 5 msec delays between DATA blocks (no needed)</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(STOP_TRAN); spi_clock(); </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 12px;">// Send STOP_TRAN and "wait" 1 byte </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=0x00; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (res!=0xFF) spi_rx(res); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Wait until line is clear</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">deselect_SD;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 9pt;"> err;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<span style="font-family: Verdana, sans-serif;">En el bucle donde enviamos los sucesivos bloques hemos añadido un delay de 40,000 ciclos (5 msec con la configuración de reloj usada). </span><br />
<span style="font-family: Verdana, sans-serif;">Este delay es completamente innecesario y se ha puesto para tener una referencia en la traza del osciloscopio. El pin RB0 marca como antes el tiempo estricto de transmisión de los 512 datos. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5Nh6GnjSCpg53Av9En9AMl2uVZ7kJBrY72ZwFe2p3ldWWXWkklXQLse0E7OAgYgBZryZzBSi2Fv6VTGUYoTqGZrpc4teap9jfjs4hOewyL7QKbJNS7XTRAvjAV7K5_mg2zIDS1DGB/s1600/oscope_pan32_multiple_write.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5Nh6GnjSCpg53Av9En9AMl2uVZ7kJBrY72ZwFe2p3ldWWXWkklXQLse0E7OAgYgBZryZzBSi2Fv6VTGUYoTqGZrpc4teap9jfjs4hOewyL7QKbJNS7XTRAvjAV7K5_mg2zIDS1DGB/s1600/oscope_pan32_multiple_write.jpg" /></a></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Vemos que el tiempo de transferencia siguen siendo los mismos 3.1 msec de antes. Pero ahora la separación entre pulsos de transferencia es de exactamente los 5 msec programados en el delay. Esto quiere decir que el tiempo que la tarjeta esta BUSY tras la transferencia es ahora despreciable. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Otra recomendación para mejorar la escritura (en el caso en que se conozca a-priori el número de sectores a escribir) es informar previamente a la tarjeta del número de sectores a escribir mediante el comando ACMD23 (con argumento = número de sectores). Esto permite a la tarjeta optimizar sus operaciones de borrado, que como sabemos pueden afectar a varios bloques a la vez. El uso de este "pre-aviso" no exime al usuario de la necesitad de enviar el byte de STOP_TRAN una vez que los bloques deseados hayan sido enviados.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Usando estas mejoras es posible conseguir tasas de escritura tan altas como las de lectura, del orden de unos 150 Kb/sec limitadas básicamente por la velocidad de la comunicación SPI.</span><br />
<br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Obviamente, el problema de intentar llegar a estas tasas de transferencia (tanto de lectura como de escritura) es que el PIC estará al 100% ocupado enviando los datos del buffer a la tarjeta a través de SPI. Pero si esta ocupado al 100% no tendrá tiempo para llenar ese buffer con cosas interesantes que merezca la pena guardar. De hecho, en los ejemplos anteriores escribíamos los mismos contenidos una y otra vez. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">El problema es algo similar a lo que pasaba en el caso de intentar llegar al límite en la tasa de muestreo del ADC. Eramos capaces de muestrear muy rápido pero no nos quedaba tiempo para hacer nada con las muestras adquiridas. La solución será la misma de entonces, el uso de interrupciones (en este caso la interrupción del módulo SSP).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com20tag:blogger.com,1999:blog-4945680608471335280.post-4104241555731594982013-04-09T16:09:00.000+02:002013-06-07T16:05:00.675+02:00Tarjetas SDSC/SDHC (inicialización y lectura de registros)<br />
<div class="MsoNormal">
<span style="font-family: Verdana;">Como un
ejemplo un poco más complicado (pero muy útil) del uso del protocolo SPI
veremos en más detalle el uso de tarjetas de memoria flash en su formato SD
(SecureDigital). Entre las posibilidades de comunicación que ofrecen dichas
tarjetas está un modo SPI. Este modo, aunque más lento que el modo SD nativo,
es más sencillo de implementar.</span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">En este tutorial nos centraremos en las conexiones hardware, la inicialización de la tarjeta (tanto para tarjetas SD standard como para las SDHC de alta capacidad), y la obtención de las características de la tarjeta (capacidad, número de sectores, número de serie, etc.) a través de sus registros CSD y CID.</span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">El objetivo es conseguir el volcado de información que aparece a la derecha</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_g9oL0qVZqYodh8hQtFn_vVGi0B7bcZwkR34wdkkBPuHiRTGIrEIfh0NBTZeC-4EVf769LLQQl1A4lqTZfQXK0zznmDT6nViYO5FW_CiMCSbq_f6MBIduFGP4S7IdNahWxpAWeRHD/s1600/foto_inicial.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_g9oL0qVZqYodh8hQtFn_vVGi0B7bcZwkR34wdkkBPuHiRTGIrEIfh0NBTZeC-4EVf769LLQQl1A4lqTZfQXK0zznmDT6nViYO5FW_CiMCSbq_f6MBIduFGP4S7IdNahWxpAWeRHD/s640/foto_inicial.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal">
<br />
<span style="font-family: Verdana;">En una entrada posterior veremos como leer/escribir datos en la tarjeta, considerando como optimizar dicha transferencia de datos.</span><span style="font-family: Verdana;"> </span><br />
<br />
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/SPI_sdhc.c">SPI_sdhc.c</a></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"></span></u></b></div>
<a name='more'></a><b><u><br /></u></b>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana;"><b>--------------------------------------------------------------------</b></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Hardware:</span></u></b><br />
<b><u><span style="font-family: Verdana;"><br /></span></u></b>
<span style="font-family: Verdana;">Las imágenes muestran el pin-out de una tarjeta SD. </span><span style="font-family: Verdana;">No todos los pines mostrados se usan en la interfaz SPI.</span><span style="font-family: Verdana;"> </span><span style="font-family: Verdana;">La siguiente tabla especifica los pines usados y su función:</span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600"
o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f"
stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
margin-left:243pt;margin-top:7.35pt;width:69pt;height:30pt;z-index:1'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><u><span style="font-family: Verdana;"><o:p></o:p></span></u></div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitjjxGqYruc-N5OUCRFabkRw5eUvjrOTXiCZT0gvu7ePZ6dpcPQE2O1YJ9rzVkGb1gCS8ox6BGIQ0pDnHFbLKkx-vrcu664y8HU2WFdMGOK_x7G-jPGwdQrUZZumbSt7kcOS71uC2R/s1600/foto_pines.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitjjxGqYruc-N5OUCRFabkRw5eUvjrOTXiCZT0gvu7ePZ6dpcPQE2O1YJ9rzVkGb1gCS8ox6BGIQ0pDnHFbLKkx-vrcu664y8HU2WFdMGOK_x7G-jPGwdQrUZZumbSt7kcOS71uC2R/s200/foto_pines.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTo94Gu-7YlR6FJ7tKxlQ_Vap5O_enH1a2HRSa2fd3-8mzterCBcFqzKw_Wl-WNeKaIRkO8RH1j9J_5kAaMcmvm2ko5g-sNrLxhERCivOKfrizZpPmf4ELk1OQdOFAMKc1TyVPFpqH/s1600/sd_pinout.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTo94Gu-7YlR6FJ7tKxlQ_Vap5O_enH1a2HRSa2fd3-8mzterCBcFqzKw_Wl-WNeKaIRkO8RH1j9J_5kAaMcmvm2ko5g-sNrLxhERCivOKfrizZpPmf4ELk1OQdOFAMKc1TyVPFpqH/s200/sd_pinout.jpg" width="200" /></a></div>
<br /></div>
<div class="MsoNormal">
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCuQrpRpsCmhDKnd0hyVNkgaiYkQuEfjmhPbsaM2Z1HtF8bypWAcCz9OwzTdtlAVS0pkTMwQz_SfZPXF0DMcZ52Et_Vdi_zJy5sncxDl4g9uXLd3VS5Z-3LNs9J8bnXOYbX1ntRhts/s1600/micro_sd_images.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" height="149" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCuQrpRpsCmhDKnd0hyVNkgaiYkQuEfjmhPbsaM2Z1HtF8bypWAcCz9OwzTdtlAVS0pkTMwQz_SfZPXF0DMcZ52Et_Vdi_zJy5sncxDl4g9uXLd3VS5Z-3LNs9J8bnXOYbX1ntRhts/s200/micro_sd_images.jpg" width="200" /></a></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 95.4pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">PIN<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">Name<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">Tipe<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Description<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">CS<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">In<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Chip
Select (asserted low)<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">SDI<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">In<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Serial
Data input<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">3<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">Vss<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">Gnd<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Ground<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">4<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">Vdd<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">V+<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Power
(3.3V usually)<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">5<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">SCL<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">In<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Clock <o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">6<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">Vss<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">Gnd<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Ground<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 25.6pt;" valign="top" width="34"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">7<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 46.4pt;" valign="top" width="62"><div class="MsoNormal">
<span style="font-family: Verdana;">SDO<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 27.8pt;" valign="top" width="37"><div class="MsoNormal">
<span style="font-family: Verdana;">Out<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.2pt;" valign="top" width="167"><div class="MsoNormal">
<span style="font-family: Verdana;">Serial
Data out<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span>
<br />
<span style="font-family: Verdana, sans-serif;">Otros
formatos (como por ejemplo microSD, a la derecha) tendrán la misma funcionalidad, aunque su pinout
puede variar.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Necesitaremos
también el socket para la tarjeta elegida (SD o microSD). En Ebay, sparkfun (<a href="https://www.sparkfun.com/products/204">https://www.sparkfun.com/products/204</a>)
o Mikroelektronika (<a href="http://www.mikroe.com/add-on-boards/storage/">http://www.mikroe.com/add-on-boards/storage/</a>)
podéis adquirir diversas tarjetas con un socket SD o microSD y alguna
electrónica adicional. Yo estoy usando un simple socket ($5-10 sin electrónica)
como el mostrado a la izquierda.
Obviamente tendremos el mismo problema de antes: la diferencia de voltaje
entre los 5V del PIC y los 3.3V de la tarjeta. Lo he resuelto de la misma forma
cutre de antes (ver entrada de memoria flash): un regulador para obtener 3.3V a
partir de los 5V del PIC, con divisores de tensión en las lineas micro <span style="font-family: Wingdings; font-size: 8.0pt; mso-ascii-font-family: Verdana; mso-char-type: symbol; mso-hansi-font-family: Verdana; mso-symbol-font-family: Wingdings;">à</span> tarjeta y conexión directa de la
tarjeta (3.3V) al micro (5V). <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvTBwF-vCtpXni1cL1NChKYUDSkV8YFn9l4oJL16Gg_do5oAW6Tb6BH-BZqRBQxI9JgkqSHxCQUoypxPOYuXhxZ3nrScBy5C_SfA_8eqI-fiw22IqUFmhYAIMSqhC8FhkXti1_qdzf/s1600/socket_sparkfun.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"> <img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvTBwF-vCtpXni1cL1NChKYUDSkV8YFn9l4oJL16Gg_do5oAW6Tb6BH-BZqRBQxI9JgkqSHxCQUoypxPOYuXhxZ3nrScBy5C_SfA_8eqI-fiw22IqUFmhYAIMSqhC8FhkXti1_qdzf/s1600/socket_sparkfun.jpg" /></span></a></div>
<span style="font-family: Verdana, sans-serif;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1DKLfp_zdLEvqJ_bcaAfsofRiamz-arj6KG5AcYPlOLbBGycxugc7E8Y5rrVfK76cAWK8raQVPveuwqFTPEMrP54Qi4iWOdrq_u7OqZL8z8z-HjlLn9ftuRzVAHoKVFnLtBWV_G-g/s1600/mikroe_converters.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1DKLfp_zdLEvqJ_bcaAfsofRiamz-arj6KG5AcYPlOLbBGycxugc7E8Y5rrVfK76cAWK8raQVPveuwqFTPEMrP54Qi4iWOdrq_u7OqZL8z8z-HjlLn9ftuRzVAHoKVFnLtBWV_G-g/s1600/mikroe_converters.jpg" /></a></span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Algunas de
las tarjetas que se pueden adquirir (como la de Mikroe mostrada a la derecha
$20), incorporan un regulador de 5 a
3.3V y conversores de niveles que serían más fiables. En este caso es sólo una
cuestión de <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">conectar
los pines correspondientes.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Recalcar
de nuevo la necesidad de resistencias pull-up en las líneas MISO y MOSI que
mantengan alta la línea en ausencia de actividad por parte del micro o tarjeta.
De nuevo, algunas de las opciones comentadas incluyen estas resistencias
pull-up. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Configuración del módulo SPI<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Antes de
hacer nada debemos elegir el modo SPI (CPOL,CPHA), velocidad, etc. para
inicializar el módulo SPI del PIC.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El modo
SPI (0,0) con SMP=0 es una combinación que me ha funcionado con
todas las tarjetas usadas. Obviamente el micro (PIC) será el master SPI. Solo
nos hace falta decidir la velocidad del reloj. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En algunos
referencias se advierte que es preciso una conexión inicial a baja velocidad
(se cita un máximo de 400Khz) y solo cuando la tarjeta ha sido convenientemente
inicializada y ha habido una negociación pasaremos a la velocidad máxima
soportada. En otros lugares se indica que dicha restricción es sólo para
tarjetas MMC. Con las tarjetas que yo he probado (SD todas ellas) la
inicialización ha sido satisfactoria arrancando a la máxima velocidad, pero no
cuesta nada realizar el primer intercambio a velocidad baja y pasar a velocidad
alta tras la inicialización.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En nuestro
caso usaremos Fosc/64 como velocidad inicial y Fosc/4 como velocidad final. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En este
proyecto usaremos un cristal de 8 MHz y la opción HSPLL en la configuración.
Con esta opción un PLL multiplica por 4 la frecuencia del cristal, por lo que
el PIC está trabajando a 32 Mhz. Para habilitar esta opción basta hacer al
principio del programa:<span style="font-size: x-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#pragma</span><span style="font-family: 'Courier New'; font-size: 9pt;"> config
OSC=HSPLL </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// PLL x 4</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> </span><span style="font-family: Verdana;">Con un
cristal "efectivo" de 32 MHz, la velocidad más lenta (Fosc/64)
corresponde a un reloj del SPI inicial de 500 Khz y una velocidad final (Fosc/4)
de 8 Mhz. La velocidad inicial se sale un poco del máximo recomendado, pero me
ha funcionado con las tarjetas probadas.</span></div>
<div class="MsoNormal">
<br />
<span style="font-family: Verdana;">Usando las
rutinas conocidas podemos inicializar el módulo SPI con la siguiente función:</span></div>
<div class="MsoNormal">
<br />
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CS line</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SD_CS
LATCbits.LATC2</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SD_CS_dir TRISCbits.TRISC2</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_SD
SD_CS=0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> deselect_SD SD_CS=1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SD_spi_init(byte clock)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SD_CS_dir=0; deselect_SD; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Configure CS line as output and set it low.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_master(clock); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Configure SPI as master and set clock </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_mode(0,0,0); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
SPI mode (0,0). Sample incoming bits at mid period </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_enable(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Enable SPI</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<span style="font-family: Verdana;">Como
hicimos en el caso de la memoria flash, previamente definimos SD_CS y SD_CS_dir
para informar al resto de las rutinas de que pin estamos usando como ChipSelect
(CS) y su correspondiente bit de dirección TRIS.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Especificación del protocolo SPI
para tarjetas SD</span></u></b><b><span style="font-family: Verdana;"><o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el
documento <b><i><a href="http://alumni.cs.ucr.edu/~amitra/sdcard/ProdManualSDCardv1.9.pdf">SanDisk
Secure Digital Card (Product Manual)<span style="font-style: normal; font-weight: normal;"> </span></a> </i></b> podéis encontrar unas especificaciones
bastante completas del protocolo para comunicarse con tarjetas SD. En
particular hay que leer el capítulo 5 que contiene la definición del protocolo
SPI. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Garamond;">Nota: todo lo que viene a continuación es una
versión muy reducida del protocolo completo. Sigo muchos atajos (confiando por
ejemplo que se que tipo de tarjeta tengo, o que voltaje acepta) y como siempre
existe la posibilidad de que tenga errores. El protocolo completo es complejo y
es posible que si no se respeta estrictamente tengamos un código que funcione
en muchos casos pero falle para cierto tipo de tarjetas que exigen una
adherencia más estricta al protocolo. En
caso de duda o problemas no hay nada como leerse las especificaciones. <o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: Garamond;">De hecho, si alguien desea
realmente enterarse de los detalles debería estar leyendo dicho capítulo 5 en
lugar de este documento.<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Además de
en una somera lectura de las especificaciones, el código presentado está basado
en varias fuentes entre las que caben destacar:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><a href="http://read.pudn.com/downloads126/sourcecode/windows/vxd/534552/sd_raw.c__.htm">http://read.pudn.com/downloads126/sourcecode/windows/vxd/534552/sd_raw.c__.htm</a> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><a href="http://read.pudn.com/downloads197/sourcecode/embed/926698/fs/MMC_SD_CardMode_Drv.c__.htm">http://read.pudn.com/downloads197/sourcecode/embed/926698/fs/MMC_SD_CardMode_Drv.c__.htm</a><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><a href="http://mikrokopter.de/mikrosvn/NaviCtrl/tags/V0.1/sdc.c">http://mikrokopter.de/mikrosvn/NaviCtrl/tags/V0.1/sdc.c</a><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Algunos de
estos códigos son para otros micros, pero la base del protocolo de comunicación
es esencialmente la misma. En general los programas citados anteriormente son
mucho más completos que el que presento aquí, considerando más tipos de
comandos, etc. <o:p></o:p></span><br />
<span style="font-family: Verdana;"><br /></span><span style="font-family: Verdana;">Una muy buena referencia del proceso de inicialización de una tarjeta SD puede encontrarse en </span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;"> </span><a href="http://elm-chan.org/docs/mmc/mmc_e.html">http://elm-chan.org/docs/mmc/mmc_e.html</a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;"><br /></span></u></b>
<b><u><span style="font-family: Verdana;"><br /></span></u></b>
<b><u><span style="font-family: Verdana;">Envío de comandos a la tarjeta SD:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El
protocolo de comunicación entre PIC y tarjeta SD se basa en el envío de
comandos desde el PIC y la recepción de respuestas de la tarjeta. La secuencia
standard es:</span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<ol>
<li><span style="font-family: Verdana;">Comando
de PIC a SD (un total de 6 bytes)</span></li>
<li><span style="font-family: Verdana;">Respuesta
de SD a PIC (normalmente 1 o 2 bytes, casi siempre 1, a veces más dependiendo
del comando usado). La tarjeta siempre responde, aunque podemos llegar a necesitar hasta 8 "peticiones" de bytes hasta que llegue las respuesta.</span></li>
<li><span style="font-family: Verdana;">Opcionalmente
un bloque de datos (en uno u otro sentido) si el comando era de
escritura/lectura de datos.</span></li>
</ol>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En este
apartado presentaremos el intercambio más sencillo consistente en Envio de Comando/Respuesta
sin datos. La figura siguiente ilustra este tipo de intercambios.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3vMXcm7gEAy4sxfqh9q4jWu324ltGq-gEJVKDjeeireKgD1OES12zHSHKsfA-CFik_xFdpfQzen_sSzqyGTh1XOaRrn8eJB6MSG4XAszZ3Z1NOQRupCaa9GplkkwxJrOhJKA2STub/s1600/intercambio_sin_datos.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3vMXcm7gEAy4sxfqh9q4jWu324ltGq-gEJVKDjeeireKgD1OES12zHSHKsfA-CFik_xFdpfQzen_sSzqyGTh1XOaRrn8eJB6MSG4XAszZ3Z1NOQRupCaa9GplkkwxJrOhJKA2STub/s640/intercambio_sin_datos.png" width="640" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> <o:p></o:p></span><span style="font-family: Verdana;">En
ocasiones (2º ejemplo de la figura) el comando exige un cierto trabajo a la
tarjeta. Para indicar que está ocupada mantendrá la línea MISO a 0.</span><span style="font-family: Verdana;"> </span><span style="font-family: Verdana;">Como dicha línea debería tener una
resistencia de pull-up que la mantenga a nivel alto por defecto si está a 0
indica que la tarjeta la está manteniendo abajo y que debemos esperar a que
termine.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El comando
enviado es simplemente un código (1 byte) seguido de un argumento de 4 bytes y
de un CRC de un byte, para un total de 6 bytes. El uso de un CRC correcto es
opcional en el protocolo SPI y generalmente se ignora su valor (aunque hay que seguir
mandando dicho byte). La única excepción
es en los primeros comandos enviados para pasar al modo SPI. Como la tarjeta no está
todavía en modo SPI si que es preciso enviar un CRC valido.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código
de comando es un valor de 6 bits (de 0 a 63). Antes de mandarlo se añade 01 en
los dos bits más significativos. Para ello haremos un OR con el valor 0b01000000=0x40. La tabla
siguiente refleja algunos de los comandos usados en el código:<o:p></o:p></span></div>
<div class="MsoNormal">
<br />
<br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_GO_IDLE_STATE 0x00 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD00: R1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_SEND_CSD 0x09 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD09: R1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_SEND_CID 0x0A </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD10: R1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_SET_BLOCKLEN 0x10 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD16: R1 arg=BLOCKLEN</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_READ_SECTOR 0x11 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD17: R1 arg=data address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_READ_MULT 0x12 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD18: R1 arg=data address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_WRITE_SECTOR 0x18 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD24: R1 arg=data address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_WRITE_MULT 0x19 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD25: R1 arg=data address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_APP 0x37 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CMD55: R1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ACMD_SEND_OP_COND 0x29 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// ACMD41 R1 (after CMD_APP_CMD)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// SDHC addemdum</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_SEND_OP_COND
0x01</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> CMD_SEND_IF_COND
0x08</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Tras la
recepción de un comando (aunque puede que no inmediatamente) la tarjeta
responderá. Hay varios formatos de respuesta, dependiendo del comando, pero el
más común es el tipo R1, de tamaño 1 byte:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUfXmtLlN6Zna-Ntg1s9LuyOLgsCR1U_VHIjwizQxNmD0BrGpBJWkDRGop7s2bko_SoK5AFS0nZJhFqq_iPlNA6qh4XbHcYoinCjcl4zcwHAuLWztbRuzrF7zDcKPiZLTdO3v657w6/s1600/R1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUfXmtLlN6Zna-Ntg1s9LuyOLgsCR1U_VHIjwizQxNmD0BrGpBJWkDRGop7s2bko_SoK5AFS0nZJhFqq_iPlNA6qh4XbHcYoinCjcl4zcwHAuLWztbRuzrF7zDcKPiZLTdO3v657w6/s320/R1.png" width="320" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El bit más
significativo debe ser 0. Un 1 en esa posición indica que el byte recibido no
es una respuesta válida. De nuevo, la idea es que el pull-up en está línea la mantendrá
alta en ausencia de actividad por parte de la tarjeta. Exigir que el 1er bit
sea un 0 permite saber si la tarjeta está activa. El resto de los bits indican
distintos tipos de errores cuando están a 1. La excepción es el bit 0 que
indica que la tarjeta esta en IDLE_STATE y corriendo el proceso de inicialización.
En el código usamos los siguientes defines para identificar estos estados:</span><br />
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span class="apple-converted-space"><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span></span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">R1_IDLE <span class="apple-converted-space"> </span>0x01 <span class="apple-converted-space"> </span><span style="color: forestgreen;">// <span class="apple-converted-space"> </span>Idle_State</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#define</span><span class="apple-converted-space"><span style="font-family: "Courier New"; font-size: 9.0pt;"> </span></span><span style="font-family: "Courier New"; font-size: 9.0pt;">R1_BAD <span class="apple-converted-space"> </span>0x80 <span class="apple-converted-space"> </span><span style="color: forestgreen;">// <span class="apple-converted-space"> </span>MSbit no nulo</span></span></div>
</div>
<br />
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las
respuestas de tipo R2 consisten en un byte adicional con información adicional (el 1er byte es identico a
R1). Hay también respuestas con un mayor número de bytes. En el código
de este tutorial solo trabajaremos con respuestas del tipo R1.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Vamos a
escribir una función que mande un comando, reciba la respuesta y compruebe que
todo va bien para poder proseguir. La función usada para mandar un comando de
tipo R1 es la siguiente (habría que escribir distintas funciones para enviar
comandos tipo R2, etc.:</span></div>
<div class="MsoNormal">
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">/// send a R1 type command and wait for an answer</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">byte
send_command_R1(byte cmd,<span class="apple-converted-space"> </span><span style="color: blue;">unsigned</span><span class="apple-converted-space"> </span><span style="color: blue;">long</span><span class="apple-converted-space"> </span>arg)</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> byte*
ptr = (byte*)&arg;<span class="apple-converted-space"> </span><span style="color: forestgreen;">// Pointer to individual bytes of argument</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> byte
k,res,crc=0xFF;</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: blue;">if</span><span class="apple-converted-space"> </span>(cmd==CMD_GO_IDLE_STATE)
crc=0x95;<span class="apple-converted-space"> </span><span style="color: forestgreen;">// <span class="apple-converted-space"> </span>CMD00
--> crc needed = 0x95</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: blue;">if</span><span class="apple-converted-space"> </span>(cmd==CMD_SEND_IF_COND) <span class="apple-converted-space"> </span>crc=0x87;<span class="apple-converted-space"> </span><span style="color: forestgreen;">// <span class="apple-converted-space"> </span>CMD08 --> crc needed = 0x87</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> cmd
= (cmd & 0x3F) | 0x40;<span class="apple-converted-space"> </span><span style="color: forestgreen;">// Makes sure cmd is 6 bit and OR it with 0x40</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: forestgreen;">// Wait up to 10 x 8 clocks until line is idle (0xFF)</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> k=10;
res=0;<span class="apple-converted-space"> </span><span style="color: blue;">while</span><span class="apple-converted-space"> </span>( (res!=0xFF) && (k--) )
{res=spi_rx(); <span class="apple-converted-space"> </span>Delay10TCYx(1);
}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: forestgreen;">// <span class="apple-converted-space"> </span>Send
command, argument and CRC (only needed for CMD00 and CMD08)</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> spi_tx(cmd);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Command</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: blue;">for</span>(k=0;k<4;k++) spi_tx(ptr[3-k]);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Argument bytes: Most Significant Byte first</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> spi_tx(crc); <span class="apple-converted-space"> </span><span style="color: forestgreen;">////
CRC (fake in all cases except for CMD00 or CMD08)</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Wait up to 10 bytes to get a R1 answer with a clear MSbit</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> res=0xFF;
k=10;<span class="apple-converted-space"> </span><span style="color: blue;">while</span><span class="apple-converted-space"> </span>( (res&R1_BAD) && (k--) )
res=spi_rx();</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: forestgreen;"> </span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span style="color: blue;">return</span><span class="apple-converted-space"> </span>res;</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">}</span></div>
</div>
<br />
<div class="MsoNormal">
<br /></div>
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: Verdana, sans-serif;">Algunos
comentarios sobre el código anterior:</span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<ul>
<li><span style="font-family: Verdana, sans-serif;">Antes
de enviar el comando se verifica que la línea esta libre (alta). Se detecta al
recibir 0xFF.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Se
manda el COMANDO + 4 bytes de argumento + CRC.</span></li>
<li><span style="font-family: Verdana, sans-serif;">El CRC enviado solo es correcto para dos comandos CMD00 y CMD08 que se mandan al principio. En todos los demás casos se usa un CRC=0xFF.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Se
espera hasta recibir una respuesta tipo R1, con el primer bit igual a 0. LLegamos a esperar hasta 10 peticiones de respuesta antes de desistir.</span></li>
</ul>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif; font-size: 9.0pt; mso-bidi-font-family: "Courier New";">Inicialización
de la tarjeta en modo SPI<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Una vez
que ya sabemos la configuración necesaria para el puerto SPI y como mandar
comandos básicos a la tarjeta, estamos en condiciones de inicializar una
tarjeta SD. Pasamos a describir los
pasos para conseguirlo.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br />
<b>Nota:</b> la inicialización completa de una tarjeta SD es un proceso complicado si queremos cubrir todas las posibilidades. En <a href="http://elm-chan.org/docs/mmc/sdinit.png">http://elm-chan.org/docs/mmc/sdinit.png</a> podéis encontrar un diagrama de flujo de los pasos a seguir. El proceso que presento aquí es una simplificación de ese gráfico que me funciona para todas las SD que he probado (SDSC v1.0, SDSC v2.0 y SDHC v2.0). Si estáis seguros de la tarjeta que váis a usar podríais simplificar aún más el código presentado. Si debemos manejar cualquier tarjeta que a la gente se le ocurra meter en la ranura, deberíamos implementar el protocolo completo.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
Tras un power-up una tarjeta SD despierta en modo SDbus. Lo primero que hay que hacer es pasarla a modo SPI. El proceso que uso en mi código es el siguiente:</span><br />
<span style="font-family: Verdana, sans-serif;"><span style="font-family: Verdana; font-size: 8.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;"><br /></span>
</span><br />
<ol>
<li><span style="font-family: Verdana, sans-serif;">Dejar
un delay inicial de algunos ms para estar seguros de que se ha
estabilizado la alimentación</span></li>
<li><span style="font-family: Verdana, sans-serif;">Inicializar SPI a la velocidad más lenta (Fosc/64)</span></li>
<li><span style="font-family: Verdana, sans-serif;">Con
CS=1 (deselect_SD), mandar al menos 74 clocks a la tarjeta. Lo conseguiremos
mandando 8 bytes (8x10=80) cualesquiera usando spi_clock().</span></li>
<li><span style="font-family: Verdana, sans-serif;">Mandarle
el comando CMD00 que pone a la tarjeta en modo SPI, dejándola en IDLE_STATE
mientras corre una especie de self-test. Comprobar que se recibe una respuesta tipo
R1 (1 bytes) con valor 0x01 (idle state). Este comando requiere un CRC correcto (00x95). </span></li>
<li><span style="font-family: Verdana, sans-serif;">Si este comando funciona correctamente tratar de enviar un comando CMD_08 a la tarjeta con argumento 0x1AA y CRC = 0x87. Este paso es fundamental si se tiene una tarjeta SDHC y se puede obviar con otras tarjetas. En comandos sucesivos ya no es necesario enviar CRCs correctos.</span></li>
<li><span style="font-family: Verdana, sans-serif;">La especificación indica que ahora deberíamos preguntar sobre
un cierto registro (OCR) y determinar el voltaje aceptado por la tarjeta y
actuar en consecuencia. También hay una serie de pasos que permiten distinguir entre las antiguas tarjetas MMC y las más
modernas SD. Si estamos seguros de que no hay problemas de voltaje y de que
nuestra tarjeta es una SD y no una MMC, podemos saltarnos dichas comprobaciones
y pasar directamente al siguiente paso.</span></li>
<li><span style="font-family: Verdana, sans-serif;"><span style="font-family: Verdana; font-size: 8.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">Si el comando CMD08<b> no fue aceptado</b>, </span>se envía el comando CMD_0x37 seguido del comando CMD_0x29. El comando CMD_0x37 (APP_CMD)
es un "prefijo" que indica que el siguiente comando es un comando
especifico de aplicación (APPLICATION
COMMAND) en vez de un comando usual. El CMD_0x29 (ACMD_SEND_OP_COND) activa el
proceso de inicialización de la tarjeta en modo SPI. Ambos comandos no precisan
argumento (aunque siempre hay que mandar 4 bytes, p.e. 0x00 00 00 00) ni CRCs
correctos. </span></li>
<li><span style="font-family: Verdana, sans-serif;">Si el comando CMD08 <b>fue aceptado</b> se envia el comando CMD_0x01 (CMD_SEND_OP_COND), de nuevo con argumento 0 y CRC cualquiera.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Si 7 u 8 funcionaron la tarjeta está inicializada y lista para aceptar todo tipo de comandos en modo SPI. Como el proceso de auto-test puede llegar a tardar hasta 1 segundo es conveniente reintentar el envio de estos comando durante cierto tiempo antes de declarar un TIMEOUT.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Trás la inicialización podemos</span><span style="font-family: Verdana, sans-serif;"> usar el comando SET_BLOCKLEN (CMD16) para fijar el tamaño del bloque de
datos (que se pasa como argumento). El tamaño "nativo" de las
tarjetas SD es de 512 bytes. En operaciones de lectura se puede especificar un
tamaño de bloque entre 1 y 512 bytes. Las operaciones de escritura deben
hacerse en bloques de 512. Lo normal es usar el BLOCKLEN nativo de 512.</span></li>
</ol>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Verdana, sans-serif;">Una vez inicializada la tarjeta, volvemos a poner la máxima velocidad posible (Fosc/4) en el reloj del módulo SPI (si es que empezamos con una velocidad lenta) para agilizar las
transferencias de información. El código completo
de la inicialización queda:</span></div>
<div class="MsoNormal">
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#define</span><span class="apple-converted-space"><span style="font-family: "Courier New"; font-size: 9.0pt;"> </span></span><span style="font-family: "Courier New"; font-size: 9.0pt;">N_trials 10</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">byte
init_SD(<span style="color: blue;">void</span>)</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>byte k,res;</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>SD_spi_init(2); <span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Slow SPI clock (Fosc/64)</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>deselect_SD;<span class="apple-converted-space"> </span><span style="color: blue;">for</span><span class="apple-converted-space"> </span>(k=0;k<10;k++) spi_clock();<span class="apple-converted-space"> </span><span style="color: forestgreen;">//80
clocks with CS=1 to start up card</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>select_SD; </span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">for</span>(k=0;k<N_trials;k++) <span class="apple-converted-space"> </span><span style="color: forestgreen;">//Try
with CMD_0x00 a few times</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=send_command_R1(CMD_GO_IDLE_STATE,0x00); </span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res==R1_IDLE)<span class="apple-converted-space"> </span><span style="color: blue;">break</span>;<span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Great, card went into IDLE_STATE</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>Delay10KTCYx(25);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//delay</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res!=R1_IDLE) {deselect_SD;<span class="apple-converted-space"> </span><span style="color: blue;">return</span><span class="apple-converted-space"> </span>4;} <span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Didn't reach IDLE_STATE</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Check a few times for SDHC with CMD_0x08</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">for</span>(k=0;k<N_trials;k++)</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=send_command_R1(CMD_SEND_IF_COND,0x1AA); </span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res==R1_IDLE)<span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Great, CMD_08 accepted</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>spi_clock(); spi_clock(); spi_clock();
spi_clock(); <span class="apple-converted-space"> </span><span style="color: forestgreen;">// Shift 4 trailing bytes</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">break</span>;<span class="apple-converted-space"> </span><span style="color: forestgreen;">//</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>Delay10KTCYx(25);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//delay_ms</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: forestgreen;">//
According to answer to CMD08 try CMD_SEND_OP, ACMD_SEND_OP, or return with
error</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">switch</span><span class="apple-converted-space"> </span>(res)</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">case</span><span class="apple-converted-space"> </span>1: <span class="apple-converted-space"> </span><span style="color: forestgreen;">//SDHC
card --> send CMD_01</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=1; k=0; <span class="apple-converted-space"> </span><span style="color: forestgreen;">// Try
with CMD_SEND_OP a few times.</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">while</span>(res
& (k<100))</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span> {</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=send_command_R1(0x01,0x40000000);<span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res&R1_BAD)<span class="apple-converted-space"> </span><span style="color: blue;">continue</span>; </span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>k++; Delay10KTCYx(10);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//delay_ms(20);</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res) {deselect_SD;<span class="apple-converted-space"> </span><span style="color: blue;">return</span><span class="apple-converted-space"> </span>2;} <span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Card failed when sending CMD_SEND_OP_COND after CMD08</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">break</span>;</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">case</span><span class="apple-converted-space"> </span>5:<span class="apple-converted-space"> </span> <span style="color: forestgreen;">// CMD08 declared illegal command, maybe it is a
normal SD card</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=1; k=0; <span class="apple-converted-space"> </span><span style="color: forestgreen;">// Try
with CMD_APP+ACMD_SEND_OP a few times.</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">while</span>(res
& (k<100))</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>{</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=send_command_R1(CMD_APP,0);<span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res&R1_BAD)<span class="apple-converted-space"> </span><span style="color: blue;">continue</span>; </span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=send_command_R1(ACMD_SEND_OP_COND,0);</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>k++; Delay10KTCYx(10);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//delay_ms(20);</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">if</span><span class="apple-converted-space"> </span>(res) { deselect_SD;<span class="apple-converted-space"> </span><span style="color: blue;">return</span><span class="apple-converted-space"> </span>1; }<span class="apple-converted-space"> </span><span style="color: forestgreen;">// Card failed when sending ACMD_SEND_OP_COND</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span><span style="color: blue;">break</span>;</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> </span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>otherwise: <span class="apple-converted-space"> </span>deselect_SD;<span class="apple-converted-space"> </span><span style="color: blue;">return</span><span class="apple-converted-space"> </span>3; <span class="apple-converted-space"> </span><span style="color: blue;">break</span>; <span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Failed CMD08</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>}</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>res=send_command_R1(CMD_SET_BLOCKLEN,512L); <span class="apple-converted-space"> </span><span style="color: forestgreen;">// Set
block length = 512</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>deselect_SD;</span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span>SD_spi_init(0);<span class="apple-converted-space"> </span><span style="color: forestgreen;">//
Fastest SPI clock (Fosc/4)</span></span><span lang="EN-GB"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;"> <span class="apple-converted-space"> </span></span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">return</span><span class="apple-converted-space"><span style="font-family: "Courier New"; font-size: 9.0pt;"> </span></span><span style="font-family: "Courier New"; font-size: 9.0pt;">(0);</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span style="font-family: "Courier New"; font-size: 9.0pt;">}</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<div style="margin-bottom: .0001pt; margin: 0cm;">
<b><u><span style="font-family: Verdana;">Lectura de registros CSD/CID de la tarjeta:</span></u></b><span style="font-family: Verdana;"> </span><o:p></o:p></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana;"><br />
Si todo ha ido bien, la rutina init_SD devuelve un valor 0 (no error),
indicando que la tarjeta está lista para aceptar todo tipo de comandos válidos
y para enviar/recibir datos. A continuación veremos como leer nuestros primeros
datos de la tarjeta, los registros CID (Card ID Data) y CSD (Card Specific
Data), conteniendo interesante información de la tarjeta, como su velocidad de
transferencia, capacidad, tamaño de sector, consumo eléctrico, fecha de
fabricación, número de serie, etc.</span><span style="font-size: 13.5pt;"><o:p></o:p></span></div>
<br />
<br /></div>
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Proceso de lectura de datos:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Para
proceder a leer el registro CSD es preciso implementar nuestro primer comando
de lectura de datos. Veremos en primer lugar como es un típico intercambio de
lectura.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Un comando de lectura se inicia con el mismo intercambio
CMD/Respuesta presentado antes. La diferencia es que si el comando tiene éxito,
la tarjeta transferirá un cierto bloque de datos a su buffer de salida y
procederá a enviarlos (cuando el master se lo pida). El número de datos depende del comando, pero el primer
dato enviado es siempre un Data Token (que en la mayoría de los casos corresponde a 0xFE) indicando que los datos pedidos
vienen a continuación. En vez del Data Token (0xFE) también podría recibirse un Error Token (0b 000xxxxx) donde los 5 bits menos significativos corresponden a banderas para diferentes errores. Por ejemplo podríamos haber pedido leer un sector fuera del rango de la tarjeta. Si se recibe un Error Token no se continua con la transmisión de datos esperada.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Un típico comando de lectura de datos tiene el siguiente
diagrama:</span><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrEEySmzAw5H-hh3golFE48rQRIDGaMfqRBnQ7D0xIdN9DbwG53lxXzTbMCaf9NBUWX1SjAUntGhbhHo-TQfZgEqYa1k-pNGukPXB7Tu8kvVy-3Gy8I6AnU0bpEBtb2vrLpwpbRsLA/s1600/operacion_lectura.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrEEySmzAw5H-hh3golFE48rQRIDGaMfqRBnQ7D0xIdN9DbwG53lxXzTbMCaf9NBUWX1SjAUntGhbhHo-TQfZgEqYa1k-pNGukPXB7Tu8kvVy-3Gy8I6AnU0bpEBtb2vrLpwpbRsLA/s640/operacion_lectura.png" width="640" /></a></div>
<div class="MsoNormal" style="text-align: justify;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Al
intercambio CMD/R le sigue la recepción de un bloque de datos. Dicho bloque
está delimitado por un Data Token con valor 0xFE y terminado por un CRC de 16
bits (que puede ignorarse en modo SPI). <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como el
intercambio Command/Response ya esta cubierto en nuestra función send_command()
basta escribir una función que reciba los datos enviados y los guarde en un
buffer indicado por el usuario:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint8 read_data_block(uint8*
buf, uint16 n) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Read data block</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint16
k;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint8
res,crc;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">res=0xFF; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res==0xFF) res=spi_rx(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Wait for first data</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (res!=0xFE) </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Data token not found, return Error Token</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(k=0;k<n;k++) buf[k]=spi_rx(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// read n bytes</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> crc=spi_rx(); crc=spi_rx(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Read CRC (16 bits) and ignore it</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(0);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Lectura del registro CSD:</span></u></b><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Veamos como usar la rutina
anterior para leer los registros CSD y CID. Ambos registros tienen 16 bytes y basta mandar el comando correspondiente para iniciar el proceso de transferencia de esos 16 bytes:</span><br />
<br />
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte read_CSD(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> byte res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=send_command_R1(CMD_SEND_CSD,0); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res==0) res=read_data_block(buf,16);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> deselect_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">byte read_CID(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> byte res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res=send_command_R1(CMD_SEND_CID,0); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(res==0) res=read_data_block(buf,16);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> deselect_SD;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<span style="font-family: Verdana, sans-serif;">Los datos de ambos registros se guardan en el buffer suministrado por el usuario (con un espacio de al menos 16 bytes).</span><br />
<div class="MsoNormal">
<br /></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Para la
interpretación de ambos registros debemos dirigirnos a las especificaciones citadas
anteriormente (en particular el apartado 3.5.3). </span><br />
<span style="font-family: Verdana, sans-serif;">Usando dichas especificaciones he escrito un par de funciones show_CID_data y show_CSD_data que vuelcan por el puerto serie algunos de los campos más interesantes de ambos registros. El registro CID contiene información sobre el fabricante, producto, número de serie y fecha de fabricación. El registro CSD lleva info muy importante sobre tamaño y número de sectores, capacidad de la tarjeta, limitaciones y forma de acceso, etc.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Veamos la salida para un par de tarjetas SD. La primera es una vieja tarjeta de 32 Mb de Panasonic. La segunda, una tarjeta más reciente de 8 Gbytes de SanDisk:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><u>Panasonic 32 Mbytes:</u></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9OkFe_1-dXWE7B-lRd44Ho60pwQyTR8fs3Gnq7vwbp5rJl182NUcZQEkIbXbZHiVHcqntkCIF8WKrgVuJRbFuP5k9wRukdYj5T0R_LLI__Uv9_VDpVsUJ0bK5t6rsv90VOTD05D41/s1600/volcado_pana.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9OkFe_1-dXWE7B-lRd44Ho60pwQyTR8fs3Gnq7vwbp5rJl182NUcZQEkIbXbZHiVHcqntkCIF8WKrgVuJRbFuP5k9wRukdYj5T0R_LLI__Uv9_VDpVsUJ0bK5t6rsv90VOTD05D41/s400/volcado_pana.jpg" width="400" /></a></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><u>SanDisk Ultra 8 Gbytes:</u></span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWOm_maWR4n0MqhsknoZtzXFcj5g8HR5g_ZovnVKyUYCh39_2mcDVykJE-LalQQrSzFyKhCYxOtxMujLgRCwDMTJhGjPVOs41Nn4tzA8wUPQ73cqJPsjQvgbYowXXriG0oTMyxzP12/s1600/volcado_ultra.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="293" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWOm_maWR4n0MqhsknoZtzXFcj5g8HR5g_ZovnVKyUYCh39_2mcDVykJE-LalQQrSzFyKhCYxOtxMujLgRCwDMTJhGjPVOs41Nn4tzA8wUPQ73cqJPsjQvgbYowXXriG0oTMyxzP12/s400/volcado_ultra.jpg" width="400" /></a></div>
<br />
<br />
<span style="font-family: Verdana, sans-serif;">La información más interesante está en el CSD, a partir de la cual podemos saber el tamaño del sector (típicamente 512 bytes) y el número de sectores o capacidad de la tarjeta. La discrepancia entre los datos del fabricante (32 Mb y 8 Gb frente a los 29 Mb y 7580 Mb obtenidos) es que yo estoy usando 1Mbyte = 1024 Kb y no 1 Mbyte = 1000 Kb).</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Otra diferencia muy importante es que la segunda tarjeta (como todas las SD mayores de 2 Gb) es de alta capacidad (SDHC). Esto será importante de cara a la lectura de datos. Las tarjetas más pequeñas admiten lecturas/escrituras parciales de datos (esto es, por debajo del amaño del sector). Esto nos permite mantener un buffer más pequeño en el PIC donde acumular los datos hasta que llega el momento de volcarlos a la tarjeta. Por el contrario en las tarjetas SDHC la lectura/escritura es sólo por bloques de 512 bytes.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">De hecho, como veremos en el siguiente tutorial, cuando usemos los comandos para escribir/leer datos, veremos que en el caso de las tarjetas SDSC (Standard Capacity) cuando especifiquemos la dirección u offset a partir del cual se van a escribir los datos, se dan en unidades de bytes. Por el contrario, en tarjetas SDHC (High Capacity) la dirección de lectura/escritura se da en unidades de bloques. </span><br />
<br /></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com19tag:blogger.com,1999:blog-4945680608471335280.post-33026844087834996722013-04-08T13:05:00.000+02:002013-06-07T16:13:04.074+02:00INTERFAZ SPI con memoria flash (M25P80) <br />
<div class="MsoNormal">
</div>
<div style="background-color: white; line-height: 19.1875px; margin-bottom: 0.5em; margin-top: 0.4em;">
<span style="background-color: transparent; font-family: Verdana;">Las memorias flash es un tipo de memoria electrónica no volátil, derivada de las EEPROM, que que puede ser borrada y reprogramada electrónicamente (</span><a href="http://en.wikipedia.org/wiki/Flash_memory" style="background-color: transparent;">http://en.wikipedia.org/wiki/Flash_memory</a><span style="background-color: transparent;">)</span><span style="background-color: transparent; font-family: Verdana;">. El tipo más común de memoria flash es el tipo NAND que es la base de las tarjetas de memoria, USB oendrives y discos de estado sólido. Al contrario que una memoria EEPROM las memorias flash de tipo NAND pueden ser escritas o borradas en bloques más pequeños que todo el dispositivo (aunque mayores que los bytes individuales). En todos estos
casos la memoria va acompañada de un controlador que hace invisible el
manejo a bajo nivel de la memoria. El usuario se reduce a escribir/leer
sectores lógicos. En esta entrada vamos a escribir algunas rutinas para
conectar una memoria flash (M25P80, 1 Mbyte) con un PIC usando una comunicación
SPI. Al contrario que en los casos citados antes vamos a manejar directamente
los sectores físicos de la memoria, por lo que además de los aspectos de la
comunicación SPI aprenderemos también algunas peculiaridades de este tipo de
memorias. </span></div>
<div style="background-color: white; line-height: 19.1875px; margin-bottom: 0.5em; margin-top: 0.4em;">
<span style="background-color: transparent; font-family: Verdana;"><br /></span></div>
<div style="background-color: white; line-height: 19.1875px; margin-bottom: 0.5em; margin-top: 0.4em;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh65MmxSCkn6aQVzWRWDp31sKKEeoH6XvX8pG0rl6-9-8h0suf7ooLgxD6s4V-xXNUqOaQN5ScJNqPYXg230cHMh65cow2woWWi8hiLYSfniBI1LSaDCuWdMxeDzOlg0_PNZ5nOyAZr/s1600/m25p80.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh65MmxSCkn6aQVzWRWDp31sKKEeoH6XvX8pG0rl6-9-8h0suf7ooLgxD6s4V-xXNUqOaQN5ScJNqPYXg230cHMh65cow2woWWi8hiLYSfniBI1LSaDCuWdMxeDzOlg0_PNZ5nOyAZr/s200/m25p80.jpg" width="192" /></a><span style="background-color: transparent; font-family: Verdana;">Para nuestro desarrollo usaremos una breakboard (de MikroElektronica, figura adjunta, unos
$10) que nos evita tener que soldar y nos da los pines correctamente espaciados
y etiquetados. Podemos ver la
alimentación (3.3V) y GND, así como las conexiones SPI (~CS, SCK, MISO, MOSI).
El único pin (que no usaremos) no identificable es ~HOLD (que permite dejar en
suspenso una comunicación. </span><span style="background-color: transparent; font-family: Verdana;">El IC
tiene un pin adicional ~WP (Write Protection) que permite implementar una
protección hardware de los datos. En esta tarjeta está atado a 3.3V por lo que
la tarjeta está "desprotegida" a nivel hardware (aunque es posible
implementar protección parcial o total de datos a través del software). </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/spi_flash.c">spi_flask.c</a></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"></span></div>
<a name='more'></a><br />
<br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;">-------------------------------------------------------------------------------------------------------------------------------</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Hardware:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Un problema con el podemos encontrarnos habitualmente es la diferencia de
niveles entre los 5V de muchos microcontroladores y los 3.3V presentes en
muchos periféricos (como por ejemplo esta memoria flash). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si estamos
usando un micro a 3.3V es simplemente una cuestión de conectar las líneas
directamente (MOSI de SDO de micro a SDI de memoria) , MISO de SDO de tarjeta a
SDI de micro, SCK con SCK) y usar la misma alimentación (3,3V) para ambos. Si
el micro va a 5V (como es nuestro caso), precisaremos:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana; font-size: 8.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">a)<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]--><span style="font-family: Verdana;">Un
regulador a 3.3V para la alimentación de la memoria<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana; font-size: 8.0pt; mso-bidi-font-family: Verdana; mso-fareast-font-family: Verdana;">b)<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]--><span style="font-family: Verdana;">Algún
dispositivo/electrónica de cambio de niveles.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el caso
SPI, al contrario que en otros sistemas (como por ejemplo I2C) hay una solución
cutre al problema del cambio de niveles, debido a que las líneas son
unidireccionales. Sabemos a priori que MOSI, CS y SCL (micro -> tarjeta) son
de entrada (desde el punto de vista del periférico) y MISO es de salida
(tarjeta -> micro). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En las
líneas de entrada podemos disponer de simples divisores de voltaje (1/3, 2/3)
que reduzcan los 5V a 2*5/3 =3.3V. La línea de salida de la tarjeta (SDO) podemos
conectarla directamente a la entrada SDI del PIC (cruzando los dedos para que
el nivel alto de la tarjeta supere el umbral de entrada del pin del PIC). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;">En la figura se adjunta esquema del montaje usado:</span><br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDixV02A54Bxim8tjty7pIf1grTToDY3e3k48_8xPBmL8tpC9dNBU3fp48N3hjtWe9onlukJuCMew0O7hEjJxyNS33NCfgn4NyIOjin2LEmOpvka0nEYF33nyqw_a-QcsXkJlWQAho/s1600/esquema.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDixV02A54Bxim8tjty7pIf1grTToDY3e3k48_8xPBmL8tpC9dNBU3fp48N3hjtWe9onlukJuCMew0O7hEjJxyNS33NCfgn4NyIOjin2LEmOpvka0nEYF33nyqw_a-QcsXkJlWQAho/s640/esquema.jpg" width="640" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;">Las resistencias R1 (2K2) y R2 (3K3) configuran un divisor de tensión para pasar de 5V a 3.3V. Las resistencias R3 (pull-ups de 10K) mantienen a nivel alto (5V o 3.3V) las líneas de datos en ausencia de actuación por parte del procesador o la memoria.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Software: configuración del puerto SPI:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Obviamente
el PIC será master en la comunicación SPI. Las especificaciones indican que la
memoria soporta hasta un máximo de 25 MHz de reloj, por lo que podemos usar sin
problemas la frecuencia máxima Fosc/4. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En cuanto
al modo SPI a usar, la siguiente gráfica del datasheet nos da la información
necesaria (C es clock, D es SDI, datos de entrada en tarjeta, y Q es SDO, datos de salida hacia el PIC):</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJs-TOnVP1NfEXD__5qm4w6vmWlbVnNy9458Co9fJZXOrtpW_HYRJXlRAww-4eRpt0kI6tzvK8vIW5QyYRhKvH2EgD89Sn7CWN0j24APA9IkPBb6su55PWX9dHg_ij7mRZFLdKPHjg/s1600/flash_modes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="281" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJs-TOnVP1NfEXD__5qm4w6vmWlbVnNy9458Co9fJZXOrtpW_HYRJXlRAww-4eRpt0kI6tzvK8vIW5QyYRhKvH2EgD89Sn7CWN0j24APA9IkPBb6su55PWX9dHg_ij7mRZFLdKPHjg/s640/flash_modes.jpg" width="640" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La memoria
admite dos polaridades de reloj (CPOL=CKP=0/1) como se observa en las dos
trazas superiores y muestrea los datos que le llegan (D) en las transiciones de
subida. Por lo tanto el micro debe usar el criterio LowToHigh (L2H=1, colocar
datos en transición de subida del reloj). Recordando que CKE = CPOL xor L2H las
posibilidades son:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: PT-BR;">CPOL=CKP=1
L2H=1 CKE = 1 xor 1 = 0 -> CPHA = 1<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: PT-BR;">CPOL=CKP=0
L2H=1 CKE = 0 xor 1 = 1 -> CPHA = 0<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Luego los
dos modos SPI admitidos son (0,0) y (1,1) expresados en formato (CPOL,CPHA), como por otra
parte se nos indica amablemente en la parte superior izquierda de la gráfica.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El otro
parámetro a determinar es SMP, relacionado con el muestreo de los bits entrantes por el PIC. Para ello nos fijamos en los datos que manda la
memoria (Q). Si elegimos modo SPI(0,0) (traza superior)
vemos que el momento adecuado para muestrear a Q en el centro del periodo de
reloj, por lo que haremos SMP=0. Si por el contrario escogemos usar modo
SPI(1,1) (2ª traza) el momento adecuado es al final del periodo (SMP=1).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Usando las
rutinas anteriores, una posible inicialización del puerto SPI sería:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FLASH_spi_init(byte clock)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> M25P80_CS_dir=0; deselect_M25P80; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Configure CS line as output and set it low.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_master(clock); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Configure SPI as master and set clock </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_mode(0,0,0); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
SPI mode (0,0). Sample at mid period</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">spi_enable(); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Enable SPI</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Previamente
debemos definir (#defines) dos variables <b><span style="color: blue;">M25P80_CS </span></b>y <b><span style="color: blue;">M25P80_CS_dir </span></b> para informar al
resto de las rutinas de que pin estamos usando como ChipSelect (CS) y su
correspondiente bit de dirección TRIS. </span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// CS line</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> M25P80_CS LATCbits.LATC2</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> M25P80_CS_dir TRISCbits.TRISC2</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80
M25P80_CS=0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> deselect_M25P80 M25P80_CS=1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Descripción de la memoria:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La
capacidad de esta memoria flash es de 1Mbyte, organizada en páginas de 256
bytes. Cada 256 páginas forman un sector (65536 bytes). Hay un total de 16
sectores, sumando 16x65536 = 2^20 = 1 Mbyte. Precisaremos por lo tanto 20 bits para la dirección de cualquier byte
de la memoria.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Además de
la zona de datos hay un registro de status de 8 bits que podemos consultar y
modificar. Los principales bits de este registro son:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 9.0pt; mso-list: l0 level1 lfo1; tab-stops: list 9.0pt; text-indent: -9.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->BP
0:2 estos tres bits permiten proteger
toda (111), nada (000) o partes (XXX) de la memoria imposibilitando su cambio o
borrado.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 9.0pt; mso-list: l0 level1 lfo1; tab-stops: list 9.0pt; text-indent: -9.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->WEL
(Write Enable Latch): es imprescindible poner a 1 este bit previo a toda operación
que suponga reprogramar o borrar datos. Actúa como un seguro. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 9.0pt; mso-list: l0 level1 lfo1; tab-stops: list 9.0pt; text-indent: -9.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->WIP
(Write in Progress) se pone a 1 mientras la memoria está ocupada en un ciclo de
programación y borrado. Sirve para que el micro sepa cuando la memoria está
lista para aceptar nuevos comando.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Software: Envío de órdenes a la
memoria:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La
estructura de un intercambio SPI micro/memoria responde a la siguiente
secuencia:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo2; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">1) <!--[endif]-->El micro envía una instrucción (1 byte)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo2; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">2) <!--[endif]-->Opcionalmente si la instrucción lo
requiere se manda una dirección (3 bytes = 24 bits)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo2; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">3) <!--[endif]-->Se envían o reciben datos según el
tipo de instrucción.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Todo
intercambio es precedido por una selección del dispositivo (CS=0) y terminado
con CS=1.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Solo el
paso 1 es obligatorio. Los pasos 2/3 son opcionales y dependen del tipo de
instrucción. Algunas instrucciones precisan todos los pasos (1-2-3) como por
ejemplo la lectura de una página de datos.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Otras son
de tipo 1-3, como por ejemplo la lectura del registro de status. Finalmente
otras son del tipo 1, instrucciones que no precisan argumentos y no devuelven
ningún dato, como poner a 1 el bit WEL.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La imagen
adjunta muestra la tabla de instrucciones, indicando las que precisan una
dirección como argumento y cuales esperan recibir o devuelven bytes:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 8pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcYmXOCjH0F29WmOAwIElkz1WmuDf_kcobSAUgfm6DCX6U8Dqnc0AS12hSMyCWJKJZYnuaSss7iyYenQRcJWmf4Q11mEuK6nSUYUTh_z0kLccwtgsghVMS98HmiVzKYKUsk0h6Fgmy/s1600/instrucciones.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="353" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcYmXOCjH0F29WmOAwIElkz1WmuDf_kcobSAUgfm6DCX6U8Dqnc0AS12hSMyCWJKJZYnuaSss7iyYenQRcJWmf4Q11mEuK6nSUYUTh_z0kLccwtgsghVMS98HmiVzKYKUsk0h6Fgmy/s640/instrucciones.jpg" width="640" /></a></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Usando la
información que conocemos sobre el modo SPI, el protocolo de intercambio de
comandos y la tabla de instrucciones dada, podemos escribir un serie de
funciones que implementen las principales funcionalidades de la memoria flash.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Iremos
comentando algunas de las peculiaridades del código según lo vayamos viendo. En
primer lugar definiremos los comandos de la tabla anterior:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_WREN
0x06 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//Write enable</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_WRDI
0x04 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//Write disable</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_RDSR
0x05 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Read status</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_WRSR
0x01 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Write status</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_READ
0x03 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Read Data</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_FAST_READ
0x0B </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Fast Read data (>20 Mhz)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">#define</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_PP
0x02 </span><span lang="PT-BR" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">// Page program</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">#define</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> ERASE_SECTOR
0xD8 </span><span lang="PT-BR" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">// Erase sector (1)</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_ERASE_ALL
0xC7 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Erase all (1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_DPD
0xB9 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Enter Deep Power Down</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CMD_REL
0xAB </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Release from DPW or read Elec signature</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><br /></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Ahora
escribiremos algunas rutinas que leen o escriben el registro de estado, o
algunos de sus bits, como WEL o los bits de protección:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Functions that
Read/Modify Status register or its bits</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_enable(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {select_M25P80;
spi_tx(CMD_WREN); deselect_M25P80;} </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Sets WEL=1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_disable(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {select_M25P80; spi_tx(CMD_WRDI); deselect_M25P80;} </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Clears WEL</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">byte read_status(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> byte res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80; spi_tx(CMD_RDSR); res=spi_rx();
deselect_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_status(byte stat)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_enable();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80; spi_tx(CMD_WRSR); spi_tx(stat);
deselect_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">byte set_protection(byte bp)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> byte stat;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat=read_status(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Gets current status</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat = stat & 0b11100011; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Erase BP bits</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat = stat | (bp<<2); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Set BP bits</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_status(stat);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">byte get_protection(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> byte stat;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat=read_status();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat = (stat>>2) & 0x07; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Extracts BP bits</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;">(stat);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">////////////////////////////////////////////////////////////////////////</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Notad que
siempre que vamos a hacer una escritura es preciso hacer WEL=1 usando la función
write_enable(). No es necesario hacer WEL=0 ya que de eso se encarga el
hardware tras ejecutar el correspondiente comando de escritura.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Un comentario sobre la función read_status(). En la tabla vemos que para
la orden RDST se indica que el número de bytes de datos (en este caso
recibidos) va de 1 a infinito. Lo que quiere decir esto es que esta orden puede
usarse para leer ininterrumpidamente los contenidos del registro. En nuestro
función, al levantar la línea CS tras recibir el primer byte interrumpimos
dicha comunicación, pero si mantenemos CS=0, los contenidos del registro
seguirán llegando (siempre que nosotros como master los "pidamos"
mandando 8 pulsos de reloj). Esta funcionalidad puede usarse para por ejemplo
comprobar si una operación de escritura/borrado ha terminado y la memoria
vuelve a estar "libre".<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La misma
estrategia se usa en otras órdenes (aquella que indican #bytes de 1 a …). Por ejemplo, en una orden de escritura o de
lectura no hay que indicar previamente el número de bytes a grabar o leer.
Simplemente se interrumpe la comunicación (~CS=1) cuando el número adecuado de
bytes han sido enviados/recibidos.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Veamos
unas funciones para la lectura/programación de una página de datos completa.
Ambas funciones reciben un número de página (0 a 4095) y un puntero a un buffer
de memoria y mueven 256 bytes de un lugar a otro.</span></div>
<div class="MsoNormal">
<span style="font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 8pt;"> <o:p></o:p></span><span style="font-size: 8pt;"> </span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Reads a page #
npage (256 bytes) and places its contents in buf[]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> read_page(uint16 npage,</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(CMD_READ);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(npage>>8); spi_tx(npage&0xFF);
spi_tx(0); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Start address of page</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<256;k++) buf[k]=spi_rx();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> deselect_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Program (1 -> 0)
the contents of buf[] to page # npage</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_page(uint16 npage,</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_enable();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(CMD_PP);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(npage>>8);
spi_tx(npage&0xFF); spi_tx(0); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Start address of page</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<256;k++) spi_tx(buf[k]);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">deselect_M25P80;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">De nuevo,
en la función write_page() hemos de usar write_enable() para poner WEL=1, antes
del comando de escritura (CMD_PP). De lo contrario dicho comando no se
ejecutaría.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En las
funciones anteriores usamos por primera vez comandos (CMD_READ y CMD_PP) que
han de ser seguidos de una dirección (inicio página a leer/escribir). La
dirección serán 3 bytes, aunque dada la capacidad de la memoria sólo los 20
bits menos significativos tienen validez (2^20 = 1024x1024 = 1 Mbyte). Dado que
una página tiene 256 bytes y hay 256 páginas en un sector, los tres bytes
enviados corresponden al sector (1er byte), página (2do byte) y offset dentro
de página (3er byte). En los casos anteriores la dirección enviada era la de un principio de la página, por lo que el
tercer byte de offset es siempre 0.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">No estamos
restringidos a lecturas/escrituras por bloques de 256 bytes. Ya hemos dicho que
el número de bytes a mandar/recibir no es parte de la instrucción. En el caso
anterior nos deteníamos tras transferir 256 bytes simplemente poniendo CS=1. Podemos
por lo tanto hacer una lectura/escritura de un número arbitrario de bytes sin
más que mantener CS=0 mientras queramos seguir manteniendo la transferencia. La
dirección de comienzo tampoco tiene por que ser el inicio de una página (puede
ser un offset distinto de 0). Con cada lectura/escritura la dirección se
incrementa automáticamente. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Sin embargo,
hay una diferencia fundamental entre lecturas y escrituras en este modo. En
modo lectura, si la dirección llega a una frontera de página la atraviesa, por
lo que en principio podríamos hacer una lectura de toda la memoria con una sola
instrucción CMD_READ. Sin embargo en escritura, si el puntero llega al final de
la página no pasa a la página siguiente sino que retrocede al principio de la
página en la que estamos. Por lo tanto no tiene sentido tratar de programar más
de 256 bytes. Se puede hacer, pero a partir de 256 empezaríamos a machacar los
primeros datos enviados. En ese caso, sólo los últimos 256 valores enviados serían
programados.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las
siguientes rutinas implementan una lectura/programación de n bytes a partir de
una dirección cualquiera:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Reads n bytes
starting @ address add and places them in buffer buf[]</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> read_bytes(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> add, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> n, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> sector,page,offset;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Gets
sector, page and offset within the page from the original address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> offset = add&0xFF; add>>=8;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> page = add&0xFF; add>>=8;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">sector=add&0xFF;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(CMD_READ);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(sector); spi_tx(page);
spi_tx(offset); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// 20 bit address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<n;k++) buf[k]=spi_rx();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> deselect_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Programs n bytes
(up to 256) in buf[] to address add.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_bytes(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">long</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> add, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">int</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> n, </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">* buf)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">int</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> sector,page,offset;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Gets
sector, page and offset within the page from the original address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> offset = add&0xFF; add>>=8;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> page = add&0xFF; add>>=8;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> sector=add&0xFF;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> write_enable();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(CMD_PP);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(sector); spi_tx(page);
spi_tx(offset); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// 20 bit address</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<n;k++) spi_tx(buf[k]);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">deselect_M25P80;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Consideremos
ahora el borrado (erase) de datos. En las memorias flash un borrado supone
poner los bits a 1 y típicamente el bloque de borrado es bastante mayor que el
bloque de lectura. Así mientras podemos programar bytes individuales o por
páginas de 256 bytes, sólo podemos borrar por sectores (256 páginas = 65536
bytes). <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Existe una
orden para borrar un sector en particular y otra para borrar todo el
dispositivo. Ambas ordenes precisan poner el bit WEL a 1 con write_enable().
Sin embargo, <b>por seguridad, en este caso no se ha incluido dicho comando dentro
de las funciones. Es responsabilidad del usuario llamar a write_enable() antes
de intentar una operación de borrado.</b></span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Erases (sets to 1)
all bits in sector # s</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> sector_erase(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> s)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(ERASE_SECTOR);</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(s); spi_tx(0); spi_tx(0); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 11px;">// Start address of sector to be erased </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">deselect_M25P80;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Erase all sectors
(final state of the memmory 0xFF)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> erase_all(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {select_M25P80;
spi_tx(CMD_ERASE_ALL); deselect_M25P80;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Ya sólo
quedan un par de instrucciones de la tabla que no hemos usado. El comando
CMD_DPD pone al </span><span style="font-family: Verdana, sans-serif;">dispositivo en un modo de bajo consumo y el comando CMD_REL lo
despierta</span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Send flash memory
to DeepPowerDown (CMD_DPD)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> power_down(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {select_M25P80; spi_tx(CMD_DPD); deselect_M25P80;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Releases (CMD_REL)
memory from DeepPowerDown state.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> power_up(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {select_M25P80;
spi_tx(CMD_REL); deselect_M25P80; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//delay_us(3);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si se usa
el comando (CMD_REL) cuando el
dispositivo está ya despierto, sirve también para obtener la firma electrónica
del dispositivo (0x13), y es una forma de comprobar si la comunicación es
correcta:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Gets electronic
signature by sendind REL when not in DeepPowerDown mode</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">byte get_signature(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> byte k;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> spi_tx(CMD_REL); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<3;k++) spi_tx(0xAA); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Three dummy bytes</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> k=spi_rx();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> deselect_M25P80;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> k;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Con esto
tenemos todas las funciones necesarias para poder usar la memoria. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Velocidad de escritura/lectura <o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Vamos a escribir un sencillo programa que lea o
escriba sucesivas páginas de la memoria (256 bytes). Lo primero que tenemos que
hacer es reservar una zona de 2456 bytes que sirva como buffer de los datos.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 9pt;">byte
page_data[256];</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="FR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR;">void</span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> main()</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">{ </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint16 page;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// TEst speed //////////////////////////////////</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> TRISB=0;
PORTB=0; TRISD=0; PORTD=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
FLASH_spi_init(0);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> page=0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
PORTDbits.RD1=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
read_page(page,page_data); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//write_page(page,page_data);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">PORTDbits.RD1=0;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">
Delay1KTCYx(20);</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> PORTB=page; page++;
page&=4095;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 9pt;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El programa simplemente inicializa el módulo SPI y
entra en un bucle donde se leen (o escriben) sucesivamente las 4096 páginas del
dispositivo. En PORTB nos da un feedback del incremento de páginas, mientras
que en PORTD.RD1 podemos ver el tiempo dedicado a la tarea de lectura de una
página. Tras cada página hacemos un delay de
20,000 instrucciones, que a 8Mz de reloj (2 MHz instrucción) corresponden a 10 msec. En las siguientes
imágenes podemos ver los tiempos dedicados a lectura (izquierda) y escritura
(derecha) de una página:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqzec_nza0Gb9eEbY4Ov48tp-dWQa3Ha8xF1Mg1izn4EaPjOPw9NGEuRfUWuAzqT7vsowJm_3YlfpnnpEmPsBP8M_Gl_Rs_fpT_C8IAUQpv0cNbtFRvjx3ZPpIxUPRMkwVezuJ2U2g/s1600/timing_both.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqzec_nza0Gb9eEbY4Ov48tp-dWQa3Ha8xF1Mg1izn4EaPjOPw9NGEuRfUWuAzqT7vsowJm_3YlfpnnpEmPsBP8M_Gl_Rs_fpT_C8IAUQpv0cNbtFRvjx3ZPpIxUPRMkwVezuJ2U2g/s640/timing_both.jpg" width="640" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se ve ambos tiempos son muy similares, unos 8.4 msec por página. Notad que dichos tiempos pueden reducirse sin más que usar un reloj más rápido. Ahora estamos usando un reloj de 2 MHz para el módulo SPI, muy alejado de los 25 MHz a los que puede llegar nuestro dispositivo. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como siempre, si no disponemos de un osciloscopio
podemos medir el voltaje en RD1 y recordando que V_RD1/Vcc deber ser
aproximadamente T / (T+10), podemos estimar el tiempo empleado (en msec). En mi
caso he medido 4.86V en Vcc y 2.19 en RD1 por lo que:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> T/(T+10) = 2.19/4.86 = 0.45, </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">de lo que se deduce que T = 8.2
msec, muy próximo a lo observado con el osciloscopio.</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Interfaz serie para probar las
rutinas de la librería<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Finalmente,
para verificar las rutinas anteriores y explorar algunas de las peculiaridades
de una memoria flash he escrito un programa que implementa una (muy sencilla)
interfaz serie. Tras arrancar, el
programa manda un mensaje al puerto serie (19200 bauds) para indicar que está
listo y presenta un prompt (>) al usuario. El usuario puede introducir una
serie de instrucciones (algunas con un argumento) de la siguiente lista. Dichas
funciones esencialmente llaman a las funciones que hemos visto. Como antes, el programa reserva un área de
datos de 256 bytes para el intercambio de datos:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"> COMANDO FUNCION USADA DESCRIPCION<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">init
arg FLASH_spi_init(arg) Inicializa modulo SPI<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">> </span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">wren write_enable(); WEL=1<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">wrdi write_disable(); WEL=0<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">rsta read_status(); Devuelve registro de status.<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">wsta
arg write_status(arg); Escribe registro de status<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">prot get_protection(); Obtiene 3 bits de protección </span></b><st1:state><st1:place><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">del</span></b></st1:place></st1:state><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"> registro status<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span lang="EN-GB" style="font-family: Wingdings; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">sprot
arg set_protection(arg); Escribe los 3 bits de protección en
registro status<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">rpag arg read_page(arg,data) Lee contenidos de una pagina y muestra los 16 </span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<b><span style="font-family: Verdana; font-size: 8.0pt;"> primeros bytes leidos por el puerto serie <o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">wpag arg write_page(arg,data) Muestra los 16 primeros bytes de la zona
de datos en</span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<b><span style="font-family: Verdana; font-size: 8.0pt;"> </span></b><b style="text-indent: -18pt;"><span style="font-family: Verdana; font-size: 8.0pt;">pantalla y escribe los 256 bytes en la
pagina dada.</span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">erase erase_all() Borra TODA la memoria (poner WEL=1 antes)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">esec arg sector_erase(arg) Borra sector dado (hay que poner
WEL=1 antes)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">sleep power_down(); Modo de bajo consumo<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">wake power_up(); Salimos del modo de bajo
consumo.<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">sign get_signature() Obtiene y muestra la firma del dispositivo<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">data --- Muestra los 16 primeros
bytes del area de datos<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span style="font-family: Verdana; font-size: 8.0pt;">sdata arg
--- Pone
los bytes en el area de datos = arg y
muestra </span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<b><span style="font-family: Verdana; font-size: 8.0pt;"> los 16</span></b><b><span style="font-family: Verdana; font-size: 8.0pt;"> primeros bytes. No
escribe en el dispositivo. </span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Wingdings; font-size: 8.0pt; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings;"><span style="font-family: 'Times New Roman';">></span><span style="font-family: 'Times New Roman'; font-size: 7pt;"> </span></span><!--[endif]--><b><span lang="PT-BR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: PT-BR;">rdat arg --- </span></b><b><span style="font-family: Verdana; font-size: 8.0pt;"> Llena de números
aleatorios la zona de datos y vuelca<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<b><span style="font-family: Verdana; font-size: 8.0pt;"> los 16 primeros
datos. No escribe en dispositivo.</span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Los tres
últimos comandos manejan simplemente el área de datos y no interaccionan con la
memoria, por lo que no usan ninguna de las funciones desarrolladas.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En nuestra
primera interacción, para comprobar que las conexiones son correctas y hemos
entendido el protocolo vamos a dar una serie de ordenes muy sencillas:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">a)
Inicializar el módulo SPI (siempre necesario).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">b) Leer
firma del dispositivo (13h)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">c) Leer
registro de status (instrucción RDSR): el manual indica que por defecto debe
ser 0x00<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">d) Poner a
1 el bit WEL (instrucción WREN) y ver si ha cambiado el registro (debería ser
0x02).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">e) Volver
a poner a 0 el bit WEL (instrucción WRDI). Comprobar el cambio con RDSR.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El resultado
de dichos comandos es el siguiente</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>M25P80 session<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>init 0 -> COD=0,ARG=0<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>sign ->
COD=14,ARG=0 Signatute =19<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rsta ->
COD=3,ARG=0 Status =0<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wren ->
COD=1,ARG=0<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rsta ->
COD=3,ARG=0 Status =2<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wrdis ->
COD=2,ARG=0<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rsta ->
COD=3,ARG=0 Status =0</b><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Pudiendose
comprobar que los resultados son los esperados. El dispositivo devuelve 19
(0x13) como firma y al poner WEL=1 (2º LSbit del registro), el registro pasa a
valer 2. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Veamos
algunos ejemplos de lectura/escritura/borrado. Empezaremos borrando el primer
sector (esec 0) y leyendo la primera página (rpag 0). El resultado deberían ser
todos 0xFF. A continuación ponemos el área de memoria a 15 (sdata 15) y hacemos
una orden de escritura a la página 0 (wpag 0). Una lectura de la misma página (rpag
0) debe darnos un montón de 0x0F's:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: "Courier New"; font-size: 8.0pt;"><b>wren
-> COD=1,ARG=0<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>esec 0 -> COD=8,ARG=0<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 0 -> COD=5,ARG=0 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>sdata 15 -> COD=10,ARG=15 Data in buffer:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wpag 0 -> COD=6,ARG=0 To be written to page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 0 -> COD=5,ARG=0 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 1 -> COD=5,ARG=1 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF</b><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Vemos que
una lectura de la página 1 (rpag 1) mantiene los datos originales (0xFF). </span><span style="font-family: Verdana, sans-serif;">Hasta
ahora todo correcto. Repitamos ahora la operación de escritura (wpag 0) pero
usando ahora un conjunto de bytes aleatorios:</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rdat 37 -> COD=11,ARG=37 Data in buffer:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;"><b>AA 33 90 D1 46 7F 4C BD 22 0B 48 E9 3E D7 84 55<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wpag 0 -> COD=6,ARG=0 To be written to page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;"><b>AA 33 90 D1 46 7F 4C BD 22 0B 48 E9 3E D7 84 55<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 0 -> COD=5,ARG=0 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;"><b>0A 03 00 01 06 0F 0C 0D 02 0B 08 09 0E 07 04 05</b><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Vemos que
algo ha ido mal. Los datos del buffer (AA, 33, 90, etc. ) no se han escrito
correctamente. Cuando leemos los datos de la página 0 vemos que sólo los 4 bits
menos significativos (A, 3, 0, etc. ) se han grabado. En los cuatro bits más
significativos se mantiene el valor 0 que teníamos. ¿Qué esta pasando?<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Lo que
ocurre es que durante este tutorial todavía no hemos mencionado algunas de las
propiedades peculiares de las memorias flash. La escritura de bytes
individuales en una memoria flash sólo puede cambiar los bits del estado 1 al
0. De hecho, se prefiere hablar de programar (pasar de 1 a 0) datos en vez de
escribir datos (que se entendería como cambiar arbitrariamente un bit). Por lo
tanto en una memoria flash una operación de borrado pone los bits a 1, mientras
que una de programación pone los 1 a 0 (pero no puede pasar de 0 a 1). Podría
parecer que la combinación de ambas permitiría escribir cualquier dato, pero el
problema es que la operación de borrado (erase) solo es aplicable a bloques de
datos, no a bytes individuales.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si intentamos ahora escribir una serie de datos aleatorios a la página 1 (que
conservaba sus valores 0xFF iniciales) veremos que funciona correctamente.</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rdat 13 -> COD=11,ARG=13 Data in buffer:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>B2 DB 58 39 CE A7 94 A5 2A B3 10 51 C6 FF CC 3D<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wpag 1 -> COD=6,ARG=1 To be written to page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>B2 DB 58 39 CE A7 94 A5 2A B3 10 51 C6 FF CC 3D<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 1 -> COD=5,ARG=1 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>B2 DB 58 39 CE A7 94 A5 2A B3 10 51 C6 FF CC 3D</b><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Hay
situaciones donde este tipo de memoria no plantearía problemas. Pensemos en un
datalogger que cada cierto tiempo guarda unos datos. Empezaríamos borrando todo
el dispositivo y el programa podría empezar a escribir sus datos desde el
inicio. Como los contenidos son inicialmente 0xFF, la operación de programar
puede escribir cualquier dato. Al llegar al final de la memoria haríamos un
comando de borrar el sector 0 y volveríamos a escribir sobre él. De esta forma
la memoria siempre conservaría el último Mbyte de datos.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Sin
embargo, en una situación normal (pensar en un sistema de archivos) necesitaremos
modificar ciertos bytes en una página/sector dados. Esto no se puede hacer
directamente, ya que si intentamos programar los nuevos datos, lo que quedaría
en la memoria sería el AND entre los nuevos datos y los antiguos. En la
práctica esto supone que en los dispositivos con memorias flash (memorias USB,
tarjetas de memoria SD, CF, etc.) el acceso a los datos es siempre por bloques,
no por bytes individuales. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Consideremos
la memoria M25P80 que nos ocupa y en los pasos necesarios para modificar unos
bytes dentro de una cierta página. Lo primero sería leer la página completa en
un buffer intermedio, modificar los bytes necesarios y volver a escribir dicha
página. Pero dicha página no puede escribirse en su mismo lugar. Deberíamos
borrar (poner a 0xFF) el contenido de la página antes de volver a programarla.
Pero en nuestro caso no podemos borrar sólo una página. Tendríamos que borrar todo el sector, lo que es
inadmisible, ya que un sector contiene otras 255 páginas que no deseamos perder.
La única solución es escribir la página modificada en otro sector que
previamente se ha <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">borrado y
vamos usando para estos menesteres. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se ve, la simple modificación de 1 byte
provoca que toda la página se mueva físicamente. Por supuesto alguien tiene que
llevar la pista a todos estos cambios. Es por esto por lo que las memorias
flash requieren unos controladores especiales que hagan trasparentes todas
estas complicaciones de cara al usuario final, que maneja sectores lógicos. Es
el controlador el que sabe la relación sectores lógicos – sectores físicos.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La cosa se
complica porque las memorias flash tienen un número de ciclos
borrado/programación. Aunque en las memorias actuales dicho número es muy alto
(del orden de 100,000 o 1,000,000) el software residente en el controlador debe
implementar estrategias de wear-leveling, asegurándose de que todos los
sectores acumulan el mismo número de ciclos de borrado. De esta forma se
maximizaría la vida útil de la memoria.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se ve
no es trivial el manejo de este tipo de memorias en aplicaciones generales. En
ese caso es mucho mejor usar, por ejemplo, tarjetas de memoria (SD, CF). Con este
tipo de dispositivos el PIC no tiene que lidiar con los sectores físicos de la
memoria flash, limitándose a escribir/leer de sectores lógicos y dejando al
controlador de la tarjeta SD que se ocupe de las peculiaridades de la memoria. <o:p></o:p></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Bits de protección<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Finalmente
un comentario sobre los bits de protección del registro de status. Dichos bits
permiten proteger (al ponerse a 1) diversas sectores de la memoria, impidiendo
su programación o borrado. Si por ejemplo partimos de la página 0 recién
borrada (valores 0xFF) y ponemos los bits de protección a 7 (sprot 7) toda la
memoria se encuentra protegida, por lo que la consiguiente orden de escritura
no tiene efecto<o:p></o:p></span></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 0 -> COD=5,ARG=0 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>sprot 7 -> COD=15,ARG=7<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>prot -> COD=16,ARG=0 Protection bits =7<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>sdata 19 -> COD=10,ARG=19 Data in buffer:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wpag 0 -> COD=6,ARG=0 To be written to page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>13 13 13 13 13 13 13 13 13 13 13 13 13 13 13 13<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 0 -> COD=5,ARG=0 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF</b><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt; mso-bidi-font-family: "Courier New";"><span style="font-family: Verdana, sans-serif;">Por el contrario un valor de 100 (4) en los bits de protección
solo protege los 8 sectores finales (páginas de la 2048 a 4095) por lo que
ahora si podemos escribir en la página 0:</span><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>sprot 4 -> COD=15,ARG=4<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>prot -> COD=16,ARG=0 Protection bits =4<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rdata 57 -> COD=11,ARG=57 Data in buffer:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>CE A7 94 A5 2A B3 10 51 C6 FF CC 3D A2 8B C8 69<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wpag 0 -> COD=6,ARG=0 To be written to page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>CE A7 94 A5 2A B3 10 51 C6 FF CC 3D A2 8B C8 69<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 0 -> COD=5,ARG=0 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>CE A7 94 A5 2A B3 10 51 C6 FF CC 3D A2 8B C8 69</b><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt; mso-bidi-font-family: "Courier New";"><span style="font-family: Verdana, sans-serif;">Pero si intentamos escribir en la página 3000 (sector 11) la
protección nos lo impide:</span><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>wpag 3000 -> COD=6,ARG=3000 To be written to page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>CE A7 94 A5 2A B3 10 51 C6 FF CC 3D A2 8B C8 69<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>rpag 3000 -> COD=5,ARG=3000 Data read from page:<o:p></o:p></b></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"><b>FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF</b><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />
<br />
<br />
<br />
<span style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><!--[if gte vml 1]><v:shapetype id="_x0000_t75"
coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe"
filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:378pt;
height:166.5pt'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.jpg"
o:title="flash_modes"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></span><br />Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com4tag:blogger.com,1999:blog-4945680608471335280.post-12058028848096913192013-04-05T12:25:00.001+02:002013-06-07T16:28:46.928+02:00Comunicaciones Serie SPI<span style="font-family: Verdana;">La familia
PIC18 dispone de varias posibilidades de comunicaciones serie. Además del
puerto USART que ya describimos, dispone de un puerto dedicado a comunicaciones síncronas serie,
el SSP (Serial Synchronous Port). Dicho puerto puede dedicarse a varios
protocolos, tales como SPI o I2C. Ambos son excluyentes, esto es, si se
configura el periférico para SPI no podrá usarse para I2C y viceversa. Si se
precisan de forma conjunta comunicaciones I2C y SPI la única solución es un
microcontrolador con dos puertos SSP o bien, implementar algunos de los dos
protocolos a través de software.</span><br />
<br />
<div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En este
tutorial vamos a examinar en el protocolo SPI (Serial Protocol Interface),
describiendo los registros SFR involucrados y detallando los procedimientos
para transmitir y recibir. Lo ilustraremos con un ejemplo muy sencillo de comunicación con un periférico SPI, un conversor DAC (MCP4822 de Microchip).</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En entradas posteriores veremos ejemplos de comunicaciones SPI con otros periféricos con protocolos de comunicación más complicados.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Archivos de código asociados a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/spi_mcp4822.c">spi_mcp4822.c</a></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"></span></div>
<a name='more'></a><span style="font-family: Verdana, sans-serif;">---------------------------------------------------------------------------------------------</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Es importante entender los conceptos básicos detrás de una comunicación SPI, que son diferentes de otros tipos de comunicaciones. </span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Empezaremos
recordando las propiedades de un registro de desplazamiento o shift register (ver figura):</span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin-P1k7vVTkgCJF7XqoBLaYdT4FVAkIDPU5JrSB0AF67hBn5HW8m9Z514Ml1P1BlFLQKv5cmCnHwoxx7s0FgQNl-JR86QpZJtbDc6YF7SmufBR9K6tKT-O1dJsVKH-akCt_HF_p0rJ/s1600/shift1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin-P1k7vVTkgCJF7XqoBLaYdT4FVAkIDPU5JrSB0AF67hBn5HW8m9Z514Ml1P1BlFLQKv5cmCnHwoxx7s0FgQNl-JR86QpZJtbDc6YF7SmufBR9K6tKT-O1dJsVKH-akCt_HF_p0rJ/s1600/shift1.jpg" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En un
registro de desplazamiento, con cada clock del reloj, un nuevo bit entra en el
registro y desplaza a todos los bits una posición. El último bit sale del
registro. Los registros de desplazamiento son la base de las conversiones paralelo/serie
y viceversa. Por ejemplo, en la UART existe un TSR (Tx Shift Register) donde se
carga el byte a enviar (de forma paralela) y van saliendo sucesivamente (serie)
los bits a enviar. Dicho TSR se carga como vimos con el dato colocado en TXREG.
De forma totalmente análoga en el circuito de recepción de la UART tenemos otro
registro RSR (Rx Shift register) donde van entrando sucesivamente (serie) los
bits recibidos. Al llenarse, el dato se transfiere (en paralelo) al registro
buffer de recepción (RCREG). Otro uso similar
(se suele denominar SIPO, Serial In, Parallel Out) de un SR se da en un “port expander”,
donde un registro (puerto extendido) se va llenando sucesivamente con datos recibidos
de forma serie. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Vemos que
en la UART tenemos sendos registros de desplazamiento para la recepción como
para la transmisión. Dichos registros son independientes entre sí. En el caso
de SPI solo tendremos un registro SSP SR (accesible a través de un buffer
SSPBUF).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">¿Cómo
podemos recibir y transmitir con un solo registro? Consideremos ahora un registro de
desplazamiento circular, donde la salida del registro se usa como entrada del
mismo:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGzN-uArfO-wj82pR2nnFYjGRYogCM-VqUXF7zoOeLMgENkWJ1h9F9Xal8YnwM0G6oAOa77xoxH_K9XjczHNOSiE3AHve20F9moHaMWwODlnEurPytt3kBGG_-GmszJPVBfub0vXbl/s1600/shift2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGzN-uArfO-wj82pR2nnFYjGRYogCM-VqUXF7zoOeLMgENkWJ1h9F9Xal8YnwM0G6oAOa77xoxH_K9XjczHNOSiE3AHve20F9moHaMWwODlnEurPytt3kBGG_-GmszJPVBfub0vXbl/s1600/shift2.jpg" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Supongamos
que nuestro registro tiene 16 bits y al ser circular, el bit que entra
“empujando” a los demás es justo el que acaba de salir por el otro lado. Ahora
pensar que este registro se parte en dos, cada uno de 8 bits, pero formando conceptualmente
un único registro de 16 bits:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLUm023yuFJqPRAnKQNdVEoatS_g_l_zGO8GMD9xwhGBeRLNZ3BulOrFmlilaUdRiAEusBo4HNQ2VAzdRdeuQYyQxVR45V2gi2s1M_iKmquJhLrEim5or22y9c2Z2mJRf7SubPPXbj/s1600/shift3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLUm023yuFJqPRAnKQNdVEoatS_g_l_zGO8GMD9xwhGBeRLNZ3BulOrFmlilaUdRiAEusBo4HNQ2VAzdRdeuQYyQxVR45V2gi2s1M_iKmquJhLrEim5or22y9c2Z2mJRf7SubPPXbj/s1600/shift3.jpg" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Lo que
tenemos es justo la base de una comunicación SPI entre dos dispositivos. Cada
una de las partes del registro circular es el registro SSPSR de cada
dispositivo y ambos comparten el reloj. La idea es que si en el SSPSR1 hay un
dato A y en el SSPSR2 un dato B, tras 8 ticks de reloj, los datos A y B se
habrán intercambiado entre los dispositivos. Esta es la razón por la que al
contrario que la UART sólo se dispone de un registro, sin diferenciar entre
entrada y salida. En el protocolo SPI no hay realmente transmisiones ni
recepciones, solo intercambios de datos A y B, ya que por cada dato enviado
debe haber siempre uno recibido. Depende de las circunstancias el cómo se
interprete una transferencia SPI:</span><span style="font-family: Verdana, sans-serif;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<br />
<ol>
<li><span style="font-family: Verdana, sans-serif;">Será una transmisión si el 1er dispositivo
tenía por objetivo era mandar el dato A al 2do dispositivo, mientras que el
dato B recibido era basura (pero no puedo "evitar" recibir dicho
dato).</span></li>
<li><span style="font-family: Verdana, sans-serif;">Será una
recepción si el dato A enviado es irrelevante y solo lo mando para obtener a
cambio el dato B (pero no hay forma de recibir nada si yo no mando algo "a
cambio").</span></li>
<li><span style="font-family: Verdana, sans-serif;">Puede ser u</span><span style="font-family: Verdana, sans-serif;">na
transmisión/recepción simultánea si tanto el dato A como el B son
significativos para la comunicación. Pensar por ejemplo en un
DigitalSignalProcesor (DSP) que recibe una serie de muestras de una señal y
efectúa algún tipo de procesado sobre ella. Tras un cierto retraso, inherente
al procesado, empezará a mandar muestras de vuelta. A partir de ese momento,
por cada muestra de la señal original que mande el host recibirá una muestra
procesada en una comunicación full-duplex.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Finalmente,
hay situaciones donde los datos intercambiados no le interesan a ningún
dispositivo. Por ejemplo, en las especificaciones del protocolo SPI de las
tarjetas SD se requiere mandar 8 clocks de reloj tras un intercambio
comando/respuesta para que la tarjeta pase a ejecutar el comando recibido. En
ese caso el microcontrolador y la tarjeta se intercambiarán un byte que a
ninguno de los dos interesa solo para que le lleguen los 8 pulsos de reloj necesarios
a la tarjeta.</span></li>
</ol>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La única
asimetría entre ambos dispositivos es que uno de ellos debe generar los pulsos
de reloj que hacen “avanzar” el registro de desplazamiento. Dicho dispositivo (a
la izquierda en la gráfica anterior) es el master y será quien controle la
transmisión.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En la
figura siguiente (extraída del datasheet
de Microchip para el PIC18F252) se ilustra lo que acabamos de contar. Como se
ve es totalmente análoga a la figura anterior, añadiendo el hecho de que el
usuario (al igual que sucedía en el caso de la UART) no puede acceder al verdadero registro de
desplazamiento SSPSR, trabajando en su lugar con un buffer SSPBUF.</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlkEZPQDMbs1RzoWdXqzNhZKjvrcoEXJHN6Wa4wMPfn36rnu3Z77oy7Rs95xlzrxyloFD0u4bSd9_QmMBaSobY4NfSDezxlqSYOBkEUBLj6pOMZt1q-j4mRDbJSzJBAGkSDUQsLxic/s1600/SPI_pic1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="323" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlkEZPQDMbs1RzoWdXqzNhZKjvrcoEXJHN6Wa4wMPfn36rnu3Z77oy7Rs95xlzrxyloFD0u4bSd9_QmMBaSobY4NfSDezxlqSYOBkEUBLj6pOMZt1q-j4mRDbJSzJBAGkSDUQsLxic/s640/SPI_pic1.jpg" width="640" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La línea
de SDO (master) a SDI (slave) también se suele etiquetar MOSI (Master Out Slave
In). Igualmente la línea que conecta SDO (slave) con SDI (master) es denominada
MISO (Master In Slave Out):<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCaNMz6i7b_NGEZIm3qNIMAvV3qIkYRh4vRJyQdEh9Fs5xg2_01TzQpqiEnBCv7Kg6AWsW-nXmJnreNSvnLrli8dW1BwwEeBE0Kxzz5ReyCKlYa7W_Ap9MMkPDZeaqIE03cnsqeQ-6/s1600/master_slave1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="81" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCaNMz6i7b_NGEZIm3qNIMAvV3qIkYRh4vRJyQdEh9Fs5xg2_01TzQpqiEnBCv7Kg6AWsW-nXmJnreNSvnLrli8dW1BwwEeBE0Kxzz5ReyCKlYa7W_Ap9MMkPDZeaqIE03cnsqeQ-6/s400/master_slave1.jpg" width="400" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Además de
las dos líneas de datos (MOSI y MISO) y el reloj (SCK), en la figura anterior
se muestra una cuarta línea (CS, Chip Select, o SS, Slave Select) que se usa
para indicar al slave que se va a iniciar una comunicación. También permite la
comunicación de un master con varios slaves:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrmKO4AF-10WCG5DumdQTE2JRLONS7CRJH0GYcdoqFdYJxMcgkwNi1I21rY-QVIL0HeS42yCaqj308tNkkRQU1g0vc00vDXFiaEpp378LlVQ_OWbyRfM6O_qOmwd_THOQnsH59OM7w/s1600/master_slave2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrmKO4AF-10WCG5DumdQTE2JRLONS7CRJH0GYcdoqFdYJxMcgkwNi1I21rY-QVIL0HeS42yCaqj308tNkkRQU1g0vc00vDXFiaEpp378LlVQ_OWbyRfM6O_qOmwd_THOQnsH59OM7w/s400/master_slave2.jpg" width="400" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La barra
encima de SS indica negación, y es la forma standard de expresar que si
queremos seleccionar al esclavo #2 debemos poner a nivel bajo SS2 y mantener
altas SS1 y SS3. De esta forma los esclavos #1 y #3 ignoraran educadamente la
conversación entre Master y Slave #2.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se
ve, si empieza a haber muchos esclavos el número de líneas dedicadas a la
selección de dispositivos crece. Además, el master tiene que estar
continuamente preguntando a los esclavos si desean algo, ya que un esclavo no
tiene ninguna forma de iniciar la conversación. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Esta es la
razón por la cual SPI es el protocolo preferido por su simplicidad cuando sólo
tenemos una única conexión master-slave. Cuando hay que manejar varios esclavos
se prefiere el protocolo I2C. Este protocolo también es de tipo serie y síncrono
(en la familia PIC18, SPI e I2C comparten el mismo puerto de comunicaciones
serie síncronas SSP), pero implementa un sistema de direcciones, por lo que no
es preciso añadir líneas adicionales para los nuevos dispositivos. <o:p></o:p></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">COMUNICACIONES SPI en el PIC:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Pasemos
ahora a detallar como implementar el protocolo SPI al trabajar sobre un PIC (asumimos
que dispone del hardware adecuado, el puerto síncrono paralelo SSP). Como todo
periférico del PIC su configuración y manejo están controlado por una serie de registros
SFR (Special Function Registers. Para el puerto SPI dichos registros SFRs son: <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">SSPCON1, SSPSTAT y SSPBUF <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">los dos
primeros son registros de configuración, mientras que el segundo es donde se
ponen los datos a transmitir (y como hemos explicado, de donde se recogerán los
datos recibidos). </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Pasamos ahora a describir las opciones posibles en la
configuración del puerto SPI en un PIC, que se determinan con una serie de bits
en los registros SSPCON1 y SSPSTAT.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;"><br /></span></u></b></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">1) Elección Slave/Master<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Obviamente
la primera elección es decidir si el PIC será el master o un dispositivo slave
en la comunicación. Los contenidos de los 4 bits más bajos de SSPCON1
determinan esta elección. Sus posibles valores son:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana, sans-serif;">Opciones modo master: 00 11 --> clock = TMR2/2<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana, sans-serif;"> 00 10 --> clock = Fosc/64<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="EN-GB"> </span>00 01 --> <span lang="EN-GB"> clock = Fosc/16</span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> 00 00 <span lang="EN-GB">--> clock = Fosc/4</span></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Opciones
en modo slave: 01 01 -> No se usa
SS<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> 01 00 -> Se usa SS<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se ve
el primer bit (SSPCON1.SSPM3) es siempre 0 para ambos modos (esto sucede porque
al estar compartido el puerto SSP, estos cuatro bits también son usados para la
configuración del modo I2C).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El segundo
bit (SSPCON1.SSPM2) determina si el dispositivo es master (0) o slave (1).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En modo
master los dos últimos bits (SSPCON1.SSPM1 y SSPCON.SSPM0) determinan las cuatro posibles
frecuencias del reloj. La frecuencia del
reloj será una fracción (4, 16, 64) del oscilador principal o puede asociarse
al ritmo del Timer2.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Por
ejemplo, con un cristal de 20 MHz podríamos tener un master con un reloj de
5MHz (0000), 1.25MHz (0001) y 312KHz (0010). La opción del TMR2/2 (0011) nos permite programar otras frecuencias a través del timer TMR2.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si hemos
escogido el modo slave, los bits restantes determinan si usaremos o no el pin dedicado
para SS (Slave Select). En la familia PIC18F4520, dicho pin es el RA4. Si el valor es 01 no se usará SS y RA4 podrá
usarse como un pin normal. Si el valor es 00 se habilita RA4 como pin de
control SS.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si vamos a
ser un dispositivo SLAVE ya no hay nada más que configurar. Lo único recomendable es hacer
SSPSTAT.SMP=0 aunque no es estrictamente necesario ya que ese es su valor por
defecto. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En cambio, si nuestro dispositivo va a actuar como MASTER debemos configurar el modo SPI en el que vamos a trabajar.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Modos SPI (master): relación
reloj/datos<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Aunque
tengamos establecida la frecuencia del reloj, todavía hay varias opciones para
el master, referidas a la polaridad de la señal de reloj, y la fase entre dicha
señal y los datos de entrada/salida.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Los bits
que determinan estos aspectos son: <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: EN-GB;">SSPCON1.CKP
(Clock polarity)<o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: EN-GB;">SSPSTAT.CKE (Clock Edge)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">SSPSTAT.SMP (Sample bit)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El primero (CKP) define la polaridad de la señal de reloj (su IDDLE_LEVEL, si está a
nivel alto o bajo cuando el puerto este inactivo). </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El segundo bit (CKE) especifica la fase de los datos de
salida con respecto al reloj.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Por último, el tercer
bit(SMP) determina el momento en que se muestrean los datos de entrada (también
referido a la señal de reloj).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El
parámetro más sencillo es la polaridad del reloj (SSPCON1.CKP) que en la
literatura SPI se suele denotar como CPOL (Clock Polarity). Si es 0 indica que
el reloj esta bajo mientras no se manda nada. Si es 1 el IDDLE_STATE del reloj
será un nivel alto (1).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El segundo
parámetro (SSPSTAT.CKE) determina la fase de los datos de salida con respecto
al reloj. En la literatura standard nos
encontramos con un parámetro totalmente equivalente CPHA (Clock Phase), aunque
su definición es inversa de CKE. Esto es, CPHA = 1-CKE.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Juntos,
CPOL y CPHA determinan lo que se conoce como el <b>modo SPI</b> usado. Generalmente se
expresa como un par de número. Así, el modo SPI (0,1) indica que debemos hacer
CPOL=0 y CPHA=1, o traducido a la nomenclatura PIC</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">SSPCON1.CKP= CPOL
= 0 <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">SSPSTAT.CKE
= (1-CPHA)= 0<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Hemos
dicho que CPHA determina el momento en el que los datos de salida están estables (y
deberían ser muestreados por el otro dispositivo), pero no hemos explicado cual
es su relación ni que significa un valor de 0 o 1.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> Para
entenderlo, veamos la siguiente figura (adaptada del datasheet de Microchip),
ilustrando las posibilidades del reloj y su relación con los datos de
entrada/salida:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKka6nTfggraDiAheNhAauMQjkZlArNK53Z-rYwTLN7-3NhCoa3Jce-vBUlddGj2gPqV0lkw83kkccyb81X-OoKG6J74rcY2-15heXQhQKpcZGyHjNd-ppYwkf5yWKrHOEUS3z18Ra/s1600/cronograma.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKka6nTfggraDiAheNhAauMQjkZlArNK53Z-rYwTLN7-3NhCoa3Jce-vBUlddGj2gPqV0lkw83kkccyb81X-OoKG6J74rcY2-15heXQhQKpcZGyHjNd-ppYwkf5yWKrHOEUS3z18Ra/s1600/cronograma.jpg" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las cuatro primeras trazas ilustran las cuatro
posibilidades de reloj y la traza etiquetada como SDO la posición de los datos
de salida. Las líneas verdes indican el momento en que los datos debería ser
muestreados.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se
ve, la interpretación de CPOL=CKP es inmediata. CKP=0 indica un estado de
reposo bajo (azul) y CKP=1 indica un estado de reposo (antes y después de
enviar datos) alto (color rojo).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Mirando la
gráfica (primeras dos trazas de reloj)
podemos ver que si CKE=0 (CPHA=1)
el "centro" del bit de salida corresponde a las "segundas"
transiciones del reloj. Por el contrario si CKE=1 (CPHA=0) el centro del bit
está alineado con la primera transición del reloj. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El
problema es que dicha interpretación no es muy intuitiva. A veces se prefiere
describir el protocolo en términos de si los bits estarán estables con las
subidas o bajadas de reloj. Con la descripción anterior si escogemos CKE=1
sabemos que el dato está listo en la primera transición de reloj, pero dicha
transición puede ser de subida (traza 3) o de bajada (traza 4), dependiendo de
la polaridad del (CPOL). <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si
queremos formalizarlo, podemos definir un nuevo parámetro Low2High, (L2H=1 si
el bit esta listo en las subidas y L2H=0 si está disponible en las bajadas) y
determinar CKE como:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: EN-GB;"> CKE = L2H xor CKP<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Finalmente
queda decidir el valor de SPSSTAT.SMP que determina el momento de muestreo de
los datos entrantes, como se aprecia en la parte baja de la gráfica anterior:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">SMP=0 los bits de entrada están alineados con el centro
del periodo de reloj <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">SMP=1 los bits de entrada están disponibles al
final del periodo de reloj.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En la
práctica, ¿cómo elegir estos parámetros para comunicar nuestro PIC con un
cierto dispositivo? Como siempre hay varias posibilidades:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<br />
<ol>
<li><span style="font-family: Verdana, sans-serif;">Reusar
un código que andaba por ahí y que funciona.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Leer
las especificaciones del dispositivo donde por algún lado vendrá descrito que
modos SPI acepta. Normalmente se describen con la pareja (CPOL,CPHA). Recordar
que CKE=1-CPHA.</span></li>
<li><span style="font-family: Verdana, sans-serif;">A
veces en vez de especificar el modo SPI nos dan un diagrama de tiempos con el
reloj y la posición esperada de datos de salida y entrada. Con lo que hemos
explicado deberíamos ser capaces de determinar los tres parámetros necesarios
(CKP, CKE, SMP).</span></li>
</ol>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Aunque la
opción 1 es muchas veces un buen punto de partida, no debemos fiarnos del todo.
Hay algunos casos en los que es posible que una elección incorrecta de datos
funcione (a medias o intermitentemente). Por ejemplo, imaginad un caso donde
los datos de entrada deberían muestrearse
en el centro del periodo (SMP=0) pero usamos SMP=1. Aunque el punto de
muestreo se ha llevado al momento de cambio de datos, posiblemente seguirá
funcionando porque el otro dispositivo necesitará un tiempo para cambiar los
datos y puede que los datos recogidos sean los correctos. Sin embargo está
claro que estamos muestreando en un momento en el que los datos pueden cambiar
de repente, por lo que cualquier cambio de timings, etc. puede hacer que lo
recibido sea basura. Si tenemos
la documentación del dispositivo no costará mucho determinar la elección de
parámetros correcta.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Una vez
establecidas las opciones solo queda habilitar el puerto SSP (con
SSPCON1.SSPEN=1) y establecer las correspondientes direcciones de los pines
involucrados (a través del correspondiente registro TRIS).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En la mayoría de los PICs los pines asociados a las líneas SCL, SDI, SD0 son respectivamente RC3, RC4 y RC5.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El pin RC4 (SDI) deberá ser configurado como entrada. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Implementación de las comunicación SPI<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Al igual
que hicimos en el caso de la UART presentaremos las típicas funciones de las
que disponemos en un compilador y luego las reescribiremos usando nuestros
recién adquiridos conocimientos.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las
funciones de un compilador respecto al módulo SPI se dividen en rutinas de
inicialización (que afectarán a SSPCON1 y SSPSTAT) y rutinas de transferencia
de datos (básicamente poner/sacar datos de SSPBUF). Por ejemplo, en el
compilador de MikroC Pro encontramos las siguientes funciones básicas:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">INICIALIZACION:
SPI_Init_advance, <o:p></o:p></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">TRANSFERENCIA: SPI_read,
SPI_write.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La primera inicializa y configuran el puerto SSP en modo SPI. Los
parámetros que se pasan a SPI_Init_advance son bastante descriptivos y
corresponden a las opciones explicadas con anterioridad. Por ejemplo:</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">_SPI_CLK_IDLE_HIGH,_SPI_CLK_IDLE_LOW -> Polaridad de reloj (CKP=CPOL)<o:p></o:p></span></div>
<div class="MsoNormal">
<code><span lang="EN-GB" style="font-size: 8.0pt; mso-ansi-language: EN-GB;">_SPI_DATA_SAMPLE_MIDDLE,_SPI_DATA_SAMPLE_END </span></code><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"> -> Muestreo de datos entrada SMP=0/1<o:p></o:p></span></div>
<div class="MsoNormal">
<code><span lang="EN-GB" style="font-size: 8.0pt; mso-ansi-language: EN-GB;">_SPI_LOW_2_HIGH,_SPI_LOW_2_HIGH </span></code><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">-> Transición datos transmitidos (L2H=1/0)<o:p></o:p></span></div>
<div class="MsoNormal">
<code><span lang="EN-GB" style="font-size: 8.0pt; mso-ansi-language: EN-GB;">_SPI_MASTER_OSC_DIV4, DIV16, DIV64, TMR2 -> Setup as master y elección de
reloj</span></code><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"> <code><o:p></o:p></code></span></div>
<div class="MsoNormal">
<code><span lang="EN-GB" style="font-size: 8.0pt; mso-ansi-language: EN-GB;">_SPI_SLAVE_SS_ENABLE,_SPI_SLAVE_SS_DIS -> Setup as slave con y sin SS
pin <o:p></o:p></span></code></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Notad que
MikroC Pro usa la convención de especificar la fase reloj/datosTX a través de
L2H (especificar si están disponibles en las subidas/bajadas de reloj) y no
directamente a través de CKE o CPHA=1-CKE.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En el caso del compilador C18, las rutinas son:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">INICIALIZACIÓN: OpenSPI<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">TRANSFERENCIA: ReadSPI, WriteSPI o de forma equivalente getcSPI,
putcSPI<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Los parámetros de la función de inicialización son:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: EN-GB;">void OpenSPI(unsigned char sync_mode, unsigned char
bus_mode, </span><br />
<span lang="EN-GB" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned char smp_phase)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">sync_mode:</span></span><br />
<span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;"><br /></span>
<span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">--> master: </span><span lang="FR" style="font-family: Courier; font-size: 9.0pt; mso-ansi-language: FR; mso-bidi-font-family: Courier;">SPI_FOSC_4, SPI_FOSC_16, SPI_FOSC_64,
SPI_FOSC_TMR2 (clock)</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">--> slave: </span><span lang="EN-GB" style="font-family: Courier; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: Courier;">SLV_SSON, SLV_SSOFF (uso o no del pin dedicado para SS)
</span><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">bus_mode:</span></span><br />
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;"><br /></span></span>
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">--> MODE_00
(CKP=0, CKE=1)<o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">--> MODE_01 (CKP=0, CKE=0)<o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">--> MODE_10 (CKP=1, CKE=1)<o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">--> MODE_11 (CKP=1, CKE=0)<o:p></o:p></span></span></div>
<div class="MsoNormal">
<span lang="FR" style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: FR;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">smp_phase </span></span><br />
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;"><br /></span></span>
<span style="font-family: Verdana, sans-serif;"><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;">--> SMPEND datos de entrada disponible al final del ciclo (</span>SMP=1)</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="FR">--> SMPMID datos de entrada disponible en el medio del ciclo (</span>SMP=0)</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como se observa la inicialización de C18 (parámetro bus_mode) sigue la nomenclatura típica de los modos SPI (CKP,
CPHA).</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Reescribir por nuestra cuenta una función de inicialización es sencillo: basta poner los bits de los registros SSPCON1 y SSPSTAT a los valores adecuados. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las siguientes funciones pueden ser usadas
para conseguir el mismo objetivo:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_enable(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Enable SSP port and set TRIS register</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> TRISCbits.TRISC3=0; TRISCbits.TRISC5=0; TRISCbits.TRISC4=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// SCL out, SDO, out,
SDI in</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SSPCON1bits.SSPEN=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Enable SPI port</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Sets SPI mode
(CPOL,CPHA,SMP) </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR;">void</span><span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> spi_mode(uint8
CPOL,uint8 CPHA,uint8 sample) </span><span lang="FR" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="FR" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> SSPCON1bits.CKP=CPOL; SSPSTATbits.CKE=1-CPHA;</span><span lang="FR" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">SSPSTATbits.SMP=sample;</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Sets clock
frequency for SPI in master mode </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// clock =3 (TMR2/2)
=2 (Fosc/64) =1 (Fosc/16) =0 (Fosc/4)</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_master(uint8 clock) </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SSPCON1 = (SSPCON1 & 0xF0) | clock;</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Set SPI port as
slave. </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// ss=0 -> no
dedicated SS pin, </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// ss=1 ->
dedicated SS pin (RA5 in PIC18F4520)</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_slave(uint8 ss) </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ss=1-ss; ss = ss+4;</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SSPCON1 = (SSPCON1 & 0xF0) | ss;</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; font-size: 9.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Remarcar
que estas funciones no aportan nada que las funciones de C18 o MikroC no puedan
hacer. Las listamos para mostrar que configurar un periférico no es complicado
y para beneficio de aquellos que usen un compilador sin soporte para SPI.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Una vez
inicializado el puerto con unas u otras funciones, estamos listos para
mandar/recibir datos. Tanto en C18 (ReadSPI, WriteSPI) como en MikroC (SPI_read,
SPI_write) tenemos un par de funciones que leen/escriben un byte en la línea
SPI.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La
siguiente función sería nuestro equivalente:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<br />
<div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">uint8 spi_transfer(uint8
x) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// basic SPI transfer</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> SSPBUF = x;
</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(SSPSTATbits.BF==0); </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">(SSPBUF);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La función
recibe un byte de datos x y lo coloca en el buffer SSPBUF. Esto provoca las
siguientes acciones:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-indent: -18.0pt;">
<br />
<ol>
<li><span style="font-family: Verdana, sans-serif;">Inmediatamente
x se transfiere al verdadero registro de desplazamiento del puerto SSPSR y el
buffer SSPBUF queda vacío, esperando los datos de llegada.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Se
inicia la transmisión (y simultánea recepción) de datos.</span></li>
<li><span style="font-family: Verdana, sans-serif;">Cuando
se han transmitido los 8 bits (y por lo tanto se han recibido 8 bits) el byte
recibido se pasa a SSPBUF y la bandera SSPSTAT.BF se pone a 1 (buffer full).</span></li>
</ol>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En nuestra
función tras poner los datos en SSPBUF monitorizamos SSPSTAT.BF hasta que se
haga 1 (señal de que los datos recibidos están listos). En ese momento se
devuelve el valor recibido (en SSPBUF). La acción de leer SSPBUF pone a 0 el
bit SSPBUF.BF (indicando buffer empty).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Notad que
la función se llama spi_transfer, sin especificar si es TX o RX, porque nosotros ya sabemos que en SPI
no hay transmisiones ni recepciones propiamente dichas, sólo transferencias. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si
por una mayor legibilidad del código queremos disponer de una función de
escritura y otra de lectura podemos simplemente usar unos #define:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// SPI functions
aliases</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_tx(x)
spi_transfer(x) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// sends TX data, ignores return value.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_rx()
spi_transfer(0xFF) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// sends dummy data, returns RX data.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_clock() spi_transfer(0xFF) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
send 8 clocks (nobody cares about the data)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
</div>
<span style="font-family: Verdana, sans-serif;">Y eso es
todo. Hemos reproducido la funcionalidad de un compilador típico. Al igual que
hicimos en el caso de la UART, conociendo los detalles podríamos adaptar las rutinas a
nuestras necesidades especificas. </span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Por ejemplo, la rutina de transferencia
anterior (al igual que las de MikroC o C18) son bloqueantes. El bucle <b><span style="color: blue;">while(SSPSTAT.BF==0) </span></b>asegura que la función vuelve con
un dato. Pero la
comunicación se interrumpe en mitad de un byte, nuestro programa se
bloquearía. El PIC cuenta con una
interrupción del puerto SSP. La bandera SSPIF se levanta cuando una recepción
se ha completado y el dato está listo para ser recogido en SSPBUF. Usando
interrupciones la función anterior podría volver sin haber completado la
transferencia y sería responsabilidad de la interrupción rescatar el dato
recibido. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Definición de la línea CS:
estrategias:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En el apartado anterior vimos las funciones necesarias para una comunicación
SPI, pero dejamos un aspecto de lado: la definición de la línea CS a
usar. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Esto es
necesario puesto que al contrario del resto de los pines (SCL,SDO,SDI = RC3,RC5,RC4) para la
línea CS podemos usar cualquier pin I/O genérico que tengamos libre. El puerto SPI no
depende de donde está ni le importa. Habrá situaciones donde no se use u otras
donde tengamos varias líneas al haber más de un dispositivo. Es por eso por lo que la declaración y manejo
de dicho línea debe hacerse dentro de las rutinas del dispositivo SPI
específico. Sin embargo, como con la mayoría de los dispositivo SPI vamos a
necesitar una línea CS, este puede ser un buen lugar para explorar como hacerlo
y las alternativas posibles.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La forma
más sencilla (aunque como veremos no la más recomendable) es hacer un par de
#defines indicando el pin que va a ser usado como línea CS y su correspondiente
bit TRIS. Por ejemplo, para usar el pin
RC1 como CS en C18 usaríamos:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// CS line</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> device_CS LATCbits.LATC1<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> device_CS_dir TRISCbits.TRISC1<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> select_device
device_CS=0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> deselect_device device_CS=1</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;">De esta
forma solo tenemos que añadir la línea device_CS_dir=0; (output) durante la inicialización del dispositivo. P</span>osteriormente, cada vez que queramos hacer un intercambio SPI haríamos: </span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><br /></span></div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"></span></div>
<div style="border: 1pt solid windowtext; font-family: 'Times New Roman'; font-size: medium; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New'; font-size: 9pt;">select_device;</span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">SPI_talk ...</span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">deselect_device;</span></div>
</div>
<div class="MsoNormal" style="font-family: 'Times New Roman'; font-size: medium;">
<br /></div>
<span style="font-family: Verdana, sans-serif;">El
problema de este enfoque viene si en otro montaje nos viene mejor usar un pin diferente como
línea CS. Si estamos usando nuestro propio código no hay problemas, cambiamos
el #define y recompilamos. El problema es si estamos escribiendo una librería.
En ese caso el usuario final tendría que estar buceando en nuestro código y
cambiando los ficheros fuente de la librería. Eso en el caso de que disponga de
los ficheros fuente. Si solo publicamos la librería ya compilada forzamos al usuario
a usar siempre el pin RC1 cuando use un dispositivo SPI. </span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Obviamente
esto no es muy conveniente, pero parece ser que en C18 no hay otra
alternativa. De hecho, en el manual de
librerías del C18 (pag. 80) indica que
si se desea p.e, usar un LCD con una selección de pines diferente de la
asignada por defecto se deben modificar las definiciones del correspondiente
fichero xlcd.h.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Este es un
caso donde el compilador de MikroC presenta una ventaja frente al C18. En
MikroC tenemos una solución más flexible: se trata de declarar dos variables (p.e.
<b><span style="color: blue;">devicename_CS</span></b> y <b><span style="color: blue;">devicename_CS_dir)</span></b> para informar al resto de las
rutinas de que pin estamos usando como ChipSelect (CS) y su correspondiente bit
de dirección TRIS. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En MikroCPro
podemos declarar dichas variables de tipo sbit y asociarlas a los
correspondientes pines:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">sbit devicename_CS at LATC.B1; // Will use RC1 as CS line<o:p></o:p></span></b></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">sbit devicename_CS_dir at TRISC.B1;<o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Esto parece
muy similar a los #defines de antes. La
ventaja es que si estamos escribiendo una librería, en el fichero fuente de la
librería declararíamos las variables <a href="http://www.blogger.com/blogger.g?blogID=4945680608471335280" name="OLE_LINK1"><b><span style="color: blue;">devicename_CS, devicename_CS_dir</span></b></a>
</span><span style="font-family: Verdana, sans-serif;">como externas,
sin asignarles ningún valor en particular. Sería el usuario en su programa
quien diera valores a dichas variables, en función de su configuración
hardware:</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Within library source file<o:p></o:p></span></b></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">extern sfr sbit devicename_CS;<o:p></o:p></span></b></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">extern
sfr sbit devicename_CS_dir;<o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el
fichero del usuario<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">sbit devicename_CS at LATC.B1; // Choose your own pin here<o:p></o:p></span></b></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<b><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">sbit devicename_CS_dir at TRISC.B1;<o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">De esta
forma el usuario puede elegir el pin a usar para cada montaje o definir
diferentes pines para varios dispositivos, sin tener que modificar la librería original.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Terminaremos este tutorial usando las rutinas dadas en un programa muy sencillo que establezca una simple comunicación SPI entre un PIC (master) y un periférico (slave). </span><br />
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span>
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span>
<br />
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Conversor Digital Anaógico (DAC) MCP4822:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">En la entrada Audio con PWM vimos como era posible usar la salida PWM del PIC como un conversor DAC de conveniencia. Si se desean mejores resultados existen por supuesto dispositivos DAC específicos.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br />
Vamos a mostrar como usar uno de estos dispositivos (MCP4822 de Microchip). ES un conversor DAC de 12 bits (4096 niveles) alimentado con 5V y que cuenta con dos canales independientes de salida. </span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Lo que nos importa en este caso es que la comunicación con dicho DAC es a través de SPI. Además se trata de </span><br />
<span style="font-family: Verdana, sans-serif;">una comunicación muy sencilla, perfecta para una primera prueba. El periférico recibe un sólo tipo de mensaje (de 2 bytes de tamaño, donde se le especifica el voltaje deseado en uno u otro canal) y no envía ninguno.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
Es por lo tanto una comunicación unidireccional, en la que esencialmente el PIC manda mensajes con los voltajes deseados y no hay que preocuparse de ningún protocolo de respuestas, validaciones, tiempos de espera, etc.</span></div>
<div class="MsoNormal">
</div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;"><br /></span></u></b></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Hardware:</span></u></b></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMPFJ-ryehbKnI9zAT6xoZm7ju3VsRfpfX8FbhGeyLS3bMFJpcoD9T7RHON4juWrMyg7CJrQDZ_HimVq1qax9AM2RuXyXXV4s0BszhLo73Ul_HhnVZ3Osb5jvvJBZdyzldwCUG3l4P/s1600/mcp%604822_pines.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"></span></a><span style="font-family: Verdana, sans-serif;"><br /></span>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMPFJ-ryehbKnI9zAT6xoZm7ju3VsRfpfX8FbhGeyLS3bMFJpcoD9T7RHON4juWrMyg7CJrQDZ_HimVq1qax9AM2RuXyXXV4s0BszhLo73Ul_HhnVZ3Osb5jvvJBZdyzldwCUG3l4P/s1600/mcp%604822_pines.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMPFJ-ryehbKnI9zAT6xoZm7ju3VsRfpfX8FbhGeyLS3bMFJpcoD9T7RHON4juWrMyg7CJrQDZ_HimVq1qax9AM2RuXyXXV4s0BszhLo73Ul_HhnVZ3Osb5jvvJBZdyzldwCUG3l4P/s1600/mcp%604822_pines.jpg" /></a><span style="font-family: Verdana, sans-serif;">El DAC MCP4822 es un integrado de 8 pines cuya descripción se muestra en la figura adjunta. La alimentación (Vdd) es a 5V por lo que no tendremos problemas de cambios de nivel con respecto al PIC. Los pines 2(CS line) ,3 (Clock) y 4 (SDI) se usarán en la comunicación SPI. Notad que no hay un pin SDO, al ser la comunicación unidireccional. El pin 7 (AVss) es tierra y los pines 8 (OUT_A) y 9 (OUT_B) corresponden a los dos canales analógicos disponibles. Finalmente el pin 5 (~LDAC) puede usarse para sincronizar la salida de ambos canales. Nosotros lo pondremos a tierra, lo que hace que el voltaje en la salida se actualice cuando el valor de la línea CS vuelve a un valor alto tras acabar la comunicación.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
La conexión PIC-DAC será por lo tanto la correspondiente al esquema siguiente:</span><br />
<span style="font-family: Verdana; font-size: 11px;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9iT-gqPDBYMKXQeSBPdAz7TZiUgiwtgUQ3C7WXtGECUEhFtF7KgEKTjkvWEQmymDdLG0BsYamFSbnVGHLZwJYxcOPas-Fn7RsyPWM5NMKMBAdF0-TeToyiHNEtnJK8et7OcqZxbyD/s1600/esquema.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9iT-gqPDBYMKXQeSBPdAz7TZiUgiwtgUQ3C7WXtGECUEhFtF7KgEKTjkvWEQmymDdLG0BsYamFSbnVGHLZwJYxcOPas-Fn7RsyPWM5NMKMBAdF0-TeToyiHNEtnJK8et7OcqZxbyD/s640/esquema.jpg" width="640" /></a></div>
<span style="font-family: Verdana; font-size: 11px;"><br /></span><span style="font-family: Verdana; font-size: 11px;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Notad que estamos usando RC1 como línea CS y que no usamos el pin SDI (RC4) del PIC, puesto que no vamos a recibir ningún dato. La salida de los canales A y B las conectamos al osciloscopio para ver los resultados. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br />
<br />
<b><u>Software:</u></b></span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El programa es muy sencillo y consiste en poco más de las funciones que ya hemos visto. </span><br />
<span style="font-family: Verdana, sans-serif;"><br />
Lo primero que hay que hacer es determinar el modo SPI con el que trabaja el periférico. En su datasheet nos dicen que soporta los modos SPI (0,0) y (1,1). Del momento de muestreo de los datos de entrada no debemos preocuparnos porque no existen.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
En la docu también se nos informa de que el dispositivo acepta hasta 20 MHz de reloj en la comunicación SPI. </span><span style="font-family: Verdana, sans-serif;">En este montaje estoy usando un reloj de 8 MHz, por lo que puedo usar la frecuencia máxima (Fosc/4 = 2 MHz) </span><span style="font-family: Verdana, sans-serif;">y aún así estar muy por debajo de las capacidades del dispositivo.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
Una rutina que inicializase la comunicación SPI con los parámetros indicados usando las rutinas presentadas antes sería:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> DAC_spi_init(byte clock)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> DAC_CS_dir=0; deselect_DAC; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Configure CS line as output and set it low.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_master(clock); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Configure SPI as master and set clock </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_mode(0,0,0); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// SPI mode (0,0). Third arg doesnt matter</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> spi_enable(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Enable SPI</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<span style="font-family: Verdana, sans-serif;">Respecto a la comunicación en si, el único tipo de comando reconocido por el DAC es un mensaje de 16 bits:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxRJ-dSKcsa8oZ0dhoaDFxjJCcCZKy75IbLYvMVJBGc9u4okdmJFkP7kimWTZnymkyO_Ewsi3VOW1WoLqB6EZEMwnJBJAWiUAv4R4A19AsEw-OAG7HvPRx6vCu4r3qtmaDcOfiUfU8/s1600/msg_DAC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="168" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxRJ-dSKcsa8oZ0dhoaDFxjJCcCZKy75IbLYvMVJBGc9u4okdmJFkP7kimWTZnymkyO_Ewsi3VOW1WoLqB6EZEMwnJBJAWiUAv4R4A19AsEw-OAG7HvPRx6vCu4r3qtmaDcOfiUfU8/s640/msg_DAC.jpg" width="640" /></span></a></div>
<span style="font-family: Verdana, sans-serif;"><br />
<br />
Los 12 bits menos significativos contienen simplemente el voltaje deseado (un valor de 0 a 4095). De los otros 4 bits, solo 3 tienen una función:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<ul>
<li><span style="font-family: Verdana, sans-serif;">El más significativo (Ã/B) indica el canal donde debe aparecer el voltaje (0-->A, 1-->B). </span></li>
<li><span style="font-family: Verdana, sans-serif;">El tercero (~GA) nos permite especificar una ganancia. Si es 0 cubrimos el rango completo de voltaje (aprox de 0 a 4V) y si es 1 solo barremos la mitad (de 0 a 2V).</span></li>
<li><span style="font-family: Verdana, sans-serif;">Finalmente (~SHDW) nos permite poner al dispositivo en un modo "apagado" (0)</span></li>
</ul>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Por lo tanto si usamos el rango completo de voltaje los valores de esos 4 bits serán 0001 si queremos usar el canal A y 1001 si queremos mandar un voltaje al canal B</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
<br />
</span><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">Finalmente las especificaciones también nos
indican que debemos mandar primero el byte más significativo. Dado un uin16 (2
bytes) que contenga el mensaje a mandar, el siguiente macro lo mandaría por la
línea:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> send_msg(msg) { select_DAC; spi_tx(msg>>8);
spi_tx(msg&0xFF); deselect_DAC; }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">Primero avisamos al DAC de que se inicia una
comunicación y luego mandamos el byte
más significativo seguido del menos significativo. Finalmente devolviendo a
nivel alto la línea CS terminamos la conversación.<o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">Vamos a escribir un programa que incremente un
contador de 0 a 4095 y mande dicho contador al canal A, por lo que en dicho
canal deberíamos ver un voltaje rampa.
En el canal B vamos a crear una sinusoide. Para ello creamos una tabla
de 256 valores de la función seno cubriendo un periodo. Los valores están
escalados entre 0 y 255 para que entren en una variable de tipo uint8 (byte):</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">uint8 tabla[256]= { </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0x80,0x83,0x86,0x89,0x8C,0x8F,0x92,0x95,0x98,0x9B,0x9E,0xA2,0xA5,0xA7,0xAA,0xAD,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0xB0,0xB3,0xB6,0xB9,0xBC,0xBE,0xC1,0xC4,0xC6,0xC9,0xCB,0xCE,0xD0,0xD3,0xD5,0xD7,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0xDA,0xDC,0xDE,0xE0,0xE2,0xE4,0xE6,0xE8,0xEA,0xEB,0xED,0xEE,0xF0,0xF1,0xF3,0xF4,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0xF5,0xF6,0xF8,0xF9,0xFA,0xFA,0xFB,0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFE,0xFD,0xFD,0xFC,0xFB,0xFA,0xFA,0xF9,0xF8,0xF6,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0xF5,0xF4,0xF3,0xF1,0xF0,0xEE,0xED,0xEB,0xEA,0xE8,0xE6,0xE4,0xE2,0xE0,0xDE,0xDC,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">0xDA,0xD7,0xD5,0xD3,0xD0,0xCE,0xCB,0xC9,0xC6,0xC4,0xC1,0xBE,0xBC,0xB9,0xB6,0xB3,</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0xB0,0xAD,0xAA,0xA7,0xA5,0xA2,0x9E,0x9B,0x98,0x95,0x92,0x8F,0x8C,0x89,0x86,0x83,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x80,0x7C,0x79,0x76,0x73,0x70,0x6D,0x6A,0x67,0x64,0x61,0x5D,0x5A,0x58,0x55,0x52,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x4F,0x4C,0x49,0x46,0x43,0x41,0x3E,0x3B,0x39,0x36,0x34,0x31,0x2F,0x2C,0x2A,0x28,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x25,0x23,0x21,0x1F,0x1D,0x1B,0x19,0x17,0x15,0x14,0x12,0x11,0x0F,0x0E,0x0C,0x0B,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x0A,0x09,0x07,0x06,0x05,0x05,0x04,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x04,0x05,0x05,0x06,0x07,0x09,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x0A,0x0B,0x0C,0x0E,0x0F,0x11,0x12,0x14,0x15,0x17,0x19,0x1B,0x1D,0x1F,0x21,0x23,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x25,0x28,0x2A,0x2C,0x2F,0x31,0x34,0x36,0x39,0x3B,0x3E,0x41,0x43,0x46,0x49,0x4C,</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">0x4F,0x52,0x55,0x58,0x5A,0x5D,0x61,0x64,0x67,0x6A,0x6D,0x70,0x73,0x76,0x79,0x7C};</span><span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">Los valores anteriores se han obtenido con el
siguiente comando MATLAB: <o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="FR" style="font-family: Verdana, sans-serif;">>> t=2*pi*[0:255]/256; tabla =
round(127.5*sin(t)+127.5); <o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">y se representan en la figura adjunta:</span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-S696HVci7NTaOSsu_Gjclgv6bhYbt-AMpw6bg1nYJAjZrI3trWkf3A_3WRBig8ojUjs2nth6c32RFZGrDzifmNZVYD2XmHU8IeTgNXiDAS29kBNDv39LRGdELQVdhtgC8jAbLvEm/s1600/tabla_sin.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-S696HVci7NTaOSsu_Gjclgv6bhYbt-AMpw6bg1nYJAjZrI3trWkf3A_3WRBig8ojUjs2nth6c32RFZGrDzifmNZVYD2XmHU8IeTgNXiDAS29kBNDv39LRGdELQVdhtgC8jAbLvEm/s320/tabla_sin.jpg" width="320" /></span></a></div>
</div>
<div class="MsoNormal">
</div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;">A partir de aquí el programa
principal queda simplemente:<o:p></o:p></span><br />
<span style="font-family: Verdana; font-size: 8pt;"><br /></span>
<br />
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> main()</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint16 d=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint16
msg;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> uint16
v;</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> DAC_spi_init(0); Delay1KTCYx(10); </span><span lang="FR" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: FR;">// Configure
SPI @ Fosc/4</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">while</span><span style="font-family: 'Courier New'; font-size: 9pt;">(1)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> {</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> msg = d + 0x1000; send_msg(msg); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Value of d to chan A </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> v = tabla[d&0xFF]; v<<=4; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// v = 16 x value in sin array </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> msg = v + 0x9000; send_msg(msg); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Value of v to chan B </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> d++; d&=0x0FFF; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
increment d and makes sure it remains within [0,4095] </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> } </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<span style="font-family: Verdana; font-size: 8pt;"><br /></span>
<span style="font-family: Verdana; font-size: 8pt;"><br /></span>
<span style="font-family: Verdana, sans-serif;">El resultado,
visto en el osciloscopio para dos escalas de tiempo, es el siguiente:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjctHI10p_GevEQ3vEtwe-WZ58LwMoJ63_4G-m3CJ3JZdYHe5KcmgOUf95jzcgUbVyM-SU2GwoVbgiubefaGPv1YIZrThbjRdqCJk0ixCC53ai0vXp1uT3UBf2IMqiOz7Ai-cPAw0J9/s1600/oscope12.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjctHI10p_GevEQ3vEtwe-WZ58LwMoJ63_4G-m3CJ3JZdYHe5KcmgOUf95jzcgUbVyM-SU2GwoVbgiubefaGPv1YIZrThbjRdqCJk0ixCC53ai0vXp1uT3UBf2IMqiOz7Ai-cPAw0J9/s1600/oscope12.jpg" /></span></a></div>
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
El canal A
(arriba) muestra la rampa del contador (de 0 a 4095 y vuelta a empezar) y el
canal B la sinusoide. La sinusoide es más rápida que la rampa porque cada ciclo
se repite cada 256 valores del contador, en vez de cada 4096. Notad también que
no estamos usando toda la resolución del DAC, ya que para el seno usamos un
valor entre 0 y 255 que posteriormente multiplicamos por 16. Por lo tanto los 4
bits menos significativos del voltaje está a 0. </span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En el
siguiente tutorial pondremos a prueba nuestras rutinas SPI con un ejemplo un
poco más complicado de interfaz con un
dispositivo SPI, en particular una memoria flash (M25P80 de 1 Mbyte de
capacidad), donde tendremos comunicaciones en ambos sentidos.</span></div>
<br />
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><br /></span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com18tag:blogger.com,1999:blog-4945680608471335280.post-2744832513686116352013-02-20T17:26:00.000+01:002013-06-07T17:40:59.059+02:00Proyecto: Levitador magnético<span style="font-family: Verdana, sans-serif;">En este proyecto escribiremos un programa para el PIC que
mantenga un imán suspendido en el aire. El PIC controlará la bobina de un
electroimán a través de un L293D. Bajo este electroimán colocaremos un imán. En
ausencia de corriente el imán siente dos fuerzas: la gravedad hacia abajo y la
atracción magnética con el núcleo (un tornillo) del electroimán. </span><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">Existe un punto donde ambas fuerzas están
equilibradas. Desgraciadamente dicho punto es inestable. Si el imán se aparta
un poco de la bobina la atracción magnética disminuye y el peso gana la
partida: el imán cae. Si el imán se acercara un poco a la bobina, la atracción
imán-tornillo es cada vez más fuerte, por lo que terminará pegándose
arriba. La idea es colocar un sensor de
flujo magnético justo debajo de la bobina. Usando este sensor el PIC puede
detectar la posición del imán y actuar en consecuencia: si el imán empieza a
caerse, hacemos pasar la corriente por el electroimán de forma que atraiga un
poco al imán y éste se recupere. Si se acerca, activamos la bobina en sentido
contrario para rechazar el imán y volverlo a llevar a la posición ideal de
equilibrio.<o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">Podéis encontrar en internet bastantes
variantes de este esquema, aunque la mayoría de ellas no usan un
microcontrolador sino un integrado (MIC502) originalmente diseñado para
modificar la velocidad de un ventilador (mediante PWM) en función de la
temperatura de un sensor. La ventaja de un enfoque con un microcontrolador </span><span style="font-family: Verdana, sans-serif;">es que tenemos muchas más posibilidades de control (podríamos p.e. hacer oscilar a voluntad el imán). En este proyecto nos limitaremos a construir el programa básico. </span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana, sans-serif;">El objetivo del proyecto es lograr algo parecido a lo mostrado en este corto video:</span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/3sLX0CEYPMo?feature=player_embedded' frameborder='0'></iframe></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana;">Al igual que en las entradas correspondientes a control de motores acompañamos el código del PIC con un código MATLAB para visualizar los resultados y jugar con los parámetros de control. </span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="PT-BR" style="font-family: Verdana;">Código asociado:<span class="apple-converted-space"> </span>
<a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/maglev_4520.c">maglev_4520.c</a> (código PIC)</span><br />
<span lang="PT-BR" style="font-family: Verdana;"> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/maglev.m">maglev.m</a>
(programa MATLAB de interfaz con el PC). </span><br />
<span lang="PT-BR" style="font-family: Verdana;">Fichero hex: </span><span class="apple-converted-space" style="font-family: Verdana;"> </span><span style="font-family: Verdana;"> </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/maglev_4520.hex" style="font-family: Verdana;">maglev_4520.hex</a><span style="font-family: Verdana;"> </span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 8pt;"></span></div>
<a name='more'></a><br />
<span style="font-family: Verdana, sans-serif;">--------------------------------------------------------------------------------</span><br />
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div align="center" style="margin: 0cm 0cm 0.0001pt; text-align: center;">
<span style="font-family: Verdana, sans-serif;"> <o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<b><u><span lang="PT-BR" style="font-family: Verdana, sans-serif;">Descripción del hardware:</span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><b>Bobina arrollada sobre un tornillo</b>: la bobina son unos 50 metros de hilo esmaltado de un diámetro aproximado de 0.25mm. La resistencia total son unos 16 ohmios. Estos datos son aproximados porque no esperaba documentar esto cuando forme la bobina. A posteriori medí su resistencia total (16 ohmios) y la compare con otros hilos de donde saque su diámetro aproximado y de ahí su longitud. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">De todas formas hay tantos factores que influirán en la calibración final (fuerza y peso del imán, tipo de sensor usado, etc.) que no es crítico que la bobina sea exactamente como la mía. Los valores anteriores pueden ser un punto de referencia.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Lo que si es importante es que la resistencia total de la bobina sea lo
suficientemente alta para que la intensidad máxima (dependiente del voltaje
usado para la bobina) no supere las especificaciones del driver usado. En
funcionamiento normal el consumo es reducido (unos 20-30 mA) pero cuando
estamos haciendo pruebas muchas veces estaremos aplicando el voltaje al
completo. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La bobina se arrolla sobre un tornillo de 8mm de diámetro que forma el núcleo del electroiman.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><b>Sensor de flujo magnético basado en
efecto Hall</b>: he probado tanto un SS49E de Honeywell como un A1302 de Allegro. Lo importante es
que sea un sensor de medida continuo, no uno de detección de polos, que tienen
una respuesta binaria. Los sensores utilizados tienen 3 pines (V, GND y
OUTPUT). La alimentación ha sido con 5V y la salida (en ausencia de campo
magnético) es de V/2, lo que corresponderá a 512 una vez convertida en nuestro
ADC. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><o:p><br /></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><b>Alimentación de la bobina</b>: uso una batería de litio de 7.5V.
Controlada con el PIC a través de un L293D, al igual que hicimos en el caso del
motor. En el peor de los casos puedo tener una intensidad de 7.5/16 = 0.5A, dentro de las posibilidades del driver (L293D) usado.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmBO6-6keCAFEjtjNjbx-0WHkOyhc3A9YARbbQrbUXZEDZC25K8l_61MS9PZpl3jvAVSaiwtT6MNro3e_XtEoGxRYSuf0g52eS_xchRltZizW9nYv-BCdj8XNK4GiMyLzHibUoSLhf/s1600/soporte.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmBO6-6keCAFEjtjNjbx-0WHkOyhc3A9YARbbQrbUXZEDZC25K8l_61MS9PZpl3jvAVSaiwtT6MNro3e_XtEoGxRYSuf0g52eS_xchRltZizW9nYv-BCdj8XNK4GiMyLzHibUoSLhf/s320/soporte.jpg" width="296" /></span></a><span style="font-family: Verdana, sans-serif;"><b>Soporte para la bobina y el sensor:</b> En el esquema adjunto podemos
observar el montaje de la bobina + sensor en un soporte de madera.
La bobina se sujeta al soporte aprovechando el propio tornillo que sirve como
núcleo del electroimán. El sensor se encuentra posicionado justo debajo del tornillo, oculto en un receso de la madera. Debajo del
sensor sería conveniente poner un material blando (un trozo de cámara de bici, espuma o similar) para
que amotigüe los numerosos golpes que se llevará el sensor
cuando el imán golpee contra él en la fase de pruebas. También se puede "cerrar" el receso de la madera con algún material (no magnético).<o:p></o:p></span><br />
<b style="font-family: Verdana, sans-serif;"><br /></b>
<b style="font-family: Verdana, sans-serif;">Conexiones:</b><span style="font-family: Verdana, sans-serif;">
del soporte anterior salen 5 conexiones. Tres de ellas corresponden al sensor:
alimentación V (5V), tierra GND y la salida del sensor S. Las dos primeras van directamente a Vcc y GND
de la placa EasyPIC, mientras que la salida del sensor la llevamos al pin que usaremos
como entrada analógica, en nuestro caso RA0.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las otras
dos conexiones (B1 y B2) corresponden a la bobina. Al igual que pasaba con un
motor, no podemos controlar directamente la bobina desde el PIC. Como deseamos
tener la capacidad de cambiar el sentido de la corriente (para que el electro
atraiga o rechace el imán) usaremos un puente H como se indicó en el tema
anterior.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">
Hemos
optado de nuevo por usar (la mitad de) un L293D. De esta forma las conexiones
de la bobina (B1,B2) irán a dos de las salidas del L293D (OUT1 y OUT2).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Respecto a
las líneas de control desde el PIC, hemos optado por la configuración que llamábamos
de tipo B) en la entrada sobre control de motores. En dicha configuración, la
salida PWM del PIC (por ejemplo RC2) se lleva directamente a una (IN1) de las
entradas del driver. El complementario de la señal PWM (obtenida con un
inversor constituido con un simple transistor) se lleva a la otra entrada IN2. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como
vimos, de esta forma, un duty cicle del 50% en la señal PWM supone que no
estamos actuando sobre el electroiman. Por el contrario, valores de 0 o 1023 suponen una máxima
atracción/repulsa del imán. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_RfnUV30ie4SJ5sCjixpu7ur8Ch6KAshfaJziCLFwj6URlaBFR8nNvYAIMOL0UnRDbNrK2Vg1oKYuBmHsULiK-PDQiRx3sgOOqonCLoiIvv2CfVG9ImqXIh1fVNwKTRxvzIZnFIlC/s1600/esquema.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="221" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_RfnUV30ie4SJ5sCjixpu7ur8Ch6KAshfaJziCLFwj6URlaBFR8nNvYAIMOL0UnRDbNrK2Vg1oKYuBmHsULiK-PDQiRx3sgOOqonCLoiIvv2CfVG9ImqXIh1fVNwKTRxvzIZnFIlC/s400/esquema.jpg" width="400" /></span></a></div>
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En cuanto
al pin ENABLE del L293D podríamos dejarlo atado a un nivel alto (5V)
continuamente. De esta forma el driver estaría siempre "encendido". Sin embargo hemos
preferido conectarlo a otro pin (RC0) del PIC, para poder desconectar/conectar
el electro desde el programa. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Aunque opcional, esta conexión es muy conveniente. Si por ejemplo el imán se
cae, el sensor detectaría que hay que subirlo y el PIC pondría a la bobina en
estado de máxima atracción. Como el electro no va a tener fuerza para levantar
al imán de la mesa, la situación se va a mantener. La bobina va a estar tirando todo el rato, tratando
(inútilmente) de recuperar el imán. Lo
mismo pasa si el imán llega a pegarse al núcleo del imán. Por mucho que lo
intente el electro no puede vencer dicha fuerza y el imán seguirá pegado al
tornillo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">El
programa puede detectar estas situaciones a través del sensor (un error grande mantenido mucho
tiempo, positivo en un caso, negativo en otro) y en esos casos puede cortar la
corriente a la bobina, poniendo a 0 el pin ENABLE del L293D. En cuanto
volvamos a acercar el imán al punto adecuado, el error volverá a tener un valor
razonable y se pondrá a 1 el
ENABLE, recuperando la funcionalidad del sistema</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">De esta
forma sólo estaremos gastando batería cuando el imán esté levitando y no cuando
se caiga o lo quitemos. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><b>Puerto serie: </b>usaremos el puerto serie (pines RC6,RC7) para mandar los resultados y recibir órdenes del PC. Como en la placa EsayPIC disponemos de un conversos de niveles y un conector DB9 no tendremos que preocuparnos de esa parte.<b><o:p></o:p></b></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><b><u><span lang="PT-BR"><br /></span></u></b>
<b><u><span lang="PT-BR">Descripción del software:</span></u></b></span><br />
<br /></div>
<span style="font-family: Verdana, sans-serif;">
</span>
<div class="MsoNormal">
</div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-family: Verdana, sans-serif;">En este proyecto vamos a usar casi todo lo que
hemos visto hasta ahora: <o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin: 0cm 0cm 0.0001pt 36pt; text-indent: -18pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">·
<!--[endif]-->Temporizadores e interrupciones para tomar medidas y controlar el
electroimán cada cierto tiempo (unas 500 veces por segundo)<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt 36pt; text-indent: -18pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">·
<!--[endif]-->Uso del ADC para leer datos de un sensor analógico (usando la
correspondiente interrupción). <o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt 36pt; text-indent: -18pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">·
<!--[endif]-->Uso del PWM para controlar un electroimán a través de un puente en
H.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt 36pt; text-indent: -18pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">·
<!--[endif]-->Uso del puerto serie para mandar datos al PC y representarlos
usando MALAB.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt 36pt; text-indent: -18pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;">·
<!--[endif]-->Algoritmo tipo PID para el control de la bobina en función de los
datos del sensor.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<div>
<span style="font-family: Verdana, sans-serif;">Lo bueno es que los detalles de todos los puntos
anteriores ya están explicados en entradas anteriores, por lo que podemos
limitarnos a ver como se enlazan en el programa final.<o:p></o:p></span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<b><span style="font-family: Verdana, sans-serif;"><br /></span></b>
<b><span style="font-family: Verdana, sans-serif;">Interrupción TX del puerto serie:</span></b></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1-f1nU9uHfuUnqEcNg2QJw4_dvbVU_kwGijVBZDyzS7dDv09fYQU6lPMubwUUPQD3B_t8yTMr2JvnUZZD2GkMvaMdo0NrwNrfAIPDDjm2uPKJoYO8CbDVyT8mU3M45_4RhYQcvTlh/s1600/linker.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1-f1nU9uHfuUnqEcNg2QJw4_dvbVU_kwGijVBZDyzS7dDv09fYQU6lPMubwUUPQD3B_t8yTMr2JvnUZZD2GkMvaMdo0NrwNrfAIPDDjm2uPKJoYO8CbDVyT8mU3M45_4RhYQcvTlh/s320/linker.jpg" width="234" /></a><span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1-f1nU9uHfuUnqEcNg2QJw4_dvbVU_kwGijVBZDyzS7dDv09fYQU6lPMubwUUPQD3B_t8yTMr2JvnUZZD2GkMvaMdo0NrwNrfAIPDDjm2uPKJoYO8CbDVyT8mU3M45_4RhYQcvTlh/s1600/linker.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"></span></a><span style="font-family: Verdana, sans-serif;">Tras los
#includes y #pragmas habituales para definir la configuración, empezamos reservando
espacio para el buffer de escritura del puerto serie (ref entrada UART INTS).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600"
o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f"
stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t75" style='position:absolute;
margin-left:385.5pt;margin-top:8.9pt;width:91.5pt;height:124.5pt;z-index:1'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.png"
o:title=""/>
<w:wrap type="square"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><span style="font-family: Verdana, sans-serif;">Ya comentamos en su momento que debido a la
estructura de la memoria del PIC en bancos de 256 bytes podríamos tener
dificultades si necesitabamos reservar un array de más de 256 bytes o si una de
nuestras variables cruza una frontera de 256 bytes. Es posible hacerlo pero no
es inmediato. En este programa ilustramos como se hace. En nuestro programa
deseamos reservar un array (tx_buf) de tamaño 256 bytes. Para ello debemos hacer dos cosas:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Verdana, sans-serif;">1) Modificar
el archivo 184520_g.lkr con la información sobre la distribución de la memoria
del modelo de PIC usado. Lo mejor es hacer una copia del original en el
directorio de nuestro proyecto y modificarla. Hay que acordarse de añadirla al
proyecto en la sección de Linker Scripts
como se muestra en la imagen adjunta. Si no se hace así el compilador
usara la copia original de su directorio y conseguiremos linkar el programa. Buscar
la sección del fichero donde se describen la posición de los distintos bancos
de memoria. El original será algo así como:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
ORIGINAL:<span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: 1pt solid windowtext; font-family: Verdana; font-size: 8pt; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr0 START=</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">0x80 END=0xFF</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr1 START=0x100 END=0x1FF</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr2 START=0x200 END=0x2FF</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr3 START=0x300 END=0x3FF </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr4 START=0x400 END=0x4FF </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
Y lo
cambiaremos por esto: <span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: 1pt solid windowtext; font-family: Verdana; font-size: 8pt; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr0 START=0x80 END=0xFF</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr1 START=0x100 END=0x1FF</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr2 START=0x200 END=0x2FF</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr3 START=0x300 END=0x3FF </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">DATABANK NAME=gpr4 START=0x400 END=0x4FF PROTECTED</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">SECTION NAME=buffer_maglev RAM=gpr4</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<span style="font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Lo único
que hemos hecho es declarar un banco (gpr4, de 256 bytes desde la posición 0x400 a
la 0x4FF) como PROTECTED, de forma que el compilador no intente meter ninguna
variable en esa zona, salvo las que explícitamente declaremos que están en ese
banco. En la línea añadida (SECTION NAME) simplemente damos un nombre
(buffer_maglev) al banco reservado para poder referirnos a él en nuestro
programa.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En el
programa principal reservaremos nuestra variable tx_buf[256] de la siguiente
forma:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: 1pt solid windowtext; font-family: Verdana; font-size: 8pt; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// USART TX BUFFER </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> BUF_SIZE 256</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> udata buffer_maglev</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">static</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 array_1[BUF_SIZE];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;">#pragma</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> udata</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;">uint8
*tx_buf=&array_1[0];</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 tx_next=0; uint8
tx_sent=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// TX indexes</span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
Usando
#pragma udata reservamos un array del tamaño adecuado y le indicamos al
compilador que lo posicione en la sección buffer_maglev que hemos definido en
el fichero anterior. Luego apuntamos nuestro puntero tx_buf al inicio de dicho
array. A partir de entonces ya podemos usar tx_buf[k] en nuestro programa.<o:p></o:p></div>
<div class="MsoNormal" style="font-family: Verdana;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
Las líneas
siguientes inicializan los punteros que se moverán sobre el buffer. Recordad
que tx_next lo incrementaremos nosotros cuando pongamos datos en el buffer. El
puntero tx_sent lo incrementara la interrupción de TX cada vez que pase un
carácter al módulo USART para que lo envíe. El código de la ISR de la
interrupción será:<span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: 1pt solid windowtext; font-family: Verdana; font-size: 8pt; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// TX_isr gets called
when TX_flag is set. That means that the port is ready to tramsmit.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// If
tx_next==tx_sent, there is nothing to send and TX_INT is disabled.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// If tx_next!=tx_sent,
next byte in TX buffer is loaded in TXREG, and the </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// pointer is
incremented, making sure it remains within the [0,BUF_SIZE-1] range </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TX_isr(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{ </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (tx_sent==tx_next) disable_TX_int; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> { PORTCbits.RC5=1; TXREG=tx_buf[tx_sent++]; PORTCbits.RC5=0;
}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
Estos
buffers son circulares, por lo que al llegar al final los punteros tx_sent y
tx_next deberían pasar a 0. Como en este caso el tamaño de los buffers es de
256 bytes y ambos punteros son de tipo uint8, no tenemos que hacer nada especial
pues pasarán de forma natural a 0 al ser incrementados desde 255.<o:p></o:p></div>
<div class="MsoNormal" style="font-family: Verdana;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
Lo único
que queda respecto al puerto serie es inicializarlo (en el main) para una
comunicación a 57600 baudios:<span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div style="border: 1pt solid windowtext; font-family: Verdana; font-size: 8pt; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ...</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
USART setup (clock 8 MHz, BRGH=1, SP = 8) --> 57600 bauds</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_TX_INT_OFF&
USART_RX_INT_OFF & USART_ASYNCH_MODE & </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> USART_EIGHT_BIT &
USART_BRGH_HIGH , 8); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";">
...<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-family: Verdana; font-size: 8pt;">
<br /></div>
</div>
<div class="MsoNormal" style="font-family: Verdana;">
<div style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal">
<b>Configuración del ADC:<span style="font-size: xx-small;"><o:p></o:p></span></b></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">... </span><span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0 = 0b00000001;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> ADCON1 = 0b00001010;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> ADCON2 = 0b10010001; </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";">
...<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal">
Estas tres
líneas configuran los registros del ADC (ver <a href="http://picfernalia.blogspot.com.es/2012/07/conversor-adc.html" style="font-family: 'Times New Roman';">entrada sobre ADC</a>). Entre las opciones configuradas:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]-->Reloj
del ADC = Fosc/8, lo que me da una frecuencia de 1 MHz para un reloj de 8 MHz.
Esto corresponde a un Tad de 1 microsegundo, que resulta compaible con las
especificaciones del 4520 (Tad > 0.75 usec).<o:p></o:p></div>
<div class="MsoNormal" style="margin-left: 18pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]-->Programación
automática de un Tacq igual a 4 Tad = 4 usec, que es superior al recomendado de
unos 2-3 usecs.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span lang="PT-BR" style="font-family: Symbol; font-size: 8.0pt; mso-ansi-language: PT-BR; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]--><span lang="PT-BR">PORTA dedicado a entradas
analógicas.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]-->No
se van a usar voltajes de referencia distintos de 0 y 5V.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><!--[endif]-->Formato
a la derecha del resultado final en los registros ADRESH:ADRESL<span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-size: 8pt;">
<b>Configuración del PWM:<o:p></o:p></b></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal">
Usando la
función OpenPWM1 junto OpenTimer2 configuramos (también en el main) la
frecuencia del PWM:<span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ...</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// PWM setup (Fpwm = (Fosc/4)/(256) = 7.81250 KHz</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
TMR2 with </span><st1:time hour="1" minute="16"><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">1:16</span></st1:time><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">
POSTscaler --> Fservo = Fpwm/16 = 488 Hz</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenPWM1(255);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenTimer2(TIMER_INT_OFF & T2_POST_1_16
& T2_PS_1_1);<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";">
...<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal">
Configuraramos
PWM con PR2=255, PRE del TMR2=1 lo que nos da (<a href="http://picfernalia.blogspot.com.es/2012/06/modulacion-pwm-pulse-width-modulation.html" style="font-family: 'Times New Roman';">entrada PWM</a>) para un reloj
de 8 MHz una frecuencia de:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="font-size: 8pt;">
<span style="font-size: 8pt;"> </span><span lang="PT-BR" style="font-size: 8pt;">Fpwm =
(Fosc/4)/(PRE x (PR2+1)) = 7.8 KHz <o:p></o:p></span></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal">
Luego
necesitaremos un timer para tomar medidas cada cierto tiempo y actuar sobre la
bobina. Podríamos usar cualquier timer, pero aprovechamos que TMR2 está
corriendo (ya que es usado en la generación del PWM) para usar su interrupción
para programar la adquisición de datos del sensor. En la inicialización
anterior del TMR2 programamos un POSTscaler de 1:16 para que la interrupción
salte cada 16 rebosamientos. Esto corresponde a 16 veces el periodo del PWM o
2.048 msec. Aproximadamente tendremos una frecuencia de actuación (servo) de
unos 500 Hz, adecuada para nuestro proyecto.<o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Para
modificar el duty cicle de la onda PWM usaremos la siguiente función (o
alternativamente la del compilador C18)<span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Set duty cicle (10
bits) for PWM1 (RC2)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_pwm1(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> duty ) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP1CONbits.DC1B0=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP1CONbits.DC1B1=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">CCPR1L=duty;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
<div class="MsoNormal" style="font-size: 8pt;">
<br /></div>
</div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Interrupción Timer TMR2:<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código
de la interrupción del TMR2 es muy sencillo:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// TMR2 INT (every
2.048 msec with a 8 MHz clock)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Starts the sampling
500 times per second</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> timer2_int(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC4=1;;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">ADCON0 = 0b00000011; </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Canal 0 GO=1</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC4=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La 1ª y 3ª
línea modificando PORTC son simplemente un control para verificar con el
osciloscopio que todo esta funcionando correctamente y pueden ser eliminadas
sin problemas. El código es simplemente una línea donde seleccionamos el canal
(AN0 = RA0) y lanzamos el proceso de la conversión analógica digital.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Como el
tiempo de adquisición está programado no hay que preocuparse de nada: el PIC
esperará a que pase los 4 usec programados y lanzará la conversión. Una vez
lista se generará la interrupción del ADC, que es donde hacemos la mayor parte
del trabajo.</span></div>
<div class="MsoNormal">
<br />
<br />
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Interrupción ADC:<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Dentro de
la interrupción del ADC es donde se hace el trabajo principal. En ella se lee
la medida del sensor y junto con el historial de errores pasados se estima la
integral y derivada del error. A partir de ellas se calcula el parámetro de
control (duty cycle del PWM) usando un controlador PID y se modifica la señal
PWM que controla la bobina (a través del driver L293D).<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> h 16</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> MAX_DUTY 511</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> error_max 51</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> TOPE 3200 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//e_max*NPAST</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// ADC int: reads
sensor output and computes PID</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> adc_int(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint8 p;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint8 JUMP;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint16 res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> PORTCbits.RC4=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">res=ADRESH; res<<=8; res+=ADRESL; </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// sensor measurement</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// Current
error</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> error=(res-Kpid[0]);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">if</span><span style="font-family: 'Courier New'; font-size: 9pt;">
(error>=error_max) error=error_max; </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">else</span><span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 9.0pt;">if</span><span style="font-family: 'Courier New'; font-size: 9pt;">
(error<=-error_max) error=-error_max;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// Integral
error</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> error_int+=
(error-error_past[next]);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> ((error_int>=TOPE) ||
(error_int<=-TOPE)) L293_ENABLE=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> L293_ENABLE=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
EStimation of derivative of error</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">using f' = (3f(x) - 4f(x-h) + f(x-2h) )/(2h) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">JUMP=255-h; JUMP++;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> error_der = 3*error;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">p = next-h; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (p>=NPAST) p-=JUMP; error_der-=4*error_past[p];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> p = p-h;
</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">
(p>=NPAST) p-=JUMP; error_der+=error_past[p];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Substitute current value for oldest value in table</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> error_past[next]=error; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> next++; next &= (NPAST-1);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt;">// Computes PID factor </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> duty = (Kpid[1]*error) +
((Kpid[3]*error_der)/h)*4 + (error_int/Kpid[2]);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// Makes sure it is in the [-512,512] range </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (duty > MAX_DUTY) duty = MAX_DUTY; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> (duty <
-MAX_DUTY) duty = -MAX_DUTY;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//
Translate it to the [0 1023] range and use it to set duty cicle.</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> duty+=512; set_pwm1((uint16)duty);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> TERMINAL</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">#else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> create_send_msg(); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">//Creates and send a message with info </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="color: #b28c00; font-family: "Courier New"; font-size: 9.0pt;">#endif</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;"> PORTCbits.RC4=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"> </span><span style="font-family: Verdana; font-size: 8pt;"> </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Algunos
comentarios sobre el código anterior:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Los
datos del PID (objetivo + constantes Kp, Ki, Kd ) están guardados en un array
Kpid en el orden citado. La única peculiaridad es que para poder operar con
aritmética entera, trabajamos con el inverso de la variable Ki, de forma que al
sumar los términos del PID dividiremos (en lugar de multiplicar) por Ki. <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Tras
recoger los datos de ADRESH, ADRESL en la variable res, calculamos el error de
la medida respecto al objetivo o target, guardado en Kpid[0].<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Para
calcular el error integral mantenemos un "historico" de errores
pasados. En este caso usamos 64 valores antiguos en el array error_past[]. La
variable next indica la posición de la tabla conteniendo el error más antiguo.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->De
nuevo, para sumar el error integral, restamos el error más antiguo (que va a
ser eliminado) y sumamos el que acabamos de medir. A la suma resultante
deberíamos multiplicarla por dt (intervalo entre muestras = 0.002048 segundos)
para estimar la integral del error. Con objeto de evitar tener que usar
aritmética en coma flotante, dicha constante se encuentra integrada en la
constante Ki (entera) usada.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Si
el error instantáneo es mayor que un cierto valor (en este caso 50) se usa un
valor máximo. Esto nos sirve para evitar posibles problemas de desbordamiento
en la suma de los errores pasados. De todas formas se puede comprobar que
errores mayores que +/- 30 son irrecuperables por el sistema (nos hemos
apartado tanto del equilibrio que la bobina no puede volver a llevar al imán de
vuelta al punto de equilibrio). <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Si
el error integral es mayor (en valor absoluto) que un cierto umbral significa
que el imán se ha caido (o se ha pegado al electro) por lo que ponemos a cero
el pin definido en L293_ENABLE (RC0). Dicho pin está conectado al
correspondiente pin del L293D y detiene la actuación sobre la bobina. En caso
contrario ponemos a 1 dicho pin.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Estimamos
la derivada del error usando la fórmula: e(n) -
4e(n-h) + e(n-2h) , donde h es un salto en muestras (hemos usado un valor de h=16). Notad que para una correcta estimación
de la derivada del error deberíamos
dividir por (2*h*dt) donde dt es el intervalo de toma de datos (2.048 msec). De
nuevo, dichos términos están incluidos dentro de la constante Kd para evitar
operaciones en coma flotante.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]--><span style="font-family: Verdana, sans-serif;"><span style="font-family: Symbol; font-size: 8.0pt; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;">·
</span><!--[endif]-->Finalmente,
antes de pasar a calcular el parámetro PID de control, guardamos el último
error en la posición indicada (next) machacando la más antigua. El contador
next se incrementa. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Una vez
que disponemos del error instantáneo, error integral y derivada del error, los
combinamos usando las correspondientes constantes Kp=Kpid[1], Ki=1/Kpid[2] y Kd=Kpid[3],
obteniendo así el valor de control a usar (entre -511 y 511). Si nos pasamos de ese intervalo lo situamos en
el valor límite -511 o +511.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Sumándole
512 a dicha cantidad estamos listos para
usarla como duty cicle del PWM.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Finalmente,
tras concluir el proceso de control, mandamos un mensaje binario a través del puerto
serie con el error medido. Como comentamos en la
entrada anterior dicho mensaje contiene un contador para verificar la
integridad de los datos recibidos en el PC. Para ello usamos la función:</span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> create_send_msg(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> int8 e; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> uint8 *ptr;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> tx_buf[tx_next++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'A'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 'A', start of packet</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> e = (int8)error; tx_buf[tx_next++]=e; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// error (1 byte)</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> tx_buf[tx_next++]=msg_cont++; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// message counter</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> tx_buf[tx_next++]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">'Z'</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;">; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 9.0pt; mso-ansi-language: EN-GB;">// 'Z', end of packect</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 9pt;"> </span><span style="font-family: 'Courier New'; font-size: 9pt;">enable_TX_int;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 9pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">que escribe directamente sobre el buffer TX del puerto serie, incrementando el contador correspondiente. </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Previamente
se han declarado el array de errores pasados y las variables donde guardamos
los distintos tipos de error:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> L293_ENABLE PORTCbits.RC0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> NPAST 64</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">int16 error_past[NPAST];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 next=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">int16 error, error_der, error_int=0;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">int16 duty;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">int16 Kpid[4];</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> reset_Kpid
{Kpid[0]=410; Kpid[1]=30; Kpid[2]=50; Kpid[3]=5; Kpid[4]=16;}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Finalmente,
nos queda definir la ISR combinando las tres interrupciones usadas</span><span style="font-family: Verdana; font-size: 8.0pt;">:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Interruption
Service</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interruptlow high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TX_flag) {
TX_isr(); TX_flag=0; }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (AD_flag) {
adc_int(); AD_flag=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">; }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TMR2_flag) { timer2_int(); TMR2_flag=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">; }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Code @ 0x0008 ->
Jump to ISR for High priority interruption</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code_0x0008(</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {_asm </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">goto</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR _endasm}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt;">#pragma</span><span style="font-family: 'Courier New'; font-size: 8pt;"> code</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Con esto
ya tenemos descrito casi todo el código usado. En el main() además de las
configuraciones del ADC, PWM y USART comentadas debemos habilitar las correspondientes
interrupciones y declarar RA0 como entrada:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ...<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> reset_Kpid;
</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Reset PID to initial state</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> c=0; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(c<=NPAST) error_past[c++]=0 </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// past
errors = 0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ...</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> L293_ENABLE=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TRISB=0x0; PORTB=0; TRISC=0; PORTC=0;
TRISA = 0xFF; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// PORTA
input, PORTB,PORTC outputs</span><span lang="EN-GB" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: EN-GB;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ...<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_AD_int; enable_TMR2_int; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Enable AD & TMR2 INTs</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_global_ints; enable_perif_ints;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">while</span><span style="font-family: 'Courier New'; font-size: 8pt;">(1);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span style="font-family: Verdana; font-size: 8.0pt;">}<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<br /></div>
<div class="MsoNormal">
<b style="font-family: Verdana;"><u><span lang="PT-BR">Puesta en marcha:</span></u></b></div>
<div class="MsoNormal" style="font-family: Verdana;">
<br /></div>
<div class="separator" style="clear: both; font-family: Verdana; text-align: center;">
</div>
<div class="separator" style="clear: both; font-family: Verdana; text-align: justify;">
Lo primero es comprobar que la secuencia de muestreo/actuación/envío de información se cumple correctamente cada 2 msec (aprox). Como hemos
comentado, los pines RC4 y RC5 se usan para poder comprobar en el osciloscopio
que todo está funcionando correctamente. RC4 se alza mientras estamos
procesando la interrupción del TMR2 y la del ADC. RC5 lo alzamos cada vez que
la interrupción TX da salida a un byte hacia el módulo USART para ser
transmitido. </div>
<div class="separator" style="clear: both; font-family: Verdana; text-align: justify;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; font-family: Verdana; text-align: justify;">
<span style="text-align: left;">El
siguiente pantallazo del osciloscopio muestra la secuencia (RC4 en canal 1,
arriba, y RC5 en canal 2, abajo): </span><span style="text-align: center;"> </span></div>
<div class="separator" style="clear: both; font-family: Verdana; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; font-family: Verdana; text-align: center;">
</div>
<div class="MsoNormal" style="font-family: Verdana;">
<br /></div>
<br />
<div class="MsoNormal" style="font-family: Verdana;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE3CDUP26NvxtIKsa3k6cx3JqMDcfIKsxH4XFzRuiYuEWQxhRKFcC7uunQLa0LCRV6sXSsJGIPy7Pn1LXdoQaRtO1pVGsJb2WFwCoEO1sbcis6xTA4lqJPPoNatpaXJIrBww2FlnuZ/s1600/oscope2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE3CDUP26NvxtIKsa3k6cx3JqMDcfIKsxH4XFzRuiYuEWQxhRKFcC7uunQLa0LCRV6sXSsJGIPy7Pn1LXdoQaRtO1pVGsJb2WFwCoEO1sbcis6xTA4lqJPPoNatpaXJIrBww2FlnuZ/s1600/oscope2.jpg" /></a></div>
<br /></div>
<div class="MsoNormal" style="font-family: Verdana;">
<br /></div>
<br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
</div>
<div class="MsoNormal" style="font-family: Verdana; text-align: justify;">
Vemos que primero entra la interrupción del TMR2 lanzando el proceso del ADC. Es casi instantánea ya que solo tiene que escribir el valor del correspondiente registro ADCON. Al terminar la conversión AD viene la interrupción del ADC, que es la que más tiempo se demora, al tener que calcular los diferentes errores, combinarlos en el PID y fijar el duty cicle. Finalmente, (canal 2 abajo) una sucesión de picos nos indican la salida de los sucesivos bytes que componen cada mensaje que se envía al PC. Podemos comprobar que para la velocidad del puerto serie usada (57600) estamos bastante al límite de lo que podemos enviar antes de que se nos venga encima la siguiente toma de datos.<o:p></o:p></div>
<div>
<br /></div>
<div>
<br />
<br />
<b style="font-family: Verdana;"><u><span lang="PT-BR">Comunicación con el PC:</span></u></b></div>
<div>
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el
main() anterior terminábamos con un bucle while en vacío. Dicho programa
funcionaría, pero al igual que antes nos interesaría poder modificar los
parámetros del PID desde el PC. Por ello hemos incluido un simple chequeo del
puerto serie y en función del carácter recibido incrementamos/decrementamos las
constantes del PID o el objetivo. </span><span style="font-family: Verdana;">Esto es
especialmente importante en este caso, donde previsiblemente tendremos que
trastear un rato antes de conseguir hacer levitar el imán.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Hay implementadas dos formas de comunicación. Para habilitar la primera de ellas basta establecer el siguiente #define al principio del programa:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><span style="font-size: 11px;">#define TERMINAL</span></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En este caso se deshabilita el envio de información constante y se usa un protocolo sencillo que es fácil usar desde cualquier terminal serie. La apariencia de dicha interfaz es la siguiente:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8khoMxiP_tmlYakZAElCaU3sMYb8sK5Cl8o8STeOAQx6vlgfKWDcQkGRkiOYuKaN4a4db3muFMVvbYkC0POCg_InpNnJ7Lm6LRw4pqC77kKkpbCwPaw8pl3aLmfqwdonInrNc0Li5/s1600/menu_term.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh8khoMxiP_tmlYakZAElCaU3sMYb8sK5Cl8o8STeOAQx6vlgfKWDcQkGRkiOYuKaN4a4db3muFMVvbYkC0POCg_InpNnJ7Lm6LRw4pqC77kKkpbCwPaw8pl3aLmfqwdonInrNc0Li5/s1600/menu_term.jpg" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Usando '*' seleccionamos el parámetro (0,1,2,3) a modificar y lo incrementamos/decrementamos con +/-. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Con '0' reseteamos los valores de target y constantes a los valores iniciales. Cada vez que hay un cambio el PIC nos vuelca los nuevos valores y continuamene nos da información sobre los errores.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Esta interfaz es adecuada para calibrar el sistema si no disponemos o no deseamos usar MATLAB.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si comentamos el #define anterior usaremos una nueva interfaz que está pensada para ser usada con el correspondiente programa MATLAB para recoger y visualizar los datos.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El programa es maglev.m y tiene un funcionamiento similar a los ya vistos. Podemos abrir el puerto serie y si parseamos los mensajes veremos aparecer gráficas con los distintos errores. Dada las limitaciones comentadas antes sobre la capacidad de mandar datos de forma continua el PIC solo envía los datos de error instantáneo. Los errores integrales y derivada se obtienen dentro del programa de MATLAB con un cálculo análogo al usado dentro del PIC.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Disponemos también de un "teclado" de 12 pulsadores que nos permiten incrementar/decrementar o resetear el objetivo y cada una de las constantes del PID. Al pulsar una tecla se mandará un caracter al PIC y este modificará la correspondiente entrada del array Kpid[]. </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En este video final se ilustra el uso de la interfaz de MATLAB y las gráficas obtenidas, al mismo tiempo que podemos ver como levita el imán.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/LdqZrnu--1k?feature=player_embedded' frameborder='0'></iframe></div>
<br />
<br /></div>
<div class="MsoNormal">
<br /></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com31tag:blogger.com,1999:blog-4945680608471335280.post-89618927913914445912013-02-01T16:03:00.005+01:002013-06-07T17:57:16.638+02:00Controlador PID para posición de un motor DC<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En el tema
anterior construimos una gráficas mostrando la relación entre el input (% PWM)
aplicado y el resultado (velocidad) obtenido por el motor. Podríamos usar esa
información para controlar nuestro motor. Si queremos que gire con una cierta
velocidad, podríamos ver que entrada (PWM) precisamos y aplicarla. Sin embargo
ya comentamos que dicha relación cambia por numerosos factores, por lo que
nunca estaríamos seguros de alcanzar la velocidad deseada.</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Técnicamente
esta situación se conoce como un control de bucle abierto, al no tener un
feedback que nos informe de lo que realmente está haciendo el motor. De hecho
disponemos de dicho feedback (la info de los encoders en cuadratura) pero hasta
ahora no la estamos usando. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En esta
entrada vamos a "cerrar" el bucle, usando el feedback de que
disponemos para controlar la posición de un
motor. La entrada suministrada por el usuario no será un PWM (de efectos
inciertos) sino un objetivo en términos de la velocidad o posición deseada del
motor. El sistema, en función del feedback recibido, variará adecuadamente su
variable de control (en este caso el ciclo ON del PWM) para conseguir el
objetivo dado. Usaremos un sencillo controlador PID para la implementación.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Al igual
que en el tema anterior, acompañaremos al código en C del microcontrolador con
un programa en MATLAB para poder mostrar de forma gráfica los movimientos del motor.</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dzFLnM2mVd4Thp7EIIvI0kVM2wE0UJ1mSQtzSKg_ufOzoqbqkzM6Ttn44NGrmmWzQ0ih6tw8ipdPmfex_6UKg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br /></div>
<div class="MsoNormal">
<br /></div>
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;">Archivos de código asociado a esta entrada: </span><br />
<span style="font-family: Verdana, sans-serif; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/PID_pos.c">PID_pos.c</a>
<a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/monitor_PID.m">monitor_PID.m (MATLAB)</a></span><br />
<br />
<span style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"></span>
<br />
<a name='more'></a><br />
-----------------------------------------------------------------------------------------------------------<br />
<br />
<div class="MsoNormal">
<b><span style="font-family: Verdana, sans-serif;">Controlador PID de posición.<o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En
aplicaciones de control el primer paso es identificar la variable que queremos
controlar y la variable que podemos modificar. En un ejemplo típico, podríamos
querer controlar la temperatura de un acuario y para ello podemos actuar sobre
el tiempo que un calentador está encendido.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En nuestro
caso la variable a controlar será la posición del motor y la variable de
actuación será el duty del PWM. Esencialmente estamos interesados en convertir
nuestro motor DC en un servomotor, al que le podamos decir a que posición
queremos que vaya. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La idea de
cualquier sistema de control es poder calcular una discrepancia (error) entre
el objetivo (posición deseada, introducida por el usuario) y la realidad
(posición del motor obtenida a través de los encoders). Dicho error se usará
como feedback para modificar la variable de control (PWM en nuestro caso).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Un
controlador PID es un tipo de control muy usado en la práctica por su
sencillez, dado que no requiere una caracterización completa del sistema. Se
basa en combinar 3 términos (Proporcional, Integral y Diferencial) relacionados con el error con unas constantes
que se pueden determinar a través de un proceso de prueba y error. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En nuestro
caso, siendo Pref la posición deseada (target u objetivo) y siendo pos
(determinada por los encoders) la posición real del motor, definiremos el error
en un momento dado como</span></div>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: Verdana, sans-serif; margin-left: 1em; margin-right: 1em;"> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-PJKcMXxuaEecRAlxt6zMqw3cgMvVqqfMHz5bsZTHNVBPvSlHkYULC1avyNqYsg0ZM5HSfpIv4vtAOl3Jycpg7xBY6k263RUTcA9UZndE5vwuvlBfzSLotzhU34Z3Jo5dxjPTnQS_/s1600/formula1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-PJKcMXxuaEecRAlxt6zMqw3cgMvVqqfMHz5bsZTHNVBPvSlHkYULC1avyNqYsg0ZM5HSfpIv4vtAOl3Jycpg7xBY6k263RUTcA9UZndE5vwuvlBfzSLotzhU34Z3Jo5dxjPTnQS_/s1600/formula1.png" /></a></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">A partir
de este error, modificaremos nuestra variable de actuación en base a la
siguiente expresión:</span></div>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp2JaUb9OKkP4ivmA3Y3d74122dzpcSC-07tKp7mgE9_pROACoaUoAoDetQhzeiGqLdz_DwhN1yEk6zr65ALPiE6deY6mZnSQYrcmRP7eICoI6YS4Ca8GerSAoehaC6jfJI6ZYRrvs/s1600/formula2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp2JaUb9OKkP4ivmA3Y3d74122dzpcSC-07tKp7mgE9_pROACoaUoAoDetQhzeiGqLdz_DwhN1yEk6zr65ALPiE6deY6mZnSQYrcmRP7eICoI6YS4Ca8GerSAoehaC6jfJI6ZYRrvs/s1600/formula2.png" /></span></a></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Por el
momento podemos considerar que pid es simplemente un valor que, en caso de ser
positivo, indica que el motor debe girar hacia delante y si es negativo, hacia
atrás. Nosotros nos ocuparíamos de convertirlo a un valor p.e. entre 0 y 1023
como vimos en el tema anterior para aplicarlo al PWM (o entre -1023 y 1023 si
usamos el montaje A).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En la
fórmula, el primer término es proporcional al error, el segundo proporcional a
su integral y el tercero va con su derivada.
<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La idea es
que el primer término trata de reducir el error actual. Si el error es positivo
(no hemos llegado a Pref), pid es positivo, por lo que aumenta la posición y se
reduce el error. Si el error es negativo (nos hemos pasado), se invierte el
duty y nos movemos en sentido contrario, acercándonos de nuevo al objetivo. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">El segundo
término refleja la influencia del "pasado" del error: nuestra
actuación no será la misma si puntualmente tenemos un cierto error que si llevamos un "rato" largo con
dicho error. En el segundo caso la actuación será más enérgica.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Finalmente
el tercer término refleja el "futuro" del error (su tendencia,
capturada en su derivada). Imaginad que estamos a 5 unidades de nuestra
posición deseada, o lo que es lo mismo, tenemos un error e=5. No es lo mismo si
nos estamos acercando al objetivo (se está reduciendo el error, derivada
negativa) que si nos estamos alejando (derivada positiva, el error está
aumentando). En el primer caso a lo mejor no hay que hacer casi nada (la propia
inercia del movimiento nos lleva al objetivo, mientras que en el otro caso está
claro que hay que corregir la situación.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En nuestro
caso en vez del continuo antes descrito tendremos una implementación discreta.
Cada cierto tiempo (en la rutina del servo de la que hemos hablado en temas
anteriores) se mide la posición actual (encoders) y se calcula un término de
error:</span></div>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1qcbYOjovKs102cH6gl_KZit-CjV7MWOvOSE_tpFfCmSe3RF90zqz6cb_Jyl6-2V-Z5jdWdCQN_Gkzzelf2uSqlajQI4CtTPGYjpGit9QrlZInVTawtRJ2uQJPMDX96mO76Taw8Gv/s1600/formula3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1qcbYOjovKs102cH6gl_KZit-CjV7MWOvOSE_tpFfCmSe3RF90zqz6cb_Jyl6-2V-Z5jdWdCQN_Gkzzelf2uSqlajQI4CtTPGYjpGit9QrlZInVTawtRJ2uQJPMDX96mO76Taw8Gv/s1600/formula3.png" /></span></a></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Para
calcular el término de control, el error instantáneo se traduce de forma
natural en el error medido en el instante n, pero para la parte integral y
derivativa tendremos que hacer aproximaciones numéricas:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">La integral se substituye por una suma de valores anteriores del error. Además se
limita en el tiempo, sumando los últimos N errores, en vez del historial
completo de errores. Formalmente tendríamos que añadir un término h (el
intervalo de tiempo entre muestras) pero dicho término (constante) puede ser
absorbido por la constante de integración Ki.</span></li>
<li><span style="font-family: Verdana, sans-serif;">En
cuanto a la estimación numérica de la derivada, lo más inmediato es
substituirla por la diferencia entre errores sucesivos, aunque pueden usarse
estimaciones más exactas. De nuevo, el factor h que aparece puede entrar dentro
de la constante Kd, por lo que no es necesario introducirlo explícitamente: </span></li>
</ul>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: Verdana, sans-serif; margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIiFy5TXnGa55OLyKZFT7qGCHR691BRgAyU888n8f5D1ztHDSDoeqMrb3qc5CPM385tQgWL6KtMmGnUwbOC1afej8YrUheRTp1Rl3-Gbck-Nf3-QmvZvRos_wkIAts89tSMut-_HzY/s1600/formula4.png" /></span></div>
<div class="separator" style="clear: both; text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En su
variante discreta el término de control a calcular para actuar sobre el PWM del
motor será por tanto:</span></div>
<div class="MsoNormal">
</div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS8vBtGC7zFlQNWLlINLoMM0MVjGW7IjNztAR-ccjUi-XN4HsQftDCVpfis5ZSipiJ0DfNHc4fV5kSZ5fc6NXEjSLAVdHgsg8DwoFBVWqVEMtRNF5gZuoAISfERk5GcIigW3QRfJ_B/s1600/formula5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhS8vBtGC7zFlQNWLlINLoMM0MVjGW7IjNztAR-ccjUi-XN4HsQftDCVpfis5ZSipiJ0DfNHc4fV5kSZ5fc6NXEjSLAVdHgsg8DwoFBVWqVEMtRNF5gZuoAISfERk5GcIigW3QRfJ_B/s1600/formula5.png" /></span></a></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Indicar por
último que no es necesario que la frecuencia de toma de medidas sea la misma
que la frecuencia de actuación del servo. Es posible, p.e. tomar medidas con
una frecuencia de 100 Hz pero solo actuar sobre el motor 20 veces por segundo
(20 Hz). En estos ejemplos por simplicidad usaremos la misma frecuencia para ambos,
por lo que tras tomar cada medida, calcularemos el término de control y
modificaremos el ciclo ON del PWM.</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana, sans-serif;"><u>Implementación (PID_pos.c)</u><o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Pasemos a la implementación. La mayor parte del código
ya la hemos visto en las entradas anteriores. </span><span style="font-family: Verdana, sans-serif;">Por ejemplo, la parte de la interrupción de
alta prioridad INT0 para contar los pulsos de los encoders es la misma, así
como el uso de la interrupción del TMR2 para la rutina del servo.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La diferencia
es que la rutina del servo antes sólo actualizaba la posición del motor (a
partir de la lectura de los encoders). Ahora, a partir de dicha posición y del
objetivo fijado tendremos que calcular el término de actuación anterior
(pid) y traducirlo a nuestro esquema particular. Por ejemplo, un pid = 0 indica
que todo esta bien y no hay que hacer nada. Eso equivale a ordenar un PWM de
512 (50%) si hemos elegido un montaje de tipo B (ver entrada anterior).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Veamos con
más detalle los añadidos a la rutina del servo (interrupción TMR2) <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (TMR2_flag)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> cont_servo++;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> ((cont_servo&0x0F)==0)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> temp=quad; vel=temp-last_quad; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//
delta = delta counter</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> last_quad=temp; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (vel>128) vel-=256; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// correct for rollover</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: 'Courier New';">else</span><span style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: 'Courier New';">if</span><span style="font-family: 'Courier New';"> (vel<-128) vel+=256; </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> pos=pos+vel; </span><span style="color: forestgreen; font-family: 'Courier New';">//
increment position </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';"> </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> error=Pref-pos; </span><span style="color: forestgreen; font-family: 'Courier New';">// Current error</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (err_idx==0) last=past[NPAST-1]; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';">
last=past[err_idx-1];</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">error_der = (error - last); </span><span style="font-family: 'Courier New';"><o:p></o:p></span><span style="color: forestgreen; font-family: 'Courier New';">// Derivative error</span></div>
<br />
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="color: forestgreen; font-family: 'Courier New';">// Acumulated error</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">
error_int-=past[err_idx]; error_int+=error;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> past[err_idx]=error;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> err_idx++;
err_idx&=(NPAST-1);</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';">compute_pid(); </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span><span style="color: forestgreen; font-family: 'Courier New';">// combine PID terms</span></div>
<br />
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> create_msg();</span><span style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">send_msg(msg,12); </span><span style="color: forestgreen; font-family: 'Courier New';">// Send data through serial port</span></div>
<br />
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> TMR2_flag=0; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">return</span><span lang="EN-GB" style="font-family: 'Courier New';">;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">}</span></div>
</div>
<br />
<br />
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La primera
parte es idéntica a la que ya conocemos. La rutina del servo se ejecuta cada
cierto número de interrupciones (en este caso, 16, que junto con un POSTscaler
de 16 para TMR2 nos da una frecuencia de unos 75 Hz para el servo). Para ello
usamos el contador cont_servo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La parte
de calcular el incremento de posición es también idéntica. Corregimos posibles rollovers de la variable quad e incrementamos la posición. A partir de aquí empezamos a hacer cosas nuevas.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">A partir
de un objetivo establecido para la posición (Pref) se calcula:</span></div>
</div>
<div class="MsoNormal">
</div>
<ul>
<li style="text-align: justify;"><span style="font-family: Verdana;">Error instantáneo (error) para la posición de ese
momento (error instantáneo).</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">Estimación de la derivada del error (error_der) restando errores sucesivos.</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">Error integral acumulado (error_int).</span></li>
</ul>
<div style="text-align: justify;">
<span style="font-family: Verdana;">Para el cálculo del error integral o acumulado se guardan
los NPAST últimos errores en un buffer circular donde van siendo machacados según
llegan datos nuevos. El error integral es simplemente la suma de los contenidos del buffer en un momento dado. Para optimizar su cálculo, lo que
hacemos es restar de la suma total el error más antiguo (antes de machacarlo) y
sumar el nuevo error (que machaca al más antiguo).</span><span style="font-family: Verdana;"> </span><span style="font-family: Verdana;">Así evitamos tener que hacer una suma de todos los datos cada vez. Tanto el buffer como su suma total se inicializan a 0 al
empezar.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"> <o:p></o:p></span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> </span><span style="color: forestgreen; font-family: 'Courier New';">// Error
integral</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">
error_int-=past[err_idx]; error_int+=error;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> past[err_idx]=error;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> err_idx++;
err_idx&=(NPAST-1);</span><span style="font-family: "Courier New"; font-size: 7.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Tras
almacenar el error más reciente se incrementa el cursor (err_idx) del buffer
circular de antiguos errores (past). En este ejemplo estamos usando un tamaño
NPAST=32 para el buffer del "pasado". Aproximadamente conservamos
algo menos de ½ segundo (32 muestras a 75 Hz) en nuestro buffer.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Finalmente,
una vez conocidos el error instantáneo, error integral (suma del buffer del
pasado) y error derivativo tenemos todo lo
necesario para saber como actuar. La rutina compute_pid() hace exactamente eso:
combina los valores de los tres términos con las tres constantes (guardadas en
un array K global), obtiene el término de control y lo convierte a un valor del
"duty cicle" del PWM que programamos en el correspondiente registro
del PIC: <span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> compute_pid(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">float</span><span lang="EN-GB" style="font-family: 'Courier New';"> ee,ed,ei;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">float</span><span lang="EN-GB" style="font-family: 'Courier New';"> pid;<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">ee = error; </span><span style="color: forestgreen; font-family: 'Courier New';">// Current error</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> ed = error_der; </span><span style="color: forestgreen; font-family: 'Courier New';">// Derivative error</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';">ei= error_int/NPAST; </span><span style="color: forestgreen; font-family: 'Courier New';">// Integral error</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> pid = K[0]*ee + K[1]*ei + K[2]*ed;<span style="color: forestgreen;"> // P,I,D terms</span></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';"> if</span><span lang="EN-GB" style="font-family: 'Courier New';">
(pid>=1.0) pid=1.0; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pid<=-1.0) pid=-1.0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//
pid in -1..1</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> pid =512+500*pid; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> set_pwm1((uint16)pid);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">return</span><span lang="EN-GB" style="font-family: 'Courier New';">;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">}</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 7.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">De nuevo
podemos elegir entre las distintas opciones discutidas en el tema anterior
sobre como conectar las líneas de control al driver del motor. Como hemos usado
el motor Maxon GM-20 para las pruebas hemos optado por el montaje (B) que
mostraba un comportamiento muy lineal entre PWM y velocidad. Por lo tanto el valor de control, entre -1 y
1 se translada al intervalo [0, 1023], de forma que un valor de control 0 vaya
a parar a 512 (50% PWM), que corresponde a mantener el motor en reposo
(nominalmente).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como vimos
en el tema anterior diferentes combinaciones de motores/drivers pueden mostrar
peculiaridades propias </span><span style="font-family: Verdana;">que hagan
necesarias algunas correcciones a la traducción entre variable de control
(-1,1) y PWM. Por ejemplo, para esta combinación de driver L293D y motor GM20
detectamos una pequeña zona muerta ("deadband") en la zona entre
PWM=500 y 520. Podríamos compensarla en "software" de la siguiente
forma:</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> pid=pid*500; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pid>0) pid+=520; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (pid<0) pid+=500; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> pid=512;</span><span lang="EN-GB" style="font-family: "Courier New"; font-size: 7.0pt; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">De esta
forma, el mínimo PWM que se adjudica a un pid no nulo es de 520, lo que asegura
que el motor se moverá algo. De la otra forma un error pequeño podría darnos un
PWM de p.e. 515. Dicho PWM, aunque nominalmente debería mover el motor, en la
práctica no tiene ningún efecto, por lo que el error no se reduciría.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Finalmente,
al final del proceso vemos un par de rutinas create_msg y send_msg(). Lo que
hacen estas rutinas es construir un pequeño paquete con los datos más
relevantes y enviarlo por el puerto serie. El paquete usado sigue el esquema
explicado en el tema anterior: empieza con el carácter 'A', sigue con unos
cuantos datos (posición, velocidad, objetivo y PWM duty) y termina con un
contador de mensajes y el carácter 'Z' cerrando el paquete.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> create_msg(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> int16 temp;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k,*ptr;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> msg[0]=</span><span lang="EN-GB" style="color: #ff40ff; font-family: 'Courier New';">'A'</span><span lang="EN-GB" style="font-family: 'Courier New';">; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> ptr=(uint8*)&pos; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<4;k++) msg[k+1]=ptr[k]; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> msg[5]=vel;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> temp=(int16)Pref;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> ptr=(uint8*)&temp; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<2;k++)
msg[k+6]=ptr[k]; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> ptr=(uint8*)&duty; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<2;k++)
msg[k+8]=ptr[k]; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">msg[10]=msg_cont; msg_cont++;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';"> msg[11]=</span><span style="color: #ff40ff; font-family: 'Courier New';">'Z'</span><span style="font-family: 'Courier New';">;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> send_msg(uint8* msg,uint8 n)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 k;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">for</span><span lang="EN-GB" style="font-family: 'Courier New';">(k=0;k<n;k++) { tx_buf[tx_next]=msg[k];
inc(tx_next);}</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">enable_TX_int;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; font-size: 7.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Tras crear
el paquete la segunda rutina lo manda por el puerto serie. Como aquí podríamos
estar mandando un volumen grande de datos hemos usado el enfoque de transmisión
de datos a través de la UART usando un buffer de transmisión e interrupciones.
Por lo tanto la segunda rutina no hace más que copiar los bytes del mensaje al
buffer de salida y activar la interrupción TX. El código de dicha interrupción
irá vaciando dicho buffer. En previsión de si aumentamos el número de datos o
la frecuencia con la que los mandamos configuraremos el puerto serie a 115200
baudios.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;"><u>Interfaz con el usuario</u><o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Para
comprobar nuestro código de control podríamos haber hecho algo similar a lo que hicimos para el caso de variar el PWM: implementar un sencillo menú donde, a través del puerto serie, el usuario pudiera dar ordenes
del tipo de: ve a la posición 2000, vuelve a la posición 0, etc.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Sin
embargo, como se trata de un programa ilustrativo, y nuestro objetivo en este entrada es entender un poco mejor como funciona un controlador PID, lo que he hecho es que el
usuario puede modificar las constantes Kp, Kd y Ki desde el PC (a través del
programa de MATLAB monitor_PID), de forma que pueda tener una idea del proceso de ajustar los parámetros de un PID.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Dentro del programa en el microcontrolador, </span><span style="font-family: Verdana;"> partimos de un objetivo Pref=0 como "target" para la posición. Cada cierto tiempo (2/3 segundos), dicho objetivo cambia, alternando entre
0 y 500 (500 ticks con este motor en modo 2X corresponden aproximadamente a 1/4 de vuelta) . En un principio las tres constantes Kp, Ki y Kd están a 0, por lo que a pesar de los posibles errores no estamos actuando sobre el motor. </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">A través de los botones de la GUI de MATLAB
podemos subir, bajar o resetear dichas constantes. Así podemos explorar el
efecto de los diferentes términos de un controlador PID en un problema sencillo
pero realista.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
siguiente screencast muestra el manejo de la interfaz de MATLAB y el ajuste de
las constantes del PID hasta obtener un resultado aceptable. Remarcar que no
siempre es necesario usar los tres términos del PID. En este caso, p.e.
obtenemos un buen resultado sólo con la parte proporcional y derivativa. <span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span>
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dx7zPKLtHcex0exoL-GJNLLa_dMWsn_ST4ACuOZ3VBaxbRWbl7q-jNJOBFnEyUUSEhUV8mHel40jciRS74Rwg' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br /></div>
<br />
<br />
<br />
<br />
<br />
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
<span style="font-family: Verdana; font-size: 11.0pt; mso-ansi-language: ES; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-fareast-font-family: "Times New Roman"; mso-fareast-language: ES;"><span style="mso-text-raise: -7.0pt; position: relative; top: 7.0pt;"><!--[if gte vml 1]><v:shapetype id="_x0000_t75"
coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe"
filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:86.25pt;
height:18.75pt' o:ole="">
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image001.wmz"
o:title=""/>
</v:shape><![endif]--><!--[if !vml]--><img height="200" src="file:///C:/DOCUME~1/antonio/CONFIG~1/Temp/msohtml1/01/clip_image002.gif" v:shapes="_x0000_i1025" width="0" /><!--[endif]--></span><!--[if gte mso 9]><xml>
<o:OLEObject Type="Embed" ProgID="Equation.3" ShapeID="_x0000_i1025"
DrawAspect="Content" ObjectID="_1421224550">
</o:OLEObject>
</xml><![endif]--></span>Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com34tag:blogger.com,1999:blog-4945680608471335280.post-54550527582862315062013-02-01T15:53:00.001+01:002013-06-07T18:07:54.058+02:00Manejo de motores DC usando PWM <div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En este tema usaremos nuestros conocimientos del PWM del PIC para guiar un motor de
corriente continua (DC). </span><span style="font-family: Verdana, sans-serif;">En esta
primera entrada simplemente aplicaremos un PWM con un duty variable al motor y
observaremos su respuesta (velocidad) usando los codificadores en
cuadratura explicados en la entrada anterior.</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Obviamente
el PIC no puede proporcionar la intensidad necesaria para mover un motor, por lo que necesitaremos algún tipo de driver o interfaz. Para poder manejarlo en las dos
direcciones usaremos un driver configurado como un puente en H (H-bridge).
Describiremos el popular integrado (aunque no especialmente eficaz) L293D. Otras
alternativas basadas en MOSFETs son más eficientes, pero el concepto y la forma
de controlar el MOTOR serán comunes.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Ficheros de código asociados a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/quad_pwm.c">quad_pwm.c</a> , <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/auto_pwm.c">auto_pwm.c</a> , <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/auto_pwm.m">auto_pwm.m</a></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"></span></div>
<a name='more'></a><br />
---------------------------------------------------------------------------------------------------------<br />
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<b><span style="font-family: Verdana, sans-serif;">Interfaz con el motor: L293 H-bridge
<o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las dos
funciones que nos interesan en nuestro driver son:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal"><span style="font-family: Verdana, sans-serif;">Capacidad para traducir
nuestras señales digitales (del microcontrolador) a corrientes de mayor
intensidad y (posiblemente) voltajes mayores.<b><o:p></o:p></b></span></li>
<li class="MsoNormal"><span style="font-family: Verdana, sans-serif;">Capacidad de invertir el
sentido de la corriente a través del motor para hacerlo girar en ambas
direcciones.</span></li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhli66APagertpIPowVrkE1Rb3_7PlbGKHKBb2JQZ91UZ0i5JqxNhgGQYq-EImjcWhQHgSTQnPLKlvbhSN7gURCT8KLh05OhTQh4Ccvsggo20vYRoFitgxvQjwirloj_B2C33SOITbo/s1600/basic-bridge.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhli66APagertpIPowVrkE1Rb3_7PlbGKHKBb2JQZ91UZ0i5JqxNhgGQYq-EImjcWhQHgSTQnPLKlvbhSN7gURCT8KLh05OhTQh4Ccvsggo20vYRoFitgxvQjwirloj_B2C33SOITbo/s200/basic-bridge.jpg" width="200" /></span></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">La
configuración que necesitamos es conocida como un puente en H (H-bridge),
reflejada en la figura de la derecha (dicha figura la he sacado de <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: left;">
<span style="font-family: Verdana, sans-serif;"><a href="http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html">http://www.mcmanis.com/chuck/robotics/tutorial/h-bridge/index.html</a>,
donde también se puede encontrar una buena explicación más detallada sobre como
funciona un puente en H.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: left;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: left;">
<span style="font-family: Verdana, sans-serif;">Vemos como
cerrando dos interruptores (arriba-izquierda + abajo-derecha) la corriente
fluye en una dirección. Si cerramos (arriba-derecha + abajo-izquierda) se causa
un cambio en el sentido de la corriente. Si se cierran los interruptores de arriba o
abajo tenemos un freno del motor. Con todo abierto el motor gira libremente. Obviamente
podemos tener un problema gordo (cortocircuito) si cerramos ambos interruptores
en un lado. Un puente H encierra una estructura de este estilo pero protegida
para evitar las opciones "desafortunadas".<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shape id="_x0000_s1026" type="#_x0000_t75"
style='position:absolute;margin-left:264.6pt;margin-top:8.1pt;width:210.5pt;
height:101pt;z-index:1'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image003.png"
o:title=""/>
<w:wrap type="square"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnOVAmq16JJklzMd_u2RmGPH72doPtKsZ7KavqX9tkbqAuOreH1I2iu3G-6eb86iKo0GVCylQrdrnhOiTQZ1MDPNUiNuC1JaEZQce__EQKpA4GcrmicMy6YEk3W_-kfkd2YeKUYPjP/s1600/L293.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnOVAmq16JJklzMd_u2RmGPH72doPtKsZ7KavqX9tkbqAuOreH1I2iu3G-6eb86iKo0GVCylQrdrnhOiTQZ1MDPNUiNuC1JaEZQce__EQKpA4GcrmicMy6YEk3W_-kfkd2YeKUYPjP/s320/L293.jpg" width="320" /></span></a><span style="font-family: Verdana, sans-serif;"></span><br />
<span style="font-family: Verdana, sans-serif;"><span style="font-family: Verdana, sans-serif;">Un integrado muy popular para un H-bridge es el L293 (o su variante
L293D). Su esquema está en la figura adjunta (todas las figuras sacadas de su
datasheet). </span>El
integrado dispone de 2 alimentaciones separadas:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
</div>
<div class="MsoNormal">
<br />
<ul>
<li><span style="font-family: Verdana, sans-serif;">Vcc1 (pin 16) --> </span><span style="font-family: Verdana, sans-serif;">voltaje lógico
(p.e. 5 o 3.3V)</span></li>
<li><span style="font-family: Verdana, sans-serif;">Vcc2 (pin 8) --></span><span style="font-family: Verdana, sans-serif;"> voltaje motor Vm (hasta 36 V)</span></li>
</ul>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">El resto
del integrado está dividido en 2 bloques funcionalmente equivalentes. Cada uno
de ellos (situados a cada lado del L293) es un H-bridge completo. Por
ejemplo, en la rama de la izquierda disponemos de:</span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt; text-indent: -18.0pt;">
</div>
<ul>
<li style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span style="text-indent: -18pt;">Pin
ENABLE : interruptor apagado/encendido (pin 1,2 EN)</span></span></li>
<li style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><span lang="EN-GB" style="text-indent: -18pt;">2 Entradas IN1, IN2 (pines 1A,2A)</span></span></li>
<li style="text-align: justify;"><span style="font-family: Verdana, sans-serif;">2 Salidas: OUT1, OUT2 (pines 1Y, 2Y).</span></li>
</ul>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Un nivel
alto/bajo (respecto al voltaje de la lógica) en las entradas IN1, IN2 se
traduce en un nivel alto/bajo de las salidas OUT1,OUT2 (pero en voltaje motor
Vm y con mucha mayor capacidad de
corriente). Cada rama puede dar unos 0.75A de forma continuada y picos de hasta
1A.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Al tener 2
puentes H completos, con un L293 podemos controlar 2 motores DC bidireccionales
o 4 motores DC unidireccionales. La figura adjunta (datasheet)
refleja el montaje con 1 motor bidireccional en el H-bridge izquierdo y 2
unidireccionales en el derecho:</span></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKHpSdOq9EZsHWEqZRaVH4jMJqNZXN9m8uKVU3GarFHkvTBvdGbY4qg1Go-hg33s69ksZPecsJLjsmqkCml1C1OWP4crXB76A978meKjVoYWkcgWjWooyUHdW38Jc18-fUd0mFAAfy/s1600/datasheet_conexiones.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKHpSdOq9EZsHWEqZRaVH4jMJqNZXN9m8uKVU3GarFHkvTBvdGbY4qg1Go-hg33s69ksZPecsJLjsmqkCml1C1OWP4crXB76A978meKjVoYWkcgWjWooyUHdW38Jc18-fUd0mFAAfy/s400/datasheet_conexiones.jpg" width="400" /></span></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Es este
ejemplo usaremos la configuración de la izquierda para controlar un motor
bidireccional. Los diodos son necesarios al manejar cargas inductivas (bobinas
o motores) para evitar los picos de corriente inducidas al cortar bruscamente
la corriente a la carga. En el L293D pueden ser obviados al disponer de diodos
internos (aunque algunos recomiendan no fiarse demasiado de esos diodos
internos y usar siempre los diodos externos, por si las moscas). Yo no los he usado en mi montaje (con un L293D) pero tengo que especificar que mis conocimientos de electrónica son casi nulos.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Para el manejo de un motor bidireccional conectaremos los bornes del motor a las salidas OUT1 y OUT2. Disponemos de 3 entradas digitales para controlar el motor:</span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> ENABLE
(pin 1), IN1 (pin 2) e IN2 (pin 3)</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Una configuración típica de control es poner p.e. un 1
lógico en IN1 y un 0 lógico en IN2. Esto provoca un voltaje de Vm en OUT1
(pin3) y 0 en OUT2 (pin6), lo que hace que el motor gire en una dirección. Si
invertimos las entradas (IN1=0, IN2=1) tendremos 0V en OUT1 y Vm en OUT2,
invirtiendo el sentido del giro. Finalmente, si ambas entradas están al mismo
valor (1/1) o (0/0) tendremos una rápida
frenada.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Todo esto
con ENABLE (pin1) a un valor alto (1 lógico), es decir, con el puente activado.
Si hacemos ENABLE=0 sería como desconectar el puente y estaremos en una
configuración de giro libre del motor.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Mientras
que la conexión al motor es siempre a través de las dos salidas OUT1 y OUT2,
tenemos dos formas posibles de regular la velocidad/sentido del motor usando la
señal PWM generada por el microcontrolador, según como conectemos las tres líneas de control (ENABLE, IN1, IN2):<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4Fv45L9FvhdogjdNYdU6q_ucZ70MRBQvf5fYBwbDKXvbWR0S_I__5SORaBgAwRY3hAHse6PqQSbC5RlI2_aRtnP5rhDr5rPfKReJGD5H2tuyHY21a8rfdSJzQrBT1QAZEBPPvDSxc/s1600/esquema_3.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4Fv45L9FvhdogjdNYdU6q_ucZ70MRBQvf5fYBwbDKXvbWR0S_I__5SORaBgAwRY3hAHse6PqQSbC5RlI2_aRtnP5rhDr5rPfKReJGD5H2tuyHY21a8rfdSJzQrBT1QAZEBPPvDSxc/s320/esquema_3.jpg" width="320" /></span></a><br />
<span style="font-family: Verdana, sans-serif;"><b>Opción A)</b> Meter PWM en ENABLE y manejar IN1, IN2 con dos pines
digitales para seleccionar la dirección de giro.
El % en ON de la señal PWM establece la fracción de tiempo en la que el
puente está dando corriente al motor y por lo tanto determina la velocidad del
mismo. Seria equivalente a pedalear un rato y dejarse ir otro. Si estamos
pedaleando todo el rato (PWM duty = 100%) iremos al máximo. Si damos 1 pedalada
y descansamos 9 (PWM = 10%) iremos mucho más lentos. La dirección (signo) se
especifica de forma independiente a través de IN1,IN2. Puede usarse un solo pin conectado a IN1 y
mandar la señal invertida a IN2. Precisaríamos un mínimo de 2 líneas de control.</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7rGvyPexsFQFLMS5zOurh_CNchATrdfm9X-1896YBjwtkAI6Akj0Pf_5tqlRhf0qPJrslffE-yzcwLw8NrrSyXHm2207es-JbT6LYaDq5TkYFSvHLrx6P3aY_lkVLQfYR0ZeRTecQ/s1600/esquema_2.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7rGvyPexsFQFLMS5zOurh_CNchATrdfm9X-1896YBjwtkAI6Akj0Pf_5tqlRhf0qPJrslffE-yzcwLw8NrrSyXHm2207es-JbT6LYaDq5TkYFSvHLrx6P3aY_lkVLQfYR0ZeRTecQ/s320/esquema_2.jpg" width="320" /></a><b style="font-family: Verdana, sans-serif;">Opcion B)</b><span style="font-family: Verdana, sans-serif;"> Una alternativa, para reducir las líneas de control
necesarias sería poner ENABLE permanentemente a 1 (puente siempre activo) y
mandar la señal PWM a IN1. A IN2 mandamos la señal PWM invertida. En ese caso
un PWM con un 50% ON corresponde a mantener el motor en reposo, ya que la mitad
del tiempo estamos empujando para un lado y la otra mitad, para el otro. Un PWM con 0% ON significa máxima velocidad en
una dirección y un 100% máxima velocidad en el otro sentido. </span><br />
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7rGvyPexsFQFLMS5zOurh_CNchATrdfm9X-1896YBjwtkAI6Akj0Pf_5tqlRhf0qPJrslffE-yzcwLw8NrrSyXHm2207es-JbT6LYaDq5TkYFSvHLrx6P3aY_lkVLQfYR0ZeRTecQ/s1600/esquema_2.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"></span></a></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">De esta forma lo que estamos haciendo es manejar signo y magnitud en la
misma línea.<b> </b>Para conseguir la señal PWM
invertida podemos usar un simple inversor (por ejemplo con un transistor). </span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En aquellos PICs con un módulo PWM mejorado (EPWM)
podríamos configurar el módulo PWM para que además de generar una señal, cree
la complementaria en otro pin. Por ejemplo la complementaria de RC2 aparece en
RD5. Esta opción tiene la ventaja de no requerir hardware externo y poder
ademas programar tiempos muertos entre subidas y bajadas, lo que puede ser una
necesidad para ciertos drivers.</span></div>
</div>
<div>
<div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Aunque los
PIC 4520 disponen de un módulo EPWM, en nuestros ejemplos vamos a usar un
inversor externo, para que el código sea aplicable a otros dispositivos que
carezcan de un módulo mejorado. Además así solo precisamos 1 línea para
controlar un motor bidireccional (el ENABLE correspondiente lo mantendremos fijo
a 1, 5V en nuestro caso):</span></div>
</div>
<div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif; text-align: center;">Tal como
hemos dibujado el esquema, en la opción B, ENABLE está siempre a 1. También
podríamos conectarlo a un pin del PIC y usarlo como un "embrague". Si
lo ponemos a 0, el puente estará desconectado y por lo tanto,
independientemente de lo que hagamos con el PWM, el motor estará en una
posición de giro libre.</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Desde el
punto de vista del software, en ambos casos debemos activar el módulo PWM. Estoy usando un oscilador de 20 MHz, por lo que usaré PR2=255 y PRE = 1 para una frecuencia de PWM
de unos 19 KHz. Esto nos permite contar con 10 bits para especificar el ciclo
de trabajo, un valor entre 0 y 1023. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<ol>
<li><span style="font-family: Verdana, sans-serif;">Si usamos
el montaje A) un PWM de 0 indica parado y 1023 máxima velocidad. El signo
(dirección de giro) se controlará independientemente con el valor de otro pin
(p.e. RC1 en el esquema anterior).</span></li>
<li><span style="font-family: Verdana, sans-serif;">Si optamos
por el montaje B) tendremos 10 bits para guiar el motor, incluyendo dirección.
Un valor de 512 lo mantendrá parado, 0 será todo en una dirección y 1023 avante
toda en el otro sentido.</span></li>
</ol>
<span style="font-family: Verdana, sans-serif;">En
nuestros ejemplos usaremos preferentemente el montaje B) por lo que
trabajaremos con un valor entre 0 y 1023, con 512 indicando reposo. De todas
formas el siguiente código permite (usando un #define) optar por luna u otra opción:</span><br />
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> PWM_TO_ENABLE</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#define</span><span lang="EN-GB" style="font-family: 'Courier New';"> DIR_PIN PORTCbits.RC1</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> set_pwm1(uint16 duty)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New';"> PWM_TO_ENABLE
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// transform range [0,1023] into
[-1023,-1023]</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (duty<512) { duty<<=1; duty=1024-duty;
DIR_PIN=0;} </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//"Negative"</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> {duty-=512; duty<<=1; DIR_PIN=1; } </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">//"Positive"</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#endif</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Set duty
</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> CCP1CONbits.DC1B0=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> CCP1CONbits.DC1B1=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">CCPR1L=duty; </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; font-size: 7.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En caso de definir PWM_TO_ENABLE a partir de un valor entre 0 y 1023 se obtiene un valor entre -1023 y 1023. El signo se usa para poner el pin que gobierna la dirección a 0/1 y el modulo se envía al PWM. Obviamente si se usa el define PWM_TO_ENABLE es preciso hacer las conexiones indicadas en el montaje A).</span><span style="font-family: Verdana;"> </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La parte
de lectura de los encoder en cuadratura para saber la velocidad del motor es igual
que antes. En la parte de hardware conectaremos las conexiones de chA y chB a
los pines RB0 y RB1, declarados como entradas. Respecto al código para leer los codificadores
en cuadratura es el mismo que el explicado en la entrada anterior, usando la
interrupción INT0 de alta prioridad para detectar los cambios en el canal
A. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Respecto
al timer para la rutina del servo podríamos haber seguido usando el TMR0. Sin
embargo, el módulo PWM tiene corriendo el timer TMR2. Sería un desperdicio no
usar la interrupción del TMR2 para el código del servo. De esta forma liberamos
el timer TMR0.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La única
pega es que al ser un timer de 8 bits la interrupción de TMR2 va a saltar
demasiado a menudo. Para reducir el problema podemos usar el POSTSCALER del TMR2.
Dicho POSTSCALER no altera la frecuencia del PWM pero sí cada cuanto salta la
correspondiente interrupción. Si usamos el valor máximo de 1:16 para el
postscaler, la interrupción saltará con una frecuencia de:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> (Fosc/4)/(256*16) = 1221 Hz
para Fosc = 20 MHz<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Es posible
que esto sea aún demasiado rápido para nuestros objetivos. Imaginad que
deseamos una frecuencia parecida a la anterior, de unos 50 Hz. Lo que podemos
hacer es tener un contador dentro de la interrupción y sólo cada cierto número
de interrupciones se ejecutaría. Tanteando, con un POSTSCALER de 15 y un
contador de 26 la frecuencia del servo sera:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> F_TMR2 = (Fosc/4)/(256*15) <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> F_servo = F_TMR2/26 = 50.08<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">muy
parecida a los 50 Hz deseados. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En el
programa principal, habilitaríamos el timer TMR2 y el modulo PWM (usando
rutinas del C18)<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="text-align: justify;">
<span style="font-family: 'Courier New';"> OpenPWM1(255); </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<div style="text-align: justify;">
<span style="font-family: 'Courier New';"> OpenTimer2(TIMER_INT_OFF
& T2_PS_1_1 & T2_POST_1_15); </span><span style="font-family: "Courier New"; font-size: 8.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Esto
arranca el timer TMR2 con PRE=1 y POST=15 (OpenTimer) y pone PR2=255 (OpenPWM),
lo que corresponde a una frecuencia Fpwm del orden de 19 KHz con 10 bits de resolución.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> </span><span style="font-family: Verdana;"> </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
postscaler de 15, junto con un contador hasta 26 dentro de la interrupción
garantiza que la rutina del servo entra 50 veces por segundo. Al igual que
antes, en la rutina del servo solo calculamos la velocidad (delta) e
incrementamos la posición del motor:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// Low priority
interruption </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New';">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New';"> interruptlow low_ISR</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> low_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">void</span><span lang="EN-GB" style="font-family: 'Courier New';">) </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 temp;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (TMR2_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// ISR TMR2 (servo)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> cont_servo++;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (cont_servo==26)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span style="font-family: 'Courier New';"> </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> temp=quad; delta=temp-last_quad;
last_quad=temp; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// delta = delta counter</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (delta>128) delta-=256; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New';">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (delta<-128) delta+=256; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New';">// rollover</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="FR" style="font-family: 'Courier New';">pos=pos+delta; </span><span lang="FR" style="color: forestgreen; font-family: 'Courier New';">// increment position</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';">
cont_servo=0;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';"> }</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';">
TMR2_flag=0;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">} </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New"; font-size: 7.0pt; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Al igual
que antes, la interfaz de programa será a través del puerto serie. El programa
nos indica que valor del duty estamos usando en el PWM y la velocidad conseguida
por el el motor (leída a través de los encoders de cuadratura). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Inicialmente
el PWM se arranca con un valor 512 (motor parado). A través del terminal del puerto serie se
puede incrementar (pulsando '+') </span><span style="font-family: Verdana;">o
decrementar ('-') el PWM y observar su efecto (velocidad) sobre el motor. En
principio los incrementos están en unidades, pero pueden hacerse saltar de 2 en
2, 4, 8 o 10. Para ello hay que pulsar '2','4','8','a' en el terminal. Tras por ejemplo pulsar '8' en el terminal, todos los incrementos ('+' o '-') serán en
saltos de 8.</span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">La velocidad se muestra en ticks/ciclo del servo y también en º/segundo.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el video siguiente mostramos como funciona la interfaz a través del puerto serie, incrementando el ciclo ON del PWM mientras observamos su efecto sobre el giro del motor usando una cámara WEB. Podemos observar </span><span style="font-family: Verdana;">un efecto de aliasing provocado por la frecuencia de muestreo de 25 fps de la cámara WEB. </span><br />
<span style="font-family: Verdana; font-size: 8pt;"><br /></span>
<span style="font-family: Verdana; font-size: 8pt;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/jLJueTbDvz8?feature=player_embedded' frameborder='0'></iframe></div>
<span style="font-family: Verdana; font-size: 8pt;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;"><u>Caracterizar comportamiento de un motor</u><o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Finalmente
el programa auto_pwm.c es una pequeña variación del anterior. En lugar de que
el usuario seleccione el ciclo de trabajo del PWM y vea su efecto el programa
va barriendo dicha variable desde 0 a 1023 y de 1023 a 0 una y otra vez. Tras
cada cambio se deja un retraso (para que se alcance y estabilice la nueva
velocidad) y se lee la velocidad del motor. Ambos datos (PWM + vel) se mandan
por el puerto serie para ser recogidos en nuestro PC por un programa en MATLAB
que ira graficando los resultados. Como el receptor de los datos ahora no es
una persona es mucho más eficaz mandar dichos datos en binario. Para ello se ha
construido un paquete de datos muy sencillo compuesto por:</span></div>
</div>
<div class="MsoNormal">
</div>
<ul>
<li style="text-align: justify;"><span style="font-family: Verdana;">'A' </span><span style="font-family: Wingdings;">à</span><span style="font-family: Verdana;"> indica inicio paquete</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">2 bytes
con el valor de PWM como entero de 16 bits sin signo</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">2 bytes
con la velocidad medida en un ciclo del servo (16 bits con signo)</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">1 byte con
un contador de mensajes que se incrementa a cada mensaje y sirve para que
nuestro programa en el PC </span><span style="font-family: Verdana;">pueda detectar paquetes perdidos.</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">'Z' </span><span style="font-family: Wingdings;">à</span><span style="font-family: Verdana;"> carácter de fin de paquete.</span></li>
</ul>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
programa de MATLAB abre el puerto serie, lee los paquetes y va pintando los datos recibidos en
una gráfica representando PWM (entrada) en el eje X frente a velocidad del
motor (salida) en el eje Y. En dicha gráfica influirán aspectos del motor,
carga, voltaje suministrado, driver usado, tipo de esquema (A o B) utilizado,
etc.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En las
gráficas siguientes podemos observar las diferencias de comportamiento entre
varios montajes y motores. Las dos primeras gráficas usan el motor Maxon GM-20
con los montajes B (izquierda) y A (derecha). La tercera gráfica (abajo) muestra el
comportamiento del motor de Pololu (montaje B).
Vemos que el motor Maxon con la opción B) (gráfica de la izquierda)
tiene un comportamiento casi lineal. Lo único que se aprecia es una pequeña
zona muerta (dead-band) alrededor del cero. Hay una banda de unos +/-10 donde
un PWM "no nulo" (distinto de 512) no es capaz de hacer mover al
motor. Si hicieramos zoom sobre ella veríamos que no es está exactamente
centrada en 512 como debería, tal vez por asimetrías en el comportamiento del
driver al subir o bajar sus salidas. Considerar todos estos datos podría ser
interesante si queremos controlar el motor, aunque en este caso, al tratarse de
un motor muy ligero, la zona muerta es casi inexistente y sería posible
ignorarla.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En la
figura de la derecha, por el contrario, el mismo motor muestra un comportamiento
distinto usando el montaje A). En este caso la velocidad del motor es
fuertemente no lineal con respecto al PWM aplicado. También se aprecia
claramente un fenómeno de "histéresis", más marcado que en el otro
caso.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj00RZHycss5y7gaLfcz6U_O4pd3r6FkwzEUSlwydkU1PMUnxwtrGXX0nSbZGbtQoAsSgAIl1cvPVW7K5_Oxx-QZss-QZuTQVo769EYU8qDx9g4P6GaWFk0LYOnlwNz50P5Hk_NqU6Z/s200/img4.png" width="200" /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZjh6vZksfr1H7cj1tkOuSw9TGeqmV_KOk7sN703-exvnFZQcS1qV72V369PtfJ1gVeXBRWDAy4r22eBkOgktZvivVeMUWtwFhtBVJxerCmzRiY3EssHGYiTVP3P_x-Gl1uf-soYJS/s1600/img4b.png" imageanchor="1" style="display: inline !important; margin-left: 1em; margin-right: 1em;"><img border="0" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZjh6vZksfr1H7cj1tkOuSw9TGeqmV_KOk7sN703-exvnFZQcS1qV72V369PtfJ1gVeXBRWDAy4r22eBkOgktZvivVeMUWtwFhtBVJxerCmzRiY3EssHGYiTVP3P_x-Gl1uf-soYJS/s200/img4b.png" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"></span></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM-Ds_LpFPDVfs0a513PYg3N4g7kB2Z_BoCGEQlsspX-48XOkWjjooSqsb7mbKdWqcvBWtJ95qhSTX4GmbKa4kyfSEj1KszDzGCdNW8uSyHImRjxzPGksQawQABnZpN3nLYHc5mb-p/s1600/img2.png" imageanchor="1" style="clear: right; display: inline !important; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiM-Ds_LpFPDVfs0a513PYg3N4g7kB2Z_BoCGEQlsspX-48XOkWjjooSqsb7mbKdWqcvBWtJ95qhSTX4GmbKa4kyfSEj1KszDzGCdNW8uSyHImRjxzPGksQawQABnZpN3nLYHc5mb-p/s200/img2.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Pololu (montaje B)</td></tr>
</tbody></table>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"></span><br />
<span style="font-family: Verdana; font-size: 8.0pt;"></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
influencia de la zona muerta puede ser muy importante para motores más grandes
y peor ajustados a los que les cueste más girar. La figura de abajo muestra
el comportamiento del motor de Pololu en el esquema B). El comportamiento es
lineal, pero en este caso no deberíamos dejar de considerar la banda muerta si
queremos controlar con precisión el motor.</span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En el video siguiente se muestra el funcionamiento del programa MATLAB cuando en el PIC tenemos ejecutandose el código correspondiente a auto_pwm.c. El video ilustra como se van generando las gráficas anteriores.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dwKJOeOIqHIcmnjXGous0itJHSlZTqGGAXZgwJq3iv5bDtGhq9_x8pTUun-wyTAOtME_bmD0slZCgL6qE9VKA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com12tag:blogger.com,1999:blog-4945680608471335280.post-55725822104472459172013-02-01T09:42:00.002+01:002013-06-07T18:15:28.230+02:00Codificadores en cuadratura<br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Tras un largo paréntesis impuesto por el trabajo, retomo el blog. En las siguientes entradas vamos a aplicar la salida PWM del micro a un motor DC con capacidad para manejarlo en ambas direcciones. Nuestro objetivo final será escribir un código de control para hacer que el motor alcance una posición dada y se detenga o se mueva con velocidad constante. Para ello necesitaremos algún tipo de información sobre la posición del motor y su velocidad. La forma más común de obtener dicha información es a través de codificadores en cuadratura. </span><br />
<span style="font-family: Verdana, sans-serif;"><br />
En esta entrada describiremos su concepto y los diferentes modos en los que podemos monitorizarlos (1X, 2X, 4X).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="border: none; padding: 0cm 0cm 1pt;">
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: Verdana, sans-serif;">Archivos de código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/quad1.c">quad1.c</a></span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: Verdana; font-size: 8pt;"></span></div>
<a name='more'></a><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Una típica forma de obtener información de un motor (u otro dispositivo giratorio) en cuanto a su posición, velocidad y dirección es el uso de 2 codificadores en cuadratura (quad encoders), normalmente etiquetados como canal A y B.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Un motor con encoders contará típicamente con 6 conexiones:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Verdana, sans-serif;">· M+ y M- : las de un motor normal (conectadas a las salidas OUT1 y OUT2 del L293)<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18pt;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Verdana, sans-serif;">· Alimentación de los encoders (a niveles lógicos): Vc (5 o 3.3V) y GND.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Verdana, sans-serif;">· 2 salidas con los datos de ambos canales, CH_A y CH_B que conectaremos a sendos pines (configurados como entradas) del microcontrolador.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Las fotos siguientes muestran dos motores que he
usado en los siguientes ejemplos. El de la izquierda (Maxon GM20) es un pequeño motor muy bien acabado y relativamente caro. El de la foto de la derecha es un motor más grande y económico (unos $35, <a href="http://www.pololu.com/catalog/category/116">http://www.pololu.com/catalog/category/116</a>). Sin embargo, de cara a estos ejemplos, ambos cuentan con
codificadores de dos canales en cuadratura y 6 conexiones como las descritas
antes, por lo que son electricamente intercambiables (ambos funcionan nominalmente a 6V)</span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana, sans-serif;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvbXl_OQ1-3mF3TveID47kQKcWo-zDnti3SFFQMizVYHCOGClX7EdPAko6oyEWIaJe3QFJkj05EtsSg2UTKFGj9vxVBVm5xYDla_0lzil_CvV4dfZmwo-5bqjnitJpMCR4cljZfjgf/s1600/maxon.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvbXl_OQ1-3mF3TveID47kQKcWo-zDnti3SFFQMizVYHCOGClX7EdPAko6oyEWIaJe3QFJkj05EtsSg2UTKFGj9vxVBVm5xYDla_0lzil_CvV4dfZmwo-5bqjnitJpMCR4cljZfjgf/s200/maxon.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTJiUM3NXbneFzqk_zCWEYGaleBMsll5275rKEW6x_v25i5MP6qWO8HnXdidcARdH6Dx951s1wyDgXtp7L_G8JOjl62F3QCUzkjYGaIrHJi7i217uJ-zQn0a4wRsNfHhTrAnkqx0Fl/s1600/pololu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTJiUM3NXbneFzqk_zCWEYGaleBMsll5275rKEW6x_v25i5MP6qWO8HnXdidcARdH6Dx951s1wyDgXtp7L_G8JOjl62F3QCUzkjYGaIrHJi7i217uJ-zQn0a4wRsNfHhTrAnkqx0Fl/s200/pololu.jpg" width="200" /></a></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;"><br />
La figura siguiente ilustra el funcionamiento de un encoger con 2 canales, A y B. Los canales pueden verse como 2 sensores (p.e. de luz) fijos. Una pantalla opaca gira con el eje del motor y alternativamente "eclipsa" a uno u otro sensor. Podemos suponer que por defecto los canales están a un nivel alto y cuando son "tapados" caen a un nivel bajo. En la ilustración siguiente los sensores están posicionados a 90º y la pantalla cubre media circunferencia.</span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw7A71oMgr7ga7QLtRKLwPIn3eQ6S1lpg0ZPNmTSa8gqfOypl_uujhDKB8gow20_c-dZn4Eend0F1RM7WZ4T-4q9BZojyA8dFCWP6d3xOdSB-NhFhJgbcw-yUVLbJioZOqksiUUKwzjD4/s1600/quad1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiw7A71oMgr7ga7QLtRKLwPIn3eQ6S1lpg0ZPNmTSa8gqfOypl_uujhDKB8gow20_c-dZn4Eend0F1RM7WZ4T-4q9BZojyA8dFCWP6d3xOdSB-NhFhJgbcw-yUVLbJioZOqksiUUKwzjD4/s400/quad1.jpg" width="400" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La figura ilustra la salida de los sensores cuando el eje gira en sentido antihorario. Las fechas marcan los eventos (caídas o ascensos de un canal) al ir tapándose o liberándose los sensores. El resultado es un par de señales (ch A y ch B) con una serie de pulsos en cuadratura (desplazamiento de fase de 90º o un cuarto de velta).<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La frecuencia de los pulsos nos indica la velocidad de giro del motor. En este caso simplificado cada periodo de ch A o ch B corresponde exactamente a una vuelta del eje.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">¿Para que son necesarios dos canales? Con uno solo podemos medir velocidad de giro pero no su sentido. Al tener dos canales en cuadratura, dependiendo del sentido de giro, uno se eclipsará antes que el otro. En este caso de giro antihorario lo que le pase a A le pasará un poco más tarde (un cuarto de vuelta después) a B. La señal en A precede a la del canal B.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">¿Como programaríamos nuestro microcontrolador para detectar la posición del motor? Lo más eficaz sería conectar el canal A a RB0 y usar una interrupción que se dispara ante un cambio externo de un pin (p.e. INT0 asociada a cambios de RB0). Activaríamos la interrupción INT0 y la configuraríamos para p.e. saltar ante una subida. Cada vez que A pase de 0 a 1 se dispararía la interrupción y se incrementará/decrementará un contador de vueltas.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">¿Cómo podemos saber si incrementar o decrementar el contador? En la siguiente figura ilustramos el caso contrario, cuando giramos en el sentido horario y el canal B es el que va adelantado.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZo6PGs9WmfZ0RhsUWrYVDtY0DkKzoN-B1jk5HM0kE_tMEfvI8kn02zo2FYuMJw3SQLWy8PKyhOWpR9LoLWfNDm2B6Kw54sbtyQWlVf43XwE_9xOEywOTV7YvPhdjaloaR3EadABWziUs/s1600/quad2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZo6PGs9WmfZ0RhsUWrYVDtY0DkKzoN-B1jk5HM0kE_tMEfvI8kn02zo2FYuMJw3SQLWy8PKyhOWpR9LoLWfNDm2B6Kw54sbtyQWlVf43XwE_9xOEywOTV7YvPhdjaloaR3EadABWziUs/s400/quad2.jpg" width="400" /></span></a></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
</div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: Verdana, sans-serif;"><br /></span>
<span style="font-family: Verdana, sans-serif;">Supongamos que monitorizamos el canal A (el conectado a RB0), no importa si la subida o la bajada. Si nos fijamos en la figura inicial vemos que cada vez que hay un cambio en A, justo a continuación, los canales se encuentran en estados opuestos. Por el contrario, en la segunda figura, tras cada cambio de A (1 o 3) ambos canales están en el mismo estado. Es esa condición la que usaremos para detectar el sentido del giro y decidir si incrementar o disminuir el contador</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El siguiente código ilustra como codificaríamos esto dentro de la rutina asociada a la interrupción del INT0: </span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">void</span><span lang="EN-GB" style="font-family: 'Courier New';">)</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (INT0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// INT0 ISR (keeps track of position)</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTBbits.RB1==PORTBbits.RB0) quad++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> quad--; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// 1x encoder</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';"> INT0_flag=0;</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';"> }</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código incrementa una variable (quad) si RB0 (ch A) == RB1 (ch B), esto es, si estamos girando en sentido horario. En caso contrario se decrementa el contador. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Encoder en modo 2X:</span></b><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código anterior corresponde a lo que se denomina un encoder 1X, ya que solo monitorizamos bien las subidas o las bajadas del canal A, pero no ambas. En el caso descrito, la resolución es de 1 vuelta del eje, ya que el canal A se eclipsa 1 vez por vuelta.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si deseamos más resolución podemos monitorizar tanto las bajadas como las subidas. En ambos casos haremos lo mismo que antes, comparar el estado de RB0 y RB1 y aumentar/disminuir el contador. En este caso como A sube y baja 2 veces por vuelta tendremos el doble (2X) de resolución.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El PIC solo permite configurar la interrupción como de subida o de bajada. ¿Cómo podemos detectar tanto las subidas como las bajadas? Sencillo: basta cambiar la configuración de la interrupción cada vez que suceda (esto es, dentro del código de la ISR).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código quedaría:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">void</span><span lang="EN-GB" style="font-family: 'Courier New';">)</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (INT0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// INT0 ISR (keeps track of position)</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTBbits.RB1==PORTBbits.RB0) quad++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> quad--; </span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> INTCON2bits.INTEDG0=~INTCON2bits.INTEDG0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// 2X encoder</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';">INT0_flag=0;</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';"> }</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Basta añadir una línea que cambia el bit que define el sentido de la detección (INTCON2.INTEDG0). Si entramos por una subida, se cambia y la próxima vez detectaremos la bajada. Cuando volvamos a entrar por una bajada, se quedará configurado para saltar a la siguiente subida. En resumen, atrapamos todos los cambios (y sin tener que preocuparnos por nada ya que todo lo hace la interrupción). La línea de incrementar/decrementar el contador no hace falta cambiarla ya que la condición de chA=chB o chA &lt;&gt;chB no cambiaba en subidas o bajadas.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Usar un encoder 2X es muy recomendable ya que:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">No requiere hardware ni interrupciones adicionales (usamos la misma interrupción INT0 que antes).<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Sólo requiere una línea adicional de código.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Duplica la resolución de nuestro contador (ahora cuenta en 1/2 vueltas).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Además de la mayor resolución hay una razón más importante para usar siempre por defecto un encoger 2X.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Un encoder 1X es perfectamente válido (salvo por su menor resolución) en el caso de un motor que se mueve en una sola dirección. Sin embargo puede introducir errores si nuestro motor puede cambiar su dirección. Consideremos la figura siguiente:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZWPNkGnCXc6URLoM61xWiW-KCshEHZOoXCbk1rGUviBwrG8r3p3Tp4BhExZbYb_ZEykxqFOBcATUAcYJyvnVx7ajwkcqSUk8bV-jA739BfD8R6P1SM3m9TDbWGS2Q9YFT8R1dTbtSVSc/s1600/quad3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="147" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZWPNkGnCXc6URLoM61xWiW-KCshEHZOoXCbk1rGUviBwrG8r3p3Tp4BhExZbYb_ZEykxqFOBcATUAcYJyvnVx7ajwkcqSUk8bV-jA739BfD8R6P1SM3m9TDbWGS2Q9YFT8R1dTbtSVSc/s400/quad3.jpg" width="400" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Tenemos un movimiento de vaiven y el borde de la pantalla tapa y libera alternativamente al sensor A (el sensor B está siempre libre). Esto provoca una serie de pulsos en A y ningún cambio en B.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Con un encoder 1X vigilando p.e. las subidas de A contaríamos 2 subidas de A (verificando que chA=1=chB) que causarían 2 incrementos del contador, cuando claramente no hemos completado ninguna vuelta.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En cambio, con un encoder 2X también veríamos 2 bajadas de A (verificando esta vez que chA=0<>1=chB) por lo que decrementaríamos el contador en dos ocasiones, cancelando los incrementos anteriores.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Esta (y no la mejora de la resolución que puede no ser importante en nuestra aplicación) es la razón por la que se recomienda el uso de un codificador 2X en estas aplicaciones.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Encoder en modo 4X:</span></b><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si por alguna razón deseamos mayor resolución en nuestro contador podemos implementar un encoder 4X. Se trata de monitorizar eventos (subidas y bajadas) en ambos canales simultáneamente.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Precisamos eso si, que el canal B esté conectado a otro pin con capacidad de interrupción (por ejemplo RB1, usando la interrupción INT1). Ahora tenemos que escribir código para las dos posibles interrupciones:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (INT0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// RB0 (ch A) change</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";"> if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTBbits.RB1==PORTBbits.RB0) quad++; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> quad--; </span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> INTCON2bits.INTEDG0=~ INTCON2bits.INTEDG0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// 2X encoder</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> INT0_flag=0;</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (INT1_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// RB1 (ch B) change</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";"> if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (PORTBbits.RB1==PORTBbits.RB0) quad--; </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">else</span><span lang="EN-GB" style="font-family: 'Courier New';"> quad++; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> INTCON2bits.INTEDG0=~ INTCON2bits.INTEDG0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// 2X encoder</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> INT1_flag=0;</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> }</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Al contrario que el encoder 2X, el uso de un encoder 4X si que tiene un "gasto" adicional. Necesitamos que la segunda línea (ch B) también tenga asociada una interrupción. Esto no era necesario en el caso 2X donde la segunda línea (ch B) podría ser cualquier pin definido como entrada.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Por ejemplo, en el caso del PIC 2520/4520 tenemos 3 interrupciones externas INT0 (RB0), INT1 (RB1) e INT2 (RB2) por lo que podríamos monitorizar hasta 3 pares de canales (3 motores) en modo 2X (conectando los respectivos canales A a los tres pines citados). Por el contrario, en modo 4X sólo podríamos monitorizar un solo motor (ya que gastaríamos RB0 y RB1 para ese fin.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En los programas siguientes de control de motores usaremos por defecto los encoders configurados en modo 2X.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Encoders con más de un ciclo por vuelta<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Por simplicidad hemos ilustrados los ejemplos anteriores con el caso de un par de sensores separados por 90º y una pantalla de 180º lo que provoca una resolución de 1 vuelta (modo 1X), 1/2 vuelta (2X) o 1/4 vuelta (4X).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Es posible aumentar la resolución "por hardware", situando más cerca los sensores A y B y usando una pantalla donde se alternen varios periodos de paso/bloqueo en cada vuelta. Algo así como lo ilustrado en la figura:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn-zzKDwmnhp3mP48IeHZC-UFNFFs6QD7tOfiPXIBEfSGuyS-Ey9pyPf-ZOexNbOPy8jIQ6G5w-0YTJJZ7m2kCwDp6yrgIVinDHLPBg9ZXcLM53bWYy1rPp7L5aKzvADvzyHEnzWppGpA/s1600/quad4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn-zzKDwmnhp3mP48IeHZC-UFNFFs6QD7tOfiPXIBEfSGuyS-Ey9pyPf-ZOexNbOPy8jIQ6G5w-0YTJJZ7m2kCwDp6yrgIVinDHLPBg9ZXcLM53bWYy1rPp7L5aKzvADvzyHEnzWppGpA/s400/quad4.jpg" width="400" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Esto corresponde a una configuración que en modo 1X tendrá una resolución de 10 unidades (de 36º) por vuelta (las 10 aspas del gráfico) y en modo 2X de 20 unidades (18º) por vuelta.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Las aspas pueden ser efectivamente una "hélice" que eclipsa/deja pasar alternativamente la luz sobre una pareja de fotodiodos (sensores A y B). Esto sucedía así en el caso de los viejos ratones de bola. Más comúnmente, los sensores A y B son un par de sensores Hall de campo magnético. Las "aspas" son entonces una serie de imanes de polos alternados N y S que hacen cambiar el estado de los sensores de forma alternativa.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Además, en muchos motores los sensores de cuadratura están montados sobre el eje "directo" del motor. Si luego el motor tiene una reductora, la resolución sobre el eje de salida de la reductora se incrementa notablemente. Por ejemplo, el motor GM-20 de Maxon que uso en estos ejemplos tiene un encoder magnético de 16 pulsos por vuelta y una reductora de 55.1:1. Eso se traduce en que cada vuelta del eje de salida son 55.1 vueltas del eje motor y por consiguiente 55.1x16 = 881.6 pulsos del encoder (en modo 1X). En modo 2X tendríamos unos 1765 ticks por vuelta, lo que corresponde a una resolución de 360º/1765 = 0.2º.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Verdana;">Implementación: quad1.c<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTYCAfuu_hciyttvojt89s8cJlti9swunD-xif6ayREE5VXS3rT3rDih4u3anWzb_mN6xI8goBl44rQwalW15qhI4oL-RAkqsAJVOs3oIgS5m_w2dg9FQjKZ2enfcKJdBv4kf_VgI0/s1600/esquema_1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTYCAfuu_hciyttvojt89s8cJlti9swunD-xif6ayREE5VXS3rT3rDih4u3anWzb_mN6xI8goBl44rQwalW15qhI4oL-RAkqsAJVOs3oIgS5m_w2dg9FQjKZ2enfcKJdBv4kf_VgI0/s200/esquema_1.jpg" width="200" /></a><span style="font-family: Verdana;">El programa quad1 implementa una lectura de los canales A y B de un motor. En esta primera prueba solo conectaremos las salidas de los canales A y B (a RB0 y RB1 respectivamente) y la alimentación (5V) y masa<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">de la lógica de los sensores. No conectaremos las conexiones del motor y lo moveremos a mano para verificar </span><span style="font-family: Verdana;">la lectura de los canales</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como nuestro objetivo final en próximas entradas será un sistema de control, quad1.c está escrito con esa idea en mente. Además de las </span><span style="font-family: Verdana;">interrupciones para contar los pulsos de los canales, tendremos otra interrupción asociada a un timer (TMR0). </span><span style="font-family: Verdana;">A dicha rutina se le suele denominar "código del servo", ya que en una aplicación de control, será la encargada de monitorizar lo que está haciendo el motor y actuar en consecuencia. En este primer ejemplo lo único que hará será determinar la velocidad y posición del motor (contador del encoder).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En principio, la velocidad del motor se expresará en cuantas "ticks" se hayan contado durante el ciclo del servo. Para pasar de dicha velocidad a otras medidas como revoluciones por minuto (rpm) o similares tendremos que conocer los datos particulares de nuestro motor (ticks/vuelta), si estamos en modo 1X,2X o 4X y finalmente la frecuencia con que se ejecuta el código del servo.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La interrupción del canal A (INT0) se declarará de ALTA prioridad, mientras que la del servo (TMR0) será de BAJA prioridad. La razón es que no podemos permitirnos perder ningún pulso por lo que la llegada de un pulso debe interrumpir cualquier otra tarea.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En relación con esto también es necesario considerar de que tipo vamos a definir la variable quad que llevará la cuenta de los pulsos (o medios pulsos en modo 2X) recibidos. En principio, en un motor girando dicho contador puede ser muy alto, por lo que podríamos usar un entero con signo de 32 bits (int32). Sin embargo, eso hace que </span><span style="font-family: Verdana;">en cada interrupción INT0 (en la que nos interesa demorarnos lo menos posible) tengamos que incrementar o decrementar un entero de 4 bytes. </span><br />
<span style="font-family: Verdana;"><br /></span>
<span style="font-family: Verdana;">Otro problema sería que mientras estamos accediendo a ese contador desde la rutina del servo, podríamos ser interrumpidos por INT0 y dicho contador modificado. Esto podría llegar a corromper nuestros datos.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Para evitar estos problemas una alternativa es declarar quad de tipo más pequeño, int16 o incluso como un byte. Las ventajas son:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">La interrupción INT0 dura lo menos posible ya que solo tiene que incrementar un byte.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36pt; text-indent: -18pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">Cuando accedamos al valor de quad en la rutina del servo, al ser un único byte lo leeremos en una sola instrucción, por lo que no hay problemas de quedarnos a medias del proceso.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La desventaja es que si el motor gira muy rápido, es posible que un byte sea insuficiente. Será suficiente si el incremento/decremento del contador en un ciclo del servo es inferior a 128. En la rutina del servo compararemos <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">el valor del contador con el último y determinaremos cuanto se ha movido y hacia donde.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El siguiente código corresponde a la rutina del servo, que en este ejemplo (reloj de 20 Mhz, preescaler 1:2 en TMR0 y un contador de 50000 entre cada cada interrupción) se ejecuta con una frecuencia de 50 Hz:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> Fservo = (Fosc/4)/(Pre * cont) = 5Mhz / 100000 = 50 Hz<o:p></o:p></span></div>
<div class="MsoNormal">
<br />
<br /></div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt;">
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New";">void</span><span lang="EN-GB" style="font-family: 'Courier New';"> low_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">void</span><span lang="EN-GB" style="font-family: 'Courier New';">)</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';">{</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> uint8 temp;</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// ISR TMR0 (servo)</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> {</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> set_TMR0(15536); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// T = 50000 ticks with 1:2 PS @ 20MHz = 50 Hz</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> PORTCbits.RC0=~PORTCbits.RC0;</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> temp=quad; delta=temp-last_quad; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// delta = delta counter</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> last_quad=temp;</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New";">if</span><span lang="EN-GB" style="font-family: 'Courier New';"> (delta&gt;128) delta-=256; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New";">// correct for rollover</span><span lang="EN-GB" style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: "Courier New";">else</span><span style="font-family: 'Courier New';"> </span><span style="color: blue; font-family: "Courier New";">if</span><span style="font-family: 'Courier New';"> (delta<-128 data-blogger-escaped-delta="" data-blogger-escaped-nbsp="" data-blogger-escaped-span=""><span style="font-family: "Courier New";"><o:p></o:p></span></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';"> pos=pos+delta; </span><span style="color: forestgreen; font-family: "Courier New";">// increment position</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';"> TMR0_flag=0;</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';"> } </span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; padding: 0cm;">
<span style="font-family: 'Courier New';">}</span><span style="font-family: "Courier New";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código calcula la diferencia entre sucesivas observaciones (delta) y lo acumula en una variable de posición (está si un entero de 4 bytes, int32). El código detecta posibles rollovers de la variable quad. Si la diferencia (delta) entre observaciones excede +128 o -128 asumimos que el contador ha dado la vuelta y corregimos en consecuencia (restando o sumando 256). Es por esto por lo que no es posible contabilizar velocidades mayores de +/-128 en cada ciclo del servo. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si nuestro motor puede girar muy rápido (o tiene muchos pulsos por vuelta) deberemos reducir el ciclo del servo para evitar overflow. Si esto no es posible no nos quedará más remedio que declarar quad de mayor tamaño. Un entero de 16 bits será suficiente en la mayoría de los casos.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El programa principal simplemente arranca el timer TMR0 y configura adecuadamente las interrupciones. La comunicación es a través del puerto serie a 9600 bauds. En el bucle principal el programa vuelca por el puerto serie los valores de la posición y velocidad (delta) del motor, ambos en pulsos del encoder. Se ha añadido la opción de elegir entre modo 1X y 2X pulsando 1 ó 2 en el terminal.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El motor usado en este ejemplo es un MAXON GM-20 con un encoder de 16 pulsos por vuelta y una reductora de 55.1:1. Por lo tanto, en modo 1X tendremos 16 x 55.1 = 881.6 ticks por vuelta. En modo 2X subiremos al doble, 1763 ticks/vuelta. La frecuencia del servo es de 50 Hz (20 ms) por lo que para pasar del valor delta obtenido a<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">revoluciones por minuto haríamos:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> vueltas = delta / 1763</span><span style="font-family: Verdana;"> tiempo = 20 ms </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> </span><br />
<span style="font-family: Verdana;"> rps = 50 x delta / 1763 <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"> rpm = 60x (50 x delta) / 1763 = 1.7015 x delta<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Este motor en sus especificaciones recomienda un máximo de 200 rpm en su eje de salida (tras la reductora) para 6V. </span><span style="font-family: Verdana;">Eso corresponde a unas 3.algo rps = 6000 ticks/sec . Con una frecuencia del servo de 50 Hz el máximo incremento sería de 6000/50 = 120. Por lo tanto, estaríamos dentro de las limitaciones de nuestro enfoque de usar una variable de tipo byte como contador.</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El video final ilustra el funcionamiento del programa, moviendo el motor de forma manual. Se muestra como en modo 2X una vuelta completa corresponde a 1765 "ticks" y a la mitad (unos 880) en modo 1X. Conectando los bornes del motor a una batería observamos una velocidad de 90 ticks (modo 2X) por periodo del servo, lo que se traduce a unas 1.70 x 90 = 150 rpm.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/nd8_Rb1Vb_4/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/nd8_Rb1Vb_4?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/nd8_Rb1Vb_4?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
</div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com11tag:blogger.com,1999:blog-4945680608471335280.post-50334914508408875672012-07-17T11:23:00.000+02:002013-06-10T10:55:28.865+02:00ADC con interrupciones<br />
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En la
entrada dedicada al conversor AD vimos como optimizar el código ejemplo del compilador de C18. Aprovechando las características
especificas de cada controlador, usando macros en vez de llamadas a funciones,
etc. conseguimos que el tiempo necesario para una conversión bajase desde unos
50 usec a 25 usec. Eso equivalía a duplicar el posible ritmo de muestreo de
20000 a 40000 muestras por segundo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En esta
entrada vamos a explorar el uso de <b>interrupciones
</b>junto con el conversor AD. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En primer
lugar veremos como usar la interrupción de un timer para asegurar un ritmo de
muestreo exacto. Posteriormente veremos como usar la interrupción asociada al
ADC para no tener que esperar mientras el conversor realiza su tarea. Esto nos
permitirá liberar gran parte de los recursos del micro, lo que será
especialmente útil si estamos cerca del ritmo de muestreo máximo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Codigo asociado a esta entrada:<span class="apple-converted-space"> </span> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/adc0_timer.c">adc0_timer.c</a>, <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/adc1_timer.c">adc1_timer.c</a></span><span style="font-size: 13.5pt;"><o:p></o:p></span></div>
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<div style="text-align: justify;">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana; font-size: 8pt;"></span></div>
<a name='more'></a><div style="text-align: justify;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
</div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<div style="text-align: justify;">
<span style="font-size: 13.5pt;">--------------------------------------------------------------------------------<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Uso de interrupciones del temporizador
para marcar el ritmo del ADC</span></u></b><u><span style="font-family: Verdana;"><o:p></o:p></span></u></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Los
programas que presentamos en la <a href="http://picfernalia.blogspot.com.es/2012/07/conversor-adc.html">entrada del ADC</a> tenían dos problemas principales:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">Entre conversiones no se hacía nada</span></b><span style="font-family: Verdana;">: el tiempo entre conversiones estaba ocupado por un delay por lo que el micro no hacía nada. Se queda esperando 200 usec, hace la
conversión y repite el ciclo. Obviamente querríamos aprovechar el espaciado
entre muestras para procesarlas de alguna manera. Podríamos substituir el delay
por la tarea que tengamos que hacer con nuestros datos. Pero si queremos mantener un ritmo de muestreo constante tendríamos que añadir el delay
necesario hasta completar el tiempo de espera. Pero eso significa que
cualquier cambio en el código nos obligaría a tirar de osciloscopio y
reajustar el delay "remanente". Claramente inaceptable. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">El intervalo programado no se cumple:</span></b><span style="font-family: Verdana;"> habíamos programado 200 usec entre toma de
muestras (5000 Hz), pero debido al tiempo dedicado a la conversión el espaciado es
mayor (entre 225 y 250 usec, dependiendo del código usado). <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Afortunadamente
la solución para ambos problemas es la misma y muy sencilla: usar una interrupción asociada a
un temporizador para lanzar las conversiones cada cierto tiempo. Dentro de la
interrupción del timer programaremos el código de la conversión AD. Dentro del
programa principal estaremos libres (salvo el tiempo de la conversión) para
procesar los datos. El código dentro del programa principal quedaría:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;"> main(</span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;">) </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> uint8 PS_MASK,pre;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> TRISC=0; PORTC=0; TRISB=0; PORTB=0;
TRISA=0xFF; </span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenADC(ADC_FOSC_16 & ADC_RIGHT_JUST
& ADC_4_TAD,</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADC_INT_OFF & ADC_VREFPLUS_VDD
& ADC_VREFMINUS_VSS, 7);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TMR0_reset=get_delay(200L,20000,&pre);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">PS_MASK=
(pre>0)? (0xF0|(pre-1)): T0_PS_1_1; </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
OpenTimer0(T0_16BIT&T0_SOURCE_INT&PS_MASK);</span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;"> </span><span lang="FR" style="font-family: "Courier New"; mso-ansi-language: FR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_TMR0_int; enable_global_ints; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Enable ints</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> start_TMR0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// starts timer</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">{</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> PORTB=res>>2;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(10);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Simplemente
configuramos TMR0 para un delay de 200 usec usando un oscilador de 20 MHz
(ayudándonos de la función get_delay que escribimos al hablar de los timers). Luego configuramos el ADC con un reloj de Fosc/16 y un retardo programado de 4 Tad.
Como ya vimos, estos parámetros son adecuados para los dispositivos 2520/4520.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Tras la
configuración del ADC y de TMR0, habilitamos las interrupciones globales y la
del TMR0 y arrancamos el contador TMR0. A partir de ahí ya no tenemos que hacer
nada, todo lo va a hacer el servicio de la interrupción. Si os fijáis, en el bucle
del main solo mostramos (cada 20 msec) los 8 bits más significativos de la
conversión en PORTB. Ahí es donde podríamos insertar nuestro código manipulando
los datos recibidos. Por supuesto, somos responsables de que lo que tengamos
que hacer con cada dato no me lleve más de unos 200 usec, que es el tiempo
disponible antes de que reciba una nueva muestra.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El trabajo
de la conversión se lleva a cabo en la interrupción del TMR0. El código es:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// High priority interrupti</span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">on </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//TMR0_isr();
//ISR de la interrupcion de TMR0</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=1; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"> <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_TMR0(TMR0_reset); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
reset counter</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(0);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0bits.GO=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (ADCON0bits.GO);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> res=ADRESH; res<<=8; res+=ADRESL; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TMR0_flag=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// clear flag</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Code @ 0x0008 ->
Jump to ISR for high priority ints</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_interrupt (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">){_asm </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">goto</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR _endasm}</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt;">#pragma</span><span style="font-family: 'Courier New'; font-size: 8pt;"> code</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En la
interrupción lo primero que se hace es resetear el contador. Esto es
fundamental para que los siguientes 200 usec empiecen a contarse ya, sin
esperar a que termine la conversión AD o el resto de las tareas. Así me aseguro
que la interrupción vuelva a entrar a los 200 usec exactos. De nuevo es mi
responsabilidad que las tareas de la interrupción no se alarguen más del
periodo estipulado. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como veis
tenemos también las mismas líneas RC0=1; RC0=0 enmarcando la tarea del ADC lo
que nos permite estimar el tiempo dedicado al ADC (y por lo tanto el tiempo
libre del procesador) con un osciloscopio o simplemente midiendo el voltaje
medio en RC0 con un voltímetro. Con un salto de 200 usec entre muestras obtengo
un voltaje de V=0.55 lo que nos da un
porcentaje de ocupación de un <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> 0.55 / 4.85 = 0.11 (11%)<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como el
periodo es ahora de 200 usec justos, el tiempo de la tarea se estima en
0.11x200 = 22 usec que es similar al esperado para una conversión. La conclusión es
que con un ritmo de muestreo de 5000 Hz (muestras/sec) dispongo de
aproximadamente un 90% del tiempo del procesador para el resto de las tareas.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Obviamente
las cosas empeoran si aumento la frecuencia de muestreo. Si reduzco el periodo
de muestreo a 100 usec (10000 muestras/sec = 10 KHz de frecuencia de muestreo)
el voltaje medido en RC0 se incrementa a casi 1V lo que supone un 20% (1/4.85)
de ocupación. Esto era de esperar porque de los 100 usec del periodo ya sabemos
que unos 20-25 usec siguen dedicados a la conversión AD. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM1uNuwy9aGiv8pTIf2qf1nXUFXcpzDYnAMTxHVZ1w9PU6nLcCHgJXDfBMLrQTadeXlvnCL7DnFmHMYb8vdk8-cTkWetBgPbxo4ZnTnLith5gtjDIaoZqPh-vhXXsv3nw4lH_0iseI/s1600/tmr_200.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM1uNuwy9aGiv8pTIf2qf1nXUFXcpzDYnAMTxHVZ1w9PU6nLcCHgJXDfBMLrQTadeXlvnCL7DnFmHMYb8vdk8-cTkWetBgPbxo4ZnTnLith5gtjDIaoZqPh-vhXXsv3nw4lH_0iseI/s200/tmr_200.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJLBvRcY8tdR7lFjlz5z3jxqMSW1v8S_hBs26Z8AJR_ltI4YwtK00obtjU6Q-o1OnpOd3eZTaMLharGuNmjYB7MOj1UAnAUfi5EEcMNGqKxaaY4OzGeyEDVL1sii4T_NCqOQEpr4Mz/s1600/tmr_100.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJLBvRcY8tdR7lFjlz5z3jxqMSW1v8S_hBs26Z8AJR_ltI4YwtK00obtjU6Q-o1OnpOd3eZTaMLharGuNmjYB7MOj1UAnAUfi5EEcMNGqKxaaY4OzGeyEDVL1sii4T_NCqOQEpr4Mz/s200/tmr_100.jpg" width="200" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM1uNuwy9aGiv8pTIf2qf1nXUFXcpzDYnAMTxHVZ1w9PU6nLcCHgJXDfBMLrQTadeXlvnCL7DnFmHMYb8vdk8-cTkWetBgPbxo4ZnTnLith5gtjDIaoZqPh-vhXXsv3nw4lH_0iseI/s1600/tmr_200.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: justify;"><span style="background-color: white;"> </span><span style="background-color: white; font-family: Verdana;"> </span></a></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">A la
derecha el caso de 200 usec en el osciloscopio. A la derecha, espaciado de 100
usec. El ancho del pulso de la conversión AD sigue siendo de alrededor de 20
usec, pero supone el doble en porcentaje en el segundo caso.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWwbxaRXdpSAJ7FRaqUdeFrQXM5aG85M6UqTWXpsRtWlAOKdDrkZLVtn1VQauuFOPGi6W65wHnoTSa_ZLKraCfHZpWhP353L_E4Y2bj7DP2KzeI5LYkB7G2mNIW4SxtQgOY6Z9GmAg/s1600/tmr_25.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: justify;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWwbxaRXdpSAJ7FRaqUdeFrQXM5aG85M6UqTWXpsRtWlAOKdDrkZLVtn1VQauuFOPGi6W65wHnoTSa_ZLKraCfHZpWhP353L_E4Y2bj7DP2KzeI5LYkB7G2mNIW4SxtQgOY6Z9GmAg/s320/tmr_25.jpg" width="320" /></a></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Está claro donde está el límite si seguimos así. El
tiempo (t) dedicado a la conversión AD no cambia (unos 20/25 usec como mínimo) y está claro que el periodo
T entre muestras no puede ser inferior a t. Si bajo el periodo a T=25 usec, del
orden del 80% del tiempo se dedica a la conversión y solo quedaría un 20%
escaso para procesar los datos. Con ese
situación mido 3.75V en RC0 lo que equivale a un 80% de ocupación (3.75/4.8 =
0.8). </span><span style="font-family: Verdana;">En la
pantalla vemos como el ciclo de trabajo es del orden del 80%.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Con este
enfoque el límite de muestreo se hallaría en unas 40000/50000 muestras por
segundo (T=25/20 usec). El problema es que para dicho ritmo apenas tendríamos
tiempo de hacer nada con los datos adquiridos, ya que del orden del 80% se
gasta en el proceso de adquisición.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;"><br /></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">El uso de la interrupción del ADC <o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">No hay
nada que podamos hacer para aumentar el ritmo de muestreo por encima de esos
40-50 KHz máximo. El ADC del PIC (de los modelos 2520/4520) necesita esos 20-25
usec por conversión y no hay forma de hacerlas más rápidas, ya que hay que respetar
los límites que nos dan en la documentación para el tiempo de adquisición y de
conversión. Incluyendo a ambos para esta
familia el tiempo total sería de unos (4+12) Tad y como Tad debe ser como
mínimo de 0.8 usec el proceso no puede tardar menos de unos 12 usec. Si
añadimos los retardos de entrada a interrupción, selección del canal, recuperación
del resultado de ADREAH/ADRESL, retorno, etc. llegamos a los 20 usec que
estamos viendo en el osciloscopio.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Ni
siquiera subir la frecuencia del oscilador funcionaría, ya que seguiríamos sin
poder incrementar el reloj del módulo AD por encima de 1/Tad. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
problema es que incluso esos ritmos de muestreo parecen poco realistas, ya que
no nos dejan tiempo libre para procesar los datos adquiridos. Veremos que,
aunque no podamos incrementar el ritmo de muestreo si que podemos liberar al
micro de la mayor parte del trabajo, de forma que podamos muestrear a 40000
muestras por segundo y tener libre al micro en un 90% (en vez de estar ocupado
al 90%) para poder procesar los datos y hacer otras tareas.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRBoQkVDuLfAO3Px-Rmh3_75d2zIQd4ym3ilqWQSJPUQ23VSX4G6vWZLAMPfxd_5nkjItrLz52EjGlkIGPfH3AHfnszr-0EwHVHY756_LKtQ7ungJ72c4rkqaU3d8JpIY8RuNFfZJw/s1600/tmr_25_RC1.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: justify;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRBoQkVDuLfAO3Px-Rmh3_75d2zIQd4ym3ilqWQSJPUQ23VSX4G6vWZLAMPfxd_5nkjItrLz52EjGlkIGPfH3AHfnszr-0EwHVHY756_LKtQ7ungJ72c4rkqaU3d8JpIY8RuNFfZJw/s320/tmr_25_RC1.jpg" width="320" /></a></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Observando
la rutina de la interrupción lectura anterior nos podemos preguntar cuanto
tiempo "perdemos" mientras el módulo AD está trabajando. Esto es,
desde que ponemos en marcha el proceso (ADCON0.GO=1) hasta que dicho bit se
pone a cero, indicando que el resultado está listo. Debería ser del orden de los
12 usec de los que hemos hablado antes (unos 16 Tad @ 0.75 usec). </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Podemos comprobarlo añadiendo unas líneas del tipo PORTCbits.RC1=1; y PORTCbits.RC1=0;</span><span style="background-color: white; font-family: Verdana;"> </span><span style="background-color: white; font-family: Verdana;">antes y después de la sentencia de espera (while). </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Si lo hacemos y medimos el voltaje en RC1 (para el caso de T=25 usec) resulta
ser de 2.7V, frente al obtenido en RC0 (3.75V). Eso indica que del orden de un
70% (2.7/3.7) del tiempo de la rutina se pierde mientras el ADC trabaja (primero
esperando y luego convirtiendo). </span><span style="background-color: white; font-family: Verdana;"> </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">A la
izquierda podemos verlo en la pantalla del osciloscopio. El pulso amarillo representa el
tiempo total de la conversión. El pulso azul, el tiempo que el microcontrolador
está bloqueado en la sentencia while(), esperando a que el ADC le informe de
que la conversión se ha completado.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">¿Podríamos
aprovechar todo ese tiempo de alguna forma? Si, ya que durante ese tiempo es el
módulo AD quien está trabajando. El micro podría estar haciendo otra cosa,
siempre que le avisen cuando el proceso termine. Para ello tenemos la
interrupción asociada al ADC. La idea es que no tenemos que quedarnos a esperar
que ADCON0.GO vuelva a ser 0. Podemos habilitar la interrupción del ADC, y está
nos avisará cuando el resultado esté listo (esto es, cuando el modulo AD haya
puesto a cero el bit GO).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Tendremos
que romper el código de conversión, repartiendo el trabajo entre dos
interrupciones. Dentro de la interrupción del timer TMR0 se selecciona el canal
y arranca la conversión (GO=1). Luego salimos y esperamos a que nos llame la
interrupción del ADC, donde se recoge el resultado de ADRESH/ADRESL. </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El código de la ISR queda:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">{</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// TMR0 ISR<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_TMR0(TMR0_reset); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
reset counter</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(0);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0bits.GO=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TMR0_flag=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// clear flag</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (AD_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// ADC
ISR</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC1=1;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> res=ADRESH; res<<=8; res+=ADRESL; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC1=0;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> AD_flag=0;
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;">;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La línea RC0 (amarillo, arriba) monitoriza el tiempo
usado en seleccionar canal y lanzar la conversión (unos 2.5 usec) dentro de la
interrupción del TMR0. La línea RC1 (azul) monitoriza el tiempo usado en
extraer el resultado de la conversión (unos 3 usec) dentro de la interrupción
del ADC. El tiempo entre ambos sucesos
(unos 15 usec), marcado con los cursores, es el tiempo que antes estabamos
esperando y que ahora hemos liberado.</span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD5LELOJqam0nulqb6q9mGMuHXyZj56J-My3lmeV5tfBVegUUGKGNYlVeXbggu9i3uRouTkvPrGcnDJVWUJp0dxo3C1Blna9d3JM-ul6KmbAElgbwaTb9ODO0NNJ_-tRFQ7IGvijz4/s1600/tmr_25_ADC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD5LELOJqam0nulqb6q9mGMuHXyZj56J-My3lmeV5tfBVegUUGKGNYlVeXbggu9i3uRouTkvPrGcnDJVWUJp0dxo3C1Blna9d3JM-ul6KmbAElgbwaTb9ODO0NNJ_-tRFQ7IGvijz4/s1600/tmr_25_ADC.jpg" /></a></div>
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">De los 25
usec entre muestras el proceso de conversión solo ocupa unos 5 usec (algo más
si incluimos el tiempo de procesar interrupciones). Vemos que se ha invertido la
situación, pasando de tener un 80% de ocupación a tener del orden de un 80%
libre para procesar las muestras.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
programa principal queda prácticamente igual, salvo que ahora tenemos que
habilitar también la interrupción del ADC y las interrupciones periféricas:</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">enable_TMR0_int; AD_flag=0;
enable_AD_int; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_global_ints; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//
Enable ints</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_perif_ints;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com2tag:blogger.com,1999:blog-4945680608471335280.post-49979497342751204612012-07-13T13:43:00.001+02:002013-06-10T11:04:25.280+02:00Proyecto: brújula electrónica<span style="font-family: Verdana;">En este proyecto vamos a ver una simple
aplicación del uso del conversor AD del
PIC. Se trata de escribir el código base de una brújula electrónica. La
idea es disponer de dos sensores magnéticos alineados en dos ejes (A y B) perpendiculares
en el plano horizontal, cada uno de ellos midiendo la correspondiente
componente del campo magnético terrestre.</span><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOUYSOjmb0ZzVDvhIy9b7qiao8ScW5W5dg_hY5OzmXgoJ7FUz_QoB2W3DGpAwr03ga9QOKgZOnEYEBGWSDhBl8DnfMy5hCMhLUWH_MxDNtAGuRopSXQJ6Jkgp-cebqnHEMX4kHrRr6/s1600/vectores.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOUYSOjmb0ZzVDvhIy9b7qiao8ScW5W5dg_hY5OzmXgoJ7FUz_QoB2W3DGpAwr03ga9QOKgZOnEYEBGWSDhBl8DnfMy5hCMhLUWH_MxDNtAGuRopSXQJ6Jkgp-cebqnHEMX4kHrRr6/s320/vectores.jpg" width="320" /></a></div>
<div align="center" style="margin-bottom: .0001pt; margin: 0cm; text-align: center;">
<br /></div>
<div style="margin: 0cm 0cm 0.0001pt; text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Con el conversor AD tomaremos dos medidas (ma y mb) "simultáneas" (separadas por unos pocos usec) de ambos sensores. A partir de ellas hallaremos el ángulo relativo (theta) entre la orientación del eje A de nuestra brújula y el norte magnético.</span> <span style="font-family: Verdana;"> </span><span style="background-color: white;"><span style="font-family: Verdana;">Además de usar el conversor AD, el proyecto nos servirá para introducir el tema de optimización de rutinas matemáticas cuando estamos usando microcontroladores. En particular en este proyecto tenemos que usar la función arco tangente para obtener el ángulo a partir de las medidas ma y mb. Veremos una implementación aproximada de dicha función, adecuada para la precisión requerida en este proyecto y con bastante menos carga (tanto de código como computacional) que la rutina matemática (atan2) </span><span style="font-family: Verdana, sans-serif;">suministrada con el compilador.</span></span></div>
<div style="margin: 0cm 0cm 0.0001pt; text-align: justify;">
<span style="background-color: white; font-family: Verdana, sans-serif;"><br /></span></div>
<div style="margin: 0cm 0cm 0.0001pt; text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><span style="background-color: white;">El</span><span style="background-color: white;"> siguiente cutrevideo trata de dar una idea del resultado final. </span></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dy3lfnwAjuonqddUkfOk0B41SV5n3dEEJGWVzBohFOjMaF-nrElYgQyM7N2vgHVK34UXe3c-mj9enRiCBK4Cw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span lang="PT-BR" style="font-family: Verdana;">Código asociado
a esta entrada:<span class="apple-converted-space"> </span> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/brujula1.c">brujula1.c</a>,
<a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/brujula2.c">brujula2.c</a></span></div>
<div class="MsoNormal">
<span lang="PT-BR"></span></div>
<a name='more'></a><span style="background-color: white; font-size: 13.5pt;">------------------------------------------------------------------------------------</span><br />
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<b><u><span lang="PT-BR"><span style="font-family: Verdana, sans-serif;">Hardware:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></span></u></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span><br />
<div style="text-align: justify;">
<span style="font-family: Verdana;"><span style="font-family: Verdana;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9J1RK0CLg7GqA7moDJM5iww1r2-CRY-TuL6uOmibVCRUPx7bMmlo6I9yjB6IXXt2p_IfehqxxbHdEz47tn10rwhyphenhyphenESG205MS9ZlXl6YnyzlfJQpPy-cdWCCD7VAFpBTBO_7WSQsN_/s1600/S-SEN-00761.jpg.thumb_150x150.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9J1RK0CLg7GqA7moDJM5iww1r2-CRY-TuL6uOmibVCRUPx7bMmlo6I9yjB6IXXt2p_IfehqxxbHdEz47tn10rwhyphenhyphenESG205MS9ZlXl6YnyzlfJQpPy-cdWCCD7VAFpBTBO_7WSQsN_/s320/S-SEN-00761.jpg.thumb_150x150.jpg" width="320" /></a></span><br />
<div class="MsoNormal" style="text-align: start;">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><span style="font-family: Verdana;">Para el sensor, hemos usado una placa de SparkFun que usa el sensor HMC1052L de Honeywell</span><span style="font-family: Verdana;">. El sensor mide el campo mágnetico en dos ejes A y B perpendiculares. Un circuito amplificador multiplica por 100 dichas señales y las pone a disposición del usuario en dos pines etiquetados como OUT1 y OUT2. Dichas salidas se conectan a los pines RA0 y RA1 del micro, usados como entradas analógicas. L</span><span style="background-color: white; font-family: Verdana;">os otros contactos son alimentación a 5V (Vcc) y masa (GND). Un quinto pin etiquetado como SET sirve para "recondicionar" el sensor si se ha visto sometido a un campo excesivo. En este montaje no lo he usado y está conectado a masa.</span></span></div>
</div>
<div class="MsoNormal" style="text-align: start;">
</div>
</div>
<div style="text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwxHmSHb57K9wVOIYKT-CmyZk1cPJUPaHMBun3Cb2LLs70wFW6X9XCl5OD6ZTs3-Gyb6o2kOKdVB6kkj4jxMrXErnvhavLzqzykNRP0B1biocCx0haEo0SInVovmd6sbgPNeRiZ9k/s1600/esquema.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTwxHmSHb57K9wVOIYKT-CmyZk1cPJUPaHMBun3Cb2LLs70wFW6X9XCl5OD6ZTs3-Gyb6o2kOKdVB6kkj4jxMrXErnvhavLzqzykNRP0B1biocCx0haEo0SInVovmd6sbgPNeRiZ9k/s320/esquema.jpg" width="320" /></a><span style="font-family: Verdana;"><span style="font-family: Verdana;"><br /></span></span></div>
<div style="text-align: justify;">
<div class="MsoNormal" style="text-align: start;">
<div style="text-align: justify;">
<span style="font-family: Verdana;">SparkFun ya no vende esta placa pero podéis encontrar otras similares, aunque algunas de ellas ya no dan una salida analógica, sino que comunican sus datos a través de una comunicación serie (SPI o similares).</span></div>
</div>
<div class="MsoNormal" style="text-align: start;">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="text-align: start;">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El único otro hardware usado será el puerto serie que usaremos para mandar los resultados al PC.</span></div>
</div>
</div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><span style="font-family: Verdana;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><span style="font-family: Verdana;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><span style="font-family: Verdana;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><span style="font-family: Verdana;"><br /></span></span></div>
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Calibración del sensor:</span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Antes de
escribir el programa principal debemos considerar la cuestión de la calibración
del sensor. La documentación nos indica que en ausencia de campo magnético en
un eje el voltaje en la salida es nominalmente Vcc/2, lo que correspondería a
un valor numérico de alrededor de 512 del ADC. A partir de ahí el voltaje puede
subir (>512) o bajar (<512) si se detecta un campo magnético positivo o negativo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El sensor
da un valor negativo (menor que Vcc/2 ) si le enfrentamos a un polo sur
magnético:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;">--</span><span style="font-family: Wingdings;">à</span><span lang="PT-BR" style="font-family: Verdana;"> A S
-> voltaje "negativo"
< 512<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;">--</span><span style="font-family: Wingdings;">à</span><span lang="PT-BR" style="font-family: Verdana;"> A N
-> voltaje "positivo" >
512<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Esto
implica que el sensor dará un valor negativo cuando el eje A apunte al Norte
magnético (que para aumentar la confusión es el equivalente a un polo Sur de un
imán (y la razón por la que los polos norte de nuestras brújulas apuntan hacia
él). Para seguir la convención de la
figura anterior deberemos cambiar el signo a las componentes medidas por el
sensor.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
problema es que el valor "medio" de 512 es puramente nominal. En esta
placa es obtenido con un divisor de voltaje por lo que puede variar ligeramente
debido a la tolerancia de las resistencias.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Hay varias
formas de fijar de forma más precisa este sesgo. Una de ellas es girar la placa
hasta encontrar el voltaje mínimo en un eje, anotarlo, y girar la placa 180º
hasta encontrar su máximo. La media de ambos valores será el "cero"
buscado. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Para el
canal A he encontrado un mínimo de 508 y un máximo de 534, lo que da un punto
medio de 521. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Otro procedimiento
es girar la placa durante un rato mientras calculamos hacemos una media de los
valores medidos. De esta forma obtenemos unos valores medios de 521 y 522 para
ambos canales respectivamente.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como se
observa el rango de valores en el que nos movemos es reducido (+/- 15 máximo). La
consecuencia de </span><span style="font-family: Verdana;">esta baja
resolución es que (en el peor de los casos) un cambio de 1 unidad en la medida
de un eje puede suponer un cambio de hasta 1/15 rads (4º) en la orientación. De
hecho la documentación del sensor recomienda usar un ADC de 12 a 16 bits si se
requiere precisión. Indican que con un conversor de 8-10 bits nos encontramos
limitados a una precisión de 3-5º. Esto
es compatible con los valores encontrados.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> <b><u>Sotfware:</u></b><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Una vez
efectuada la calibración, el programa para nuestra brújula (por lo menos en su
primera versión) será poco más de lo que vimos cuando presentamos el conversor AD.
Tras los
#include y #pragmas habituales hacemos algunas definiciones y usamos la
función ADC_Read que escribimos para leer un canal.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_CR putc((</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)0x0D,stdout)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_LF putc((</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)0x0A,stdout)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CH_A 0 </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Channel A in RA0</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CH_B 1 </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Channel
B in RA1</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> USE_360 </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// (0º
-> 360º) instead of (-180º -> 180º)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(ch) { ADCON0 &= 0b11000011; ADCON0 += (ch<<2); }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 ADC_read(uint8 ch)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 res; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(ch);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(ADCON0bits.GO);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">res = ADRESH; res=(res<<8)+
ADRESL;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> res;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En el
programa principal, configuraremos el puerto serie (para enviar resultados) y
el conversor ADC:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> main(</span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
int16 rr;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
int16 res1,res2;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">float</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> rumbo;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
TRISC=0; PORTC=0; </span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">
// Configure ADC<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> TRISAbits.TRISA0=1; TRISAbits.TRISA1=1; </span><span lang="FR" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// RA0,RA1
inputs</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
OpenADC(ADC_FOSC_16 & ADC_RIGHT_JUST & ADC_4_TAD, </span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
ADC_INT_OFF & ADC_VREFPLUS_VDD & ADC_VREFMINUS_VSS, 7);<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Configure USART @ 9600 (20 MHz)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_TX_INT_OFF &
USART_RX_INT_OFF & USART_ASYNCH_MODE & </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> USART_EIGHT_BIT & USART_BRGH_HIGH
, 129); </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> puts(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"Electronic Compass (ver 0.0)"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">); send_CR; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Send start message to USART</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(250); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 1/2 sec</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> res1 = ADC_read(CH_A)-521; res2 =
ADC_read(CH_B)-522; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> res1=-res1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//res2=-res2; // positive for
eastern deviations</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New';"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">PORTCbits.RC0=1; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rumbo=atan2((</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)res2,(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)res1); rumbo=rumbo*57.2958; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//degrees</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#ifdef</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> USE_360</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(rumbo<0) rumbo+=360; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 0-360</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#endif</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rr=(int16)rumbo;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">printf(</span><span style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"(CH_A=%4d) (CH_B=%4d)
-> %d\n"</span><span style="font-family: 'Courier New'; font-size: 8pt;">,res1,res2,rr); send_CR; </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Tras la
configuración entramos en un bucle while tomando 2 medidas por segundo del
campo magnético en ambos ejes. Tras
restar los sesgos (521,522) a las medidas cambiamos su signo. Notad que el
signo del canal B (res2) no cambia (o lo que es lo mismo cambia dos veces). El
segundo cambio de signo es para seguir el criterio convencional de las brújulas
de que si nuestro eje A apunta al este del norte magnético obtenemos una
declinación positiva.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Una vez
hechas estas correcciones basta llamar a la función arco tangente (atan2) para
estimar el ángulo de discrepancia con el norte (o sur) magnético. Al contrario
que la función atan(y/x) la función atan2(x,y) recibe los argumentos (x,y) por
separado, lo que le permite discriminar en que cuadrante se encuentra el
ángulo. La función atan2 devuelve su valor en radianes, por lo que
multiplicamos por 57.2958 (= 180/pi) para obtener grados. Si queremos valores
entre 0 y 360º deberemos corregir (sumar 360) si el ángulo resultante es
negativo.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbRgJ6En_yPs3uQs87CXHqAgnfJXSfeIgt-esHZ4sNskigG6NBrhpXvNeycyKMihzIQRdh3ZWdsOo8XaJarEbLGC7RZzMEAuFvBTGbSJlSyW3N_bjXhMOFcpLTTr-ZYqaa-bcBD587/s1600/salida.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbRgJ6En_yPs3uQs87CXHqAgnfJXSfeIgt-esHZ4sNskigG6NBrhpXvNeycyKMihzIQRdh3ZWdsOo8XaJarEbLGC7RZzMEAuFvBTGbSJlSyW3N_bjXhMOFcpLTTr-ZYqaa-bcBD587/s200/salida.jpg" width="200" /></a><span style="font-family: Verdana;">La captura de la derecha muestra la salida del
puerto serie. El campo en el canal A es casi nulo, lo que indica que dicho eje
es perpendicular al campo magnético, por lo que la declinación es de unos 90º.
También se observa que dada la escasa resolución, un salto de 1 en el canal A
supone unos 4º de cambio, pasando de 86º a 90º sin saltos intermedios. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTsvjOkEuzpOWJNTKLkVwtIq-zptpoufrcaQlNanDqv5dQPCTb3I_ipYWVoMMML5JT8jRdSU6vywDvrBuWvjmTSwYJkCRJi1TcBsD9QsScLpnrm8rpIGEaUaNyXjD7T9W84uj4dykK/s1600/salida_buffer.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTsvjOkEuzpOWJNTKLkVwtIq-zptpoufrcaQlNanDqv5dQPCTb3I_ipYWVoMMML5JT8jRdSU6vywDvrBuWvjmTSwYJkCRJi1TcBsD9QsScLpnrm8rpIGEaUaNyXjD7T9W84uj4dykK/s200/salida_buffer.jpg" width="200" /></a><span style="font-family: Verdana;">Es posible
reducir estos saltos si en lugar de tomar una medida tomamos una serie (8 o 10)
medidas muy cercanas entre si, sumando sus resultados y llamando a la función
atan2 con los resultados acumulados. No haría falta calcular la media, ya que
la función atan2 no cambia si ambos argumentos están multiplicados por el mismo
valor. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La segunda
captura muestra la salida usando la acumulación de 8 valores. El valor del
canal B es ahora de 122-124 en vez de 15-16 (15 x 8 = 120). Ahora la salida muestra menos saltos,
mostrando cambios de alrededor de 1º. La contrapartida es que cada medida no
corresponde a un instante de tiempo, sino a un promedio durante el tiempo que
hemos tardado en tomar las 8 medidas. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana;">Optimización:</span></u></b><span style="font-family: Verdana;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwISMDA-Lrs4N0X4NUiZ5gzYNPV-aq2hF9IMvgld2xcFRDR3KhWT2pello9c3afaINzVxRID3grjrW8142Hm486t1NpKB9R-hUY2PPGJZv70gfJ9IbQdZAzsuwIuvE_ryCV6IlKlHM/s1600/atan_float_timing.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwISMDA-Lrs4N0X4NUiZ5gzYNPV-aq2hF9IMvgld2xcFRDR3KhWT2pello9c3afaINzVxRID3grjrW8142Hm486t1NpKB9R-hUY2PPGJZv70gfJ9IbQdZAzsuwIuvE_ryCV6IlKlHM/s320/atan_float_timing.jpg" width="320" /></a><span style="font-family: Verdana;">El código
anterior es sencillo porque su principal complicación, el cálculo del arco
tangente, ha sido llevada a cabo por la función atan2 del compilador que usa
aritmética de coma flotante. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El problema (no en esta, pero si en otras
aplicaciones) es que usar este tipo de funciones tiene un alto coste en un
microcontrolador de 8 bits. Este coste es debido a la alta precisión
suministrada por la función atan2. </span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La salida de dicha función tiene una
precisión del orden de 10^-8 (la precisión de la representación en coma
flotante usada, usando 4 bytes por número real). Este error es del orden de una
millonésima de grado. Dicha precisión es totalmente innecesaria, dada la
imprecisión de los datos de partida de nuestros sensores (como ya vimos,
nuestra resolución no es mucho mejor de un grado). <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Esta innecesaria precisión tiene un coste tanto en
tamaño de código como en velocidad de ejecución. La función añade 2K words al
tamaño del código, lo que podría ser un problema en muchos microcontroladores,
o en un proyecto más complicado donde estemos cerca del límite de la memoria de
programa del microcontrolador.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En cuanto
al tiempo de ejecución, el pantallazo adjunto muestra la duración del computo
del ángulo, mediante el socorrido método de poner a 1 la línea RC0 y bajarla
tras terminar el cálculo. Vemos que tarda 1.75 msec. De hecho esta duración es
variable, ya que dependiendo del ángulo resultante el cálculo puede tardar más
o menos. Esto implica que sería imposible actualizar el ángulo más de unas 600
veces por segundo. En este proyecto esto no resulta un problema (ya que en una
brújula electrónica basaría con refrescar la pantalla unas 10/20 veces por
segundo) pero en otros puede ser insuficiente. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Si no
deseamos tanta precisión y tenemos escasez de recursos podemos hacer nuestra
propia implementación de la función, adaptándola a la precisión requerida. Una
posibilidad es construir una tabla de valores, interpolando entre ellos. El
tamaño de la tabla vendrá dictado por nuestros requerimientos de precisión (en
este caso del orden de un grado).<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Otra
alternativa (la que veremos aquí) es construir una aproximación a la función
atan2 usando aritmética entera (para que sea más rápida) usando un algoritmo de
tipo CORDIC (COordinate Rotation DIgital Computer). También en este caso es
posible ajustarse a la precisión requerida, no haciendo más trabajo del
necesario.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Los algoritmos
CORDIC (<a href="http://en.wikipedia.org/wiki/CORDIC">http://en.wikipedia.org/wiki/CORDIC</a>)
se usan para calcular funciones trigonométricas (y otras) basándose en
rotaciones de un vector en el plano complejo. En este caso, se parte de un
vector de coordenadas (x,y) que forma un ángulo theta con la horizontal.
Obtener dicho ángulo es nuestro objetivo. El algoritmo se divide en dos partes:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><span style="font-family: Verdana;">Se
rota el vector hasta reducirlo a un ángulo más cercano a cero. La gracia es
usar rotaciones con ángulos cuyas tangentes sean 1, 0.5, 0.25, etc. (45.0º, 26.55º, 14.03º, etc.). El interés de estos ángulos es que
posibilitan rotaciones que sólo involucran sumas y desplazamientos de bits
(multiplicaciones x2).<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><span style="font-family: Verdana;">Una
vez reducido el ángulo a un valor suficientemente pequeño (dependiendo de la
precisión requerida) se estima su arco tangente aprovechando el hecho que
atan(x) es similar a x para x pequeñas.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';">
</span></span><span style="font-family: Verdana;">Se
suma el ángulo obtenido a los usados en las rotaciones y se obtiene una
aproximación de la función arco tangente.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La ventaja
de este método (además de no usar multiplicaciones) es que es posible hacer más
o menos trabajo en función de la precisión deseada. El siguiente código
implementa la función atan2 con un error máximo de 1/64º<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// atan2 function
using integer arithmetic</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// The arguments must
be positive and below 512: 0<=(x,y)<=512</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Returns the angle
in units of 1/128 degrees</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Works only for the
1st quadrant (0<=angle<=90º)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Needs additional
code to determine the quadrant and return an angle between 0 and 360º</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Maximum error does
not exceed 2 units = 2/128 = 1/64 = 0.015º</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Error variance is
about 0.78 units = 0.006º</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Within the 0-45º
range: 45% error=0, 52% error=1, 2%
error=2</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">uint16 int_atan2(uint16 y, uint16 x)</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> uint16
angle,y2,t;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 ang[4]={5760, 3400, 1797, 912}; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
atan(1,1/2,1/4,1/8) in 1/128º units</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 k,bbb;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Singular cases</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (y==0) {</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 0; } </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
0º</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span style="font-family: 'Courier New'; font-size: 8pt;"> (x==0) {</span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> 11520;} </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 90º</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> <span lang="EN-GB">angle=0;</span></span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ((y<<3)>x)
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//If I'm above atan(1/8) rotate until
atan<=1/8 -> x < 8y</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<4;k++)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> t = (y<<k);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (t>=x) { angle+=ang[k]; y2=y; y = t-x; x = (x<<k)+y2; }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Computes integer approximation for y/x. </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// The
result is placed in t = 1024 * 8 y/x
y/x=[0 1/8] -> t=[0 1024]</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">t=0;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> y <<=4; </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// y <- y*16</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">for</span><span style="font-family: 'Courier New'; font-size: 8pt;">(k=0;k<10;k++)</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> t<<=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (y>=x){y-=x; t++;}</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> y<<=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (y>=x) t++;
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// final rounding</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Apply
lineal interpolation to y/x=t :: 1024 -> 912 = 7.125º = atan(1/8)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> t *=57; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 912/1024 aprox. 57/64 </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> t>>=5;
bbb=t&0x01; t>>=1; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (bbb) t++; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// divide by 64 with rounding</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> angle = angle+t+1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Add the interpolated angle to the previous rotation</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> angle;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Algunos
comentarios:</span></div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<ul>
<li><span style="font-family: Verdana;">La
función asume x ,y >=0 (primer cuadrante). Para implementar la función para
cualquier ángulo se precisa añadir código adicional, chequeando los signos de
x,y y determinando el cuadrante resultante.</span></li>
<li><span style="font-family: Verdana;">La
precisión de 1/64º es todavía exagerada para nuestra aplicación. A base de no
bajar hasta un ángulo tan pequeño podemos construir una función más rápida
aunque menos precisa.</span></li>
</ul>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;">La
siguiente función tiene un error máximo de 1º y es por lo tanto adecuada para
nuestra implementación:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Rotate angle until
angle < atan(1/2)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Linear
interpolation using angle = (y/x)*53 + 0.5 </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Works in 1/2º units
and divide by 2 before returning the results (in degrees) </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">uint16 atan2_cordic(uint16 y, uint16 x)</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> uint16
angle;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> int16
t;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> uint8
b;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Singular cases</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (y==0) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 0; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (x==0) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 90; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 0º and 90º</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Rotate
until angle is below atan(1/2). </span><span lang="FR" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">Angle in 1/2º
units </span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> angle=0;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> t=y-x;
</span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">(t>=0)
{angle=90; x+=y; y=t;}</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> t=(y<<1)-x; </span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">(t>=0) {angle+=53; x<<=1; x+=y; y=t;}</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">y*=106; y/=x; y++;
</span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// (x/y)*106 + 1</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> angle+=y; </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Add previous rotation</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">b=angle&0x01; angle>>=1; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (b) angle++; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
divide by 2 with rounding</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> angle;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Esta
gráfica muestra el error (en grados) de esta aproximación para todos los
valores de x,y entre 0 y 200:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFUzi0LqqaS_OhTXhdO69DLy-VFK_22Bpjk8uYHxBxrlZRU8ehQSud6-XI7iyvhSxjp3i8tpL2odvc-fIqVuxomuCvJyFlaAit6aoF6t5ptTc3ZBGwT2PzAMfCG5CayV1mDf2K6mlA/s1600/errores.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFUzi0LqqaS_OhTXhdO69DLy-VFK_22Bpjk8uYHxBxrlZRU8ehQSud6-XI7iyvhSxjp3i8tpL2odvc-fIqVuxomuCvJyFlaAit6aoF6t5ptTc3ZBGwT2PzAMfCG5CayV1mDf2K6mlA/s640/errores.jpg" width="640" /></a></div>
<div class="MsoNormal">
<br /></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El
s¡guiente código (en brujula2.c) muestra las dos formas alternativas de calcular
la función arco tangente, incluyendo también la determinación del cuadrante: <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Using atan2 library
function </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rumbo=atan2((</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)acum2,(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">float</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)acum1);
rumbo=rumbo*57.2958; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//degrees</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rr=(int16)(rumbo);<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Using
approximation </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> r1=acum1; </span><span lang="PT-BR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> (r1<0) r1=-r1;</span><span lang="PT-BR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> r2=acum2;
</span><span lang="PT-BR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> (r2<0)
r2=-r2; </span><span lang="PT-BR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rr
= atan2_cordic(r2,r1); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Computes angle in 1<sup>st</sup> quad (0,90º) using
abs values </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Determines quad and modify angle (-180, 180) accordingly </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span style="font-family: 'Courier New'; font-size: 8pt;"> (acum1<0)
rr-=180;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span style="font-family: 'Courier New'; font-size: 8pt;">
(acum1*acum2<0) rr=-rr; </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span style="font-family: 'Courier New'; font-size: 8pt;">
((acum1==0)&&(acum2<0)) rr-=180;</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
</div>
<div class="MsoNormal">
<br />
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">El ahorro tanto en código como en velocidad es considerable. Nuestro nuevo código (función + código para determinar los cuadrantes) ocupa en total menos de 200 palabras, frente a las 2000 de la función de la librería. Un factor x10 en reducción del tamaño del código.</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbVDJkjtm_QZECFgmW09LHoqjDRXj2y38ey5hk3RzMCrs4iqFXj-AfBUqPYc373zGwx1a11Uz_EvbqelDw2epi-hc1MQNWyjCy3sMJiROUNh6ctZKqVaKhZ-rfeJvEOowci1SywUSg/s1600/comparacion_atan.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbVDJkjtm_QZECFgmW09LHoqjDRXj2y38ey5hk3RzMCrs4iqFXj-AfBUqPYc373zGwx1a11Uz_EvbqelDw2epi-hc1MQNWyjCy3sMJiROUNh6ctZKqVaKhZ-rfeJvEOowci1SywUSg/s320/comparacion_atan.jpg" width="320" /></a></div>
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En cuanto
a la velocidad, la gráfica adjunta ilustra el tiempo necesario para
ejecutar la nueva función (amarillo) frente a la librería (azul, derecha). Unos
0.1 ms frente a los 1.75 ms de antes. Una ganancia de casi un factor 20. En
azul, a la izquierda, el pulso más estrecho muestra el tiempo (unos 0.25 ms)
usado por la primera función que vimos, con un error máximo de 1/64º. Puede ser
una buena opción si queremos mayor precisión, pero sin llegar a la millonésima de grado que nos ofrece la función de
librería.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 8pt;"><span style="background-color: white; font-size: 8pt;"> </span> </span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com2tag:blogger.com,1999:blog-4945680608471335280.post-78702557182864229202012-07-13T13:41:00.001+02:002013-06-10T11:16:02.271+02:00Conversor ADC<br />
<div class="MsoNormal">
<span style="font-family: Verdana;">En otro tutorial vimos como
el módulo PWM funcionaba como una especie de conversor digital -> analógico
(DAC). El conversor analógico-digital (ADC) que equipa a muchos
microcontroladores hace justo lo contrario, convirtiendo un voltaje analógico externo
en un número, con el que podremos operar. <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Como
siempre empezaremos con una introducción sobre los fundamentos de un conversor
AD y los registros usados para su manejo en los PIC. Tras entender el proceso, presentaremos
las rutinas de C18 para el manejo del ADC y escribiremos nuestras propias
funciones, que nos permitirán optimizar el rendimiento del ADC y no depender de
un compilador en particular.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">En la
siguiente entrada veremos como al igual que pasaba con el puerto serie, usando
interrupciones podemos optimizar el rendimiento del PIC mientras estamos usando
el conversor AD.<o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-family: Verdana;">Codigo asociado a esta entrada:<span class="apple-converted-space"> </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/adc1.c"> adc1.c</a></span></div>
<div class="MsoNormal">
<o:p></o:p></div>
<a name='more'></a><br />
<div style="margin-bottom: .0001pt; margin: 0cm;">
<div style="text-align: justify;">
------------------------------------------------------------------------------------------<o:p></o:p></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Conceptos básicos de un ADC:<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Un
ADC convierte mide el voltaje V en un pin (que tendrá que estar declarado como
entrada con el correspondiente registro TRISA) y lo convierte en un número. El
voltaje se mide en referencia a un voltaje mínimo, Vref(-) , y a un voltaje
máximo, Vref (+):</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 9.0pt;">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 9.0pt;">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> </span><span style="font-family: Verdana, sans-serif;"> </span><span lang="FR" style="font-family: Verdana; font-size: 8.0pt; mso-ansi-language: FR;"><span style="font-family: Verdana, sans-serif;">V_norm = ( V –
Vref(-) ) / (Vref(+) –Vref(-) )</span><o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="margin-left: 9.0pt;">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">La
fórmula anterior corresponde a un voltaje normalizado. Si el voltaje V alcanza
el máximo (Vref+) tendremos una salida de 1 y si se queda en el mínimo (Vref-)
una salida de 0.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Normalmente
Vref- suele ser Vss=GND=0V y Vref+ = Vcc = 5V, pero pueden usarse otros
voltajes de referencia. Si por ejemplo queremos medir una señal que sabemos que
oscila entre 2 y 3 voltios usaríamos Vref-=2 y Vref+=3. Así aprovecharíamos
mejor el rango dinámico del conversor.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 9.0pt;">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Como
el microcontrolador no va a manejar números en coma flotante, el voltaje
normalizado se expresa con un entero, convirtiendo el intervalo real [0,1] en
el intervalo de niveles enteros entre [0 y Nmax-1]. La resolución del ADC es
una característica fundamental y nos dice el número de niveles con los que
cubrimos el intervalo [0,1]. Por ejemplo, en los PIC solemos tener una
resolución de 10 bits, que representan 2^10=1024 niveles. El intervalo real
[0,1) se aplicaría al intervalo [0,1023]. Si asumimos un rango de 5V, tendremos
que la resolución de cada nivel es de r=5/1024 V=4.88 mV. Según la
documentación de Microchip (esto puede variar para otros microcontroladores)
cualquier voltaje entre [0 y r] (o por debajo de 0, lo que corresponde a V<Vref-) se cuantificaría en el nivel 0.
Entre r y 2r tendríamos una salida de nivel 1. Así hasta llegar a nivel 1023
que cuantificaría voltajes por encima de 1023r = 1023x 5/1024 = 4.995V. Como se
ve, voltajes por debajo de Vref- o por encima de Vref+ son posibles y se
cuantifican como nivel mínimo 0 o máximo, 1023.
Niveles por debajo de 0V o por encima de la tensión de alimentación
(normalmente 5V) pueden ser dañar el PIC.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 9.0pt;">
<div style="text-align: center;">
<br /></div>
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 162.0pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 13.4pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 13.4pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">Nivel<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 13.4pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">Voltaje<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.75pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;"><r<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 13.4pt; mso-yfti-irow: 2;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 13.4pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 13.4pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">[r,2r]<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.75pt; mso-yfti-irow: 3;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">[2r,3r]<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.75pt; mso-yfti-irow: 4;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">…<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">…<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.75pt; mso-yfti-irow: 5; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">1023<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.75pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.3pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">>1023r<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal" style="margin-left: 9.0pt;">
<div style="text-align: center;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Aunque
un PIC puede tener del orden de 8-12 posibles canales (pines) de entrada
analógica, solo tiene normalmente un único módulo ADC, lo que significa que no
podemos tomar medidas simultáneas de varios canales. Si es necesario, lo que
podemos hacer es ir conectando (seleccionando) los sucesivos canales al ADC
para ir midiendo sus voltajes.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">El
proceso de una conversión ADC se divide en un </span><b style="font-family: Verdana;">tiempo de adquisición Ta</b><span style="font-family: Verdana;"> (durante
el cual un condensador interno se carga al voltaje exterior) y un </span><b style="font-family: Verdana;">tiempo de
conversión Tc</b><span style="font-family: Verdana;"> (durante el cual se desconecta el pin exterior y se cuantifica el
voltaje del condensador).</span></li>
</ul>
<ul>
<li><span style="font-family: Verdana;">El
tiempo de adquisición Ta depende de las características eléctricas del PIC (en
particular de la capacidad del condensador). Si no se respeta este tiempo, el
condensador no habrá alcanzado el nivel del voltaje exterior y la medida será
incorrecta. Los datasheet de los PIC indican los Ta recomendados para diversas
familias.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Otro
aspecto importante de la adquisición es recordar que Microchip recomienda una </span><b style="font-family: Verdana;">impedancia máxima</b><span style="font-family: Verdana;"> para el sensor (o lo
que sea) suministrador de voltaje que está conectado a nuestro pin. En la
mayoría de los casos se recomienda que dicha impedancia no supere los </span><b style="font-family: Verdana;">2.5 Kohmios</b><span style="font-family: Verdana;">. Según entiendo con mis
escasos conocimientos de electrónica, impedancias mucho mayores harían que
(debido a corrientes de pérdida siempre presentes) el condensador no llegara
nunca a cargarse al voltaje de entrada o tardase mucho en hacerlo, lo que daría lugar a que la medida
posterior fuese incorrecta. Si la impedancia de nuestra fuente es muy superior a
la recomendada deberíamos plantearnos insertar un driver.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 18.0pt; mso-list: l0 level1 lfo1; tab-stops: list 18.0pt; text-indent: -9.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">El
tiempo de conversión Tc depende fundamentalmente del número de bits del
conversor. La unidad básica es el llamado Tad, aproximadamente el tiempo
necesario para ganar un bit adicional. La conversión total tarda entre 11 y 14
Tad (contando con la descarga final del condensador para estar listo para otra
medida. El reloj del ADC se debe ajustar (como una fracción del oscilador
principal) para que dicho Tad no sea inferior a un valor mínimo especificado en
los datasheet. Por ejemplo para la familia PIC18F252/452 el Tad mínimo es de
1.6 usec y Tc = 14 Tad. En cambio para la familia PIC18F2520/4520 tenemos un
Tad mínimo de 0.75 usec y un Tc = 11 Tad.</span></li>
</ul>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Un
comentario final: aunque es muy conveniente tener un ADC integrado dentro del
microcontrolador, si lo pensamos en términos de nivel de ruido, etc. las
cercanías de un microcontrolador con la líneas de reloj, rápidos cambios en las
líneas digitales, comunicaciones, etc. no es el mejor sitio para ubicar un ADC.
Esto quiere decir que si estamos muy interesados en la precisión, tal vez sería
conveniente considerar un ADC aparte, que nos comunicaría los datos adquiridos a
través de SPI o similares. Una vez dicha la advertencia nos centraremos en como
usar de la forma más eficiente el ADC de un microcontrolador (en este caso un
PIC).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Los registros de control del ADC en
un PIC (familia 18F 2520/4520)<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Para estos
ejemplos voy a usar código para la familia PIC18F2520/4520 con algunos
comentarios sobre la familia 252/452. El conversor AD es una de los módulos de
un PIC donde hay más diferencias entre modelos: distintos número de canales AD,
diferentes formas de programar que canales son digitales o analógicos, la
posibilidad o no de programar tiempos de adquisición, etc.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Esto hace
que la configuración del ADC sea bastante dependiente del modelo y siempre sea
bueno tener a mano la documentación ante comportamientos inesperados. Por
ejemplo, los registros asociados al puerto serie son los mismos entre una
amplia gama de dispositivos. Por el contrario, es fácil que el número de
registros de configuración cambie entre modelos.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La familia
PIC18F2520 tiene 3 registros de control asociados al ADC (ADCON0, ADCON1 y
ADCON2). Por el contrario, la familia 252/452, al tener menos funcionalidades,
sólo necesita 2 (ADCON0 y ADCON1). De todas formas, los nombres y funciones de
los bits comunes serán los mismos que los aquí descritos, aunque pueden estar
situados en diferentes registros.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Además de
los registros de control tenemos otros dos registros ADRESH y ADRESL (AD result
High/Low) donde se guarda el resultado de la conversión, pero estos si son
comunes entre dispositivos.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Veamos un
resumen de estos registros (de nuevo, los datasheet de Microchip son los
mejores manuales de usuario):<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Registro ADCON0:</span></u></b><span style="font-family: Verdana;"> permite seleccionar (CHS) el canal
del que tomaremos la medida. También tiene el bit que habilita el conversor
(ADON) y que arranca (GO) el proceso de conversión.<b><u><o:p></o:p></u></b></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 12.0pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.9pt;" valign="top" width="71"><div class="MsoNormal">
<span style="font-family: Verdana;">Bit #<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 51.5pt;" valign="top" width="69"><div class="MsoNormal">
<span style="font-family: Verdana;">Bit 7<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 6<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 58.3pt;" valign="top" width="78"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 5<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 53.8pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 53.8pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 3<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 41.1pt;" valign="top" width="55"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 2<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 1<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 0<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.0pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.9pt;" valign="top" width="71"><div class="MsoNormal">
<span style="font-family: Verdana;">Nombre<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 51.5pt;" valign="top" width="69"><div class="MsoNormal">
<span style="font-family: Verdana;">X<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">X<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 58.3pt;" valign="top" width="78"><div class="MsoNormal">
<span style="font-family: Verdana;">CHS3<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 53.8pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">CHS2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 53.8pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">CHS1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 41.1pt;" valign="top" width="55"><div class="MsoNormal">
<span style="font-family: Verdana;">CHS0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">GO<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">ADON<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.0pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.9pt;" valign="top" width="71"><div class="MsoNormal">
<span style="font-family: Verdana;">Función<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 51.5pt;" valign="top" width="69"><div class="MsoNormal">
<span style="font-family: Verdana;">No usado<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;"> No</span><br />
<span style="font-family: Verdana;"> usado<o:p></o:p></span></div>
</td>
<td colspan="4" style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 207.0pt;" valign="top" width="276"><div class="MsoNormal">
<span style="font-family: Verdana;">Selección
de canal: </span><br />
<span style="font-family: Verdana;">desde 0 (0000) a 12 (1100)<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">Lanza
ADC<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">ON/OFF<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">ADON</span></b><span style="font-family: Verdana;">: Encendido (1) o apagado (0) del
modulo ADC.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">GO</span></b><span style="font-family: Verdana;">
: Se pone a 1 para iniciar el proceso de conversión. Cuando la
conversión ha terminado el módulo lo pone a 0. Así es como sabemos que podemos
recoger el resultado (en ADRESH/ADRESL)<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">CHS</span></b><span style="font-family: Verdana;">: selecciona cual de los posibles
13 canales analógicos se conecta al ADC para medir.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Registro ADCON1:</span></u></b><span style="font-family: Verdana;"> dedicado a seleccionar cuales de
los posibles canales se van a usar como entradas analógicas y a programar el
uso o no de voltajes de referencia externos (distintos de los valores 0 y 5V
por defecto)<b><u><o:p></o:p></u></b></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 12.0pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.6pt;" valign="top" width="57"><div class="MsoNormal">
<span style="font-family: Verdana;">Bit #<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.8pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 7<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 6<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 67.3pt;" valign="top" width="90"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 5<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 53.8pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 40.9pt;" valign="top" width="55"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 3<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 2<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 1<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 0<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.0pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.6pt;" valign="top" width="57"><div class="MsoNormal">
<span style="font-family: Verdana;">Nombre<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.8pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">X<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">x<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 67.3pt;" valign="top" width="90"><div class="MsoNormal">
<span style="font-family: Verdana;">VCFG1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 53.8pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">VCFG0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 40.9pt;" valign="top" width="55"><div class="MsoNormal">
<span style="font-family: Verdana;">PCFG3<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">PCFG2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">PCFG0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">PCFG0<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.0pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.6pt;" valign="top" width="57"><div class="MsoNormal">
<span style="font-family: Verdana;">Función<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.8pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">No usado<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">No</span><br />
<span style="font-family: Verdana;">usado<o:p></o:p></span></div>
</td>
<td colspan="2" style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 121.1pt;" valign="top" width="161"><div class="MsoNormal">
<span style="font-family: Verdana;">Uso (1)
de </span><br />
<span style="font-family: Verdana;">Vref (+),Vref(-)<o:p></o:p></span></div>
</td>
<td colspan="4" style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 217.3pt;" valign="top" width="290"><div class="MsoNormal">
<span style="font-family: Verdana;">Reparto canales </span><br />
<span style="font-family: Verdana;">digitales / analógicos <o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">VCFG1</span></b><span style="font-family: Verdana;">: por defecto (0) usamos Vss=Gnd=0V
como Vref-. Si es 1 se tomara como Vref-
el voltaje presente en AN2.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">VCFG0</span></b><span style="font-family: Verdana;">: Lo mismo que el anterior pero
para Vref+. Por defecto usaremos Vdd (alimentación, típicamente 5 o 3.3V) como
Vref+. Si es 1 se usa el voltaje presente en AN3 como Vref+.<o:p></o:p></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">PCFG:</span></b><span style="font-family: Verdana;">
Posiblemente no necesitaremos todos los posibles canales analógicos.
Estos bits permiten decidir cuales de los pines se dedican a canales analógicos
y cuales permanecen como canales digitales. Los valores posibles van desde 0000
(todos analógicos) a 1111 (todos digitales).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Los
canales analógicos se denotan en la documentación como AN0, AN1, AN2, etc. Los
dispositivos con 8 canales (252/452) los reparten entre el puerto A y el E. Los
que tienen 13 canales usan también parte del puerto B (2520/4520). Mirar la
documentación, porque el orden no es consecutivo. Por ejemplo, para el 4520<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 23.4pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 11.8pt;" valign="top" width="16"><div class="MsoNormal">
<span style="font-family: Verdana;">Canal<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN0<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN1<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN2<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN3<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN5<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN6<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN7<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN8<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN9<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN10<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN11<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">AN12<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 11.8pt;" valign="top" width="16"><div class="MsoNormal">
<span style="font-family: Verdana;">Pin<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RA0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RA1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RA2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RA3<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RA5<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RE0<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.55pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RE1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RE2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RB2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RB3<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RB1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RB4<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 34.6pt;" valign="top" width="46"><div class="MsoNormal">
<span style="font-family: Verdana;">RB0<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Registro ADCON2:</span></u></b><span style="font-family: Verdana;"> información para determinar los
tiempos Ta y Tc del conversor y la forma en la que el resultado (10 bits) se
guarda en ADRESH:ADRESL (16 bits).<b><u><o:p></o:p></u></b></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr style="height: 12.0pt; mso-yfti-irow: 0;">
<td style="border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.6pt;" valign="top" width="57"><div class="MsoNormal">
<span style="font-family: Verdana;">Bit #<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.8pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 7<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 6<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 5<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 4<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 3<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 2<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 1<o:p></o:p></span></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">bit 0<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.0pt; mso-yfti-irow: 1;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.6pt;" valign="top" width="57"><div class="MsoNormal">
<span style="font-family: Verdana;">Nombre<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.8pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">ADFM<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">x<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">ACQT2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">ACQT2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">ACQT2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">ADCS2<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 66.7pt;" valign="top" width="89"><div class="MsoNormal">
<span style="font-family: Verdana;">ADCS1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 55.7pt;" valign="top" width="74"><div class="MsoNormal">
<span style="font-family: Verdana;">ADCS0<o:p></o:p></span></div>
</td>
</tr>
<tr style="height: 12.0pt; mso-yfti-irow: 2; mso-yfti-lastrow: yes;">
<td style="border-top: none; border: solid windowtext 1.0pt; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 42.6pt;" valign="top" width="57"><div class="MsoNormal">
<span style="font-family: Verdana;">Función<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 52.8pt;" valign="top" width="70"><div class="MsoNormal">
<span style="font-family: Verdana;">Formato<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 54.0pt;" valign="top" width="72"><div class="MsoNormal">
<span style="font-family: Verdana;">No usado<o:p></o:p></span></div>
</td>
<td colspan="3" style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 162.0pt;" valign="top" width="216"><div class="MsoNormal">
<span style="font-family: Verdana;">Programación
T adquisición<o:p></o:p></span></div>
</td>
<td colspan="3" style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; height: 12.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 176.4pt;" valign="top" width="235"><div class="MsoNormal">
<span style="font-family: Verdana;">Reloj
del ADC<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">ADFM</span></b><span style="font-family: Verdana;">: Formateo del resultado. El
conversor da 10 bits que se guardan en dos registros (ADRESH:ADRESL) de 8 bits,
por lo que 6 de los 16 bits estarán vacíos. Si ADFM=1 el resultado está
desplazado a la derecha, por lo que los 6 bits más significativos de ADRESH
estarán vacíos. Si es 0 se justifica a la izquierda y son los 6 bits menos
significativos de ADRESL los que están vacíos.
El caso ADFM=1 se suele usar cuando nos interesan los 10 bits. El
resultado se puede pasar a un entero de 16 bits como: <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">
res = (ADRESH<<8)+ADRESL;<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El caso
ADFM=0 se suele usar si sólo queremos los 8 bits más significativos. En ese
caso basta hacer: res = ADRESH;</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">ACQT</span></b><span style="font-family: Verdana;">: bits para la programación del T
de adquisición. Recordar que el tiempo de adquisición es el que debemos esperar
después de seleccionar (conectar) un canal al ADC mientras se carga el
condensador cuyo voltaje posteriormente mediremos. Si escogemos 000 el usuario
es responsable de la espera (de unos pocos usec, especificada en la
documentación) entre la selección del canal (poner los bits CHS adecuados en
ADCON0) y el inicio del proceso de conversión (poner a 1 el bit GO de ADCON0). <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El modo
manual (000) era la norma entre familias anteriores, que de hecho no contaban
con estos bits de configuración. En la familia 2520/4520 es posible programar
dicho tiempo de espera. De esta forma tras seleccionar el canal podemos
inmediatamente lanzar la conversión (ADCON0.GO=1) y el módulo esperara el
tiempo programado antes de iniciar la conversión. Esto permite optimizar el
aprovechamiento del ADC como veremos.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El tiempo
de adquisición es la suma de varios factores, siendo los principales la
capacidad del condensador a cargar y el tiempo que tarda el amplificador del
ADC en estabilizarse. Es importante consultar el datasheet si queremos
optimizar el muestreo porque podemos encontrarnos bastantes diferencias entre
diversos modelos.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">ADCS</span></b><span style="font-family: Verdana;">: seleccionan la velocidad del reloj del ADC como una fracción (div = 2, 4, 8, 16, 32, 64)
del reloj principal (aunque también es posible asociarlo a un oscilador RC
independiente). El inverso de la frecuencia del ADC determina el llamado Tad,
que viene a ser el tiempo dedicado a obtener cada bit del resultado:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> F_ad = Fosc / div </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"> Tad = 1/F_ad = div / Fosc
(en microsec si Fosc está en MHz)<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Obviamente
deberíamos escoger un divisor bajo para obtener la frecuencia más alta (Tad más
pequeño) posible para tardar lo menos posible en cada conversión. Sin embargo
hay una limitación: el Tad no puede ser menor que un cierto tiempo mínimo dependiente
del modelo. Por ejemplo para la familia 252/452 se recomienda que Tad sea como
mínimo 1.6 usec. En cambio para la 2520/4520 podemos bajar a 0.75 usec.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Eso
significa que si tenemos un cristal de 20 Mhz, el divisor escogido sería:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">1:32 si tenemos un 452, ya que Tad = div / Fosc = 32/20
Mhz = 1.6 usec = recomendado<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">1:16 si
tenemos un 4520 ya que Tad = div / Fosc = 16/20 MHz = 0.8 usec > 0.75 usec
recomendados<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Nuestro primer programa con el ADC<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El proceso
a seguir para una conversión (según se describe en la documentación de Microchip)
es el siguiente:<o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l1 level1 lfo2; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ol>
<li><span style="font-family: Verdana;">Configurar
el ADC con la asignación de canales (PCFG), programar el reloj del ADC (bits
ADCS), seleccionar o no voltajes de referencia (VCFG), etc.</span></li>
<li><span style="font-family: Verdana;">Una
vez configurado, habilitar el ADC (ADON=1)</span></li>
<li><span style="font-family: Verdana;">Escoger
canal (bits CHS) a usar (el pin dado se conecta al condensador)</span></li>
<li><span style="font-family: Verdana;">Esperar
(delay) Ta mientras se carga el condensador (este paso puede ser evitado
programamos la espera)</span></li>
<li><span style="font-family: Verdana;">Lanzar
la conversión (GO=1)</span></li>
<li><span style="font-family: Verdana;">Esperar
a completar a que la conversión concluya (GO=0).</span></li>
<li><span style="font-family: Verdana;">Extraer
el resultado de ADRESH:ADRESL</span></li>
<li><span style="font-family: Verdana;">Si
hemos terminado con el ADC, apagarlo para reducir consumo.</span></li>
</ol>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Ahora que
conocemos los detalles escribiremos el primer programa para un PIC18F4520 usando
las rutinas de C18 y no tendremos dificultades en imaginar que está haciendo
cada rutina por debajo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Las
rutinas básicas para operar en C18 con el ADC pueden verse en este código
ejemplo del manual de C18:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> OpenADC(ADC_FOSC_16&ADC_RIGHT_JUST,
ADC_INT_OFF&ADC_VREFPLUS_VDD&ADC_VREFMINUS_VSS,7); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// (1)-(2)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> SetChanADC(ADC_CH0); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Paso 3)</span><span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> Delay10TCYx(5); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Paso 4) -> delay de
adquisición</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> ConvertADC(); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Paso 5)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">while</span><span style="font-family: 'Courier New'; font-size: 8pt;">( BusyADC()
); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Paso 6)
-> delay de conversion.</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> res = ReadADC(); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Paso 7) </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> closeADC(); </span><span style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt;">// Paso 8)</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vemos que
C18 tiene casi una función para cada paso del proceso. Por ejemplo, el
compilador MikroC Pro es mucho más monolítico, lo que lo hace más simple pero
menos adaptable. En MikroC Pro, todo lo anterior se resume en una sola llamada:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> <b>res = ADCRead(0);</b> que configura, selecciona canal 0, espera,
lanza conversión y cuando termina devuelve res.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Los
parámetros que recibe OpenADC son esencialmente los valores de ADCON0, ADCON1 y
ADCON3. Como siempre la ventaja es que damos valores a dichos registros
combinando diversas banderas más fáciles de recordar. Para aquellos
dispositivos con sólo disponen de ADCON0 y ADCON1 la función sólo usa dos
parámetros en vez de tres. Con SetChanADC seleccionamos (ADC_CH0) AN0=RA0 como
el pin cuyo voltaje vamos a medir. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Normalmente
la configuración del ADC se hace una sola vez y luego se hacen sucesivas
conversiones (posiblemente de diferentes canales). Podemos agrupar el código
anterior en una función que reciba como argumento el canal a muestrear y haga
todas las etapas (aunque como veremos más adelante, en ciertas circunstancias
es más eficiente "romper" la función para no tener una función
bloqueante):<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 ADC_read(uint8
ADC_channel)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 ad_res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> SetChanADC(ADC_channel);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10TCYx(5);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ConvertADC();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(BusyADC());</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ad_res = ReadADC();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> ad_res;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Una
llamada al código anterior mide el voltaje del canal deseado una sola vez. Si
el voltaje en el canal analógico está cambiando rápidamente, querremos muestrearlo
muchas veces por segundo para seguir sus cambios. Supongamos que queremos tomar
2000 muestras por segundo. A esto es a lo que se suele denominar una frecuencia
de muestreo de 2000 Hz. Con este ritmo, deberemos lanzar tomar una muestra cada
1/2000 seg = 0.2 msec = 200 usec/muestra.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">El código
quedaría:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> TRISB=0; TRISC=0; TRISAbits.TRISA0=1;<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: PT-BR;"> while</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="PT-BR" style="font-family: "Courier New"; mso-ansi-language: PT-BR; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=1; res=ADC_read(ADC_CH0);
PORTCbits.RC0=0; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTB=res>>2; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10TCYx(250);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="background-color: white;"> </span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<!--[if gte vml 1]><v:shape id="_x0000_s1028" type="#_x0000_t75"
style='position:absolute;margin-left:333pt;margin-top:1.4pt;width:125.5pt;
height:97.45pt;z-index:3'>
<v:imagedata src="file:///C:\DOCUME~1\antonio\CONFIG~1\Temp\msohtml1\01\clip_image003.jpg"
o:title="esquema_leds"/>
<w:wrap type="square" side="left"/>
</v:shape><![endif]--><!--[if !vml]--><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi93UYp3xPY3iJuCh-FF2A2FYlrfOwccuDjZMw1zAX-S0geClWgyDB1xw6ZnxWCopMA8gFVM-HB-P3ODiVB673oSX5Bk2T2YMVhy5bbCEbEZC9GXUWWTPja5mx32E0widc1NPqqxuVa/s1600/esquema_leds.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi93UYp3xPY3iJuCh-FF2A2FYlrfOwccuDjZMw1zAX-S0geClWgyDB1xw6ZnxWCopMA8gFVM-HB-P3ODiVB673oSX5Bk2T2YMVhy5bbCEbEZC9GXUWWTPja5mx32E0widc1NPqqxuVa/s320/esquema_leds.jpg" width="320" /></a><span style="font-family: Verdana; font-size: 8.0pt;"></span></div>
<div class="MsoNormal">
<span style="background-color: white; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<span style="background-color: white; font-family: Verdana, sans-serif;">Declaramos PORTB y PORTC como salidas y RA0 como entrada.
Dentro del bucle, tras el código de la conversión, simplemente esperamos 500
usec (2500 ciclos @ 20 MHz) antes de una nueva conversión. Hemos dejado fuera
la configuración del ADC (misma línea de antes) y el apagado del módulo (porque
lo estamos usando continuamente).</span></div>
<span style="font-family: Verdana, sans-serif;">Para ver
si está funcionando hemos conectado un potenciómetro en RA0 y una tira de LEDS
en PORTB, donde mostramos los 8 bits más significativos del resultado. Moviendo el potenciómetro veremos cambiar los
LEDs.</span><br />
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La orden
de poner RC0 a 1 al arrancar la conversión y de bajarlo al terminar es para
controlar el tiempo que tardamos. </span><span style="background-color: white; font-family: Verdana, sans-serif;">Con un
osciloscopio podríamos ver claramente el tiempo dedicado a la conversión como
la parte en la que este alta la señal del pin RC0. Como ya hemos hecho en otras
ocasiones, incluso con un simple voltímetro podemos estimar dicho tiempo de
forma bastante aproximada. En particular para este programa he medido un
voltaje en RC0 de 0.56V. El voltaje que el mismo voltímetro me da para Vcc es
de 4.86V. El voltaje medido en RC0 dividido por 4.86 representa el porcentaje
en el que RC0 está en alto del total del periodo. Por lo tanto podemos escribir
que si t es el tiempo dedicado a la conversión entonces:</span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> t / (t + 500) = fracción de tiempo en alto = 0.56/4.5
= 0.11 (11%)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Despejando
obtenemos un valor aproximado para t de unos 60 usec.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Obviamente
esto funcionará cuando el periodo sea lo suficientemente rápido para que el
voltímetro responda con el valor medio del voltaje a lo largo del periodo.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: Verdana, sans-serif;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivf3BKHZ3mASV21QQWVEa0Efjz665ZLEiRFMH0-HTipHPxqKVLoc5ECx3zHHQRr3KYm5UhN2mGF6butXnTQbtUxuU60xOP-9XhQiQTb6WeJjYM_5Jb3B8ISEr0JIyQwytwz6X64lJf/s1600/adc0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivf3BKHZ3mASV21QQWVEa0Efjz665ZLEiRFMH0-HTipHPxqKVLoc5ECx3zHHQRr3KYm5UhN2mGF6butXnTQbtUxuU60xOP-9XhQiQTb6WeJjYM_5Jb3B8ISEr0JIyQwytwz6X64lJf/s200/adc0.jpg" width="200" /></a> <span style="background-color: white;"> </span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLSxWLdcJMHLKVmWozf2C4eZ-g4hfcoBbqxNeJeptS8b68W0sQUGOUYeRYG1JD3c_EzEqdPkrifOUgxitv3OGQL2mnp76Q1lnird-luQ1gHF-9YdcHWIwSnAWa3o63gClee2y-GK0/s1600/adc0_zoom.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLSxWLdcJMHLKVmWozf2C4eZ-g4hfcoBbqxNeJeptS8b68W0sQUGOUYeRYG1JD3c_EzEqdPkrifOUgxitv3OGQL2mnp76Q1lnird-luQ1gHF-9YdcHWIwSnAWa3o63gClee2y-GK0/s200/adc0_zoom.jpg" width="200" /></a></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La captura
de la izquierda muestra varios pulsos de conversión. Vemos que el espaciado
entre pulsos no son los 500 usec sino unos 560. La razón es que además de los 500
usec programados en el delay, precisamos otros 60 usec para completar la
conversión AD (lo que concuerda con la estimación del voltímetro). Vemos que el
espaciado entre terminar una conversión y empezar otra si son los 500 usec
exactos que hemos programado. <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">A la
derecha, en un zoom del pulso de captura vemos con mayor precisión el
tiempo dedicado a la conversión, unos 55 usec.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfO2vQsD3X8pErJ3cybkPdxI7ejG1O5aBB-VO4oGjkfRcIlAh9FD6_ZlZFd_QgufxZf7imQXEiv9FX5K3e1x_mYV6AkjbiJWN1D5szWDEK9UlypDVd113CXWXPix4tI4kbJROcSmxP/s1600/adc1bis.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><span style="font-family: Verdana, sans-serif;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfO2vQsD3X8pErJ3cybkPdxI7ejG1O5aBB-VO4oGjkfRcIlAh9FD6_ZlZFd_QgufxZf7imQXEiv9FX5K3e1x_mYV6AkjbiJWN1D5szWDEK9UlypDVd113CXWXPix4tI4kbJROcSmxP/s200/adc1bis.jpg" width="200" /></span></a><span style="font-family: Verdana, sans-serif;">Esta duración del proceso de conversión (55-60 usec)
nos impone un límite máximo de unos 15-18000 muestras por segundo a nuestros
proyectos (además, si nos acercamos a dicho límite el micro no podrá hacer nada
más, al estar ocupado en un 100% en tomar muestras). <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si en el
programa anterior cambiamos el delay entre muestras a Delay10TCYx(1); (equivalente a 2 usec) veremos que
el voltaje del pin RC0 sube a 4.42V, lo que corresponde a una ocupación del 92%
(4.42/4.86). En la figura adjunta se aprecia gráficamente dicha dedicación casi
exclusiva al proceso de conversión. El espaciado entre muestras es de 59 usec
(55 + delay) lo que corresponde a unas 17000 muestras por segundo (16950 en la
medida del osciloscopio) <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Aunque
15000 muestras por segundo pueden ser más que adecuadas, vamos a ver que es
posible mejorar dichos resultados, aprovechando lo que hemos visto de la
programación del ADC en base a registros de control y el estudio de las
especificaciones detalladas del micro que estamos usando.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<b><u><span style="font-family: Verdana, sans-serif;">Modificaciones del código:<o:p></o:p></span></u></b></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En primer
lugar escribiremos una función equivalente a la anterior (ADC_read2) pero
evitando usar las llamadas a las funciones de C18. De esta forma nos damos
cuenta de que implementar dichas funciones es muy sencillo y nos evitamos
llamadas a funciones (lo que esperamos que mejore el tiempo necesario):<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(ch) { ADCON0 &= 0b11000011; ADCON0 |= (ch<<2); }</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 ADC_read2(uint8 ch)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 ad_res; </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(ch); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//SetChanADC(ADC_channel);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10TCYx(5);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//ConvertADC();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(ADCON0bits.GO); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//while(BusyADC()); </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ad_res =ADRESH; ad_res<<=8;
ad_res+=ADRESL; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//ad_res = ReadADC();
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> ad_res;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si
repetimos el bucle anterior con esta función vemos que el tiempo baja a unos 45
usec, una ganancia del 15%.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Podemos
mejorar un poco más si nos ajustamos a las especificaciones del PIC usado
(18F2520/4520). La documentación indica que para esta familia basta un tiempo
de adquisición (entre seleccionar canal y lanzar conversión) de unos 3 usec, lo
que a 20 MHz equivale a unos 15 ciclos . Claramente los 50 ciclos (10 usec) de
antes son excesivos. Nos bastaría con especificar un retrado de p.e. 20 ciclos:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 ADC_read2b(uint8 ch)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 ad_res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(ch); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//SetChanADC(ADC_channel);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10TCYx(2);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//ConvertADC();</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(ADCON0bits.GO); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//while(BusyADC());
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ad_res =ADRESH; ad_res<<=8;
ad_res+=ADRESL; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//ad_res = ReadADC();
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> ad_res;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Con esto
bajamos a unos 40 usec, otro 10% adicional. Notad que dependiendo del PIC usado
este código tendría que ser modificado.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Finalmente
podemos usar una característica adicional de la familia 18F2520/4520. El tiempo
de adquisición puede ser preprogramado, lo que hace que podamos lanzar la
conversión nada más seleccionar el canal. Tras poner a 1 el bit GO, el módulo
ADC no lanza la conversión inmediatamente sino que espera el tiempo programado.
El tiempo se especifica en unidades de Tad y hay que programarlo en la
configuración (OpenADC) del módulo:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 8pt;"> OpenADC(ADC_FOSC_16 & ADC_RIGHT_JUST
& ADC_4_TAD, </span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 8pt;"> ADC_INT_OFF & ADC_VREFPLUS_VDD
& ADC_VREFMINUS_VSS, 7);</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En este
caso preprogramamos un delay de 4 x Tad. Como Tad = 16/20 = 0.8 usec eso
equivale a 3.2 usec, que es superior al tiempo de adquisición mínimo
recomendado para estos PIC. La función de conversión queda ahora:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 ADC_read2b(uint8 ch)</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 ad_res;</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> select_ADC(ch); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//SetChanADC(ADC_channel);</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ADCON0bits.GO=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">// Launch conversion without delay</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(ADCON0bits.GO); </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//while(BusyADC());
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ad_res =ADRESH; ad_res<<=8;
ad_res+=ADRESL; </span><span lang="EN-GB" style="color: forestgreen; font-family: "Courier New"; font-size: 8.0pt; mso-ansi-language: EN-GB;">//ad_res = ReadADC();
</span><span lang="EN-GB" style="font-family: "Courier New"; mso-ansi-language: EN-GB; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: "Courier New"; font-size: 8.0pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> ad_res;</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: "Courier New"; mso-bidi-font-family: "Times New Roman";"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como vemos
no tenemos que preocuparnos del delay, ya que el módulo lo respetará. Con este
nuevo código la duración de la llamada a la función es de unos 24 usec. Las
ganancias se pueden detectar con la bajada del voltaje del pin RC0 o más
gráficamente, monitorizando RC0 con el osciloscopio. En la figura se adjuntan
las capturas de la duración de la función para el original y las
tres modificaciones propuestas (de arriba abajo y de izquierda a derecha). Vemos que hemos conseguido reducir a la mitad
el tiempo, pudiendo llegar hasta unas 40000 muestras/segundo (24 usec por conversion).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: center;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLSxWLdcJMHLKVmWozf2C4eZ-g4hfcoBbqxNeJeptS8b68W0sQUGOUYeRYG1JD3c_EzEqdPkrifOUgxitv3OGQL2mnp76Q1lnird-luQ1gHF-9YdcHWIwSnAWa3o63gClee2y-GK0/s1600/adc0_zoom.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLSxWLdcJMHLKVmWozf2C4eZ-g4hfcoBbqxNeJeptS8b68W0sQUGOUYeRYG1JD3c_EzEqdPkrifOUgxitv3OGQL2mnp76Q1lnird-luQ1gHF-9YdcHWIwSnAWa3o63gClee2y-GK0/s200/adc0_zoom.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoBZZwQs5aAJzhGj40aLuFVcR_CmQJPyd1YNtXFL0SCYnRaPVL2-7DvUD-5iCiMXmUo3MErKTvp8X_unw9g2py9CfLOmG0QtHym6-KUgok-aNcJal1GEY_P8hNFmQj6lHM8GIibRr1/s1600/modif1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoBZZwQs5aAJzhGj40aLuFVcR_CmQJPyd1YNtXFL0SCYnRaPVL2-7DvUD-5iCiMXmUo3MErKTvp8X_unw9g2py9CfLOmG0QtHym6-KUgok-aNcJal1GEY_P8hNFmQj6lHM8GIibRr1/s200/modif1.jpg" width="200" /></a></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal" style="text-align: center;">
<div style="text-align: center;">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRAM3r4ZP-VMBl2NeCJPly-gAjF8y8B_bepxH8g4lE1lY4fWophdgQVQfunb0O03HzO2cKU2jy244FQHtmpipHgQUs_p_spevryCzueo5-vF7m2V0x3sIdS85VIqtuBE64Zu1bnJJj/s1600/modif3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRAM3r4ZP-VMBl2NeCJPly-gAjF8y8B_bepxH8g4lE1lY4fWophdgQVQfunb0O03HzO2cKU2jy244FQHtmpipHgQUs_p_spevryCzueo5-vF7m2V0x3sIdS85VIqtuBE64Zu1bnJJj/s200/modif3.jpg" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGcAwGC7KnYMHxnbwTZwlLWqoDwhWmIQL31E0OYcoyxfoNQKx9mnBYs4fH9boJGflCdGXSFcjj0UjM6uXrgwXQ8-_A2KMoZ1TqaVxgw9Ube0_WePZkWpBCHH0ddHjaBzuMRmPfiwTG/s1600/modif2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGcAwGC7KnYMHxnbwTZwlLWqoDwhWmIQL31E0OYcoyxfoNQKx9mnBYs4fH9boJGflCdGXSFcjj0UjM6uXrgwXQ8-_A2KMoZ1TqaVxgw9Ube0_WePZkWpBCHH0ddHjaBzuMRmPfiwTG/s200/modif2.jpg" width="200" /></a></div>
<div class="MsoNormal" style="text-align: center;">
<div style="text-align: center;">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
</div>
<div style="text-align: center;">
<br /></div>
<div class="MsoNormal" style="text-align: center;">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En otra
entrada veremos como combinar el uso del ADC con interrupciones. En primer
lugar veremos como usar una interrupción de un temporizador para lanzar la
conversión AD a intervalos exactos. En segundo lugar veremos como usar la
interrupción del propio módulo ADC para evitar que la función anterior sea
bloqueante. El uso de la interrupción AD nos permite no tener que esperar
(línea</span><span style="font-family: 'Courier New';">
</span><span style="color: blue; font-family: "Courier New";">while</span><span style="font-family: 'Courier New';">(ADCON0bits.GO)) </span><span style="font-family: Verdana;">hasta que el módulo termine: la
interrupción nos avisará cuando el resultado este listo en ADRESH:ADRESL.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Antes de
explorar esta combinación de ADC + INTS, vamos a ver un pequeño proyecto (brújula
electrónica ) en el que usaremos lo que
ya sabemos del ADC. Consiste en leer el voltaje de dos sensores magnéticos (en
dos ejes perpendiculares) y combinar su información para obtener una desviación
en grados respecto al norte magnético.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com17tag:blogger.com,1999:blog-4945680608471335280.post-23578506655558005622012-06-27T15:52:00.001+02:002013-10-09T09:35:20.978+02:00Aplicación: Audio con PWM<span style="font-family: Verdana; text-align: justify;">Una
aplicación inmediata (y más interesante que los LED de colores del programa anterior) de la
modulación PWM es intentar reproducir un archivo de audio digital tipo WAV
usando el módulo PWM del PIC como un DAC (Digital-Analog Converter) incorporado.</span><br />
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Obviamente
el principal problema es dónde guarda el PIC el audio a reproducir. En la memoria de un PIC pueden caber unos 1000/2000
bytes, lo que a un ritmo de típico de 8 o 10 KHz solo da para una fracción de
segundo. Lo que vamos a hacer en esta aplicación es recibir los datos a través
del puerto serie. Si ajustamos la velocidad del puerto serie a 115200, teniendo
en cuenta que para cada byte necesitamos mandar 10 bits (datos + start + stop)
esto se traduce a un ritmo de unos 11500 bytes/segundo, muy cercano a 11025 que
es una típica frecuencia de muestreo de archivos de audio. Según lleguen los
datos por el puerto serie los usaremos para modificar el ciclo de trabajo del
módulo PWM que previamente habremos configurado. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">A la izquierda tenemos una foto con el hardware usado. A la derecha, un video donde pueden oírse el resultado, junto con una captura de la señal PWM en el osciloscopio:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ6GfhvqJhKdBf7GvZq8YuLCbJu4DKxt_36vpD4z6Bzchwzm-IQmJ40dnjRn4_TBfL49pyQiSw3l86zLT8FUJ5eBlHrsRQyby4fhT_HTsJ4ejAqItn181TdHoH5GVX23YgucAwx4xx/s1600/IMGP4376red.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="152" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ6GfhvqJhKdBf7GvZq8YuLCbJu4DKxt_36vpD4z6Bzchwzm-IQmJ40dnjRn4_TBfL49pyQiSw3l86zLT8FUJ5eBlHrsRQyby4fhT_HTsJ4ejAqItn181TdHoH5GVX23YgucAwx4xx/s200/IMGP4376red.jpg" width="200" /> <iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dxfBVsrJ2UzP3qG4lTWXd_0ykwJB2dKeuc1w14U9ob_bT3f9RjngemIpilQieYYrbtI-4no5ZjxYgQxt945Lw' class='b-hbp-video b-uploaded' frameborder='0'></iframe></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Código asociado a esta entrada: </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/PWM_audio_serial.c" style="background-color: white; font-family: Verdana;">PWM_audio_serial.c</a><br />
<span style="background-color: white; font-family: Verdana;">Proyecto C18 completo: </span><a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/proyecto.rar" style="background-color: white; font-family: Verdana;">proyecto.rar</a></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: Verdana;"></span></div>
<a name='more'></a><div style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">------------------------------------------------------------------------------------------------------------------------------<o:p></o:p></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div style="text-align: justify;">
<b style="background-color: white;"><u><span style="font-family: Verdana;">Hardware:</span></u></b></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Obviamente
la salida del pin PWM del micro no puede conectarse directamente a un buzzer o
altavoz, por lo que será necesario usar algún tipo de driver. Para esta
aplicación, un simple transistor NPN bastará.
El esquema de salida (asumiendo que usamos RC2 como salida PWM) es el
siguiente:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxRmQ_w1Rzm7b1LaMDmO5kpWnf45J7-re4FhXsKsatUMG7B6FyJxvuqUe3hWu59TgPaBH88CzrPyiYHqfvfRvBnJrOGNr69mOcAJ_49GDNwFhqf7mAIWmTjlhSAG0lQnyJkRsM5YL1/s1600/esquema.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="189" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxRmQ_w1Rzm7b1LaMDmO5kpWnf45J7-re4FhXsKsatUMG7B6FyJxvuqUe3hWu59TgPaBH88CzrPyiYHqfvfRvBnJrOGNr69mOcAJ_49GDNwFhqf7mAIWmTjlhSAG0lQnyJkRsM5YL1/s320/esquema.jpg" width="320" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como
"altavoz" he usado uno de esos zumbadores que vienen en los teléfonos
de juguete. Dado que un buzzer no deja de ser una inductancia sería conveniente
usar un diodo para reducir/suprimir el kickback de la bobina cuando el PWM
caiga a cero. Como las intensidades que manejamos son pequeñas puede que no sea
imprescindible y de hecho yo no lo he usado en mi montaje. La resistencia usada
puede estar en el rango 1-5 K<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En la foto
siguiente se muestra el "montaje de audio" acoplado a la placa EasyPic6. Negro es la masa común, rojo son 5V
al colector del transistor y el cable naranja trae la señal PWM desde RC2 a la
base del 2222A a través de una resistencia de 2K2.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdUh6f4mLVM2WVs9023joA6d91lYueLMjg7Ye8dYDbyCqEyFhSKA-S94zlMRWmvtvFp2D_lUEOYid2NMqRT-DlzPEDwjqaOPRkov-ydPYhTQd_lplJL3Os-Kjc8vFFycGSc7EXLNow/s1600/IMGP4376red.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdUh6f4mLVM2WVs9023joA6d91lYueLMjg7Ye8dYDbyCqEyFhSKA-S94zlMRWmvtvFp2D_lUEOYid2NMqRT-DlzPEDwjqaOPRkov-ydPYhTQd_lplJL3Os-Kjc8vFFycGSc7EXLNow/s320/IMGP4376red.jpg" width="320" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 19px;"><b><u><br /></u></b></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Como vamos a usar el puerto serie, será </span><span style="background-color: white; font-family: Verdana;">preciso un convertidor de niveles (MAX232 o similar) entre el puerto serie del PIC y el del PC. En mi caso he usado el convertidor integrado en la placa EasyPIC.</span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;"> </span><span style="background-color: white; font-family: Verdana;"> </span>
</div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Software:<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El primer
aspecto es decidir la frecuencia PWM a usar. Una cuestión importante es
conseguir que dicha frecuencia sea lo más alta posible, para distanciarla de
las frecuencias de la señal de audio a reproducir (en un rango de hasta unos
5KHz). Sabemos que, dada la frecuencia
del cristal, Fosc, la frecuencia PWM
viene dada por:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> </span><span lang="FR" style="font-family: Verdana;">F_pwm
= F_osc / (4*PRE*(PR2+1)) <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Para un
oscilador de 20 MHz sabemos que la máxima frecuencia que podemos usar manteniendo
1024 (10 bits) posibles niveles para el ciclo de trabajo es de Fosc/1024 = 19.6
KHz. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Sería
interesante poder aumentar más
la frecuencia. Si nos limitamos a 8 bits de resolución (muy adecuado porque trabajaremos con ficheros WAV con 8 bits/muestra = 256 niveles)
podríamos multiplicar por 4 dicha frecuencia hasta llegar a 20000/256 = 78 KHz.
Esta elección corresponde a un divisor previo PRE=1 y PR2=63.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Además de
esta forma no tendremos que reescalar los datos de audio (entre 0 y 255). Basta
asignar al ciclo de trabajo del PWM el valor recibido a través del puerto
serie.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En cuanto
a la recepción de datos por el puerto serie, la idea es implementarlo a través
de la interrupción de recepción de forma que cada vez que se reciba un carácter
se use su valor para fijar el "duty" del PWM. De esta forma no hay que guardar los valores
recibidos. La diferencia entre la frecuencia de recepción de datos (11500 bytes/sec) y la frecuencia ideal de reproducción (11025 muestras/sec) es lo suficientemente pequeña para que podamos ignorarla.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vamos con
el programa que resulta ser muy sencillo. Como siempre arrancamos con los
#includes y #pragmas de siempre. Vamos a usar las funciones de C18 para inicializar el
puerto serie y el módulo PWM por lo que debemos
incluir los ficheros adecuados:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm;">
<span style="font-family: Verdana; font-size: 8pt;"> </span><span lang="EN-GB" style="background-color: white; color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="background-color: white; font-family: 'Courier New'; font-size: 8pt;"> <p18F4520.h></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <delays.h></span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <timers.h></span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <pwm.h></span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <usart.h></span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config OSC=HS</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config PWRT = OFF, BOREN = OFF </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config WDT = OFF, WDTPS = 128</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config PBADEN = OFF, LVP = OFF</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> "../int_defs_C18.h" </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Defs about enabling interrupts, flags, etc.</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> "../tipos.h"<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 get_usart_speed(uint32
baud, uint32 Fosc, uint8* spbrg)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// baud rate
1200,2400,4800,9600,19200, ..., 115200 </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Fosc = Frequency
osc in KHz -> 20MHz = 20000 </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Returns 0
(USART_BRGH_LOW), 1 (USART_BRGH_HIGH), or 2 (cannot get speed requested)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// It places in spbrg
the value to be used as argument spbrg in OpenUSART</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 FF;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 shift;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Fosc=Fosc*1000; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> baud>>=1; Fosc=Fosc/baud+1;
Fosc>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// computes round(Fosc/baud)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FF=(uint16)Fosc;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ((FF>16320)||(FF<16)) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 2;
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Baud rate too low or too high </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh = (FF>4096)? 0:1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Decides between BRGH=0 o BRGH=1</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> shift= (brgh==1)? 3:5; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FF>>=shift; FF--; FF>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Computes round(FF/64 -1) or round(FF/16-1)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> *spbrg = (uint8)FF;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">También hemos incluido la rutina get_usart_speed que usaremos para fijar la
velocidad a 115200 bauds.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En cuanto
a la rutina de interrupción del puerto serie es muy simple. </span><span style="background-color: white; font-family: Verdana;">El inicio
es simplemente un contador de bytes recibidos (cada 256 bytes incrementa PORTB).
Esta parte es prescindible, ya que solo trata de dar un feedback visual de si
se están recibiendo bytes a través del puerto serie.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La parte
central de la ISR es simplemente coger el carácter recibido (en RCREG) y usarlo
para establecer el ciclo de trabajo del PWM. Para ello colocamos sus dos bits
menos significativos en CCP1CON.DC1B0 y CCP1CON.DC1B1 y los 8 más
significativos (en este caso 6) en el registro CCPR1L. Ya hemos remarcado que
con la configuración usada del PWM tenemos sólo 256 niveles del ciclo de
trabajo, lo cual es ideal en esta aplicación porque los valores que llegan son
justamente bytes:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 cont=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// High priority
interruption </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 duty;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (RX_flag)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> cont++; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (cont==0) PORTB++;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> duty = RCREG; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP1CONbits.DC1B0=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP1CONbits.DC1B1=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCPR1L=(duty);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> RX_flag=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Code @ 0x0008 ->
Jump to ISR for high priority ints</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_interrupt (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">){_asm </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">goto</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR _endasm}</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span style="font-family: 'Courier New'; font-size: 8pt;"> code</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como siempre que hemos pensado bien
las cosas y hemos decidido que una interrupción haga el trabajo, en la rutina
principal queda poco que hacer:</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Inicializar
el módulo PWM (PR2=63, PRE=1 => 78
KHz, 256 niveles de resolución).</span></li>
<li><span style="font-family: Verdana;">Inicializamos
el puerto serie a 115200 bauds.</span></li>
<li><span style="font-family: Verdana;">Habilitamos
la interrupción de recepción del puerto serie (junto con las interrupciones
globales y periféricas).</span></li>
<li><span style="font-family: Verdana;">Esperamos
(while) sin hacer nada hasta que lleguen cosas por el puerto serie y la
interrupción de recepción haga su trabajo.</span></li>
</ul>
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main()</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh,brgh_config,sp; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TRISB=0; PORTB=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Configure </span><st1:place><st1:placename><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">Serial</span></st1:placename><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><st1:placetype><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">POrt</span></st1:placetype></st1:place><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> @ 115K</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(115200,20000,&sp);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh_config=(brgh)?
USART_BRGH_HIGH:USART_BRGH_LOW;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_ASYNCH_MODE &
USART_EIGHT_BIT & brgh_config, sp);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Configure PWM1 (RC2) @ 78 KHz with 256 levels od duty cicle</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenPWM1(63); </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenTimer2(TIMER_INT_OFF & T2_PS_1_1); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Starts TMR2 with 1:1 prescaler</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Enable RX int,
along with global and peripherical ints.</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_RX_int; enable_perif_ints;
enable_global_ints;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span style="font-family: 'Courier New'; font-size: 8pt;">(1);</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Para
probar el programa basta mandar (usando vuestro programa de terminal favorito)
cualquier fichero WAV (configurado a 11025 Hz, 1 canal, 8 bits/sample) al
puerto serie configurado a 115200 bauds.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Los
resultados se muestran en el siguiente vídeo que ya vimos al principio <a href="http://youtu.be/sRahHYadGtg">http://youtu.be/sRahHYadGtg</a><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En el
video vemos una captura de la pantalla del osciloscopio. El canal 1 (arriba)
muestra la señal PWM a la salida del PIC. El canal 2 (abajo) muestra el voltaje
en el "altavoz". El periodo de la señal es constante (unos 13 usec) y
corresponde a la frecuencia PWM (78 KHz). El ciclo de trabajo cambia con los contenidos de la señal, aunque su correlación con el audio no se aprecia bien por la lenta actualización
de la pantalla del osciloscopio. En el audio podemos escuchar el resultado,
grabado a través de un micrófono colocado junto al altavoz. </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;">El resultado es bastante cutre desde el punto de vista
de calidad de audio, pero ilustra bien las posibilidades de la modulación PWM
como un conversor Digital/Analógico.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Se puede
usar cualquier WAV a 11025, 1 canal y 8 bits (1 byte) por muestra. Al principio
puede sonar un "click". Es simplemente el resultado de mandar al
"altavoz" la cabecera del fichero WAV. Afortunadamente dicha cabecera
es muy corta y enseguida llegan los datos de audio. Si el fichero está
configurado como MONO y 8 bits/muestra entonces cada byte corresponde a una
muestra y el audio se escuchará "correctamente".<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si no
disponéis de un fichero WAV de las características descritas, aquí podéis
descargaros un ejemplo para probar vuestro montaje: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/test_11025.wav">test_11025.wav</a>.<o:p></o:p></span></div>
</div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Las posibilidades de mejora son muchas:</span></div>
<ul>
<li style="text-align: justify;"><span style="font-family: Verdana;">Parsear los datos del fichero WAV para saltarnos la cabecera y mandar sólo el audio.</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">Usar un verdadero DAC externo en lugar del módulo PWM como conversor digital/analógico.</span></li>
<li style="text-align: justify;"><span style="font-family: Verdana;">Usar una tarjeta de memoria como fuente de datos.</span></li>
</ul>
<div>
<div style="text-align: justify;">
<span style="font-family: Verdana;">Exploraremos algunas de ellas en sucesivas aplicaciones.</span></div>
</div>
</div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com29tag:blogger.com,1999:blog-4945680608471335280.post-64772150208616140332012-06-27T15:52:00.000+02:002013-06-10T11:29:32.939+02:00Modulación PWM (Pulse Width Modulation)<div style="text-align: justify;">
<span style="font-family: Verdana;">Nuestro
controlador (digital) eventualmente tendrá que interactuar con el mundo
exterior (analógico). Al margen de usar dispositivos externos (convertidor
digital analógico o DAC) muchos microcontroladores cuentan con un módulo PWM
(Pulse Width Modulation) que puede usarse (con ciertas limitaciones) para
mandar "ordenes" analógicas.</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En este
tutorial describiremos en que consiste la modulación por ancho de pulsos (PWM),
veremos las rutinas disponibles en C18 y, como hacemos habitualmente,
describiremos los registros asociados y su funcionalidad.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Aprovecharemos
los conocimientos adquiridos para escribir una rutina para inicializar el
módulo PWM especificando la frecuencia deseada y escribiremos un pequeño
programa para usar los dos módulos PWM de un PIC para crear transiciones de
colores en un LED bicolor.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En una
entrada posterior aplicaremos lo que hemos aprendido a una aplicación más
interesante usando el módulo PWM como conversor DAC para un archivo de audio.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Archivos de código asociados a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/pwm1.c">pwm1.c</a> y <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/pwm2.c">pwm2.c</a></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">--------------------------------------------------------------------------------------------</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;"></span></div>
<a name='more'></a><div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Descripción de la modulación por
ancho de pulso (PWM)<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En algunos
de los tutoriales anteriores usábamos un truco para estimar la ocupación del
PIC. Consistía en poner a 1 un cierto pin mientras estábamos haciendo una
cierta tarea. Luego, nos bastaba con medir el voltaje medio (con un voltímetro)
en dicho pin. Dicho voltaje (dividido por los 5V de alimentación) nos daba el %
del tiempo que el pin estaba alto. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
modulación PWM consiste precisamente en eso. El módulo PWM del micro genera una
onda cuadrada con una frecuencia dada (típicamente bastante alta, por ejemplo
10 KHz). Luego nosotros podemos ir cambiando el ciclo de trabajo (% del periodo en ON) de la
señal:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI2i32b-_4GbE2C3SGklI0sdJxYYUe7WwP6eA1qVzZkROBRsqJlR8Wb4Ekd89357jyWyh6IcfBFqb_iUBRrTI9Gec5tKUThwR9tjNADkgmg-ftjr81kRTSupFu4cY5lLQjKTw-OBok/s1600/diagrama_PWM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgI2i32b-_4GbE2C3SGklI0sdJxYYUe7WwP6eA1qVzZkROBRsqJlR8Wb4Ekd89357jyWyh6IcfBFqb_iUBRrTI9Gec5tKUThwR9tjNADkgmg-ftjr81kRTSupFu4cY5lLQjKTw-OBok/s200/diagrama_PWM.jpg" width="200" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana; font-size: 8pt;"> </span><span style="background-color: white; font-family: Verdana;">Si usamos
un dispositivo externo con un ancho de banda suficiente (p.e. un osciloscopio)
veremos la señal al completo, esto es, la modulación rápida (o portadora) de 10
KHz y las variaciones más lentas (señal a transmitir) del ciclo de trabajo.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si por el
contrario aplicamos un filtro paso-bajo a la señal PWM, los cambios rápidos (10
KHz) de la señal se eliminarán y simplemente veremos los cambios lentos del
ciclo de trabajo, observando un voltaje "medio" entre 0 y 5V
dependiendo del ciclo de trabajo (0% -> 100%) programado. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">No siempre es necesario implementar un filtro paso-bajo de forma explícita. Muchas
veces usamos un dispositivo externo (voltímetro, motor, etc) con suficiente
"inercia", de forma que no es capaz de seguir los cambios rápidos de
la señal (los 10 KHz). Por así decirlo el dispositivo (motor, altavoz) lleva
incorporado su propio filtro paso-bajo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Lo que
hemos conseguido es una especie de conversor digital analógico que nos
permite traducir una orden digital (ciclo de trabajo del periodo PWM) en una variable analógica (el voltaje medio a la salida entre 0 y 5V).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Obviamente
tendremos algunas limitaciones. Como queremos que desaparezca la frecuencia de
modulación (los 10 KHz) de antes los cambios (frecuencia) de la señal que
queremos transmitir deben ser lo suficientemente lentos (frecuencia baja) para
que no desaparezcan también en el filtrado paso-bajo (explícito o implícito) de
nuestro dispositivo. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b style="background-color: white;"><u><span style="font-family: Verdana;">El módulo(s) PWM de un PIC</span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
parámetro fundamental de una modulación PWM es la frecuencia (o su inverso el
periodo) de modulación. En los PIC dicha frecuencia es programable (con ciertas
limitaciones) en base a varias variables:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">La
frecuencia del oscilador principal Fosc<o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">El
pre-scaler (PRE) o divisor previo del timer TMR2 que puede tomar los valores 1:1, 1:4
o 1:16<o:p></o:p></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
<span style="font-family: Symbol;">·<span style="font-family: 'Times New Roman';"> </span></span><span style="font-family: Verdana;">El
registro PR2 (0-255) asociado al timer TMR2<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
frecuencia PWM responde a la fórmula: </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"> </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"> F_pwm = F_osc / [4 x PRE x (PR2+1)] <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;">o lo que
es lo mismo, el periodo del PWM será el inverso de dicha frecuencia:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="FR" style="font-family: Verdana;"> T_pwm = [ (PR2+1) x 4 x PRE ] x Tosc<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El valor máximo del divisor previo PRE es 16 y el de (PR2+1) es 256. Por lo tanto la frecuencia PWM más baja posible será Fosc/16384. Para un oscilador de 20 MHz
tenemos una Fpwm mínima de 1.22 KHz
(20000/16384).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Notad que
el módulo PWM usa el timer TMR2, por lo que éste no podrá usarse como
temporizador de propósito general mientras se esté usando PWM. Si que es
posible usarlo (y ahorrarnos gastar otro timer) si queremos hacer saltar una interrupción
cada cierto tiempo. El postscaler del TMR2 no tiene efecto sobre la frecuencia
PWM, pero si influye sobre cuando salta (si está habilitada) la correspondiente interrupción (TMR2_flag).
Si por ejemplo el post-scaler es 1:16
entonces la interrupción del TMR2 saltará cada 16 periodos del PWM.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Lo primero
que tenemos que hacer para usar el módulo PWM es habilitarlo indicando que va a usarse como generador de una onda PWM, ya que dicho
módulo es compartido con otras funciones (Capture/Compare). La forma de hacerlo es poner a 11XX los 4 bits menos significativos del registro <b>CCP1CON</b>. Los PIC18 suelen tener 2
módulos PWM por lo que existe un segundo registro <b>CCP2CON</b>. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Podemos
habilitar uno o los dos módulos independientemente. Sin embargo, como ambos
usan el registro PR2 y el timer TMR0 como base de tiempos, la frecuencia programada
será la misma en ambos módulos.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Lo que si
es posible variar por separado es el ciclo de trabajo (duty cicle o DC) de cada
módulo. El ciclo de trabajo se codifica con un número de hasta 10 bits (0-1023)
almacenado de la siguiente forma:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">CCPR1L</span></b><span style="font-family: Verdana;"> : 8 bits más significativos del
ciclo de trabajo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="font-family: Verdana;">CCP1CON.DC1B0 y DC1B1</span></b><span style="font-family: Verdana;">
(bits 5 y 6 de CCP1CON): Guardan los 2 bits menos significativos.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
programación del % ON del segundo módulo es similar pero usando los registros
CCP2CON y CCPR2L.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Con los 10
bits dados el ciclo de trabajo se podrá especificar en principio con 1024
niveles (0 corresponde a 0% y 1023 al 100%). Sin embargo, los valores válidos pueden ser menores que los 1024 posibles.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La razón
es que el valor de DC (duty_cicle) determina el tiempo que la señal se mantiene
alta (ON) de la forma:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="FR" style="font-family: Verdana;"> T_on = [ DC x PRE]
x Tosc <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Recordando
que el tiempo total del periodo es: </span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;"> T_pwm = [ (PR2+1) x 4 x PRE
] x Tosc<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Comparando
ambas fórmulas y siendo obvio que el tiempo total ON no puede exceder el tiempo
total del periodo tenemos que el valor máximo de DC es (PR2+1) x 4. Por lo tanto,
aunque podemos dar a DC cualquier valor entre 0 y 1023 está claro que en
realidad debemos limitarnos al rango [ 0, (PR2+1)x4 ]. Valores más altos van a
hacer que Ton > Tpwm, o lo que es lo mismo, la señal PWM se mantiene alta
todo el rato (100%). <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En
resumen, para mantener la máxima resolución (10 bits) a la hora de especificar
DC es preciso usar PR2=255. Para </span><span style="background-color: white; font-family: Verdana;">una cierta
frecuencia del oscilador Fosc podemos optar por tres frecuencias con la máxima
resolución:</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; margin-left: 41.4pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Registro PR2<o:p></o:p></span></b></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 144.0pt;" valign="top" width="192"><div class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">PRE (divisor previo de TMR2)<o:p></o:p></span></b></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">F_pwm<o:p></o:p></span></b></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div class="MsoNormal" style="text-align: center;">
<b><span style="font-family: Verdana;">Para Fosc = 20 MHz<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">255<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 144.0pt;" valign="top" width="192"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Fosc / 1024<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">19.75 KHz<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">255<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 144.0pt;" valign="top" width="192"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">4<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Fosc / 4096<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">4.88 KHz<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">255<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 144.0pt;" valign="top" width="192"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">16<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 72.0pt;" valign="top" width="96"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">Fosc / 16384<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 117.0pt;" valign="top" width="156"><div class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;">1,22 KHz<o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Frecuencias
por debajo de Fosc/16384 no son posibles porque los valores de PR2 y PRE están ya en su máximo posible. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Frecuencias
por encima de Fosc/1024 son posibles pero a costa de bajar PR2 y por lo tanto
disponer de menor resolución para el ciclo de trabajo. Por ejemplo si aceptamos
trabajar con 8 bits (valores de DC de 0 a 255) podemos llegar a una frecuencia
de:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="FR" style="font-family: Verdana;"> F_pwm =
F_osc / [PRE x 4 x (PR2+1)] = Fosc/(1 x 256) = 78 KHz </span></div>
<div style="text-align: justify;">
<span lang="FR" style="font-family: Verdana;"><br /></span></div>
<div style="text-align: justify;">
<span lang="FR" style="font-family: Verdana;">para un oscilador de 20 MHz.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La razón
por la que para frecuencias muy altas no podemos especificar con tanta
precisión el ciclo es que el periodo empieza a hacerse muy pequeño. En el caso
anterior (Fpwm = Fosc/256) es obvio que en un ciclo del PWM sólo entran 256
ciclos del oscilador. Como es imposible que el micro haga algo entre ciclos de
reloj, está claro que sólo puede bajar la línea del PWM en 256 puntos como
mucho (esto es, con una resolución de 8 bits).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Valores de
frecuencias intermedios son también posibles, pero de nuevo van a exigir
PR2<255. Por ejemplo para conseguir 10 KHz con un oscilador de 20 MHz</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> Fosc / Fpwm =20000/10 = 2000 = 4 x PRE x
(PR2+1) -> PRE x (PR2+1) = 500 <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">lo que
puedo conseguir con PRE=2 y PR2 = 249. Pero entonces el valor del ciclo de
trabajo (DC) tiene que moverse en el rango 0 a 4(PR2+1) = 1000. Con DC=1000 ya
alcanzamos un 100% del ciclo de trabajo y valores superiores no tendrán ningún
efecto extra.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En cuanto
al pin de salida al que se manda la señal PWM, usualmente la salida PWM1 va al
pin RC2 y la del PWM2 al RC1 (notad el cambio 1-2). En algunos dispositivos (consultar
datasheet) es posible cambiar la salida de PWM2 a otro pin mediante un bit de
configuración.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> </span><span style="background-color: white; font-family: Verdana;">Las
rutinas básicas del compilador C18 para manejar los módulos PWM son las
siguientes (las declaraciones se encuentran en pwm.h):</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">OpenPWM1(uint8
periodo) : habilita el módulo y
hace PR2=periodo<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">SetDCPWM1(uint16
duty_cicle) : establece ciclo de trabajo
0% -> 100%<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">ClosePWM1(); : deshabilita modulo
PWM<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Notad que
las rutinas anteriores no tocan el timer TMR2. Es responsabilidad del usuario invocar
a la rutina OpenTimer2 para fijar el valor del divisor o pre-scaler y arrancar
el temporizador.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
siguiente programa (código en pwm1.c) pone en marcha ambos módulos y va
variando el ciclo de trabajo de PWM1 entre 0 y DC_max (valor máximo = 1023, correspondiente
a un 100%). Simultáneamente el ciclo de PWM2 se establece como el valor complementario.
Tras los #include (no olvidar añadir pwm.h, timer.h y delays.h) y los #pragma de
configuración habituales el programa principal es simplemente: <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main()</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 DC_max, dd=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> int8 inc=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> DC_max=1023;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenPWM1(255); OpenPWM2(255); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Set PWM1 and PWM2 with PR2 = 255</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenTimer2(TIMER_INT_OFF & T2_PS_1_1); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Starts TMR2 with 1:1 prescaler</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> SetDCPWM1(dd); SetDCPWM2(DC_max-dd); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Set complementary DC in PWM1 and PWM2</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> dd+=inc; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Increase duty cicle</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ((dd==DC_max) || (dd==0)) inc=-inc; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// If we get to DC_max or 0 reverse direction.</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(5);</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vemos que
hemos usado PR2=255 y pre-scaler = 1. Esto nos da una frecuencia PWM de :<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"> Fpwm =
Fosc/(4 x 256 x1) = 20000 KHz / 1024 = 19.5 KHz<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El
siguiente video es una captura de pantalla del osciloscopio monitorizando PWM1
y PWM2. Se observa que el periodo del PWM (unos 51 usec, correspondientes a
19.5 KHz) no cambia y es común a ambos canales. El tiempo en ON de PWM1
(arriba) es justo el tiempo OFF del PWM2 (abajo) ya que los hemos programado
para ser complementarios: dd y (DC_max-dd)</span></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dyaH3WlC8Lw20VKG9E4MzR_XM_cIpxPI9BoWYEqpjR5YB_HWYxSovwTbH_Dn3Y8a72uoJmdhsoMNtQBcI4V_g' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Los saltos
que se observan en las transiciones del duty_cicle son debidas a la frecuencia
(baja) con la que se refrescan en pantalla los datos del osciloscopio. En el
osciloscopio se ve una variación gradual, como corresponde a un incremente
de 1 en 1 en el ciclo de trabajo.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vamos a
cambiar la frecuencia haciendo </span><span style="font-family: 'Courier New';">OpenPWM1(199);OpenPWM2(199); </span><span style="font-family: Verdana;">lo que corresponde a (PR2+1)=200 y
a una frecuencia de 20000/(4x200) = 25 KHz.</span><span style="font-family: 'Courier New';"> </span><span style="font-family: Verdana;">En el siguiente video vemos la captura del osciloscopio:</span></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dy1tSZnwnxE-n-P_EtpEOUg8q7OEzYa-WQJV1ORdfjSUEzfKd9GnFH-BeLpmCGOnN-w8kO5YQx_81AJownyWA' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
frecuencia son justo los 25 KHz esperados. Sin embargo, se aprecia que algo va mal. Ahora
ambos canales no son complementarios. El canal PWM1 llega al 100% y permanece
allí, no empezando a bajar hasta después de un rato. El comportamiento de PWM1 y PWM2 no parece ser el que hemos programado. </span><span style="background-color: white; font-family: Verdana;">La
evolución del ciclo de trabajo antes describía la función de la izquierda (como
correspondía a nuestro programa), y ahora parece describir la de la derecha.</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVQW4VGlw0AiiFDsjY7HkdptHLIJKZrD3sAm0qqAAJBDiAtw8zm_3mmLLj_FapYh2-uz2NNCUXBbWQX_q4IG3h6YL39cTfno37hu6u15gVP3j19ditxnY7hpLkPggVkcPR97OoNFYs/s1600/evolucion_duty.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVQW4VGlw0AiiFDsjY7HkdptHLIJKZrD3sAm0qqAAJBDiAtw8zm_3mmLLj_FapYh2-uz2NNCUXBbWQX_q4IG3h6YL39cTfno37hu6u15gVP3j19ditxnY7hpLkPggVkcPR97OoNFYs/s320/evolucion_duty.jpg" width="320" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La razón
es que al haber bajado PR2 hemos subido la frecuencia (correcto) pero sin
darnos cuenta también hemos alterado el rango de valores posible para DC. El
valor máximo para el que alcanzamos e 100% es de 4x(200) = 800. </span><span style="background-color: white; font-family: Verdana;">Al llegar
dd a 800, la señal PWM alcanza un 100% y se mantiene mientras dd sigue subiendo
hasta 1023 y vuelve a bajar. Sólo cuando volvemos a entrar en el rango [0 800] volvemos
a notar variación.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En
resumen, recordar que si PR2 no es 255 el valor máximo de DC no será 1024 sino
DC_max = 4 x (PR2+1).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Nuestras propias rutinas</span></u></b><span style="font-family: Verdana;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Ahora que
entendemos como funciona el módulo PWM y conocemos los registros involucrados,
vamos a escribir nuestras propias rutinas de manejo del PWM. En primer lugar
las rutinas para ajustar el duty cicle:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_pwm1(uint16 duty)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP1CONbits.DC1B0=(duty& 0x01);
duty>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//Least Significant bit</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP1CONbits.DC1B1=(duty& 0x01);
duty>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 2nd Least Significant bit</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCPR1L=(duty); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 8
Most Significant bits</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_pwm2(uint16 duty)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP2CONbits.DC2B0=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> CCP2CONbits.DC2B1=(duty& 0x01);
duty>>=1;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">CCPR2L=(duty);</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vemos que
sólo es cuestión de poner los 2 bits menos significativos del argumento en los
bits DC1b0 y DC1b1 de CCP1CON y los 8 más significativos en CCPR1L. Lo mismo
para los registros CCP2CON y CCPR2L para PWM2.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Obviamente,
estas rutinas no aportan nada sobre las suministradas por C18, sólo nos
permiten confirmar que lo que se está haciendo no es nada complicado. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Veamos una
rutina con algo de "valor añadido". Era un poco incomodo tener que
acordarnos de configurar y arrancar TMR2 por separado. Vamos a escribir una rutina
que combine la configuración del módulo y el arranque del timer TMR2. Además,
en vez de aportar como argumentos los valores de PR2 y del prescaler de TMR2
vamos a especificar la frecuencia Fpwm deseada (en KHz) y dejar que la rutina
calcule y configure los registros adecuados. Como siempre está rutina puede ser
combinada con las del C18. Podemos usar esta rutina para inicializar el módulo
y luego usar las rutinas de C18 para fijar el ciclo de trabajo. El código es el
siguiente:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> uint16 setup_PWM(uint16
Fosc, uint8 Fpwm, uint8 ch)</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//Fosc
-> F oscillator in KHz, Fpwm ->
desired Fpwm in KHz</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// ch ->
configure channel 1 (1), 2 (2) or both (3)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> // Returns max posible value of duty cicle</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
uint16 x, DC_max;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
uint8 pre;</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 log2,pr2;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> x = Fosc>>1; x=(x/Fpwm)+1;
x>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Computes round((Fosc/4)/Fpwm)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (x>16384) {pre=16; pr2=255;} </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Requested Fpwm too low -> set Fpwm = Fosc/16384</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> pre=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(x>256) {x>>=2; pre++;} </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Find pr2 and pre so that (pr2+1)*pre=(Fosc/4)/Fpwm</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;">pr2=(x-1); </span><span lang="PT-BR" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// pre 0,1,2 -> 1:1, 1:4, 1:16</span><span lang="PT-BR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="PT-BR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (ch&1) { TRISCbits.TRISC2=0; CCPR1L=0; CCP1CON =
0b00001100; } </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// SET channel 1</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (ch&2) { TRISCbits.TRISC1=0; CCPR2L=0; CCP2CON =
0b00001100; } </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Set channel 2 </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PR2=pr2;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> T2CON = 0b00000100 | pre; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
start TMR2 with prescaler pre and postscaler 1:1</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
T2CON = 0b0 1111 1 00 ;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// | | |
|</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// | | |
|_ Prescale: 00 (1) 01 (4) 1X(16)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// | | |____ TIMER2 on/off (1=on, 0=off)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// | |______ PostScaler: 1:(bbbb+1) 0000:
1:1 1111: 1:16</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// |___________ Not used</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> DC_max
= pr2; DX_max++; DC_max<<=2; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 4 x (PR2+1)
// MAX value for Duty cicle</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> DC_max; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La rutina
recibe la frecuencia del oscilador y la frecuencia PWM deseada (ambas en KHz,
uint16 para Fosc y uint8 para Fpwm) y el canal PWM que deseamos inicializar (1
para PWM1, 2 para PWM2 o 3 para ambos). Todo esto pensando en PICs con dos
módulos PWM, aunque sería fácilmente modificable para otros casos. El tener una sola función para inicializar
todos los canales tiene sentido porque los parámetros calculados (PR2,
pre-scaler) son comunes entre canales. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La función
calcula el valor de PR2 y PRE que consiguen la frecuencia pedida y los usa para
el registro PR2 y para configurar el divisor previo del TMR2. También arranca
el timer por lo que no es necesaria una llamada adicional.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si la frecuencia
requerida es demasiado baja se fija la frecuencia permitida más baja posible.
Como es posible que en PR2 resulte un valor < 255, la función devuelve el
valor de DC que corresponde a un 100% del ciclo ON.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Usando las
nuevas rutinas podríamos reescribir el programa anterior como:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main()</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 DC_max,dd=0;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> int8 inc=1; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> DC_max=1023;
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Nominal Value for DC max</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> DC_max=setup_PWM(20000,10,3); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Set both channels @ Fpwm=10 KHz for a 20 MHz
oscillator</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="FR" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_pwm1(dd); set_pwm2(DC_max-dd); </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> dd+=inc; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Increase duty cicle</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ((dd==DC_max) || (dd==0)) inc=-inc;</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Reverse direction.</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(5);</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vemos como
para DC_max no usamos el valor nominal 1023 sino el que nos devuelve la función setup_PWM.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
aplicación más sencilla que podemos ver del uso de PWM es modular la
luminosidad de un LED. Al contrario que con una lámpara incandescente no
podemos atenuar un LED bajando su voltaje ya que al ser esencialmente un diodo,
pasará de no conducir (OFF) a conducir (ON) con una muy pequeña variación de
voltaje. Lo que podemos hacer con PWM es encenderlo y apagarlo muy rápidamente
(a la frecuencia del PWM). El tiempo ON del ciclo (duty) determinará la
luminosidad aparente del LED (en este caso el elemento integrador o paso bajo
es nuestro ojo, que es incapaz de apreciar como el LED se enciende y se apaga).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En el
ejemplo siguiente usamos la salida de PWM1 y PWM2 para modular el color e
intensidad de un Led bicolor RG. Usaremos RC1 y RC2 conectados al positivo de
los leds R y G y pondremos el negativo común a tierra:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKkyq_FeicJvFXPfmSV7UNmNpvFsjqroojaJUxWemr-xu8U6A8vbQ8JkEg0lM26_jTpV_ydlE7LYBLcuojGC-3LCiqQCvI17FBXG0LNmyGlwYlMAsdbf4HZAckUvRZ2EP6Hd3vgg7W/s1600/esquema.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="123" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKkyq_FeicJvFXPfmSV7UNmNpvFsjqroojaJUxWemr-xu8U6A8vbQ8JkEg0lM26_jTpV_ydlE7LYBLcuojGC-3LCiqQCvI17FBXG0LNmyGlwYlMAsdbf4HZAckUvRZ2EP6Hd3vgg7W/s200/esquema.jpg" width="200" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">El
diferente valor de las resistencias usadas (800K, 100K) es para compensar la
mayor eficiencia del LED rojo e intentar que la luminosidad de ambos LED estén
equilibradas.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El código (pwm2.c)
es muy similar al anterior, pero ahora los valores del ciclo de trabajo los
sacamos de un par de tablas (básicamente una oscilación sinusoidal dando más
preferencia a los niveles cerca del 0). El tamaño de ambas tablas corresponde a
dos números primos y se ha elegido así para que se de una mayor combinación de
colores, antes de que empiecen a repetirse las combinaciones. También se han
definido un par de macros que incrementan los respectivos punteros p1 y p2 a las
tablas, haciéndolos voltear al llegar al final. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Como ambas
tablas son de sólo lectura una posibilidad sería colocarlas en la memoria de
programa (usando el calificador const rom) para no gastar memoria de datos. <span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> N1 61</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> N2 59</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 duty1[N1]={ </span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 121, 153,
192, 239, 294, 357, 428, 507, 590, 676, 761, 840, 909, 964,1001,1018,</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 1012, 985, 939, 876, 801,
719, 633, 548, 467, 392, 324, 265, 215, 172, 137, 108,</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 84, 65,
50, 38, 29,
22, 16, 11,
8, 5, 3,
2, 1, 0,
0, 0,</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 1, 2,
4, 6, 9,
13, 18, 25,
33, 44, 57,
74, 95}; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint16 duty2[N2]={</span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 121, 155,
195, 244, 302, 369, 444, 526, 613, 702, 789, 867, 934, 983,1012,1018,</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 1000, 961, 902, 829, 746,
658, 569, 484, 405, 334, 272, 219, 174, 137, 107, 83, </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 64, 49,
37, 27, 20,
14, 10, 7,
4, 2, 1,
0, 0, 0,
1, 2, </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 3, 5,
8, 12, 17,
24, 32, 42,
56, 73, 95}; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 p1=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 p2=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> inc_p1 {p1++; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(p1==N1) p1=0; }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> inc_p2 {p2++; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(p2==N2) p2=0; }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main()</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">setup_PWM(20000,5,3);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_pwm1(duty1[p1]); inc_p1;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> set_pwm2(duty2[p2]); inc_p2;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(5);</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En la
siguiente película podemos ver el resultado. A la derecha, los LEDs de la placa
EasyPic6 correspondientes a RC1 y RC2 se van encendiendo y apagando. A la
izquierda el LED Red-Green conectado a ambas salidas va cambiando de color. </span></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dyDRLtqclPg9jr_Ba8m2knBZnvMZ7b8O80VmyTn4xp780JV4Vco777HS_g-pfhIj4sJ5PmhlfWcHpxG01V80Q' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El problema del video es que los sensores de las cámaras digitales son muy sensibles al rojo (de hecho más al infrarrojo), saturandose el canal rojo y no apreciandose correctamente los detalles de las transiciones de color.</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com55tag:blogger.com,1999:blog-4945680608471335280.post-50256382592918152382012-06-22T15:06:00.002+02:002013-06-10T11:36:47.079+02:00Decodificador de un mando a distancia<br />
<div class="MsoNormal">
<span style="font-family: Verdana;">Vamos a escribir una aplicación que junta los tres temas sobre los que hemos hablado hasta
ahora: timers, interrupciones y UART. El
objetivo es detectar los pulsos y medir sus tiempos de un mando a distancia por
infrarrojos, obteniendo un volcado por el puerto serie similar a este:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXLqBNJB1PqXJD___VFfhAvuEQuJ-ULFd4ZPuEMsEiqxnwolxieISq3mkhxNL60ms8mYSWdsa6LXnZ2ctVyOTCZyt73AOXZQrogLvDs8voffZlxjCwXKjSzdNyD2DIc0fmTwqBTzJt/s1600/volcado_sony_1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXLqBNJB1PqXJD___VFfhAvuEQuJ-ULFd4ZPuEMsEiqxnwolxieISq3mkhxNL60ms8mYSWdsa6LXnZ2ctVyOTCZyt73AOXZQrogLvDs8voffZlxjCwXKjSzdNyD2DIc0fmTwqBTzJt/s200/volcado_sony_1.jpg" width="167" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Esta
información la podremos usar para determinar qué protocolo se está usando.
Posteriormente, una vez que sabemos que protocolo usa nuestro mando será simple
escribir otro programa que decodifique o emule los pulsos. Esto puede ser muy
útil en muchos proyectos para usar un mando por infrarrojos para enviar órdenes
a nuestro sistema.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Codigo
asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/IR_timing.c">IR_timing.c</a></span></div>
<div class="MsoNormal">
</div>
<a name='more'></a>------------------------------------------------------------------------------------------------------------<br />
<br />
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana;">Hardware:<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Un mando a distancia manda una serie de pulsos con una modulación AM con una portadora de alrededor de unos 40 KHz. Usaremos un módulo TSOP38238 (Vishay) para demodular la señal. </span></div>
</div>
<div style="text-align: justify;">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Este módulo (y otros similares) eliminan la modulación de la
portadora (en este caso está sintonizado a 38 KHz) y a la salida nos presentan
los pulsos enviados por el mando. Normalmente son del tipo "active
low" por lo que la salida está por defecto en un nivel alto y cuando baja
a 0 es que se está recibiendo un pulso. El TSOP38238 se alimenta a 5V por lo
que su interfaz con el PIC es inmediata. </span><span style="background-color: white; font-family: Verdana;">La resistencia y el condensador en la alimentación se recomiendan en el datasheet. </span><span style="font-family: Verdana;">La salida del módulo está conectada al pin RB0. </span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoizDyBAFgRJfGU7KV1mEJAfFC-ACtZ9PvPVQFwjuOoZmwMsJdfcxWZlNYCT61hriXscWX1oeMekbDyjhvTzLaTqf5w5PjFzf1RHYedNkYQT_Csy-_44Fh3olHcnpTR3SkHYBtdGjh/s1600/TSOP38238_sml.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoizDyBAFgRJfGU7KV1mEJAfFC-ACtZ9PvPVQFwjuOoZmwMsJdfcxWZlNYCT61hriXscWX1oeMekbDyjhvTzLaTqf5w5PjFzf1RHYedNkYQT_Csy-_44Fh3olHcnpTR3SkHYBtdGjh/s1600/TSOP38238_sml.jpg" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ4Dtwefe4Jmfh2wyzlGIwR0i1B-QO1JXSwcP69eceJ5mk1LlKalNGAZ0g1-KeRaC6edd5e7ODqe1x8b-ei0LbzqIbkH3xV-gEwB63WtvhG7KZUrF753eP8jdQNTJ77vM28QBHkzwB/s1600/esquema.jpg" imageanchor="1" style="background-color: white; clear: right; display: inline !important; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQ4Dtwefe4Jmfh2wyzlGIwR0i1B-QO1JXSwcP69eceJ5mk1LlKalNGAZ0g1-KeRaC6edd5e7ODqe1x8b-ei0LbzqIbkH3xV-gEwB63WtvhG7KZUrF753eP8jdQNTJ77vM28QBHkzwB/s400/esquema.jpg" width="400" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Adicionalmente usaremos el puerto serie
para enviar la información recolectada al PC. Como siempre, si vuestro sistema
de desarrollo no cuenta con un conversor de niveles (MAX232 o similar) tendréis
que implementarlo por vuestra cuenta o adquirir alguno en eBay por no más de 5 euros:</span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrTilfOrndXZI8QE7LrXX0vWlRhIHT_hQASB2tTsmPnIf4BGeQbE8R4Wu4v0W13ZksmUSpiS4Lq1S3SkIe-eiyH-_Ck37IEQICDxA9XHgNOTsE1wJ56sxlrE_Fg0lXCQmkRhsto2CZ/s1600/TTL_rs232.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="199" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrTilfOrndXZI8QE7LrXX0vWlRhIHT_hQASB2tTsmPnIf4BGeQbE8R4Wu4v0W13ZksmUSpiS4Lq1S3SkIe-eiyH-_Ck37IEQICDxA9XHgNOTsE1wJ56sxlrE_Fg0lXCQmkRhsto2CZ/s200/TTL_rs232.JPG" width="200" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="text-align: justify;"><span style="font-family: Verdana, sans-serif;"><u>Software:</u></span></b></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Sería
sencillo hacer un bucle monitorizando el pin RB0 y usar un timer para medir los
tiempos involucrados en los pulsos ON (abajo) y OFF (arriba). El problema, como
siempre, es que con ese enfoque el PIC no podría hacer otra cosa. Lo que
haremos es usar la interrupción INT0 (asociada a cambios del pin RB0) para
detectar los pulsos. De esta forma mantenemos el PIC libre para otras
funciones.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">El aspecto
general de un paquete enviado por el mando puede verse en la siguiente imagen:</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4A6mm_FsFR6dejO_Ep2hi42DnFBmD-V9QJiD2GoGiBrMJiYa6TsU-wetQ8LXjp2Ql-F9BDYzwls67CBWCrR_QoKQK64QoY-T3e_SySSwwwrN5DOCOA2qRbhw356_xyAivxreEqn7Y/s1600/pulso.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4A6mm_FsFR6dejO_Ep2hi42DnFBmD-V9QJiD2GoGiBrMJiYa6TsU-wetQ8LXjp2Ql-F9BDYzwls67CBWCrR_QoKQK64QoY-T3e_SySSwwwrN5DOCOA2qRbhw356_xyAivxreEqn7Y/s400/pulso.jpg" width="400" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana, sans-serif;">Por defecto, la señal
esta en nivel alto (inactivo). El paquete consiste en una serie de pulsos ON
(bajo) y OFF (alto). Obviamente tras bajar/subir varias veces terminaremos
arriba. Normalmente suele haber un pulso ON inicial más largo como indicación
de START, pero eso depende del protocolo. La sucesión de ON/OFF codifica los
bits del mensaje. Hay muchas posibilidades (codificación Manchester,
codificación por ancho de pulsos, etc). Es
este proyecto no estamos interesados en decodificar, sólo en ver la información
sobre la duración de los pulsos ON y OFF. Con estos datos tendríamos una idea
del protocolo que usa el mando y podremos modificar el programa para obtener
los códigos. Considerando estos objetivos, la idea general a aplicar en nuestro
software se basa en:</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">Empezamos
activando la interrupción INT0 en modo HIGH to LOW para detectar el inicio de
un paquete. Al mismo tiempo se pone a cero el timer 0 y se arranca para medir
tiempos.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">Cada
vez que detectemos un cambio en RB0 guardaremos valor del timer 0 y volveremos
a resetearlo para medir el siguiente pulso.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">Con
lo anterior mediríamos los tiempos entre bajada y bajada. Como interesa
discriminar entre tiempo abajo (ON) y arriba (OFF) lo que haremos es que cada
vez que entre la interrupción INT0 cambiaremos el sentido de la detección. De
esta forma si entramos con una bajada, pondremos la detección a subida y así
medimos el tiempo abajo.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">El
timer 0 se resetea a cada cambio. Usaremos la interrupción del TMR0 como
indicador de que hace mucho que no hay cambios y que por lo tanto el pulso ha
terminado. En ese caso se deja de monitorizar la línea y simplemente volcamos
los tiempos (convertidos a milisegundos) de todas las transiciones.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">Para
volcar los tiempos usaremos el puerto serie. Podríamos usar el enfoque de
interrupciones explicado antes, pero como no es crítico usaremos en principio
las funciones bloqueantes del compilador.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Explicaremos el
programa (IR_timing.c) paso a paso. Comenzamos con los #include, #defines y #pragma config
habituales, así como la función get_usart_speed:</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <p18F4520.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config OSC=HS</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config PWRT = OFF, BOREN = OFF </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config WDT = OFF, WDTPS = 128</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> config PBADEN = OFF, LVP = OFF</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> "..\int_defs_C18.h"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> "..\tipos.h"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <delays.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <usart.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <stdio.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <timers.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> start_TMR0 T0CONbits.TMR0ON=1;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stop_TMR0 T0CONbits.TMR0ON=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_CR putc((</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)0x0D,stdout)</span><span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// send CR </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 get_usart_speed(uint32
baud, uint32 Fosc, uint8* spbrg)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// baud rate 1200,2400,4800,9600,19200,
..., 115200 </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Fosc = Frequency
osc in KHz -> 20MHz = 20000 </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Returns 0
(USART_BRGH_LOW), 1 (USART_BRGH_HIGH), or 2 (cannot get speed requested)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// It places in spbrg
the value to be used as argument spbrg in OpenUSART</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 FF;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 shift;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Fosc=Fosc*1000; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> baud>>=1; Fosc=Fosc/baud+1;
Fosc>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// computes round(Fosc/baud)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FF=(uint16)Fosc;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ((FF>16320)||(FF<16)) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 2;
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Baud rate too low or too high </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh = (FF>4096)? 0:1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Decides between BRGH=0 o BRGH=1</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> shift= (brgh==1)? 3:5; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FF>>=shift; FF--; FF>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Computes round(FF/64 -1) or round(FF/16-1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> *spbrg = (uint8)FF;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">A continuación tenemos el código de
la interrupción INT0. Está declarada de alta prioridad par asegurarnos de que
no perdemos nada. En un principio el programa arranca con un status=WAIT
(esperando un paquete). Cuando se detecta el arranque del paquete ponemos en
marcha TMR0 y habilitamos su interrupción para disponer de una base de tiempos
y pasamos a status = SCANNING. Si estamos en modo SCANNING simplemente
guardamos el tiempo transcurrido desde la última vez que estuvimos por aquí e
incrementamos una variable que lleva la cuenta del número de transiciones. En
ambos casos se pone a 0 el timer y se invierte el sentido de la detección de
cambios:</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> WAIT 0</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> SCANNING 1</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 stat=WAIT;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 n_changes=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 timings[80];</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 ir_detected=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interrupt high_ISR </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// High priority interruption </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR (</span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;">) </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">{</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">
(INT0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// INT0 int -> detected change in RB0</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 t;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> t=TMR0L; TMR0L=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// store
time since last transitioon, reset TMR0L</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (stat==WAIT) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Start scanning </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> { start_TMR0; enable_TMR0_int;
stat=SCANNING;}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> timings[n_changes++]=t; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// save t and increase counter</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> INTCON2bits.INTEDG0=~INTCON2bits.INTEDG0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Detect next change</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">INT0_flag=0;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Code @ 0x0008 ->
Jump to ISR for high priority interruption</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code_0x0008(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {_asm </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">goto</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR
_endasm}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Ahora viene el código de la
interrupción del TMR0, declarada como de baja prioridad. Como cada vez que
detectamos un cambio se hace TMR0L=0, la interrupción no entra mientras haya
actividad en la línea. Una vez que la línea se queda en OFF ya no hay cambios y
nadie se ocupa de resetear el contador, por lo que terminará rebosando y se
provocará la interrupción.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En la interrupción lo primero que
se hace es volver al status de esperar inicio de paquete (status=WAIT, parar
TMR0 y esperar un cambio HIGH2LOW). </span><span style="background-color: white; font-family: Verdana;">A continuación se verifica que el
número de transiciones no es muy bajo (para evitar "falsos positivos"
por alguna transición espurea en la línea). Todos los protocolos tendrán un
mínimo de 12-16 transiciones. Si hay un número suficiente de transiciones se procede a desactivar la interrupción INT0
(esto es, dejamos de monitorizar la línea) y volcamos los datos por el puerto
serie. Para evitar incluir un código complejo dentro de la interrupción (lo que
no es aconsejable) lo que se hace es poner a 1 la bandera ir_detected. En el
programa principal detectaremos dicha bandera y volcaremos los resultados.</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 1.0pt 1.0pt 1.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interruptlow low_ISR
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Low priority interruption </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> low_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TMR0_flag) </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Way too long since last transition </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> stat=WAIT; stop_TMR0; INT0_high2low; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
wait for next packet </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (n_changes>8)
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// At least 8 transitions -> dumps timings</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> disable_INT0_int; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Do not pay attention to RB0 </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ir_detected=1;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> n_changes=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">TMR0_flag=0;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Code @ 0x0018 ->
Jump to ISR for Low priority interruption</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code low_vector = 0x0018</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code_0x0018 (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">){_asm </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">goto</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> low_ISR _endasm}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 1.0pt 1.0pt 1.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> code</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La siguiente función vuelca los resultados
guardamos (los timings de los pulsos). Como obviamente la línea parte de OFF y
vuelve a OFF tendremos un número impar de pulsos, empezando con un pulso de
start (ON) </span><span style="font-family: Verdana, sans-serif;">y luego una sucesión de pares
(OFF/ON). Usamos printf para volcar los resultados a la salida standard (puerto
serie).</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Lo único más críptico es la
conversión de los tiempos a microsegundos. Los tiempos guardados (uint8's)
están en unidades de ticks de reloj. Con la configuración escogida para el
TIMER0, cada paso del contador corresponde a 51.2 microsegundos. Una
aproximación con aritmética entera y que evita dividir es multiplicar por 205 y
dividir por 4 (>>2) lo que corresponde
a 205/4 = 51.25, lo suficientemente cerca para la aplicación en curso.
Obviamente esta conversión será dependiente de los parámetros elegidos al
configurar TMR0.</span><span style="font-family: Verdana; font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 6pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
dump_timings(</span><span lang="FR" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
uint8 k;</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">uint16 t1,t2;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span style="font-family: 'Courier New'; font-size: 8pt;"> (n_changes==0) </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;">;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> t1=timings[0]*205;
t1>>=2;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> printf(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"PACKET START ON %d (ms)\n"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">,t1); send_CR; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (k=1;k<n_changes;k+=2)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
t1=timings[k]*205; t1>>=2; </span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">
t2=timings[k+1]*205; t2>>=2; </span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">printf(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"%2d)
OFF/ON %4d %4d (ms)\n"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">,(k+1)>>1,t1,t2);
send_CR; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> printf(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"-------------------------\n"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">); send_CR; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> n_changes=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El programa principal abre el
puerto serie (115200 bauds) y configura TMR0 (sin arrancarlo). Se habilita la interrupción INT0 (que siempre
es de alta prioridad) y la interrupción del TMR0 (baja prioridad).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La parte más delicada es escoger
los parámetros del Timer1. Hemos escogido usar modo 8 bits porque es suficiente
para los tiempos involucrados y nos ahorramos manejar contadores de 16 bits. Se
ha escogido un divisor de 1:256 lo que corresponde a 256x0.2 = 51 usec. Está
será la máxima resolución de los timing hallados (ya que se miden en multiplos
de 51 usec). Es adecuada porque típicamente los pulsos más pequeños en los
mandos a distancia son del orden de 400-600 usec, por lo que entran del orden
de 10 pasos como mínimo. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La consecuencia inmediata de dicha
elección es que el rebosamiento por falta de actividad sucederá al cabo de 256
x 51 = 12.5 msec. Esto determina que los pulsos más largos detectables serán de
12 msec. Si un pulso (ON/OFF) dura más de 12 msec el programa considerará que
ya no va a haber más actividad y declarará (erróneamente) un fin de
paquete. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Tras habilitar las interrupciones, del
grueso del trabajo se encargan ellas. El programa principal simplemente entra
en un bucle donde se monitoriza la bandera ir_detected. Si se pone a 1 es señal
de que hemos detectado un paquete y llamamos a la función que vuelca la
información por el puerto. Tras terminar de volcar los resultados volvemos a
habilitar la monitorización de la línea.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 sp, brgh, brgh_config;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 temp;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> //Configuracion puerto serie. </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(115200,20000,&sp); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh_config = (brgh)?
USART_BRGH_HIGH:USART_BRGH_LOW;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_ASYNCH_MODE &
USART_EIGHT_BIT & brgh_config, sp); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> disable_TX_int; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
By default TX int is enable using AND masks</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// TIMER0
8bit,1:256, @20MHz -> dt=256*0.2=50.2 usec, overflows in 13 msec </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;">OpenTimer0(T0_8BIT&T0_SOURCE_INT&T0_PS_1_256);
</span><span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="FR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">stop_TMR0; TMR0L=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> INT0_high2low; enable_INT0_int; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Enable INT0 int (always a high priority int)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_TMR0_int; set_TMR0_low; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Enable TMR0 int with low priority</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_priority_levels;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_high_ints; enable_low_ints;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> puts(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"IR remote timings"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">);
send_CR;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (ir_detected==1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ir_detected=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> dump_timings();</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> enable_INT0_int;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana;">Veamos los
resultados. Se adjuntan dos volcados del puerto serie al pulsar un par de
teclas de un mando SONY:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXLqBNJB1PqXJD___VFfhAvuEQuJ-ULFd4ZPuEMsEiqxnwolxieISq3mkhxNL60ms8mYSWdsa6LXnZ2ctVyOTCZyt73AOXZQrogLvDs8voffZlxjCwXKjSzdNyD2DIc0fmTwqBTzJt/s1600/volcado_sony_1.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXLqBNJB1PqXJD___VFfhAvuEQuJ-ULFd4ZPuEMsEiqxnwolxieISq3mkhxNL60ms8mYSWdsa6LXnZ2ctVyOTCZyt73AOXZQrogLvDs8voffZlxjCwXKjSzdNyD2DIc0fmTwqBTzJt/s200/volcado_sony_1.jpg" width="167" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"> </span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9_qUjW9as7uZPNYxGswpLHsAsljNF0PQVNS3BVsUlkQuyUWsMTJ635MXXOs_x7xlVZ70SoDuVvZ66X3bWaZ_NwWiTotjH9mIqzrLKgtrgglqYiE1d_cril2WaLt62HrP33TzzYy12/s1600/volcado_sony_2.jpg" imageanchor="1" style="background-color: white; margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9_qUjW9as7uZPNYxGswpLHsAsljNF0PQVNS3BVsUlkQuyUWsMTJ635MXXOs_x7xlVZ70SoDuVvZ66X3bWaZ_NwWiTotjH9mIqzrLKgtrgglqYiE1d_cril2WaLt62HrP33TzzYy12/s200/volcado_sony_2.jpg" width="166" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="background-color: white; font-family: Verdana;"><br /></span></div>
<div class="MsoNormal">
<span style="background-color: white; font-family: Verdana;">Vemos que empezamos
siempre con un START largo (2400 usec) y luego hay una serie de OFF/ON. La
parte OFF es siempre constante (512 usec) pero la parte ON oscila entre 615 y
1230 usec. Claramente los 0/1 están codificados en esta duración. De hecho el
protocolo usado por SONY establece un bit de START de 2400 usec, unos pulsos
OFF de 600 usec y unos pulsos ON de 600 (0) o 1200 (1):</span></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6vSocGSpOe7RA9nsUf6EYUuAIiLp2nYukTFPgVCE4bWdA4XZuxezzQQA958_GkYq23jRtsAgqPR9ROWqjlbTKxudCXdVZEBsJ1SWmMNq-JLrfF3MZ9QDtdK_tKD1PUdHhGpU_E9Ac/s1600/pulso1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6vSocGSpOe7RA9nsUf6EYUuAIiLp2nYukTFPgVCE4bWdA4XZuxezzQQA958_GkYq23jRtsAgqPR9ROWqjlbTKxudCXdVZEBsJ1SWmMNq-JLrfF3MZ9QDtdK_tKD1PUdHhGpU_E9Ac/s320/pulso1.jpg" width="320" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">En el
primer caso se decodificaría como 110010000100010 y el segundo como
101010000100010. El protocolo como vemos es de 15 bits (otras variantes del
protocolo pueden tener más o menos bits, pero respetando la codificación basada
en la duración del pulso ON con pulsos OFF constantes.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Otro
pequeño detalle es que mientras que los tiempos del pulso ON se ajustan
bastante bien a las especificaciones (dada la resolución que tenemos de 50
usec), los tiempos OFF son sistemáticamente más pequeños. La diferencia puede
verse también en un osciloscopio, por lo que es posiblemente debida al
comportamiento del módulo demodulador y no a nuestro programa<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Probemos
ahora con un remoto para disparar a distancia una cámara de fotos (Pentax).
Este es el resultado:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;">PACKET START ON 12915 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 1) OFF/ON 2870
1025 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 2) OFF/ON 922 1076 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 3) OFF/ON 922 1025 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 4) OFF/ON 922 1025 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 5) OFF/ON 922 1025 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 6) OFF/ON 922 1025 (ms)<o:p></o:p></span></div>
<div class="MsoNormal" style="text-align: center;">
<span lang="EN-GB" style="font-family: Verdana; font-size: 8pt;"> 7) OFF/ON 922 1025 (ms)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<br />
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Vemos que
arranca con un pulso ON muy largo (con 12-13 msec ha debido de estar a punto de
saltar la interrupción por inactividad).
Luego sigue una zona OFF de 3 msec y termina con una sucesión de ON/OFF de 1
msec.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Para
terminar un volcado del mando de una TV LG. Se aprecia que el inicio del
paquete viene marcado por un par de pulsos muy largos, el primero el doble del
otro: ON = 9 msec, OFF = 4.4 msec <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">A partir
de entonces los pulsos ON son prácticamente constantes con un valor nominal de
600 msec (563-615). Al contrario de antes, los bits claramente vienen ahora
codificados en los pulsos OFF con valores de 500-1500 usec.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWkEckpjKB5srHGdW2aAvGTePi6lZKNra-JgUScHHhsaXCtRX53_9weJKsM9XDHotq5xIf6GP8H_Qth4jUyUS8mvGiguLgzhFYugZKhF91BfQDLKzms3NZMz9g5PpKyRwy4Fqh3fu_/s1600/volcado_LG.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWkEckpjKB5srHGdW2aAvGTePi6lZKNra-JgUScHHhsaXCtRX53_9weJKsM9XDHotq5xIf6GP8H_Qth4jUyUS8mvGiguLgzhFYugZKhF91BfQDLKzms3NZMz9g5PpKyRwy4Fqh3fu_/s1600/volcado_LG.jpg" /></a></div>
<div class="MsoNormal">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana;">Para dar
una idea de la variedad de protocolos existentes en el fichero<u> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/volcado.txt">volcado.txt</a></u> se
adjunta la salida obtenida con uno de esos mandos de TV universales en los que
se pulsa la tecla MUTE y el mando va probando con un montón de
códigos/protocolos hasta encontrar uno que tiene efecto sobre la TV.</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com2tag:blogger.com,1999:blog-4945680608471335280.post-72201814834325122042012-06-22T13:54:00.004+02:002013-06-10T11:38:46.222+02:00Comunicaciones UART con paridad<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En muchos
compiladores las rutinas del puerto serie asumen los valores por defecto de
comunicación con 8 bits de datos y sin paridad. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Vamos a
ver como, con los conocimientos adquiridos, es muy sencillo establecer una
comunicación serie usando por ejemplo paridad. esto puede ser muy útil si
tenemos que interactuar con un periférico que sólo soporte este tipo de
comunicaciones.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;">Código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/uart_paridad.c">uart_paridad.c</a></span></div>
</div>
<a name='more'></a><div style="text-align: justify;">
------------------------------------------------------------------------------------------------------------</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El siguiente
programa inicializa el puerto serie a 9600 baudios y manda repetidamente la
cadena de texto "ABCD…" usando las rutinas send_byte( ):<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch; </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh,sp;
</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(9600,20000,&sp); setup_UART(brgh,sp); </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//brgh_config=(brgh)?
USART_BRGH_HIGH:USART_BRGH_LOW;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//OpenUSART(USART_ASYNCH_MODE
& USART_EIGHT_BIT & brgh_config, sp);</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (ch=65;ch<=90;ch++) send_byte(ch); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
ASCII from A to Z</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_byte_parity(0x0D); send_byte(0x0A); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// LF/CR </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(250); Delay10KTCYx(250); </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Wait for 1 second</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si abrimos
HyperTerminal (u otro terminal) y lo configuramos a 9600 veremos llegar la
cadena "ABCDE … XYZ" cada segundo. Si ahora reconfiguramos en el
terminal estableciendo como propiedades del puerto serie 9600 baudios, 8 bits
datos, even parity y volvemos a conectarnos veremos que no se recibe nada (o
tal vez algún carácter raro aislado). La razón es que nuestro terminal espera
ahora un noveno bit con la correspondiente paridad, y el PIC no lo está
enviando.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Una vez
que hemos perdido el miedo a usar los SFR de la UART en el PIC podemos
restablecer la comunicación con sólo un par de sencillos comandos. El siguiente
código añade soporte para transmisión del bit de paridad. Si lo compiláis y
volcáis al PIC veréis como la ristra de "ABCD…" vuelven a aparecer en
vuestro terminal.</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_byte_parity(uint8 ch)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 ch_org,p;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch_org=ch;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> p=0; </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(ch) {p+=(ch&1); ch>>=1;} p&=1;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TXSTAbits.TX9D=p;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_byte(ch_org); </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch;</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh,sp;
</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(9600,20000,&sp); setup_UART(brgh,sp); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TXSTAbits.TX9=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// enable ninth bit TX</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">for</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (ch=65;ch<=90;ch++) send_byte_parity(ch); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
ASCII from A to Z</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_byte_parity(0x0D);
send_byte_parity(0x0A); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// LF/CR </span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(250); Delay10KTCYx(250); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Wait for 1 second</span><span lang="EN-GB" style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New';"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Apenas
hemos cambiado nada:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">Tras
inicializar la UART se habilita la transmisión en formato 9 bits usando el bit
TX9 de TXSTA.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">En
vez de usar la antigua rutina send_byte hemos escrito otra send_byte_parity.</span></li>
</ul>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: Verdana;">En
la nueva rutina se calcula el bit de paridad (even). El datasheet de Microchip
especifica que es responsabilidad del usuario que el noveno bit esté colocado
en TXTSTA.TX9D antes de poner los otros 8 bits en TXREG. Por consiguiente
primero colocamos el bit de paridad y luego llamamos a la vieja rutina
send_byte(), que colocaba el byte dado en TXREG.</span></li>
</ul>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En el caso
de recepción el funcionamiento sería el mismo. Se habilitaría la recepción de 9
bits (RCSTA.RX9=1) y tras cada recepción encontraríamos el noveno bit
esperándonos en RCSTA.RX9D.<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana; font-size: 8pt;"><br /></span></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com0tag:blogger.com,1999:blog-4945680608471335280.post-25725044510178585212012-06-22T13:52:00.002+02:002013-06-10T11:44:30.539+02:00Comunicaciones UART con interrupciones<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En el
tutorial anterior hemos visto que lo que un compilador hace al escribir/leer
de la UART no es muy complicado. Esencialmente se reduce a leer/escribir de un
par de registros (TXREG, RCREG) verificando previamente que están libres (caso
de TXREG) o que sus contenidos se han renovado (caso de RCREG).</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Aprovecharemos
estos conocimientos para implementar un programa de transmisión/recepción de
datos más eficaz, usando las interrupciones asociadas a la UART, tanto de recepción (RX, activada al recibir un byte) como de transmisión (TX, activada cuando la UART está libre para mandar otro byte).</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Asimismo
usaremos dos buffers de mayor capacidad, uno de recepción (donde la
interrupción RX depositará los datos recibidos) y otro de transmisión (de donde
la interrupción de TX cogerá los datos a transmitir).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Veremos
como la implementación de estas técnicas puede llevarnos a drásticas
reducciones de la ocupación del PIC, liberándolo para otras tareas. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">También
veremos como nuestra implementación con buffers e interrupciones puede
configurarse como la salida por defecto stdout, pudiendo ser usada directamente
por rutinas como printf, puts, etc. de forma transparente para el usuariuo.<o:p></o:p></span></div>
</div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana, sans-serif;">Código asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/uart3_int.c">uart3_int.c</a></span></div>
</div>
<div class="MsoNormal">
<span lang="PT-BR" style="font-family: Verdana, sans-serif;"></span></div>
<a name='more'></a><div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">--------------------------------------------------------------------------------------------</span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div style="text-align: justify;">
<span style="background-color: white; font-family: Verdana, sans-serif;">En la
implementación con buffers que haremos, el "usuario" no toca los registros
RXREC ni TXREG, sino sólo los buffers de rx/tx. Dichos buffers estarán
implementados como buffers circulares, de forma que si el usuario p.e. no va
procesando los datos recibidos estos se sobrescribirán si se supera la longitud
del buffer.</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Lo ideal
en el caso de buffers circulares es que su tamaño sea una potencia de 2, lo que
facilitará resetear el índice del buffer al llegar al final. Si por ejemplo el
tamaño del buffer es 64, cada incremento del índice debe venir seguido de:</span><span style="font-family: Verdana;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><span style="color: blue; font-family: 'Courier New';">ind++;
ind&=63; </span></b><span style="font-family: Verdana;">lo que es más eficaz que: </span><b><span style="color: blue; font-family: 'Courier New';">ind++; if(ind==64)
ind==0;<o:p></o:p></span></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Lo ideal
sería usar buffers de 256 entradas que son especialmente eficaces. En efecto,
si usamos una variable de 8 bits (unsigned char) como índice, dicha variable se
reseteará automáticamente al llegar a 256 sin necesidad de añadir la
instrucción extra. Para una variable de 8 bits, la instrucción </span><b><span style="color: blue; font-family: 'Courier New';">ind &= 255</span></b><span style="font-family: Verdana;"> es superflua.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
inconveniencia es que en C18 si queremos declarar un array de 256 bytes o más
hay que hacer algunos apaños. No es complicado, pero retrasaremos dicha lección
hasta más adelante. Para no complicarnos, en este ejemplo usaremos un tamaño de
128. Veamos como reservar los buffers de entrada/salida así como los punteros
(índices) asociados:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> BUF_SIZE 128</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#define</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> inc(x) {x++; x&=(BUF_SIZE-1);}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 tx_buf[BUF_SIZE]; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// TX buffer</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 tx_next=0; uint8
tx_sent=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// TX indexes</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 rx_buf[BUF_SIZE]; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// RX buffer</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 rx_next=0; uint8
rx_read=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// RX indexes</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Hay dos
punteros asociados a cada buffer, inicializados ambos a 0. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">RX buffer: </span></div>
<div style="text-align: justify;">
</div>
<ul>
<li><b style="font-family: Verdana;">escribe en él</b><span style="font-family: Verdana;"> la interrupción de RX,
incrementando rx_next.</span></li>
<li><b style="font-family: Verdana;">lee de él</b><span style="font-family: Verdana;"> el usuario, incrementando
rx_read.</span></li>
<li><span style="font-family: Verdana;">Si rx_read==rx_next es que no hay nuevos
caracteres a procesar.</span></li>
</ul>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">TX buffer: </span></div>
<div style="text-align: justify;">
</div>
<ul>
<li><b style="font-family: Verdana;">escribe en él</b><span style="font-family: Verdana;"> el usuario (lo que
desee transmitir), incrementando tx_next.</span></li>
<li><b style="font-family: Verdana;">lee
de él</b><span style="font-family: Verdana;"> la interrupción de TX, cada vez que manda un byte, incrementando
tx_sent.</span></li>
<li><span style="font-family: Verdana;">Si ambos son iguales, no hay nada nuevo que
mandar.</span></li>
<li><span style="font-family: Verdana;"><br /></span></li>
</ul>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Se ha
definido una macro para incrementar los punteros. En ella se incrementa el
puntero y se voltea si se sale del intervalo [0, BUF_SIZE-1].<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si el
usuario no procesa los caracteres recibidos es posible que se pierdan al
voltear el buffer de recepción. En este caso se podría disponer de una bandera
de buffer_overflow que se dispararía si rx_next supera a rx_read. En nuestro
caso no se implementará este control, ignorando posibles overflows del buffer.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Las correspondientes
rutinas de interrupción (ISR) son muy simples (como por otra parte debería ser </span><span style="font-family: Verdana;">todo
código de interrupción). Para la recepción, si se ha recibido algo (RX_flag) se
coloca el contenido de RCREG en rx_buf, incrementándose rx_next:</span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// RX_isr gets
executed when RX_flag is set. That means a new byte is waiting in RCREG. </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// The code picks it
and places it in the next available (rx_next) pos of the RX buffer, </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// increasing rx_next
in the process. Somewhere else the user must read the </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// new bytes (from
rx_read to rx_next) from the RX buffer.</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> RX_isr(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rx_buf[rx_next] = RCREG; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Read RX char and place it in the RX buffer</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> inc(rx_next);
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//rx_next++; rx_next&=(BUF_SIZE-1);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">RX_flag=0;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si el
buffer de transmisión está libre (TX_flag) y hay algo que transmitir se carga
el correspondiente byte de tx_buf en el registro de transmisión TXREG y se
incrementa tx_sent:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// TX_isr gets called
when TX_flag is set. That means that the port is ready to tramsmit.</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// If
tx_next==tx_sent, there is nothing to send and TX_INT is disable.</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// If
tx_next!=tx_sent, next byte in TX buffer is loaded in TXREG, and the </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// pointer is
incremented, making sure it remains within the [0,BUF_SIZE-1] range </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TX_isr(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (tx_sent==tx_next) disable_TX_int; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">else</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> { TXREG=tx_buf[tx_sent]; inc(tx_sent); }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">TX_flag=0;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
interrupción de recepción estará siempre activa (no queremos perder nada) pero
la de transmisión se desactiva si no hay nada que mandar (tx_sent==tx_next).
Esto evita que estemos entrando continuamente en la interrupción de transmitir
(porque el registro TXREG está disponible) cuando no tenemos nada que mandar.
Es responsabilidad del usuario activar la interrupción TX (enable_TX_int) cuando
escriba algo al buffer de salida.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Juntando
ambas rutinas en la rutina de interrupción:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// High priority
interruption </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> interrupt high_ISR</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR (</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (RX_flag) RX_isr(); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TX_flag) TX_isr(); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Code @ 0x0008 ->
Jump to ISR </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code high_vector = 0x0008</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> code_0x0008(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">) {_asm </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">goto</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> high_ISR _endasm}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#pragma</span><span style="font-family: 'Courier New'; font-size: 8pt;"> code</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Y eso es
todo. Ahora lo único preciso es que
nuestras rutinas de escribir al puerto serie deben mover caracteres al buffer
de transmisión (de tx_next en adelante, incrementando tx_next) y las rutinas de
lectura cogerlos del buffer de recepción (desde rx_read hasta rx_next,
incrementando rx_read):</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El usuario
sólo debe modificar (incrementándolos adecuadamente) los punteros tx_next y
rx_read. El incremento de los punteros tx_sent y rx_next es responsabilidad de
las rutinas de interrupción.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Veamos las
ventajas de este tipo de enfoque.
Imaginad un programa en el que cada cierto tiempo hay que mandar cierta
información por el puerto serie. En C18 el stream stdout corresponde por
defecto al puerto serie, por lo que al usar rutinas como puts o fprintf los
resultados se volcarán al puerto serie. El siguiente programa abre el puerto
serie a 9600 y usar puts para mandar la cadena "0123456789ABCDEF" por
el puerto serie:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <usart.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <stdio.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 sp, brgh, brgh_config;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TRISC=0; PORTC=0; <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(9600,20000,&sp); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh_config = (brgh)?
USART_BRGH_HIGH:USART_BRGH_LOW;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_ASYNCH_MODE &
USART_EIGHT_BIT & brgh_config, sp); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//Open port @ 9600 </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=1; puts(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"0123456789ABCDEF"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">); PORTCbits.RC0=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">Delay10KTCYx(25); </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 50 msec
delay </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Hemos incluido </span><span style="font-family: 'Courier New';"><usart.h></span><span style="font-family: 'Courier New';"> </span><span style="font-family: Verdana;">y</span><span style="font-family: 'Courier New';"> </span><span style="font-family: 'Courier New';"><stdio.h></span><span style="font-family: 'Courier New';"> </span><span style="font-family: Verdana;">para poder usar OpenUSART() y
puts(). Tras abrir el puerto entramos en un bucle donde mandamos la cadena y
ponemos un delay de 50 msec. Abriendo un terminal @ 9600 veríamos llegar repetidamente la cadena "ABC …
".</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Notad que hemos puesto el pin RC0 a
1 durante el tiempo en que puts está ocupado mandando el mensaje. La figura
siguiente corresponde a una captura de RC0 con el osciloscopio mientras el programa está
ejecutándose:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43Tvds9fO7XLvlzW7K4qZTwN3qibARmp4EFeJWxgvbLcztBGOHDoHR8eOebZOVVsTmAUEvLFKGgVP8Ic_GMqRb6mtnHk1Zq7mIOYDiD3yTqq4ouHDarnVw8yZ-b3n_lpPTAO88fMd/s1600/uart3_intc.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj43Tvds9fO7XLvlzW7K4qZTwN3qibARmp4EFeJWxgvbLcztBGOHDoHR8eOebZOVVsTmAUEvLFKGgVP8Ic_GMqRb6mtnHk1Zq7mIOYDiD3yTqq4ouHDarnVw8yZ-b3n_lpPTAO88fMd/s1600/uart3_intc.jpg" /></a></div>
<div align="center" class="MsoNormal" style="mso-layout-grid-align: none; text-align: center; text-autospace: none;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Claramente es lo esperado. La
rutina puts() bloquea al PIC durante unos 18 msec (tiempo necesario para mandar 16 chars + LF a
9600 bauds). Luego viene un espaciado de 50 msec (delay) y el proceso se
repite. El PIC está mandando 16 bytes en 68 msec (unos 230 bytes por segundo) y
esto le ocupa un 25% (18/68) de su tiempo.
Incluso sin tener un osciloscopio se puede estimar el tiempo de
ocupación tomando una medida del voltaje en RC0. En este caso obtenemos unos
1.3V. 5V corresponderían a una ocupación total (RC0 alto todo el tiempo), por
lo que 1.3 V correspondería a un porcentaje de un 25-30% (obviamente este
método es aproximado y puede depender de las características del voltímetro
usado). <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Veamos como mejoran las cosas
usando nuestro enfoque de interrupciones. Es interesante darnos cuenta de que
podemos aprovechar nuestro trabajo sin tener que modificar apenas nada. Hemos
dicho que por defecto C18 usa el puerto serie como salida standard (stdout). El
usuario puede redireccionar la salida standard sin más que:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<ul style="margin-top: 0cm;" type="disc">
<li class="MsoNormal" style="text-align: justify;"><span style="font-family: Verdana;">Hacer stdout = _H_USER; para indicar a C18 que
sus rutinas de salida deben usar la función de usuario _user_putc( ) en
vez de la definida por defecto.</span><span style="font-family: 'Courier New';"><o:p></o:p></span></li>
<li class="MsoNormal" style="text-align: justify;"><span style="font-family: Verdana;">Escribir una rutina propia llamada
_user_putc(char) que escriba un carácter en el stream escogido.</span></li>
</ul>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Nosotros
seguiremos usando el puerto serie como salida, pero ahora en la rutina
_user_putc, en vez de usar los comandos que escriben directamente al puerto
serie usaremos nuestro buffer de salida:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">int</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> _user_putc(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> tx_buf[tx_next]=ch; inc(tx_next);
enable_TX_int; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> ch;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La rutina
coloca el carácter recibido en el buffer de transmisión (buffer TX), en la posición tx_next. A
continuación incrementa dicho puntero y habilita la interrupción de
transmisión, indicando que tenemos algo que mandar. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Y ya esta.
A partir de ahora (tras redefinir stdout) siempre que usemos las rutinas de salida
puts, printf, etc. por debajo estaremos usando nuestro sistema de buffers de
una manera transparente.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">El nuevo
programa principal apenas ha cambiado:</span><span style="font-family: Verdana; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 sp, brgh, brgh_config;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;">stdout =
_H_USER;</span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> TRISC=0; PORTC=0; </span><span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="PT-BR" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">brgh=get_usart_speed(9600,20000,&sp); </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//setup_UART(brgh,sp); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh_config = (brgh)?
USART_BRGH_HIGH:USART_BRGH_LOW;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_ASYNCH_MODE &
USART_EIGHT_BIT & brgh_config, sp); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> enable_RX_int; enable_global_ints;
enable_perif_ints; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTCbits.RC0=1; puts(</span><span lang="EN-GB" style="color: #a020f0; font-family: 'Courier New'; font-size: 8pt;">"0123456789ABCDEF"</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">); PORTCbits.RC0=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">Delay10KTCYx(25); </span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// 50 msec
delay </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La única
diferencia es la redefinición de stdout (_H_USER) y la habilitación de las
interrupciones de las que depende nuestro sistema de buffers. El bucle
principal no ha cambiado. Si ejecutamos el programa volveremos a ver llegar por
el terminal la misma cadena "ABCD …".<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Veamos el
retardo de la función puts (ahora usando nuestra _user_putc) a través del pin
RC0. Como en este caso estamos "pasándole" el trabajo a las
interrupciones hemos puesto también RC1=1 durante el tiempo en el que la
interrupción está activa ya que es también tiempo dedicado a mandar cosas por
el puerto serie. Veamos la ocupación tanto en puts (RC0, arriba en amarillo)
como en la interrupción (RC1, abajo en azul).<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNrY0JespQQcovljVsPiEgVjn1k__GLoiZGqSMzFVlrQhnDyvbWQVFCuz9FM7PwparhnCojpLSI-tMPogBLuczSqtMv8vwM8rB_xiW8XiU4F0aUk2-W-yfGT2iYz4_s_U88hbSVWv/s1600/uart3_inta_ok.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlNrY0JespQQcovljVsPiEgVjn1k__GLoiZGqSMzFVlrQhnDyvbWQVFCuz9FM7PwparhnCojpLSI-tMPogBLuczSqtMv8vwM8rB_xiW8XiU4F0aUk2-W-yfGT2iYz4_s_U88hbSVWv/s1600/uart3_inta_ok.jpg" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;"><br /></span></div>
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
ocupación de RC0 ha sido reducida drásticamente, ya que con nuestra nueva
rutina puts() no espera a que los caracteres hayan sido enviados, simplemente
los copia al buffer de salida. De hecho ahora estamos enviando más bytes por
segundo ya que el siguiente bloque se manda 50 msec después (sin contar el
tiempo que tardan en salir los caracteres). El ritmo es ahora de unos 16/17
bytes cada 50 msec (unos 340 bytes/sec, un 50% más que antes).</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En RC1 la
cosa parece más similar. El ancho del pulso sigue siendo unos 18 msec (ya que
16 caracteres a 9600 baudios no pueden tardar menos en salir). Sin embargo
dicho periodo de actividad no es sólido (ya que la interrupción solo tiene que
poner un byte en TXREG). La clave es no esperar a que el periférico termine. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Si hacemos
un zoom de la zona de un periodo de actividad veremos lo siguiente:<span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUJM9JlOwKn2VHrx9gWJ49rciZ_ipoqz57QKJqPvIv7gXl-RKEd2Lfz4p4N6DlZYPpUQ1rp_iNs4FC9jy3bNyMSNePbFANw712xN7fDZ3LT8UZrcni13ZRMmaUA53sXLTWro8q-dzV/s1600/uart3_intb_ok.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUJM9JlOwKn2VHrx9gWJ49rciZ_ipoqz57QKJqPvIv7gXl-RKEd2Lfz4p4N6DlZYPpUQ1rp_iNs4FC9jy3bNyMSNePbFANw712xN7fDZ3LT8UZrcni13ZRMmaUA53sXLTWro8q-dzV/s1600/uart3_intb_ok.jpg" /></a></div>
<div align="center" class="MsoNormal" style="text-align: center;">
<span style="font-family: Verdana;"><span style="font-size: 11px;"><br /></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">El pulso
amarillo inicial (menos de 1 msec) es el tiempo usado por puts para volcar los
16 bytes al TX buffer. Los pulsos azules (aún más cortos) corresponden al
tiempo usado por la interrupción en ir colocándolos en TXREG. Están espaciados
porque la interrupción no vuelve a entrar hasta que el periférico no ha termina
y libera TXREG.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Todo el
tiempo en el que RC1 está abajo (la mayoría) el PIC puede estar haciendo otras
tareas. De hecho la dedicación en el periodo de 18 msec que antes tardábamos en
mandar el mensaje es del orden de 1 msec. En total el PIC está dedicado a la
tarea de comunicaciones 1 msec cada 50 msec. Un 2% frente al 25% de antes (a
pesar de estar mandando un 50% más de bytes como vimos).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">De nuevo
podríamos usar un voltímetro para estimar la ocupación sin tener un
osciloscopio. Basta usar el mismo pin, p.e. RC0, tanto para la interrupción
como para puts. El voltaje medido es de 0.12V lo que corresponde a 0.12/5
= 0.024 (2.4%) lo que es compatible con
lo visto en el osciloscopio. <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">La
desventaja del enfoque de interrupciones es que somos nosotros los responsables
de no mandar más bytes por segundo que los que puede procesar el puerto serie.
Si lo hacemos tendremos un overrun del buffer de TX y habrá caracteres
perdidos. Con el enfoque de esperar obviamente eso no puede pasar (a costa de
no hacer otra cosa). <span style="font-size: xx-small;"><o:p></o:p></span></span></div>
</div>
<div class="MsoNormal">
<br /></div>
Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com3tag:blogger.com,1999:blog-4945680608471335280.post-77900226527265292702012-06-22T13:43:00.001+02:002013-06-10T11:48:35.002+02:00Comunicaciones puerto serie (UART)<div style="text-align: justify;">
<span style="font-family: Verdana;">Vamos a dedicar un par de entradas a examinar con cierto
detalle el funcionamiento de las comunicaciones asíncronas (UART, o lo que habitualmente
se conoce como el puerto serie) de la familia PIC18.</span></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">Nos centraremos en el software, dejando de lado el aspecto
hardware, sobre todo la conversión de niveles si la comunicación es entre un
PIC y el PC o entre dos microcontroladores con diferentes voltajes (p.e. 3.3V y
5V). En mis pruebas he usado el conversor de niveles integrado en la placa
EasyPIC6. En general habrá que usar un conversor de niveles basado en el Max232
o similar. Una búsqueda de RS232 MAX232 TTL en ebay nos mostrará varias
posibilidades a partir de unos $5.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">En primer lugar presentaremos las funciones básicas que la
mayoría de los compiladores tienen para abrir el puerto serie, enviar/recibir,
etc. Luego escribiremos nuestras propias rutinas. El objetivo no es prescindir
de las rutinas del compilador, sino entender los fundamentos para ser capaces
(cuando sea necesario) de saltarnos las limitaciones de un compilador en
particular.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana;">También escribiremos una función que nos permita
configurar el puerto serie a partir de la velocidad en baudios, sin tener que
calcular y programar los registros asociados.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;">Código
asociado a esta entrada: <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/uart0.c">uart0.c</a> <a href="http://artico.lma.fi.upm.es/numerico/antonio/blog/uart1.c"> uart1.c </a></span></div>
</div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;"></span></div>
<a name='more'></a><div style="text-align: justify;">
------------------------------------------------------------------------------------------------------------</div>
<div style="text-align: justify;">
<br /></div>
<div class="MsoNormal" style="text-align: justify;">
<span lang="PT-BR" style="font-family: Verdana;"></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana, sans-serif;">Funciones básicas de manejo de
puerto serie: (uart0.c)<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">En primer lugar vamos a ver un sencillo código en C que
establece una comunicación serie entre el PIC y p.e. un PC usando las rutinas
del compilador. Dos compiladores que uso habitualmente son el C18 de Microchip
y el MikroC Pro de Mikroelectronica. No importa que estéis usando algún otro
compilador porque la idea es profundizar un poco más sobre que hace un compilador
al manejar el puerto serie de un PIC.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Las
funciones básicas de ambos compiladores en relación al puerto serie son:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div align="center">
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 78.05pt;" valign="top" width="104"><div class="MsoNormal">
<b><span style="font-size: 8pt;">FUNCION<o:p></o:p></span></b></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.55pt;" valign="top" width="119"><div class="MsoNormal">
<b><span style="font-size: 8pt;">MikroC Pro <o:p></o:p></span></b></div>
</td>
<td style="border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.8pt;" valign="top" width="168"><div class="MsoNormal">
<b><span style="font-size: 8pt;">C18<o:p></o:p></span></b></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 78.05pt;" valign="top" width="104"><div class="MsoNormal">
<span style="font-size: 8pt;">Inicialización<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.55pt;" valign="top" width="119"><div class="MsoNormal">
<span style="font-size: 8pt;">UART1_init<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.8pt;" valign="top" width="168"><div class="MsoNormal">
<span lang="EN-GB" style="font-size: 8pt;">Open_USART</span><span style="font-size: 8pt;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 78.05pt;" valign="top" width="104"><div class="MsoNormal">
<span style="font-size: 8pt;">Data ?<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.55pt;" valign="top" width="119"><div class="MsoNormal">
<span style="font-size: 8pt;">UART1_Data_ready
<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.8pt;" valign="top" width="168"><div class="MsoNormal">
<span lang="EN-GB" style="font-size: 8pt;">DataRdyUSART</span><span style="font-size: 8pt;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 78.05pt;" valign="top" width="104"><div class="MsoNormal">
<span style="font-size: 8pt;">Leer<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.55pt;" valign="top" width="119"><div class="MsoNormal">
<span style="font-size: 8pt;">UART1_read <o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.8pt;" valign="top" width="168"><div class="MsoNormal">
<span lang="EN-GB" style="font-size: 8pt;">ReadUSART /
getcUSART</span><span style="font-size: 8pt;"><o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 78.05pt;" valign="top" width="104"><div class="MsoNormal">
<span style="font-size: 8pt;">Escribir<o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 89.55pt;" valign="top" width="119"><div class="MsoNormal">
<span style="font-size: 8pt;">UART1_write <o:p></o:p></span></div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 125.8pt;" valign="top" width="168"><div class="MsoNormal">
<span lang="EN-GB" style="font-size: 8pt;">WriteUSART / putcUSART</span><span style="font-size: 8pt;"><o:p></o:p></span></div>
</td>
</tr>
</tbody></table>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Usando las
funciones anteriores, un sencillo programa en C18 que abre el puerto serie a
9600 bauds, lo monitoriza el puerto serie y rebota lo que recibe sería el
siguiente (notad que es necesario incluir usart.h):</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: #b28c00; font-family: 'Courier New'; font-size: 8pt;">#include</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> <usart.h></span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TRISB=0; PORTB=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_ASYNCH_MODE &
USART_EIGHT_BIT & USART_BRGH_HIGH,129);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (DataRdyUSART())</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch = get_byte(); send_byte(ch+1);
send_byte(0x0D); send_byte(0x0A);<o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTB++;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(5);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><span style="background-color: white;">El mismo
programa en MikroC</span><span style="background-color: white;"> </span><span style="background-color: white;">Pro:</span></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">TRISB=0; PORTB=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">UART1_Init(9600); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (UART1_Data_Ready())</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch = UART1_Read(); UART1_Write(ch+1); UART1_Write(0x0D);
UART1_Write(0x0A); <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">PORTB++;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> delay_ms(10);</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> } </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Si
conectamos PIC y PC, cualquier cosa que tecleemos en un terminal nos es
devuelta como el carácter siguiente en la tabla ASCII, debido a que enviamos
(ch+1) donde ch es el carácter recibido. Además se manda un retorno de carro y
salto de línea. Según la configuración de nuestro terminal es posible que
veamos tanto el carácter que hemos tecleado como el que envía el PIC. Además
PORTB se incrementa con cada carácter recibido de forma que podemos ver un
feedback visual de los bytes recibidos.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Lo que
vamos a hacer ahora es volver a escribir las funciones anteriores pero usando
nuestro propio código, lo que implicará manejar los SFR (Special Function
Register) del PIC asociados a la UART. El efecto colateral será que entenderemos como funcionan
a "bajo nivel" dichas comunicaciones.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Hay 5
registros que tendremos que conocer y manejar:<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">TXSTA -> Status de TX, con el indicamos las
opciones de transmisión<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">RXSTA -> Status de RX, opciones de recepción.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">SPBRG -> determina la velocidad de las
comunicaciones (bauds) junto con el bit BRGH de TXSTA<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">RCREG y TXREG -> registros donde se guarda el
byte recibido y donde ponemos el byte a transmitir.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">La más
complicada es la inicialización de la UART. Afecta a los distintos bits de
TXTSTA, RXSTA y SPBRG. </span><span style="font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> setup_UART(uint8 brgh,uint8 spbrg)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TRISCbits.TRISC6=0; TRISCbits.TRISC7=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
RC6 out (tx), RC7 in (rx)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TXSTA =
0b00100110;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">/*TXSTA = 0x00; // Clear TX status</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> TXSTA.SYNC=0;
// Async mode</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> TXSTA.TXEN=1;
// Enable TX</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> TXSTA.TRMT=1;
// TRS empty (we start with an
empty TX register)*/</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> RCSTA = 0b10010000;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">/*RCSTA =0x00; // Clear RC status</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> RCSTA.SPEN=1; // </span><st1:place><st1:placename><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">Enable</span></st1:placename><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><st1:placename><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">Serial</span></st1:placename><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><st1:placetype><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">Port</span></st1:placetype></st1:place><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> RCSTA.CREN=1; // Enable Receiver*/</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// BRGH=0
-> Baud Rate = Fosc / (64 * (SPBRG+1))</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// BRGH=1
-> Baud Rate = Fosc / (16 * (SPBRG+1))</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TXSTAbits.BRGH=brgh; SPBRG = spbrg; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La rutina
setup_UART inicializa la UART para una comunicación asíncrona con 8 bits. La
velocidad (bauds) se calcula en función de los parámetros BRGH y SPBRG, junto
con la frecuencia del oscilador Fosc:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">BRGH=0 -> baud
= F_osc / (64 x(SPBRG+1)) <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">BRGH=1 -> baud = F_osc / (16x(SPBRG+1))<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Con un
oscilador de 20 MHz, para una velocidad de 9600 baudios usaríamos BRGH=1 y
SPBRG=129, obteniendo<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"> baud = 20000000/(16 x 130) = 9615<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">suficientemente
próxima al valor correcto.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">En la
rutina también se determina la dirección (out) del pin TX y la del pin RX (in).
En este ejemplo (familia PIC18F2520/4520) son RC6 y RC7 respectivamente. No
estoy seguro de que esto sea necesario (tal vez la dirección de RC6/RC7 se
establezca automáticamente al habilitar el receptor y el emisor) pero por si
acaso...<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Enviar un
byte es una simple cuestión de esperar a que el buffer de salida esté vacío
(consultando flag TXSTA.TRMT) y cuando lo esté, poner el carácter a transmitir
en el buffer de TX. Automáticamente el bit TRMT se pondrá a 0 (buffer lleno),
por lo que una siguiente llamada a la función
tendría que esperar a terminar de mandar el carácter.</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> send_byte(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">unsigned</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (TXSTAbits.TRMT==0);
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// wait until TX buffer is empty</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">TXREG=ch;</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Para ver
si se ha recibido algo se consulta la bandera de la interrupción de recepción
del puerto serie (definida como RX_flag como ya vimos):</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> rx_ready(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> RX_flag;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">}</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Finalmente,
si se ha detectado (rx_ready) una recepción, una llamada a get_byte recupera el
byte recibido (que está esperándonos en RCREG). También se quita la bandera
RX_flag para indicar que estamos de nuevo a la espera.</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> get_byte(</span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> RX_flag=0; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Clear RX flag</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span style="font-family: 'Courier New'; font-size: 8pt;"> RCREG;
</span><span style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Devuelve byte recibido</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">El
siguiente código usa estas funciones para hacer exactamente lo mismo que antes:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">char</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> TRISB=0; PORTB=0;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> setup_UART(1,129);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">while</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">(1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> (rx_ready())</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ch = get_byte(); send_byte(ch+1);
send_byte(0x0D); send_byte(0x0A); <o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> PORTB++;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Delay10KTCYx(5);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> }</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">¿Hemos
ganado algo? Obviamente nada si sólo
queríamos hacer lo que hacíamos en el programa inicial. Para ello nos bastaban
las rutinas que ya existían en nuestro compilador. Las ventajas aparecen cuando necesitamos apurar un poco más:<span style="background-color: white;"> </span></span></div>
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<div style="text-align: justify;">
</div>
<ol>
<li><span style="font-family: Verdana, sans-serif;">Las
rutinas standard en muchos compiladores solo soportan el modo de comunicación
más usual (8 bits sin paridad). Si por ejemplo queremos usar paridad no nos
sirven. Sin embargo ahora que sabemos lo fácil que es enviar o recibir bytes
será muy sencillo cambiar algunos bits en TXSTA y/o RXSTA para establecer una comunicación
usando p.e. paridad o 9 bits.</span></li>
<li><span style="font-family: Verdana, sans-serif;">L</span><span style="font-family: Verdana, sans-serif;">as
rutinas standard (y las que hemos escrito, ya que eran intercambiables) son
bloqueantes. Antes de escribir debemos esperar a que el buffer de transmision
(1 byte) se libere. Antes de recibir debemos estar continuamente preguntando
(rx_ready) si se ha recibido algo.</span></li>
</ol>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Imaginad
que el PIC está conectado a un sensor que genera unos 1000 bytes/segundo que
deben ser enviados al PC). Cada byte supone como mínimo 10 bits (start + 8 bits
+ stop) , por lo que para poder enviar 1000 bytes/sec precisaremos un enlace de
aproximadamentelo unos 1000 x 10 (podría valernos 9600). Si en estas circunstancias
usamos las rutinas originales, todos los recursos del PIC estarían prácticamente
dedicados a la transmisión de los datos.</span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Esta
situación puede implementarse mucho más eficientemente usando interrupciones y
esperando que la UART nos avise de que ha recibido un dato o que está libre
para enviar otro. El resto del tiempo el PIC puede estar haciendo otras cosas.
La diferencia puede ser grande. Si esperamos a que se complete la TX, enviar un
byte puede costarnos del orden de 1 ms ( @ 9600 bauds). Usando interrupciones el
único trabajo del microcontrolador será poner un byte en TXREG, lo que
esencialmente nos llevará una instrucción. Transmitir dicho byte seguirá
llevando 1 ms, pero el que estará ocupado durante ese tiempo será el periférico
(UART).<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Habiendo
aprendido como funciona por debajo la UART será muy sencillo implementar tanto
la recepción como la transmisión usando interrupciones.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<b><u><span style="font-family: Verdana, sans-serif;">Determinación de SPBRG y BRGH en
función de la velocidad en baudios<o:p></o:p></span></u></b></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Vimos que
aunque la función de MikroC Pro era menos versátil en la configuración del puerto
serie tiene la ventaja de que bastaba con darle la velocidad y ella se
encargaba de determinar los parámetros SPBRG y el bit BRGH. Esto es posible
porque en un proyecto de MikroC Pro se especifica la velocidad del oscilador.
Por la misma razón en MikroC Pro podemos especificar delays en unidades absolutas (msec o usec) en vez de limitarnos
a ciclos como en C18.<o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span style="font-family: Verdana, sans-serif;">Es muy
sencillo escribir una función que calcule los valores correctos de SPBRG y BRGH
y nos lo devuelva para usarlos en una llamada a nuestra rutina setup_UART o a
la OpenUSART de C18:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">uint8 get_usart_speed(uint32
baud, uint32 Fosc, uint8* spbrg)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// baud rate
1200,2400,4800,9600,19200, ..., 115200 </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Fosc = Frequency
osc in KHz -> 20MHz = 20000 </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Returns 0
(USART_BRGH_LOW), 1 (USART_BRGH_HIGH), or 2 (cannot get speed requested)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// It places in spbrg
the value to be used as argument spbrg in OpenUSART</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> {</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint16 FF;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 shift;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> Fosc=Fosc*1000; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> baud>>=1; Fosc=Fosc/baud+1;
Fosc>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// computes round(Fosc/baud)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FF=(uint16)Fosc;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">if</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> ((FF>16320)||(FF<16)) </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> 2;
</span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Baud rate too low or too high </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh = (FF>4096)? 0:1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">//
Decides between BRGH=0 o BRGH=1</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> shift= (brgh==1)? 3:5; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> FF>>=shift; FF--; FF>>=1; </span><span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;">// Computes round(FF/64 -1) or round(FF/16-1)</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> *spbrg = (uint8)FF;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">return</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> </span><span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">La forma
de usar esta rutina para inicializar la UART en conjunción con setup_UART()
sería:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh,sp;
</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(38400,20000,&sp);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;"> setup_UART(brgh,sp); </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si
preferimos seguir usando la rutina de C18 (OpenUSART) para inicializar la
USART:</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div style="border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; padding: 1.0pt 4.0pt 1.0pt 4.0pt;">
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="color: blue; font-family: 'Courier New'; font-size: 8pt;">void</span><span style="font-family: 'Courier New'; font-size: 8pt;"> main() </span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">{</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> uint8 brgh,brgh_config,sp; </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> brgh=get_usart_speed(38400,20000,&sp);</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="color: forestgreen; font-family: 'Courier New'; font-size: 8pt;"> </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;">brgh_config=(brgh)?
USART_BRGH_HIGH:USART_BRGH_LOW;</span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"> OpenUSART(USART_ASYNCH_MODE &
USART_EIGHT_BIT & brgh_config, sp); </span><span lang="EN-GB" style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
<div class="MsoNormal" style="border: none; mso-border-alt: solid windowtext .5pt; mso-layout-grid-align: none; mso-padding-alt: 1.0pt 4.0pt 1.0pt 4.0pt; padding: 0cm; text-autospace: none;">
<span style="font-family: 'Courier New'; font-size: 8pt;">}</span><span style="font-family: 'Courier New'; font-size: 8pt;"><o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Verdana, sans-serif;">Si solo
vamos a inicializar el puerto es obviamente más eficiente calcular nosotros los
valores a usar y programarlos directamente. De esta forma nos ahorraríamos los
30-40 palabras de memoria de programa que ocupa la rutina anterior. Este
enfoque es más útil si queremos dinámicamente cambiar la velocidad del puerto
serie durante el programa.</span><span style="font-size: xx-small;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<span style="font-size: 8pt;"><br /></span></div>
<br />
<br />
<br />
<br />
<br />Antoniohttp://www.blogger.com/profile/11418720561812415814noreply@blogger.com24