sábado, 9 de julio de 2011

RTC DS1307 Y ATMEGA8


Ver I2C + RTC DS3231 usando C

En éste post mostraré un programa que permite configurar un DS1307. Como sabemos el DS1307 se comunica por I2C.
El programa tiene dos partes que son ejecutadas por dos interrupciones.

En la interrupción del timer 1, que se ejecutará cada 1000ms (1seg), leerá la hora y fecha del DS1307 y se mostrará en un LCD.

Por el uart llega información que permite leer ó escribir el DS1307.
La información para escribir(configurarlo a una hora y fecha determinada) consta de 8 bytes que son:

| CABECERA(1) | COMANDO(1) | HORA(1) | MIN(1) | SEG(1) | FECHA(1) | MES(1) | AÑO(1) |

La cabecera es 0xBA
El comando puede ser ‘W’(0x57) para escribir y ‘R’(0x52) para leer.
El resto de datos deben estar en BCD.
Un ejemplo de esto es: BA 57 12 21 08 08 07 11
Donde la hora es 12:21:08 y la fecha es 08/07/11.

En el caso que se quiera leer solamente hay que enviar BA 52 y la respuesta a esto será por ejemplo BA 57 12 30 12 08 07 11 , donde se indica que la hora leída es 12:30:12 08/07/11

El esquema es el siguiente:

sch (Small)

Ahora mostraré las macros usadas.
  
mac2

mac3

mac4

mac5

mac6

Ahora las rutinas para I2C y DS1307.

i2c1

i2c3

i2c4

Como ya sabemos cada esclavo que se conecta al bus I2C debe tener una dirección y en éste caso la dirección del DS1307 es 0b1101000 + el bit de R/W, es por ello que para escritura se envía D0 y para lectura D1.

Ahora las rutinas del UART.

u1

u2

u3

u4

u5

Por último el mensaje principal.
Hay que tener en cuenta que se esta usando el RC interno.

main1

main2

main3

En el siguiente video se muestra el funcionamiento del programa.


El programa que se muestra para configurar el DS1307 lo hice en visual C#, éste programa lo pueden descargar de éste enlace RTC_DS1307.
Si no lo pueden abrir instalen netframework 3.5.

sábado, 11 de junio de 2011

CRC KERMIT Y CCITT EN ATMEGA

Cuando se tiene aplicaciones que involucran transmisión de datos siempre es importante tener un medio para detectar errores o para verificar la integridad de dicha información, es aquí donde entra a tallar el Chequeo de Redundancia Cíclica (CRC).

En éste post mostrare un par de rutinas para hacer el calculo del CRC KERMIT Y CRC CCITT en assembler de ATMEL.

Los resultados pueden ser chequeados en On-line CRC calculation

Aquí no hay mucho que decir así que pasare a mostrar las rutinas.

CRC1

Aqui hay dos buques que calcularan el crc de la cadena de texto (“JONATHAN RAUL SEMINARIO”) que se encuentra en la memoria de programa.

CRC2

CRC3

Las rutinas son muy similares, tienen la misma cantidad de instrucciones (22 instrucciones) y son ejecutadas en la misma cantidad de ciclos de instrucción(28 c.i). Si trabajamos con un XTAL=16MHz nos tomará 1.75us calcular el crc de cada byte.


Bueno, eso es todo en éste post…bye !!!

domingo, 5 de junio de 2011

Input Capture Unit


El timer1 incorpora una unidad de captura la cual puede capturar eventos externos y darnos un tiempo referencial en el cual estos ocurrieron.
La señal que indica el evento puede ser aplicado al pin ICP1 o vía la unidad de comparación analógica. El tiempo que es capturado puede ser usado para medir frecuencia, duty-cycle u alguna otra característica de la señal aplicada.

En el siguiente gráfico de muestra el diagrama de bloques de la unidad de captura.

bloques

