sábado, 30 de enero de 2010

SDCC i2c LM75


#include <pic16f873a.h>
#include <i2c.h>
typedef unsigned int word;
word at 0x2007 CONFIG = _HS_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF;

//-- Pines de conexionado para el LCD
#define RW RA2
#define RS RA1
#define E RA0


//-- Valor inicial del timer0 para hacer una pausa de 10ms
//-- Divisor del prescar a 256
#define T_10ms 61

/*********************************************/
/* Habilitar el dato escrito en el puerto B */
/*********************************************/
void enable()
{
//-- Hay que garantizar un tiempo minimo de 500ns
//-- A 20Mhz, las instrucciones tardan 200ns.
//-- Por eso nos curamos en salud y repetimos la instruccion
//-- tres veces.
E=1; E=1; E=1;
E=0; E=0; E=0;
}

/**********************************/
/* Enviar un comando al LCD */
/**********************************/
void lcd_cmd(unsigned char cmd)
{
RS=0;
PORTB=cmd;
enable();
cmd<<=4;
PORTB=cmd;
enable();
delay(1);
}

/*********************************/
/* Escribir un dato en el lcd */
/*********************************/
void lcd_write(unsigned char car)
{
RS=1;
PORTB=car;
enable();
car<<=4;
PORTB=car;
enable();
delay(1);
}

unsigned char ConfigLM75()
{
// Envia Bit de Start
i2c_SendStart();
i2c_WaitMSSP();

// 2º Envio la direccion del modulo
i2c_SendByte(0b10010000);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}


i2c_SendByte(0b00000000);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// termino el envio
i2c_SendStop();
i2c_WaitMSSP();

return 1;
}

unsigned char LeerLM75(unsigned char address, unsigned char *datoh, unsigned char *datol)
{
i2c_SendStart();
i2c_WaitMSSP();

i2c_SendByte(address);

i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

*datoh=i2c_ReadByte();

i2c_SendAck();
i2c_WaitMSSP();

*datol=i2c_ReadByte();

// Mando NACK
i2c_SendNack();
i2c_WaitMSSP();

// Mando el Stop
i2c_SendStop();
i2c_WaitMSSP();

return 1;
}

void DEC_ASCII(unsigned char dato, unsigned char *D1, unsigned char *D2,unsigned char *D3)
{
*D1 = dato / 100;
*D2 = (dato % 100) / 10;
*D3 = (dato % 100) % 10;

*D1 = 0b00110000 | *D1;
*D2 = 0b00110000 | *D2;
*D3 = 0b00110000 | *D3;
}
/*-----------------------------------------------*/
void main(void)
{
unsigned char ret;
unsigned char datoh, datol, D1, D2, D3;

TRISB=0b00001111;
TRISA=0b00000000;
ADCON1=0x06;

//-- Configurar temporizador para hacer pausas
T0CS=0; PSA=0;
//-- Configurar el prescaler (division entre 64)
PS2=1; PS1=1; PS0=1;

i2c_configure();
//-- Pausa inicial
delay(10);

//Inicializando el LCD
RW=0; E=0;
lcd_cmd(0b00101000);
lcd_cmd(0b00000110);
lcd_cmd(0b00001110);
lcd_cmd(0b00000010);
lcd_cmd(0b00000001);

ConfigLM75();

delay(10);

while(1){
lcd_cmd(0b00000010);
delay(10);
ret=LeerLM75(0b10010001, &datoh, &datol);
if (ret==1) {
DEC_ASCII(datoh, &D1, &D2, &D3);
lcd_write(D1);
lcd_write(D2);
lcd_write(D3);
}else{
LED = 1;
}
}
}

Las resistencias pullup son de 4K7 (Lauraa n.n)


viernes, 22 de enero de 2010

SDCC Leer una eeprom i2c y escribir en un LCD

Utilizando los codigos anteriores podemos leer la eeprom e imprimirla en el LCD
el caracter que grabe es la J.


//24C08A 256X4
//0xA6 = 10100110 identificador de eeprom y bit's de paginas
i2c_write_byte(0xA6, 0x0, 0x4A);
delay(10);

ret=i2c_read_byte(0xA6, 0x0, &dato);
if (ret==1) {
lcd_write(dato);
}else{
LED = 1;
}



while(1);

domingo, 17 de enero de 2010

SDCC LCD a 4 bit's

Del sitio iearobotics.com hay un ejemplo para manejar LCD a 8bits, en este caso lo adapte para 4 bits.

#include <pic16f873a.h>
typedef unsigned int word;
word at 0x2007 CONFIG = _HS_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF;

//-- Pines de conexionado para el LCD
#define RW RA2
#define RS RA1
#define E RA0


//-- Valor inicial del timer0 para hacer una pausa de 10ms
//-- Divisor del prescar a 256
#define T_10ms 61

