Paso 7: Implementación de código abierto I2C ATTiny USI - USI I2C esclavo
Así, como usuario final, usted probablemente está más interesado en cómo la biblioteca de su propio código de interfaz! Esto es fácil, y aquí está el porqué. He eliminado con los buffers de recepción/transmisión que fueron utilizados en otras implementaciones de USI I2C (principalmente los basados en la aplicación-nota de AVR312) y en cambio implementar el registro del Banco protocolo descrito al principio de este tutorial. El Banco se almacena como una matriz de punteros, no valores de datos, por lo que debe fijar variables locales en el código de direcciones de memoria en el I2C registrar Banco estableciendo los punteros a las variables. Esto significa que el código de la línea principal no tener encuesta I2C buffers o manejar salidas de datos, los valores se actualizan instantáneamente siempre que llegan. También permite que las variables de programa ser consultados en cualquier momento por la interfaz I2C sin afectar el código de la línea principal (que no sea el retraso debido a la interrupción). Es un sistema bastante ordenado. Tomemos nuevamente un ejemplo breve.
Por ejemplo, supongamos que tenemos un generador PWM de software muy básico que es conducir un LED. Queremos ser capaces de cambiar el valor PWM (un valor de 16 bits, sólo por el hecho de aprender sobre punteros) sin hacer el bucle principal complicado. Con la magia de esclavo I2C asincrónica, podemos hacer eso!
#include "usi_i2c_slave.h"
Definir una referencia a la matriz de puntero I2C esclavo registro Banco
extern char * USI_Slave_register_buffer [];
int main()
{
Crear valor PWM de 16 bits
unsigned int pwm_val = 0;
Asignar el byte bajo del valor de pwm a I2C dirección interna 0 x 00
Asignar el byte alto del valor de pwm a I2C dirección interna 0 x 01
USI_Slave_register_buffer [0] = (unsigned char *) & pwm_val;
USI_Slave_register_buffer [1] = (unsigned char *)(&pwm_val) + 1;
Inicializar a I2C esclavo con dirección del dispositivo esclavo 0 x 40
USI_I2C_Init(0x40);
Configurar pin A0 como salida para LED (asumiremos que cualquier chip estamos en tiene pin A0 disponibles)
DDRA | = 0 X 01;
while(1)
{
PORTA | = 0 X 01; Encender LED
para (unsigned int i = 0; i < pwm_val; i ++)
{
PORTA & = ~ (0 x 01); Apagar el LED
}
}
}
Y ahí lo tienen! El bucle principal no hace referencia a I2C en todo, pero al enviar un valor PWM a la ubicación de 16 bits en I2C dirección interna 0 x 0 x 00/01, podemos controlar totalmente el PWM del LED! Para que mayor estabilidad (para asegurarse de que sólo los valores del puntero que está utilizando están disponibles y para evitar que los punteros) le sugiero que cambie el #define USI_SLAVE_REGISTER_COUNT que el número de registro de punteros que necesita, ni más, ni menos. Cuando se intenta un acceso (lectura o escritura) en un índice de registro fuera de la gama 0 x 00 a USI_SLAVE_REGISTER_COUNT - 1, nada está escrito y se devuelve cero.