Se puede ver que las entradas pueden ser el pin ICP1 o el comparador analógico. LA unidad también cuenta con un modulo de cancelación de ruido el cual tomará 4 muestras de la señal y si las 4 son iguales la señal será valida. También ésta el modulo de detección de flanco que nos permite seleccionar entre los flancos de subida(‘1’) o bajada(‘0’).
Cuando el evento ocurre los 16bits del contador TCNT1 son escritos al registro ICR1, también  en éste mismo instante se generará un interrupción( siempre que se activen los flag’s TICIE1 en el registro TIMSK y I en SREG.

En éste post usaré la unidad de captura para medir la frecuencia de una señal cuadrada.
El principio de medición consiste en capturar el valor de cuenta del timer1 (TCNT1) en un periodo de la señal a medir, luego con el valor de la captura , la frecuencia a la que trabaja el uC y conociendo el pre-escaler usado podremos fácilmente encontrar la frecuencia de la señal.

Por ejemplo: Si se trabaja con una F_CPU=16MHz, el valor capturado es ICR1=0x08BB y el pre-escaler usado es 64, entonces la frecuencia de la señal es:

image

Aplicando los datos a la formula:

image

Ahora pasaré a mostrar el código. Hay algunas macros y rutinas que ya he mostrado en post anteriores pero las estoy volviendo a mostrar.

Primero mostrare las macros.






m24

Ahora mostraré la rutinas de conversión de binario a ascii.

binascii1

binascii2

Ahora la rutinas para manejo del LCD.

lcd1

lcd2

lcd3

Las rutina de retardo que es usado junto a las macros delay_ms y delay_us.

retardo

La rutina para efectuar la división.

div1

div2

Y por último el código principal.






main23


main24

El funcionamiento del programa es como sigue.
  • Se configura los periféricos, se habilita la interrupción y se espera a que ésta ocurra.

  • Cuando ocurra la interrupción por captura el programa saltará a la rutina “CAPTURA_EVEN”, aquí tomará el valor capturado y lo pondrá en dos registros(R19:R18=ICR1H:ICR1L).
  • Se verificara si el timer se ha desbordado, en caso de ser así se mostrará un mensaje indicado que aquella es una frecuencia que no se puede medir(“fuera de rango”).

  • Si no se ha desbordado se calculará la frecuencia, con la formula ya antes mostrada, y se guardará en FRECASCII.

  • Luego del calculo de mostrará la frecuencia en el LCD.

  • Se espera 300ms y luego se espera al siguiente flanco de subida para iniciar la siguiente captura de datos (la medida de la frecuencia se toma entre dos francos de subida).
Hay que tener presente que con este método no se puede medir frecuencias muy altas, mientras mayor es la frecuencia mayor es el error en la medición. En un próximo post  mostraré como usar el mismo timer para hacer medidas de frecuencias mas altas.
Espero este pequeño ejemplo le ayude..!!!

Ahora un video del programa en funcionamiento.


lunes, 30 de mayo de 2011

TIMER 1

En éste post mostraré un pequeño ejemplo de como configurar el timer 1 (16 bits) para tener una gran variedad de bases de tiempo, las cuales pueden ser usadas para generar retardos, pulsos a una determinada frecuencia, etc.

Programa : TIMER

Sin mas preámbulo pasaré a mostrar las macros usadas.


A ésta macro solamente hay que indicarle el tiempo con el cual se quiere configurar el timer (en ms).
El pre-escaler del timer se puede cambiar modificando CSN.

macros2

MOVIF pone un inmediato en la RAM, ya sea en el espacio de datos o en el espacio de registro especiales.

El programa principal es el siguiente:

main1

Esta parte configura dos pines como salidas (PB0 y PB1), también configura el TIMER 1 a 100ms, configura el pre-escaler del timer y por ultimo habilita la interrupción por desborde u overflow.

main2

Cada vez que el timer se desborda se conmutará los pines PB0 y PB1, y también hay que volver a configurar el timer.

En el siguiente video se muestra el funcionamiento del programa.


sábado, 21 de mayo de 2011

Manejo del WDT

A diferencia de otros uC’s en los ATmega el WDT se puede habilitar y deshabilitar por programa, pudiendo cambiar el tiempo de reset a voluntad.

En éste post mostraré como habilitar y deshabilitar el Watch Dog Timer en cualquier ATmega.

En nuestro archivo de macros tenemos que agregar el siguiente codigo. (Link al programa)

wdt1

Estas definiciones no son aplicables a todos los ATmega, en un ATmega8 solamente de puede llegar a 2 segundos mientras que en un ATmega324P se puede llegar hasta 8 segundos.

wdt2

La macro anterior permite habilitar el wdt.

wdt3

La macro anterior permite deshabilitar el wdt.

Ahora mostrare en sencillo ejemplo de su uso.

wdt4

sábado, 2 de abril de 2011

I2C en ATmega8

En éste post mostrare un par de ejemplos de como usar el bus i2c para escribir y leer datos en una memoria EEPROM serial (24C16).
La memoria 24C16 tiene una capacidad de 2048 bytes agrupados en 8 páginas de 256 bytes cada una.
Todos los esclavos del bus i2c tienen una dirección la cual les permite ser seleccionados; en el caso de estas memorias seriales la dirección es en parte configurable o fija, esto dependerá del fabricante. En el siguiente gráfico se muestra dos memorias de fabricantes distintos.

Programas

eeproms

La primera es una memoria de ATMEL, la cual permite configurar parte de la dirección mediante los pines A2, A1 y A0; los bits B2B1B0 son usados para seleccionar la pagina de la dentro de la memoria.
La otra es una memoria de FAIRCHILD, ésta ya trae parte de dirección fija(1010), los bit A2A1A0 permiten seleccionar la pagina de la memoria a la cual se accederá.
La velocidad del reloj para esto dispositivos se indica en sus hojas de datos, en los ejemplos usaremos 100KHz. Para configurar dicha velocidad se usa la siguiente formula, la cual se puede encontrar en el manual de del uC que se usara, yo la obtuve del manual del ATmega8.
 formula

La forma de escribir  datos es la siguiente:

write

Se inicia la transmisión con un “START”, luego se selecciona el esclavo “DEVICE ADDRESS” en modo de escritura “0”, después del “ACK” enviado por el esclavo se enviara la dirección donde se escribirá “WORD ADDRESS”, por último se envía el dato a escribir. Hay que cada ciclo de escritura tiene una duración, éste tiempo dependerá del dispositivo.

La forma de leer datos es la siguiente:

read

Se inicia la transmisión con un “START”, luego se selecciona el esclavo “DEVICE ADDRESS” en modo de escritura “0”, después del “ACK” enviado por el esclavo se enviara la dirección donde se leerá “WORD ADDRESS”, nuevamente se envía un “START” o también conocido como “RESTART”, por último se lee el dato.

Bueno, como ya es costumbre mostrare las macros que usare en estos ejemplos.

macros

Ahora mostrare las rutinas para iniciar y usar el bus i2c.

rutinasi2c1

rutinasi2c2

rutinasi2c3

Ahora el un sencillo ejemplo se escritura y lectura de algunos datos en una EEPROM.

i2c1

El ejemplo no hace otra cosa que escribir algunos datos a partir de la dirección 0x05 de la pagina 0, luego los leerá.

El circuito es el siguiente:

simu_0

Con el uso de debuger i2c se puede ver la transferencia de datos:

simu_2

El final la memoria debe quedar así:

simu_1

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

El segundo ejemplo consiste en enviarle al ATmega8, por el uart, un comando para que éste lea o escriba en la EEPROM.

‘W’+PAGINA+DIRECCIÓN+DATO se usara para escribir en la EEPROM.
‘R’+PAGINA+DIRECCIÓN se usara para leer en la EEPROM.

Por ejemplo si se envía por el uart ‘W’ 0x06 0x66 0x99 el uC escribirá en la dirección 0x66 de la pagina 6 el dato 0x99. Y si enviamos ‘R’ 0x03 0x79 estaremos leyendo el datos que esta guardado en la posición 0x79 de la pagina 3.

Agregaremos algunas rutinas al archivo RUTINAS_I2C.asm:

rutinasi2c4

Las rutinas usadas en el uart son las siguientes:

uart1

uart2

El programa principal es mostrado a continuación.

i2c2

Ahora les mostrare un vídeo con el funcionamiento del programa anterior.

En el vídeo se escribe 0x99 en la dirección 0x66 de la página 6 (dirección absoluta en la memoria es 6*0x100 + 0x66 = 0x666), luego éste dato es leído. También se escribe 0x58 en la posición 0x67 de la misma página.