void timer0_delay(unsigned char t0ini)
{
//-- Dar valor inicial del timer
TMR0=t0ini;

//-- Flag de interrupcion a cero
T0IF=0;

//-- Esperar a que transcurra el tiempo indicado
while(T0IF==0);
}

/*******************************************************/
/* Pausa */
/* ENTRADA: duracion de la pausa en centesimas (10ms) */
/*******************************************************/
void delay(unsigned int duracion)
{
unsigned int i;

for (i=0; i<duracion; i++)
timer0_delay(T_10ms);
}

/*********************************************/
/* Habilitar el dato escrito en el puerto B */
/*********************************************/
void enable()
{
//-- Hay que garantizar un tiempo minimo de 500ns
//-- A 20Mhz, las instrucciones tardan 200ns.
//-- Por eso nos curamos en salud y repetimos la instruccion
//-- tres veces.
E=1; E=1; E=1;
E=0; E=0; E=0;
}

/**********************************/
/* Enviar un comando al LCD */
/**********************************/
void lcd_cmd(unsigned char cmd)
{
RS=0;
PORTB=cmd;
enable();
cmd<<=4;
PORTB=cmd;
enable();
delay(1);
}

/*********************************/
/* Escribir un dato en el lcd */
/*********************************/
void lcd_write(unsigned char car)
{
RS=1;
PORTB=car;
enable();
car<<=4;
PORTB=car;
enable();
delay(1);
}

void main(void)
{
TRISB=0b00000000;
TRISA=0b00000000;
ADCON1=0x06;

//-- Configurar temporizador para hacer pausas
T0CS=0; PSA=0;
//-- Configurar el prescaler (division entre 64)
PS2=1; PS1=1; PS0=1;

//-- Pausa inicial
delay(1);

//-- Inicializar lcd (para trabajar a 4 bits)
RW=0; E=0;
lcd_cmd(0b00101000);

//-- Modo de funcionamiento
lcd_cmd(0b00000110);

//-- Encender el LCD
lcd_cmd(0b00001110);

//-- Cursor a HOME
lcd_cmd(0b00000010);

//-- CLS
lcd_cmd(0b00000001);

//-- Enviar una cadena
lcd_write('H');
lcd_write('O');
lcd_write('L');
lcd_write('A');
lcd_write('!');

while(1);
}

lunes, 4 de enero de 2010

SDCC i2c con PIC16F87x

EL codigo lo saque de iearobotics funciona exelente, lei una eeprom sin problemas.

#include <pic16f873a.h>
typedef unsigned int word;
word at 0x2007 CONFIG = _HS_OSC & _WDT_OFF & _PWRTE_ON & _BODEN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF;

#define T_10ms 61
#define LED RA0
void timer0_delay(unsigned char t0ini)
{
//-- Dar valor inicial del timer
TMR0=t0ini;

//-- Flag de interrupcion a cero
T0IF=0;

//-- Esperar a que transcurra el tiempo indicado
while(T0IF==0);
}


/*******************************************************/
/* Pausa */
/* ENTRADA: duracion de la pausa en centesimas (10ms) */
/*******************************************************/
void delay(unsigned int duracion)
{
unsigned int i;

for (i=0; i<duracion; i++)
timer0_delay(T_10ms);
}

/*
****************************************
* FUNCIONES DE BAJO NIVEL DEL I2C *
****************************************
*/

// Envia Ack
// SDA = 0
void i2c_SendAck()
{
ACKDT = 0; // Establece un ACK
ACKEN = 1; // Lo envia
}


// Envia Nack para finalizar la recepecion
// SDA = 1
void i2c_SendNack()
{
ACKDT = 1; // Establece un NACK
ACKEN = 1; // Lo envia
}


// verifica ACK
// Mira si en el 9 pulso de reloj (SCL en estado a 1) la señal SDA está a 0
unsigned char i2c_CheckACK()
{
if ( ACKSTAT == 0 ) {
return 0; // correcto (lo he recibido )
} else {
return 1; // incorrecto (no lo he recibido)
}
}


// Envia la condicion de STOP
// Libera el BUS I2C, SDA y SCL a nivel alto
// SDA=1 cuando SCL=1.
void i2c_SendStop() {
PEN = 1; // send stop bit
}


// Envia la condicion de START
// Inicializa el Bus I2C, SCL y SDA a nivel bajo
// Estando SCL=1 pone SDA=0, luego pone SCL=0
void i2c_SendStart()
{
SEN = 1; // send start bit
}

// Espera a que el I2C reciba algun evento
void i2c_WaitMSSP()
{
while (SSPIF == 0); // Espera evento
SSPIF=0; // Limpia FLAG
}


// Espera a que el I2C reciba algun evento
unsigned char i2c_MSSP_Status()
{
return SSPIF;
}




// Repeated start from master
// Queremos transmitir más datos pero sin dejar el BUS, es decir
// sin mandar previamente un STOP. O por ejemplo si queremos mandar un STOP y seguidamente un
// START para que ningún otro dispositivo ocupe la línea usaremos esto.
void i2c_SendRStart() {
RSEN=1;
}


