Ce programme simule un capteur I2C. Il utilise le module TWS présent sur les MCU AtTiny20/40/441/841/1634.
Le maître peut faire un accès en lecture simple, ou en lecture-écriture de façon à accèder à un registre particulier. Chaque valeur mesurée est stockée dans un registre 16 bits, octet de poids faible en premier.
Le programme utilise le chien de garde pour cadencer les séquences de mise en sommeil.
Sans traffic I2C, le MCU est réveillé toutes les 8 secondes.
Le timer chien de garde est remis à zéro à chaque échange I2C avec un délai de 15ms. Le MCU sera donc endormi 15ms après le dernier échange I2C pour 8s.
Une incrémentation de tous les registres capteurs est effectuée toutes les 4 interruptions chien de garde (simulation d'une évolution capteur).
LED1 est allumée lorsque le MCU est réveillé.
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <util/atomic.h>
#include <avrio/led.h>
#include <avrio/delay.h>
#include <avrio/mutex.h>
#include <avrio/tws.h>
#define OWN_ADDRESS (0x10)
#define NOF_REGISTERS 5
static volatile uint8_t buffer[NOF_REGISTERS * 2];
static volatile uint8_t rd_index;
ISR (WDT_vect) {
}
int
main (void) {
uint8_t wdt_count = 0;
power_all_disable();
power_twi_enable();
for (uint8_t i = 0; i < NOF_REGISTERS; i++) {
buffer [i * 2 + 1] = i + 1;
}
vTwsInit (OWN_ADDRESS << 1);
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
wdt_enable (WDTO_8S);
sei();
for (;;) {
wdt_enable (WDTO_8S);
wdt_count++;
if (wdt_count % 4 == 0) {
for (uint8_t i = 0; i < sizeof (buffer); i += 2) {
uint8_t r = buffer[i];
r++;
ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {
buffer[i] = r;
}
}
}
cli();
sleep_enable();
sei();
sleep_cpu();
sleep_disable();
}
}
return 0;
}
uint8_t
wdt_enable (WDTO_15MS);
if (rd_index >= sizeof (buffer)) {
rd_index = 0;
}
return buffer[rd_index++];
}
void
wdt_reset();
rd_index = data;
}
void get_mcusr (void) \
__attribute__ ( (naked)) \
__attribute__ ( (section (".init3")));
void get_mcusr (void) {
MCUSR = 0;
wdt_disable();
}