Creo que encontré la librería junto a muchas otras muy interesantes como control de GLCD,Decodificacion de protocolo NMEA, RC5, etc....en cuanto la pruebe pongo mis resultados.
Follow along with the video below to see how to install our site as a web app on your home screen.
Nota: This feature currently requires accessing the site using the built-in Safari browser.
/*************************************************
LIBRERÍA DE CONTROL PARA BUS I2C EN MODO MASTER.
PROGRAMADOR: Moyano Jonathan.
Fecha: Setiembre del 2010.
Compilador: WinAVR
************************************************/
// Acá definimos el puerto y los pines involucrados en la comunicación I2C.
// Puerto SCL.
#define SCLPORT PORTD // PUERTO RELOG I2C.
#define SCLDDR DDRD // DIRECCIÓN PUERTO RELOG.
// Puerto SDA.
#define SDAPORT PORTD // PUERTO DATOS I2C.
#define SDADDR DDRD // DIRECCIÓN PUERTO DATOS.
#define SDAPIN PIND // PUERTO DE ENTRADA DE DATOS.
// Asignaciones de pines.
#define SCL PD4 // PUERTO DE RELOG SCL I2C.
#define SDA PD3 // PUERTO DE DATOS SDA I2C.
// i2c 1/4 bit delay. (5uS)
#define QDEL asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
// i2c 1/2 bit delay. (10uS)
#define HDEL asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
#define I2C_SDA_LO SDAPORT &= ~(1<<SDA); // Pone la línea SDA, en bajo nivel.
#define I2C_SDA_HI SDAPORT |= 1<<SDA; // Pone la línea SDA, en nivel alto.
#define I2C_SCL_LO SCLPORT &= ~(1<<SCL); // Pone la línea SCL, en bajo nivel.
#define I2C_SCL_HI SCLPORT |= 1<<SCL; // Pone la línea SCL, en nivel alto.
#define I2C_SCL_TOGGLE HDEL I2C_SCL_HI HDEL I2C_SCL_LO
#define I2C_START I2C_SDA_LO QDEL I2C_SCL_LO // Condición de START.
#define I2C_STOP HDEL I2C_SCL_HI QDEL I2C_SDA_HI HDEL // Condición de STOP.
// Definición de funciones:
// Iniciamos las comunicaciones.
static void i2c_start(void);
// Paramos las comunicaciones;
static void i2c_stop(void);
// Enviamos datos por el bus I2C.
int i2c_write(int data);
// Recibimos datos por el bus I2C.
int i2c_read(void);
/*****************************************************************************************/
// FUNCIONES PARA TRABAJAR CON EL BUS I2C.
static void i2c_start(void) {
I2C_START
}
static void i2c_stop(void) {
I2C_SDA_LO // Limpiamos la línea de datos.
I2C_STOP
}
int i2c_write(int data) {
uint8_t mascara = 0x80;
uint8_t i = 8;
while(i--) {
if(data & mascara) //Si es 1.....
I2C_SDA_HI // Pone a nivel alto la salida SDA.
else // Si no es 1....
I2C_SDA_LO // Pone a nivel bajo la salida SDA.
mascara >>= 1;
I2C_SCL_TOGGLE // Cambio de flanco en el pin SCL.
}
I2C_SDA_HI // Dejamos SDA en alto.
SDADDR &= ~(1<<SDA); // Configuramos SDA como entrada.
HDEL // Esperamos 10us.
I2C_SCL_HI // Dejamos SCL en alto.
i = SDAPIN & (1<<SDA); // Obtenemos el bit ACK.
HDEL // Esperamos 10us.
I2C_SCL_LO // Dejamoslínea SCL en bajo.
SDADDR |= 1<<SDA; // Configuramos nuevamente SDA como salida.
HDEL // Esperamos 10us.
return i; // Retornamos el valor de ACK.
}
int i2c_read(void) {
uint8_t datos = 0;
uint8_t i = 8;
I2C_SDA_HI // Dejamos SDA en alto.
SDADDR &= ~(1<<SDA); // Configuramos SDA como entrada.
while (i--)
{
HDEL // Esperamos 10us.
I2C_SCL_HI // Dejamos SCL en alto.
datos <<= 1; // Rotamos el resultado a la izquierda.
if (SDAPIN & (1<<SDA))
datos += 1; // Si hay un uno en la línea de datos lo agregamos
// al arreglo.
HDEL // Esperamos 10us.
I2C_SCL_LO // Dejamoslínea SCL en bajo.
}
SDADDR |= 1<<SDA; // Configuramos nuevamente SDA como salida.
I2C_SCL_TOGGLE // Cambio de flanco en el pin SCL.
I2C_SDA_HI // Dejamos SDA en alto.
return datos; // retornamos con el dato leido.
}
/*************************************************
PROGRAMAS DE EJEMPLO PARA EL ATTINY2313 - 20PU.
PROGRAMADOR: Moyano Jonathan.
Fecha: Setiembre del 2010.
Programa: Graba 4 datos en una memoria EEPROM 24CL256. Luego
lee las memorias y muestra los valores guardados en
el puerto B.
Cristal: 8Mhz.
Programador: PK2-ISP.
************************************************/
#include <avr/io.h> // Definiciones de hardware.
#include <util/delay.h> // Librería para generar retardos.
#include <util/i2c_software.c> // Librería para el manejo de I2C por
// software.
void init_ext_eeprom()
{
SDAPORT |= 1<<SDA; // Pone la línea SDA, en nivel alto.
SCLPORT |= 1<<SCL; // Pone la línea SCL, en nivel alto.
}
void write_ext_eeprom(uint32_t address, uint8_t valor)
{
int status;
i2c_start();
i2c_write(0xa0);
i2c_write((address>>8)&0x1f);
i2c_write(address);
i2c_write(valor);
i2c_stop();
i2c_start();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
}
uint8_t read_ext_eeprom(uint32_t address) {
uint8_t _datos;
i2c_start();
i2c_write(0xa0);
i2c_write((address>>8)&0x1f);
i2c_write(address);
i2c_start();
i2c_write(0xa1);
_datos =i2c_read();
i2c_stop();
return(_datos);
}
int main(void)
{
DDRB = 0x1F; // PB0-PB4 salidas.
PORTB = 0x00; // Ponemos todas las salidas a 0.
uint8_t k; // Variable auxiliar.
init_ext_eeprom();
write_ext_eeprom(0x01,0x01);
write_ext_eeprom(0x02,0x02);
write_ext_eeprom(0x03,0x03);
write_ext_eeprom(0x04,0x04);
while(1) // Loop infinito.
{
for(k=0; k<=4; k++){
PORTB = read_ext_eeprom(k);
_delay_ms(250);
}
}
}
/*************************************************
PROGRAMAS DE EJEMPLO PARA EL ATTINY2313 - 20PU.
Fecha: Setiembre del 2010.
Programa: Guarda 1 dato en la EEPROM y luego lo lee.
Cristal: 8Mhz.
Programador: PK2-ISP.
************************************************/
#include <avr/io.h>
#include "i2cmaster.h"
#include <util/delay.h>
char i,status;
int main(void)
{
DDRB = 0x07; // PB0-PB2 salidas.
PORTB = 0x00; // Ponemos todas las salidas a 0.
i2c_init(); // Iniciamos I2C.
i2c_start_wait(0xA0+I2C_WRITE);
i2c_write(0x00); // Dirección ALTA.
i2c_write(0x01); // Dirección BAJA.
i2c_write(0x05); // Datos.
i2c_stop();
i2c_start_wait(0xA0+I2C_WRITE);
i2c_write(0x00); // Dirección ALTA.
i2c_write(0x01); // Dirección BAJA.
status = i2c_rep_start(0XA0+I2C_READ);
if(status != 0) {
i2c_stop();
PORTB = 0x04;
_delay_ms(2000);
}
else
i = i2c_readNak(); // Leemos dato.
PORTB = i;
_delay_ms(2000);
i2c_stop();
}
Aparte tengo una pequeña duda, no se si utilizaste el grabador USBASP, bueno este es de programación serial y según las hojas de datos, para grabar un micro con cristal externo con grabadores seriales se debe introducir una señal de clock externa al pin XTAL1. el hecho es que nunca lo he probado, No sabes si ¿realmente se puede grabar con el USBASP un micro configurado en cristal externo...? o por intentarlo el micro puede quedar -ingrabable- para programadores seriales...
/*****************************************************************
Fecha: Setiembre del 2010.
Cristal: 4Mhz.
Programador: Moyano Jonathan
*****************************************************************/
#include <avr/io.h> // Definiciones de hardware.
#include <util/delay.h>
// Declaramos funciones utilizadas.
void spi_init(uint8_t velocidad); // Inicia el bus SPI y setea velocidad de trabajo.
uint8_t spi_write(uint8_t dato); // Escribe un dato en el bus SPI.
// Definimos los pines para la comunicación SPI.
#define SDI PINB6
#define SDO PINB5
#define SCK PINB7
void spi_init(uint8_t velocidad) {
if (velocidad==1) { // Si velocidad = 1, la velocidad del bus es máxima.
PORTB |= (1<<SDO)|(1<<PINB4);
DDRB = (1<<SCK)|(1<<SDI)|(1<<PINB4);
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK);
PORTB &= ~(1<<PINB4); // Habilitamos esclavo.
} else { // Si velocidad es 0....
PORTB |= (1<<PINB4); // Deshabilitamos esclavo.
DDRB &= ~((1<<SCK)|(1<<SDO)|(1<<SDI)|(1<<PINB4));
USICR = 0;
}
}
uint8_t spi_write(uint8_t dato) {
USIDR = dato; // Carga el dato a enviar.
USISR = (1<<USIOIF);
do {
USICR = (1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC); // Configuramos la USI.
} while ((USISR & (1<<USIOIF)) == 0); // En caso de que termine de enviar el dato, retorna el valor
// De USIDR.
return USIDR;
}
Una vez más gracias por la info, me agrada mucho que coloques códigos con comentarios asi son fáciles de entender...Acá les dejo el código para manejar dispositivos mediante SPI usando la USI del ATtiny2313:
Una vez intente hacerlo con un oscilador en base a AO's pero no funcionó, pls será que puedes darnos algun Link...eso de perder sincronia con el oscilador en los AVR pero se soluciona facil con el 555