miércoles, 22 de diciembre de 2010

Programador USBasp

Ya todos conocen la importancia de tener un buen programador o quemador de uC's; en el mercado existe una gran diversidad de los mismos y a diferentes precios, pero para que pagar por uno de ellos cuando podemos hacerlo nosotros mismos.
En la pagina http://adf.ly/1X64cL encontraremos todo lo necesario para la construcción del famoso USBasp. Yo personalmente lo uso todos los días y hasta ahora no me ha fallado.
El esquema del circuito es muy sencillo, la cantidad de componentes es mínima y puede funcionar inclusive con win7-64bits.
En el siguiente enlace se puede encontrar la información necesaria ( esquema, layout, firmware, etc..) para su implementación.
USBasp.

El software para programación que recomiendo es Sinaprog, el cual puede ser descargado de el siguiente enlace SinaProg-1.4.5.10.
*** NEW  SinaProg 2

Ésta entrada no serviría de nada sin un pequeño aporte de mi parte.
Agregándole una cantidad mínima de componentes podemos llegar a esto:


El cual permitirá programar placas que ya tengan el famoso conector ISP de atmel y también otros uC's usando el ZIF-SOCKET (mega8,16,32,164P,324P...).
El layout de éste lo pueden encontrar aquí LAYOUT, ésta hecho en proteus.


PROGRAMANDO ATMEGA128

  

 
 
PROGRAMANDO ATMEGA324P


Para poder usar éste programador en Windows 7-64 bits tienen que usar el siguiente driver USBasp-Win7-x64. USBasp-Win7-x64.7z
El proceso de instalación se muestra en las siguientes imagenes.




Espero esta entrada sea de utilidad para ustedes, hasta la próxima.









Parte 2 (17/03/16):
En la siguiente imagen se muestra el nuevo programador USBasp.
Al final de este post dejare los archivos para la implementación.

image

El esquema del programador se muestra en la siguiente figura.
El firmware fue modificado para generar una frecuencia de reloj por el pin PB1/OC1A (de 2KHz a 6MHz). Esta frecuencia, aplicada al pin XTAL1 del uC a programar, permitirá usar cualquier cambianación de fuses.

ZIF


SinaProg 2.1
Esquemas USBasp zif – proteus
USBasp firmware modificado


Vendo Programador AVRISP XPII, compatible con AVRISP mkII. Funciona al 100% con Atmel Studio 7. 
PRECIO: S/. 120.00




martes, 26 de octubre de 2010

UART E INTERRUPCIONES

Al igual que en otros uC aquí lo único que hay que hacer es configurar lo necesario en los registros correspondientes (velocidad, cantidad de bits, etc.). Los registros a los que me refiero se pueden encontrar en todos los ATmega y son los siguientes:
Descargar programa.


Pasaremos a dar una pequeña explicación de la función de cada registro.


UDR es el registro en que permite acceder al byte que ha llegado al uart, y también permite escribir el valor que se enviara. Es decir que cuando se quiere enviar un dato por el uart éste debe ser escrito en UDR, y cuando se quiera leer se debe hacer la lectura de UDR. UDR pondrá o sacara el dato de buffer de transmisión (TXB) o de recepción (RXB) según sea el caso.


-RXC (Recepción Completa): Se pone a "1" cuando se ha recibido un dato y se pone a "0" cuando el buffer de recepción esta vació.

-TXC (Transmisión Completa): Se pone a "1" cuando se ha transmitido por completo una trama de bytes (o un solo byte) y ya no hay nada más por transmitir. Se pone a "0" cuando se ejecuta la interrupción por transmisión completa o también puede ser puesto a "0" por programa.

-UDRE (Registro de Datos esta Vació): Se pone a "1" cuando UDR esta vació, es decir se puede transmitir nuevos datos.

-FE (Error en trama): Se pone a "1" cuando hay errores en la trama (por ejemplo cuando el bit de stop es "0"). Éste bit es válido hasta que se lee UDR.

-DOR (Saturación de Datos): Se pone a "1" cuando el buffer de recepción está lleno (2 datos) y se detecta un bit de Start. Éste bit es válido hasta que se lee UDR.