// Leer Byte por el I2C
// Devuelve byte leido
unsigned char i2c_ReadByte() {
RCEN=1; // Activar el RCEN

i2c_WaitMSSP();
return SSPBUF;
}




// Envia un Dato por el Bus I2C
// Entrada el dato a enviar
void i2c_SendByte(unsigned char dato) {
SSPBUF=dato;
}



// Fallo en el I2C
void i2c_fail() {
i2c_SendStop();
i2c_WaitMSSP();
}



/*
**************************************
* FUNCIONES DE ALTO NIVEL del I2C *
**************************************
*/


/* Configurar I2C
Configuramos el I2C como Master
y a una velocidad de 1Mhz
*/

void i2c_configure()
{
// configuramos SCL y SDA como pines de entrada
TRISC=TRISC | 0x18; // 1 entrada / 0 salida

SSPSTAT=0x0;
SSPSTAT=SSPSTAT | 0x80; // SMP=1 Slew rate disable for 100Kh @@@
// CKE=0 (modo maestro I2C) y UA=0 (7 bits)

SSPCON=0x08; // I2C master mode (uso la formula del reloj con SSPAD)
SSPCON=SSPCON | 0x20; // enable I2C SSPEN=1

SSPCON2=0x00; // no se usa por ahora
// velocidad = FOSC / ( 4 * (sspad + 1) )
// Fosc=20Mhz

SSPADD=49; // 49->100Khz @@@
//SSPADD=24; // 24 -> 400khz @@@

// Limpia Flags de eventos
SSPIF=0; //Limpia flag de eventos SSP
}



// manda un byte al dispositivo i2c
unsigned char i2c_write_byte(unsigned char address, unsigned char reg,
unsigned char dato)
{
// 1º Envia Bit de Start
i2c_SendStart();
i2c_WaitMSSP();

// 2º Envio la direccion del modulo
i2c_SendByte(address);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// 3º mando el registro sobre el que voy a actuar
i2c_SendByte(reg);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// 4º mando el dato
i2c_SendByte(dato);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// 6º termino el envio
i2c_SendStop();
i2c_WaitMSSP();

return 1; // Byte mandado correctamente
}


// Lee 1 byte1 del dispositivo i2c
// El dato leido lo devuelve por el parametro dato
unsigned char i2c_read_byte(unsigned char address, unsigned char reg,
unsigned char *dato)
{

// 1º Envia Bit de Start
i2c_SendStart();
i2c_WaitMSSP();

// 2º Envio la direccion del modulo
i2c_SendByte(address);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// 3º mando el registro sobre el que voy a actuar
i2c_SendByte(reg);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// 4º Repeated start
i2c_SendRStart();
i2c_WaitMSSP();

// 4º mando direccion indicando lectura
i2c_SendByte(address | 1);
i2c_WaitMSSP();
if (i2c_CheckACK()!=0) {
i2c_fail();
return 0; // Ha habido un error, salgo de la rutina
}

// 5º leo el byte
*dato=i2c_ReadByte();

// 6º Mando NACK
i2c_SendNack();
i2c_WaitMSSP();

// Mando el Stop
i2c_SendStop();
i2c_WaitMSSP();

return 1; // Lectura correcta

}

//----------------------------
//- Comienzo del programa
//----------------------------

void main(void)
{
unsigned char ret;
unsigned char dato;

TRISB=0x00;
TRISA=0x00;
//-- Configurar el puerto A como digital
ADCON1=0x06;

//-- Configurar temporizador para hacer pausas
T0CS=0; PSA=0;
//-- Configurar el prescaler (division entre 64)
PS2=1; PS1=1; PS0=1;

//-- Pausa inicial
delay(100);

//-- Configurar el I2C como master
i2c_configure();

//-- Hago una pausa antes de empezar
delay(10);

//24C08A 256X4
//0xA6 = 10100110 identificador de eeprom y bit's de paginas
i2c_write_byte(0xA6, 0x0, 0xAA);
delay(10);

ret=i2c_read_byte(0xA6, 0x0, &dato);
if (ret==1) {
PORTB = dato;
}else{
LED = 1;
}


while(1);

}

Recuerden que la memoria 24C08A no utiliza los pines A0 A1 ya que los usa para acceder a los
bancos que son 4 segun la hoja de datos de atmel.
Osea para formar la palabra de control:

1010 -> identificador de la memoria, luego A2,A1,A0, R/W
en el ejemplo se accedio al 4 banco de 256 bits

10100000 para escribir el primer banco
10100001 para leer el primer banco

el pin A2 sera entonces para direccionar otras unidades conectadas al bus i2c.


IRC

#freenode->#usljujuy

Seguidores

Eventos n_n

Tira Ecol Nano,Bilo y Luca