Изучил i2C . наверное целый месяц читал описание работы шины и смотрел кучу примеров в интернете. В итоге родилась такая библиотека для 24схх
Код: Выделить всё
// назначаем ноги I2C протокола
#define SCL DDRD.5 // шина I2C
#define SDA DDRD.6 //
#define SCL_IN PIND.5 //
#define SDA_IN PIND.6 //
#define WP DDRD.7
#define EEPROM_BUS_ADDRESS 0xA0
unsigned char xx, i2c_repeat_;
// ======================
void i2c_dly()
{
for(xx=2000;xx>0;xx--)
{
#asm("nop")
//#asm("nop")
}
}
// ======================
void i2c_start_()
{
SDA = 0; //1 // последовательность стартовых битов i2c
i2c_dly();
SCL = 0; //1
i2c_dly();
SDA = 1; //0
i2c_dly();
SCL = 1; //0
i2c_dly();
}
// ======================
void i2c_stop_()
{
SDA = 1; // последовательность завершающих битов i2c
i2c_dly();
SCL = 0;
i2c_dly();
SDA = 0;
i2c_dly();
}
// ======================
// Пишем в память
void i2c_tx(unsigned char d)
{
char z;
i2c_repeat_=1;
if (i2c_repeat_)
{
for(z=8; z; z--)
{
i2c_dly();
if(d&0x80) SDA = 0; // 1
else SDA = 1; // 0
i2c_dly();
SCL = 0; // 1
while(SCL_IN==0); // ждем высокого уровня
i2c_dly();
SCL = 1; // лог.0
i2c_dly(); //if (SDA_IN) { i2c_stop_; z=0; } // раб не может принимать данные
d <<= 1;
}
SDA = 0; // 1
SCL = 0; // 1
i2c_dly();
if (SDA_IN==1) { i2c_repeat_=1; i2c_start_(); } // повторяем байт если приняли 1
else { i2c_repeat_=0; }
}
i2c_dly();
SCL = 1; // 0
i2c_dly();
}
// ======================
// читаем память
unsigned char i2c_rx(volatile unsigned char ack)
{
char z, d=0;
SDA = 0; // лог.1
//SCL = 1; // log.0
i2c_dly();
for(z=0; z<8; z++)
{
d <<= 1;
if(SDA_IN) d |=1;
SCL = 0; // лог.1
while(SCL_IN==0); // ждем высокого уровня
i2c_dly();
SCL = 1; //лог.0
i2c_dly();
}
if(ack) SDA = 1;
else SDA = 0;
i2c_dly();
SCL = 0; //1
i2c_dly(); // отсылаем (N)ACK бит
SCL = 1; //0
i2c_dly();
SDA = 0; //1
i2c_dly();
return d;
}
// ======================
void i2c_init_()
{
WP=1;
SDA=0;
SCL=0;
delay_ms(1);
i2c_start_();
delay_ms(1);
i2c_stop_();
delay_ms(1);
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
SCL=1; //0
i2c_dly();
SCL=0; //1
i2c_dly();
//return;
WP=0;
}
// ======================
void eep_write_(unsigned char adress, unsigned char data)
{
WP=1;
i2c_start_(); // отсылка стартовой последовательности
i2c_tx(EEPROM_BUS_ADDRESS); // I2C адрес 24С с нулевым битом чтения/записи
i2c_tx(adress); // отсылка адреса байта памяти
i2c_tx(data); // запись данных
i2c_stop_(); // отсылка завершающей последовательности
WP=0;
}
void eep_write_1byte_page(unsigned char adress, unsigned char data)
{
WP=1;
i2c_start_(); // отсылка стартовой последовательности
i2c_tx(EEPROM_BUS_ADDRESS); // I2C адрес 24С с нулевым битом чтения/записи
//i2c_tx(0); // 9 бит адреса
i2c_tx(adress); // отсылка адреса байта памяти
i2c_tx(data); // запись данных
WP=0;
}
//читаем с памяти
unsigned char eep_read_(unsigned char address)
{
unsigned char data;
WP=1;
i2c_start_(); // отсылка стартовой последовательности
i2c_tx(EEPROM_BUS_ADDRESS); // I2C адрес 24C с нулевым битом чтения/записи
//i2c_tx(0); // 9 бит адреса
i2c_tx(address); // адрес ячейки памяти
i2c_start_(); // отсылка стартовой последовательности (делаем restart)
i2c_tx(EEPROM_BUS_ADDRESS | 1); // I2C адрес 24С с установленым битом чтения/записи
data = i2c_rx(1); // получение значения и отсылка подтверждения.
// Адрес внутреннего регистра увеличится на единицу автоматически.
// внимание ! Мы не подтверждаем получение последнего байта.
// i2c_stop_(); // отсылка завершающей последовательности
//посылаем команду "стоп"
return data; //возврощаем значение прочитаного
WP=0;
}
unsigned char eep_read_page()
{
unsigned char data;
WP=1;
data = i2c_rx(1); // получение значения и отсылка подтверждения.
return data; //возврощаем значение прочитаного
WP=0;
}
void eep_write_page(unsigned char data) // запись страници
{
WP=1;
i2c_tx(data); // запись данных
WP=0;
}
А вот уже когда перенес функцию в другой проект, тут уже начались глюки....
Прикрепляю проект и исходник той простой программки на всяк случай.
Так вот вопрос к профессионалам и специалистам , в чем это глюк? Это протеус лагает? или у меня в функциях косяк?
вот так я ее применяю для записи и чтения страницы:
Код: Выделить всё
// чтение
left = eep_read_(0x00); // левый канал громкости
right = eep_read_page(); // правый канал громкости
left1 = eep_read_page(); // 1
left2 = eep_read_page(); // 2 левый канал 1,2,3 входа
left3 = eep_read_page(); // 3
right1 = eep_read_page(); // 1
right2 = eep_read_page(); // 2 правый канал 1,2,3 входа
right3 = eep_read_page(); // 3
volume_mode = eep_read_page(); // алгоритм громкости
menu = eep_read_page();
pwm1 = eep_read_page(); // ШИМ день
pwm2 = eep_read_page(); // ШИМ ночь
sel_input = eep_read_page(); // переменная для упр. реле входов
sel_output = eep_read_page(); // переменная для упр. реле выходов
auto_return = eep_read_page(); // флаг активации авто выхода
high_end_mode = eep_read_page(); // флаг эко режима
i2c_stop_();
delay_ms(50);
flags_pass = eep_read_(16);
pass0 = eep_read_page(); // пароль для входа
pass1 = eep_read_page();
pass2 = eep_read_page();
order = eep_read_page(); // наушники/АС
light_night = eep_read_page(); // яркость ночь константа для АЦП
light_day = eep_read_page(); // яркость день константа для АЦП
enable = eep_read_page(); // флаг активации детект. ночь / день
i2c_stop_();
delay_ms(50);
// Запись
#asm("cli")
eep_write_1byte_page(0x00,left);
eep_write_page(right);
eep_write_page(left1);
eep_write_page(left2);
eep_write_page(left3);
eep_write_page(right1);
eep_write_page(right2);
eep_write_page(right3);
eep_write_page(volume_mode);
eep_write_page(menu);
eep_write_page(pwm1);
eep_write_page(pwm2);
eep_write_page(sel_input);
eep_write_page(sel_output);
eep_write_page(auto_return);
eep_write_page(high_end_mode);
i2c_stop_();
delay_ms(50);
eep_write_1byte_page(16,flags_pass);
eep_write_page(pass0);
eep_write_page(pass1);
eep_write_page(pass2);
eep_write_page(order);
eep_write_page(light_night);
eep_write_page(light_day);
eep_write_page(enable);
eep_write_page(EEP_CORRECT);
i2c_stop_();
delay_ms(50);
#asm("sei")Быть может Вы меня будете ругать за то что я выкладываю всю функцию... но иначе никак , так как я не могу определить проблему.
Платы получу еще не скоро с завода чтоб попробовать в железе код. Проект в котором не работает код заточен под мега168. Что еще заметил:
Протеус 3.14здит по поводу скорости работы тактовой частоты 168 меги. Она реально раз в 50 медленнее работает чем надо....
Меня интересует: правильно ли я написал функцию ?
С ув. Артем