-PE (Error de Paridad): Se pone a "1" cuando se ha detectado un error de paridad, siempre que esté habilitada esta función.

-U2X (Doble velocidad de transmisión): Éste bit sólo es válido en transmisión asíncrona y debe ser puesto a 1 para duplicar la velocidad de transmisión.

-MPCM (Modo de Comunicación Multi-Procesador): Se debe poner a "1" para activar la detección de direcciones en la transmisión con múltiples uC's.


-RXCIE (Habilitación de Interrupción por Recepción Completa). Éste bit se debe poner a "1" para habilitar dicha interrupción. Tener en cuenta que para que ocurra la interrupción el bit "I" (Interrupción Global) del registro de estado (SREG) debe estar en "1".

-TXCIE (Habilitación de Interrupción por Transmisión Completa). Éste bit se debe poner a "1" para habilitar dicha interrupción. Tener en cuenta que para que ocurra la interrupción el bit "I" (Interrupción Global) del registro de estado (SREG) debe estar en "1".

-UDRIE (Habilitación de Interrupción porque El Registro de Datos esta Vació).Éste bit se debe poner a "1" para habilitar dicha interrupción. Tener en cuenta que para que ocurra la interrupción el bit "I" (Interrupción Global) del registro de estado (SREG) debe estar en "1".

-RXEN (Habilitar Recepción). Se debe poner a "1" para habilitar la recepción. Poniendo éste bit a "0" se limpia e buffer RXB.

-TXEN (Habilitar Transmisión). Se debe poner a "1" para habilitar la transmisión.

-UCSZ2 (Tamaño del Carácter). Éste bit combinado con UCSZ1:0 del registro UCSRC permiten seleccionar el número de bits en la transmisión y recepción (5, 6, 7, 8 o 9 bits).

-RXB8 (Bit 8 del dato Recibido). Cuando se ha seleccionado 9 bits los 8 primeros llegan al registro UDR y el noveno a RXB8. Éste bit debe ser leído antes de leer UDR.

-TXB8 (Bit 8 del dato a Enviar). Cuando se ha seleccionado 9 bits los 8 primeros se deben poner al registro UDR y el noveno a TXB8. Éste bit debe ser escrito antes de escribir UDR.


-URSEL (Selección de Registro). Éste bit no sólo existe en los uC que tienen un uart (i.e ATmega8), esto ya que comparte UCSRC comparte la misma posición de I/O en la memoria con UBRRH. Éste bit debe ser "1" para poder escribir en UCSRC.

-UMSEL (Selección del modo del USART). Si se pone a "1" se activa la operación síncrona.

-UPM1:0(Tipo de Paridad). Permite seleccionar el tipo de paridad usado.


-USBS (Seleccionar Bits de Stop). Si se pone a "1" la transmisión tendrá 2 bits de stop, caso contrario 1 bit de stop.
-UCSZ1:0(Tamaño del Carácter).Éste bit combinado con UCSZ2 del registro UCSRB permiten seleccionar el número de bits en la transmisión y recepción (5, 6, 7, 8 o 9 bits).

VELOCIDAD DE OPERACIÓN.

La velocidad de operación esta dada por:


Donde UBRR=UBRRH:UBRRL, que son los registro donde se colocara el valor correspondiente a la velocidad deseada.

INTERRUPCIONES.
Las interrupciones se encuentran vectorizadas, es decir que cada interrupción tiene una posición de memoria a la que se dirigirá cuando esta ocurra. Las interrupciones del ATmega8 son las siguientes.

Ahora mostraré un pequeño ejemplo en el cual usaremos las macros creadas en post anteriores. (XTAL=16MHz)


En el ejemplo se espera el dato que llega por el uart, se le suma 1 a dicho dato y se vuelve a enviar.

Ahora haremos lo mismo pero usando Interrupciones.


