Вот что у меня получилось с прерываниями.. Выигрыш по скорости в сравнении с тупым ожиданием примерно в два раза. Стоит ли оно того? проверил на IAR'е и gcc, вроде работает, только кода много получается - без оптимизации около 500 байт для чипов с EEPROM > 256 байт, и около 400 для чипов с EEPROM <= 256 байт.
Код
/* файл ee_mgr.c */
// Использование динамической памяти отбросил (не актуально для мелкоконтроллеров с менее 8k RAM)
#include <avr\io.h>
#include "ee_mgr.h"
#ifndef _ee_mgr_header_present
// объявление возможных ошибок
#define ERROR_MSG_TOO_LONG 0
#define ERROR_BUSY -1
#define ERROR_NOT_ENOUGH_FREE_SPACE -2
// объявление констант
#define EE_BUFFER_LENGTH 16
#endif
#define FALSE 0
#define TRUE 1
#define CARDINAL unsigned char
#define cli asm("cli")
#define EE_ReadyForAction (EECR & (1 << EEWE))
// реализована пока только функции записи в EEPROM,
// чтение по прерыванию сделать нельзя да и было бы медленнее!
char EE_Buf[EE_BUFFER_LENGTH]; // общий буфер для чтения и запис
CARDINAL EE_CurrentPos = 0;
CARDINAL EE_Count = 0;
WORD EE_StartAddress;
char EE_Busy = FALSE;
int EEPROMWriteMsg(WORD address, void *msg, int count)
{
char *amsg;
CARDINAL i;
if (count > EE_BUFFER_LENGTH)
return ERROR_MSG_TOO_LONG;
if (EE_Busy)
return ERROR_BUSY;
if ((address + count) > E2END)
return ERROR_NOT_ENOUGH_FREE_SPACE;
amsg = msg;
EE_CurrentPos = 0;
for(i=0; i < count; i++)
EE_Buf[i] = amsg[i];
EE_Busy = TRUE;
EE_Count = count;
EE_StartAddress = address;
return count;
}
// апаратно зависимая функция инициализации записи EEPROM
void InitializeEEPROMWriteByte(WORD address, char data)
{
char sreg_mirror;
sreg_mirror = SREG;
cli;
EEAR = address;
EEDR = data;
EECR |= (1 << EEMWE);
EECR |= (1 << EEWE)|(1 << EERIE);
SREG = sreg_mirror;
}
// функция для вызова в основном цикле программы
void EEPROMDispatch(void)
{
char data_byte;
WORD address;
if ((!EE_Busy)|(!EE_ReadyForAction))
return;
// Запись очередного байта
if (EE_Count == EE_CurrentPos) // сообщение полностью записано
{
EE_Busy = FALSE;
return;
}
data_byte = EE_Buf[EE_CurrentPos];
address = EE_StartAddress + EE_CurrentPos;
InitializeEEPROMWriteByte(address, data_byte);
EE_CurrentPos++;
}
это header (учитывается размер EEPROM'а, для маленьких чипов)
Код
/* файл ee_mgr.h */
#define _ee_mgr_header_present
// объем буфера под EEPROM очередь
#define EE_BUFFER_LENGTH 32
#ifdef E2END
#if (E2END < 0x100)
#define WORD unsigned char
#else
#define WORD short
#endif
#else
#define WORD int
#endif
#ifndef EERIE
#define EERIE 3
#endif
// коды возможных ошибок при обращении к функции записи
#define ERROR_BUSY -1
#define ERROR_NOT_ENOUGH_FREE_SPACE -2
#define ERROR_MSG_TOO_LONG 0
// Макрос, который необходимо вызывать в обработчике прерывания EEPROM_Ready
#define EEPROMReadyHandler EECR &= ~(1 << EERIE)
void EEPROMDispatch(void); // функция для вызова в основном цикле программы
int EEPROMWriteMsg(WORD address, void *msg, int count); // запись любых структур
Пример применения (gcc):
Код
SIGNAL (SIG_EE_READY)
{
EEPROMReadyHandler;
}
int main( void )
{
char str[] = "zzz";
EEPROMWriteMsg(0x20, str, sizeof(str));
asm("sei");
for(;;)
{
EEPROMDispatch();
}
}
Принимается любая критика!
Сообщение отредактировал defunct - Mar 3 2006, 02:18