Код: Выделить всё
#define F_CPU 8000000UL // Я использую кристалл 8 МГц
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
struct config_t {
uint8_t cwl;
uint8_t cwh;
uint8_t tpsacold;
uint8_t divider;
uint8_t alternate;
uint8_t injpwm;
uint8_t injpwmt;
};
struct config_t config;
struct config_t config_ee EEMEM;
volatile uint8_t eeprom_store_idx; /* счетчик обрабатываемых байт данных*/
volatile uint8_t eeprom_store_busy; /* флаг, eeprom занято*/
/*
Эта функция запускает процесс сохранение структуры конфигурации из sram в
eeprom и немедленно возвращает управление,позволяя обработчику прерывания
EEPROM продолжить работу по сохранению данных.
*/
uint8_t storeConfig(void) {
if (eeprom_store_busy) {
return -1; /* eeprom занято, подождите! */
}
eeprom_store_idx = 0; /* обнулить счетчик обрабатываемых байт данных*/
eeprom_store_busy = 1; /* установить флаг, eeprom занято*/
EECR |= _BV(EERIE); /* разрешить прерывание от eeprom */
return 0;
}
/*
время выполнения этого прерывания может быть достаточно высоким в случае
самой плохой ситуации, это должно быть обязательно исследовано!
*/
SIGNAL(SIG_EEPROM_READY) {
uint8_t *pe, *ps;
uint8_t ebyte;
pe = (uint8_t *)&config_ee + eeprom_store_idx; /* адрес данных в eeprom */
ps = (uint8_t *)&config + eeprom_store_idx; /* адрес данных в sram */
ebyte = eeprom_read_byte(pe);
/* перезаписывать данные в eeprom будем только если это необходимо */
/*
сравним содержимое структур в sram и eeprom, выход из цикла
осуществляем по первому найденному различию в данных
*/
while( (ebyte == *ps) && (eeprom_store_idx != (sizeof(struct config_t) - 1)) ) {
eeprom_store_idx++;
pe++;
ps++;
ebyte = eeprom_read_byte(pe);
}
/* записываем новое значение в eeprom */
if (ebyte != *ps)
eeprom_write_byte(pe, *ps);
/*
если последняя запись в структуре не достигнута переходим к поиску
следующего различия данных в sram и eeprom
*/
if (eeprom_store_idx == sizeof(struct config_t)-1) { /* запись закончена */
EECR &= ~_BV(EERIE); /* запретить прерывание от eeprom */
eeprom_store_busy = 0; /* сбросить флаг, eeprom занято*/
PORTB &= ~_BV(PB7); /* погасить светодиод */
} else { /* переходим к следующему различию */
eeprom_store_idx++;
PORTB |= _BV(PB7); /* зажечь светодиод */
/*
необходимо отметить, если светодиод горит более 5 сек следует снять питание
с контроллера иначе возможно повреждение eeprom
*/
}
}
int main(void){
DDRB |= _BV (PB7); //установить как выход LED
PORTB &=~ _BV (PB7); //установить 0 LED
config.cwl=50; //0x32
config.cwh=65; //0x41
config.tpsacold=155; //0x9B
config.divider=48; //0x30
config.alternate=4; //0x04
config.injpwm=94; //0x5E
config.injpwmt=223; //0xDF
uint8_t i=0;
if (i==0)
{
eeprom_write_byte(0x11, config.injpwm);
i++;
}
sei();
while(1){
storeConfig();
}
}
:10000000 32000000000000FFFFFFFFFFFFFFFFFF C7
:10001000 FF5EFFFFFFFFFFFFFFFFFFFFFFFFFFFF 91
Для записи остальных переменных нужно шесть раз сбросить работу МК, нажатием на кнопку RESET.
Предполагаю что обработчик прерывания SIG_EEPROM_READY не генерируется постоянно. Либо сбрасывается EERIE где-то. Что я делаю не так? Где может быть ошибка?