El vector de interrupción por recepción completa está ubicado en la dirección 0x000B, es allí donde se dirigirá el PC cuando ocurra la interrupción, es por ello que allí debemos decirle a donde debe ir para ejecutar la rutina correspondiente. Luego al terminar la rutina se retornara con un RETI (retorno de interrupción). Tener en cuenta que se debe habilitar "I" en SREG, esto lo hace la instrucción SEI.

sábado, 9 de octubre de 2010

MÁS MACROS

Algunas de las instrucciones no tienen acceso a toda la memoria de los ATmega, como por ejemplo:

Se puede apreciar que estas instrucciones solamente tienen acceso a las 64 primeras posiciones de la RAM, luego para poder acceder al resto de posiciones tendremos que usar instrucciones como las siguientes. 
Para evitar  recordar esto podemos crear macros que nos faciliten el trabajo, así con la misma macro podremos acceder tanto a las posiciones menores a 0x40 como al resto de la RAM. Quizá se pregunten por qué no usar LDS y STS para acceder a toda la memoria, la razón para no hacer esto es que estas instrucciones ocupan el doble de espacio que IN y OUT, por ello es mejor usar estas instrucciones solamente cuando sea necesario.

Las macros son:
Ahora con un pequeño programa donde usaremos estas macros veremos cómo se comporta el compilador. 

Si desensamblamos el pequeño programas mostrado arriba veremos lo siguiente:

Cómo se puede apreciar el compilador ya discrimino y colocó la instrucción correspondiente, esto nos ahorrará mucho trabajo ya que podemos usar esta macro para acceder a los registros de configuración (SFR) y al resto de la RAM. 

Otro par de instrucciones muy importantes son:


Estas instrucciones ponen a “1” y “0”, respectivamente, un bit de un registro de la RAM que se encuentre en posiciones menores a 0x20. Aunque están hechas para operar sobre los puertos de I/O podemos extender su poder mediante las macros.

En la macro primero debemos verificar que el valor del bit se encuentre en el rango de 0 a 7, luego si el registro se encuentra en una posición mayor a 0x3F tendremos que usar instrucciones como LDS y STS, si es mayor que 0x1F y menor a 0x40 se usaran las instrucciones IN y OUT, al final si la posición de memoria es menor a 0x20 usaremos SBI o CBI según dea el caso. SBR pone a “1” el bit indicado en el registro y CBR lo pone a “0”.
Ahora usaremos estas macro y veremos su comportamiento.

En el programa mostrado se incluyen 2 errores que deben ser detectados por el compilador.
Vemos que efectivamente los errores son detectados.

Ahora corregiremos los errores y veremos el código desemsamblado.

Ahora vemos que el compilador ya remplazo las instrucciones de acuerdo a las posiciones de memoria que se especifican.



Por último haremos macros para aumentar el alcance de un par de instrucciones de salto muy importantes como son:
Las macros creadas son:
La forma de uso es igual al de las anteriores macros, teniendo en cuenta que el salto no siempre sera posible entre macros. 

sábado, 18 de septiembre de 2010

MACROS

Macros: Las macros asignan un nombre simbólico a un bloque de sentencias fuente. Luego se puede usar dicho nombre para representar esas sentencias. Opcionalmente se pueden definir parámetros para representar argumentos para la macro.


Las macros de definen así:


.MACRO      nombre_de_la_macro
..... instrucciones a ejecutar
.ENMACRO


Un ejemplo de su uso puede ser las instrucciones del inicio de pila.


 Cuando se quiera iniciar la pila solamente hay que colocar INICIA_PILA.


Ya que no se cuenta con una instrucción para Adherir un Inmediato a un Registro (Rn +k), pero sí la instrucción que resta (Rn-k), podemos crear una macro que realice esta operación.


Esta macro de nombre "ADDI"  resta al registro que es identificado por "@0"  el negativo del inmediato "@1", esto es @0 - (-(@1)) = @0 + @1 .  Si queremos sumarle al Registro R19=127 el inmediato 46.
Luego de esto R19=127+46 = 173

Ahora para hacer más manejable el código podemos crear un archivo que incluya todas nuestras macros. Nuestras subrutinas también las pondremos en otro archivo.




Nuestro proyecto final queda.



viernes, 17 de septiembre de 2010

ENLACES DE AYUDA..... SOS

DATA SHEET:

                  


Para mayor detalle sobre las instrucciones ver la hoja de datos de cada uC. También pueden usar la ayuda del AVR STUDIO ( Help --> Assembler Help ).
                              

jueves, 16 de septiembre de 2010

La Pila, llamadas a subrutinas y retardos por software

En esta entrada hablaré de una muy importante como lo es el Stack o Pila, así como de las instrucciones, ya conocidas, PUSH y POP, las llamadas a subrutinas y cómo generar retardos por software.

//*****************************************************************************************************
//*****************************************************************************************************
La Pila en Atmel: Esta estructura es diferente a la de otros uC (por ejemplo los PIC) ya que no cuenta con un hardware dedicado, esto es porque tenemos la libertad de usar toda la capacidad de la RAM ( por ejemplo en un atmega324p tendríamos  como máximo 2K posiciones de pila) . Para poder usar la pila ésta debe ser definida al inicio de cada programa en el cual se use instrucciones como: (RCALL, ICALL, CALL, PUSH, POP, RET, RETI).  La declaración de la pila se hará colocando el valor de inicio de la misma en los registros SPH y SPL (Stack Pointer High y Stack Pointer Low). El valor del SP irá decrementando a medida se llena la pila, y aumentará a medida se va liberando. 
Particularmente recomiendo iniciar el SP a la posición final de la RAM, así no tendremos problemas con las posiciones de memoria que usemos como variables.




En el ejemplo mostrado arriba se puede ver cómo definir la pila a la posición final de la RAM. RAMEND ( Fin de la RAM) es una constante que se encuentra definida en .include "mxdef.inc"  y es diferente para cada uC. Por ejemplo en el atmega8 RAMEND=0x45F=1119.
1119 bytes es mayor que 1K=1024bytes, esto es ya que en la RAM están los 32 Registros de trabajo con los que cuenta este uC además de los registro de entradas/salidas  que sumados dan 0x5F=95 bytes. 32 (registros) + 63(reg i/o) + 1024(SRAM) = 1119 bytes.

LDI R17,HIGH(RAMEND) // R17 <-- 0x04
- Carga Inmediato al registro R17, la funcion HIGH nos devuelve el byte alto de RAMEND= 0x45F 
---> HIGH(RAMEND)= 0x04
LDI R16,LOW(RAMEND)   // R16<-- 0x5F
OUT SPH,R17 // Pone R17 en SPH
OUT SPL,R16               //  Pone R16 en SPL

Finalmente la pila queda definida : SP=0x45F.

RETARDOS:
~~~~~~~~~~
Crear rutinas de retardos siempre es necesario, para ello crearemos una rutina general que nos permita obtener retardos en ms.
    
La idea general es anidar rutinas de este tipo.



Por ejemplo: si tenemos f=16MHz y queremos una rutina de 1ms. 
1ms= (V)(X+4)/16MHz--> para V=250, X=60. X=60 significa que nuestra rutina tendrá 60 instrucciones NOP, para evitar esto aplicaremos el paso anterior a 60 --> 60=(V1)(X1+4) --> V1=12 y X1=1; finalmente obtenemos una rutina que para f=16MHz demora 1ms.

 
Si queremos hacer esto aún más general tendremos que anidar lo anterior en otro bucle, obteniendo lo siguiente:

Para usar esta rutina tendremos que cargar el valor del retardo en R20 y  llamar a la etiqueta RETms.

El siguiente programa hará parpadear un led con algunos retardos.



Si este ejemplo lo simulan con AVR Studio o Proteus pueden ver cómo en el final de la RAM se irán guardando los valores del PC al llamar a la rutina de retardo.

Aquí podemos ver el inicial valor de SP.


Aquí vemos PC=0x000008, en la siguiente instrucción PC=0x000009 se guardará en la última posición de la RAM o memoria de datos
 


Aquí PC saltó a la etiqueta  RETms y la dirección 0x000009 se guardó en el final de la RAM.