Перейти к содержанию

Владимир Анатольевич

Members
  • Постов

    3
  • Зарегистрирован

  • Посещение

Информация

  • Город
    Киев

Электроника

  • Стаж в электронике
    3-5 лет
  • Сфера радиоэлектроники
    Фрилансер

Достижения Владимир Анатольевич

Новичок

Новичок (1/14)

  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

0

Репутация

  1. Всем привет. Может кто поможет? Столкнулся с проблемой считывания байтов из чипа 24LC64. Считывая первые четыре байта с использованием Чипа ATmega16 и индикатора LCD1602A и программы написанной в ATMEL STUDIO 6 получаю на индикаторе вот такой ответ FF FF FF FF. А считывая тот же чип в программаторе PonyProg 51 получаю совершено другой результат. int main(void) { port_ini(); lcd_ini(); eeInit(); char charPer; setPos(0,0); str_lcd(" "); setPos(0,1); str_lcd(" "); uint16_t address = 0; charPer = eeReadByte(address); setPos(0, 0); sendChar(BinToHex((charPer >> 4) & 0x0F)); sendChar(BinToHex(charPer & 0x0F)); address = 1; charPer = eeReadByte(address); setPos(2, 0); sendChar(BinToHex((charPer >> 4) & 0x0F)); sendChar(BinToHex(charPer & 0x0F)); address = 2; charPer = eeReadByte(address); setPos(4, 0); sendChar(BinToHex((charPer >> 4) & 0x0F)); sendChar(BinToHex(charPer & 0x0F)); address = 3; charPer = eeReadByte(address); setPos(6, 0); sendChar(BinToHex((charPer >> 4) & 0x0F)); sendChar(BinToHex(charPer & 0x0F)); }
  2. Большое Вам спасибо за совет и за код. Всё заработало. Но почему то появилась новая проблема. При обращении к функции charPer = eeReadByte(address); Я отправляю ей адрес байта для считывания. И в ответ получаю перменную uint8_t data c значением равным адресу ячейки. Вместо содержимого ячейки. Просмотрев код ошибок не заметил. Может что то неправильно с соединением ножек 24LC64... У меня к стати ношка 7 вообще без подключения.
  3. Ребята всем привет. Нужна Ваша помощь. Ситуация такая. Делаю устройство для считывания байтов с микрухи 24LC64. На базе ATMEGA16 и китайского индикатора LCD1602A. Программу пишу в ATMEL STUDIO 6. Запись байтов происходит нормально. А вот считывание не очень. На индикаторе постоянно высвечивается какой-то мусор. Уже три дня прыгаю с бубном и результата ноль. Может Вы дадите совет. #define F_CPU 16000000UL #include <avr/io.h> #include <util/delay.h> #include "i2c_eeprom.h" #include <string.h> #include <avr/interrupt.h> #define e1 PORTD|=0b00001000 // установка линии E в 1 #define e0 PORTD&=0b11110111 // установка линии E в 0 #define rs1 PORTD|=0b00000100 // установка линии RS в 1 (данные) #define rs0 PORTD&=0b11111011 // установка линии RS в 0 (команда) void eeInit(void) { /*Настраиваем Генератор скорости связи*/ TWBR = (F_CPU/slaveF_SCL - 16)/(2 * /* TWI_Prescaler= 4^TWPS */1); /* Если TWI работает в ведущем режиме, то значение TWBR должно быть не менее 10. Если значение TWBR меньше 10, то ведущее устройство шины может генерировать некорректные сигналы на линиях SDA и SCL во время передачи байта. */ if(TWBR < 10) TWBR = 15; /* Настройка предделителя в регистре статуса Блока управления. Очищаются биты TWPS0 и TWPS1 регистра статуса, устанавливая тем самым, значение предделителя = 1. */ TWSR &= (~((1<<TWPS1)|(1<<TWPS0))); } uint8_t eeWriteByte(uint16_t address,uint8_t data) { /*****УСТАНАВЛИВАЕМ СВЯЗЬ С ВЕДОМЫМ********/ do { //Инициализация Регистра управления шиной в Блоке управления /*Перед началом передачи данных необходимо сформировать т.н. условие начала. В состоянии покоя линии SCL и SDA находятся на высоком уровне. Ведущее устройство (Контроллер AVR в нашем примере), которое хочет начать передачу данных, изменяет состояние линии SDA к низкому уровню. Это и есть условие начала передачи данных.*/ /* а)Сброс флага прерывания TWINT (Флаг TWINT сбрасывается программно путем записи в него логической 1) для разрешения начала новой передачи данных б)Уст. бит условия СТАРТ в)Уст. бит разрешения работы TWI */ TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //Ждем, пока шина даст добро (возможно, линия пока еще занята, ждем) //TWINT бит устанавливается аппаратно, если TWI завершает текущее задание и ожидает реакции программы while(!(TWCR & (1<<TWINT))); /*Проверяем регистр статуса, а точнее биты TWS3-7, которые доступны только для чтения. Эти пять битов отражают состояние шины. TWS2-0 "отсекаем" с помощью операции "И 0xF8". Если TWS7-3 = 0x08, то СТАРТ был успешным.*/ if((TWSR & 0xF8) != TW_START) return false; /*К шине I2C может быть подключено множество подчиненных устройств (к примеру, много микросхем внешней памяти EEPROM). Для того, чтобы все микросхемы и контроллер знали, от кого и кому передается информация, в протоколе реализована Адресация ведомых устройств. В каждой микросхеме, предназначенной для работы с I2C, на заводе "зашит" определенный адрес. Мы этот адрес передаем по всей шине, т.е. всем ведомым. Каждый ведомый получает этот адрес и смотрит, типа мой это или чужой. Если мой, то О КРУТО, со мной хочет работать контроллер AVR. Так вот и происходит "рукопожатие" между ведущим и ведомым.*/ /*Так вот, мы хотим работать с микросхемой памяти 24LC64, поэтому по шине нам надо передать ее адрес. Она узнает свой адрес, и будет знать, что данные на запись адресуются именно ей. А остальные микросхемы, если они есть, эти данные будут просто игнорировать.*/ /*Постоянная часть адреса 24LC64 - 1010 (см. даташит на 24XX64), 3 бита - переменные (если вдруг мы захотим подключить несколько одинаковых микросхем c одинаковыми заводскими адресами, они пригодятся; в ином(нашем) случае выставляем нули), далее бит 0 - если хотим записывать в память или 1 - если читаем данные из памяти I2C EEPROM*/ //TWDR = 0b1010'000'0; TWDR = (slaveAddressConst<<4) + (slaveAddressVar<<1) + (WRITEFLAG); /*Говорим регистру управления, что мы хотим передать данные, содержащиеся в регистре данных TWDR*/ TWCR=(1<<TWINT)|(1<<TWEN); //Ждем окончания передачи данных while(!(TWCR & (1<<TWINT))); /*Если нет подтверждения от ведомого, делаем все по-новой (либо неполадки с линией, либо ведомого с таким адресом нет). Если же подтверждение поступило, то регистр статуса установит биты в 0x18=TW_MT_SLA_ACK (в случае записи) или 0x40=TW_MR_SLA_ACK (в случае чтения). Грубо говоря, если TW_MT_SLA_ACK, то ведомый "говорит" нам, что его адрес как раз 1010'000 и он готов для записи (чтения, если TW_MR_SLA_ACK).*/ }while((TWSR & 0xF8) != TW_MT_SLA_ACK); /*Здесь можем уже уверенно говорить, что ведущий и ведомый друг друга видят и понимают. Вначале скажем нашей микросхеме памяти, по какому адресу мы хотим записать байт данных*/ /*****ПЕРЕДАЕМ АДРЕС ЗАПИСИ********/ /*Записываем в регистр данных старший разряд адреса (адрес 16-битный, uint16_t))..*/ TWDR=(address>>8); //..и передаем его TWCR=(1<<TWINT)|(1<<TWEN); //ждем окончания передачи while(!(TWCR & (1<<TWINT))); /*Проверяем регистр статуса, принял ли ведомый данные. Если ведомый данные принял, то он передает "Подтверждение", устанавливая SDA в низкий уровень. Блок управления, в свою очередь, принимает подтверждение, и записывает в регистр статуса 0x28= TW_MT_DATA_ACK. В противном случае 0x30= TW_MT_DATA_NACK */ if((TWSR & 0xF8) != TW_MT_DATA_ACK) return false; //Далее тоже самое для младшего разряда адреса TWDR=(address); TWCR=(1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); if((TWSR & 0xF8) != TW_MT_DATA_ACK) return false; /*****ЗАПИСЫВАЕМ БАЙТ ДАННЫХ********/ //Аналогично, как и передавали адрес, передаем байт данных TWDR=(data); TWCR=(1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); if((TWSR & 0xF8) != TW_MT_DATA_ACK) return false; /*Устанавливаем условие завершения передачи данных (СТОП) (Устанавливаем бит условия СТОП)*/ TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Ждем установки условия СТОП while(TWCR & (1<<TWSTO)); return true; } uint8_t eeReadByte(uint16_t address) { //uint8_t data; //Переменная, в которую запишем прочитанный байт uint8_t data; // 1 //Точно такой же кусок кода, как и в eeWriteByte... /*****УСТАНАВЛИВАЕМ СВЯЗЬ С ВЕДОМЫМ********/ do { TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); if((TWSR & 0xF8) != TW_START) return false; TWDR = (slaveAddressConst<<4) + (slaveAddressVar<<1) + WRITEFLAG; TWCR=(1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); }while((TWSR & 0xF8) != TW_MT_SLA_ACK); /*****ПЕРЕДАЕМ АДРЕС ЧТЕНИЯ********/ TWDR=(address>>8); ////// TWCR=(1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); if((TWSR & 0xF8) != TW_MT_DATA_ACK) return false; TWDR=(address); TWCR=(1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); if((TWSR & 0xF8) != TW_MT_DATA_ACK) return false; /*****ПЕРЕХОД В РЕЖИМ ЧТЕНИЯ********/ /*Необходимо опять "связаться" с ведомым, т.к. ранее мы отсылали адресный пакет (slaveAddressConst<<4) + (slaveAddressVar<<1) + WRITEFLAG, чтобы записать адрес чтения байта данных. А теперь нужно перейти в режим чтения (мы же хотим прочитать байт данных), для этого отсылаем новый пакет (slaveAddressConst<<4) + (slaveAddressVar<<1) + READFLAG.*/ //Повтор условия начала передачи TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //ждем выполнения текущей операции while(!(TWCR & (1<<TWINT))); /*Проверяем статус. Условие повтора начала передачи (0x10=TW_REP_START) должно подтвердиться*/ if((TWSR & 0xF8) != TW_REP_START) return false; /*Записываем адрес ведомого (7 битов) и в конце бит чтения (1)*/ //TWDR=0b1010'000'1; TWDR = (slaveAddressConst<<4) + (slaveAddressVar<<1) + READFLAG; //Отправляем.. TWCR=(1<<TWINT)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); /*Проверяем, нашелся ли ведомый с адресом 1010'000 и готов ли он работать на чтение*/ if((TWSR & 0xF8) != TW_MR_SLA_ACK) return false; /*****СЧИТЫВАЕМ БАЙТ ДАННЫХ********/ /*Начинаем прием данных с помощью очистки флага прерывания TWINT. Читаемый байт записывается в регистр TWDR.*/ TWCR=(1<<TWINT)|(1<<TWEN); //Ждем окончания приема.. while(!(TWCR & (1<<TWINT))); /*Проверяем статус. По протоколу, прием данных должен оканчиваться без подтверждения со стороны ведущего (TW_MR_DATA_NACK = 0x58)*/ if((TWSR & 0xF8) != TW_MR_DATA_NACK) return false; /*Присваиваем переменной data значение, считанное в регистр данных TWDR*/ data=TWDR; /*Устанавливаем условие завершения передачи данных (СТОП)*/ TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //Ждем установки условия СТОП while(TWCR & (1<<TWSTO)); //Возвращаем считанный байт return data; } ////////////////////////////////////////////////// void port_ini(void) { PORTD=0x00; DDRD=0xff; } //----------------------------------------------------------- void sendHelfByte(unsigned char per) { per<<=4; e1; _delay_us(50); PORTD&=0b00001111; PORTD|=per; e0; _delay_us(50); } //----------------------------------------------------------- void sendByte(unsigned char per, unsigned char mode) { if(mode==0) { rs0; }else{ rs1; } unsigned char hc=0; hc=per>>4; sendHelfByte(hc); sendHelfByte(per); } //----------------------------------------------------------- void setPos(unsigned char x, unsigned char y) { char adress; adress = (0x40*y+x)|0b10000000; sendByte(adress, 0); } //----------------------------------------------------------- void sendChar(unsigned char per) { sendByte(per, 1); } //----------------------------------------------------------- void lcd_ini(void) { _delay_ms(15); sendHelfByte(0b00000011); _delay_ms(4); sendHelfByte(0b00000011); _delay_us(100); sendHelfByte(0b00000011); _delay_us(1); sendHelfByte(0b00000010); _delay_us(1); sendByte(0b00101000, 0); _delay_us(1); sendByte(0b00001100, 0); _delay_us(1); sendByte(0b00000110, 0); _delay_us(1); } //----------------------------------------------------------- void str_lcd(char per[]) { int count; for(count=0; per[count]!='\0'; count++) { sendChar(per[count]); } } //char simvol1; int main(void) { // Берём данные из чипа 24cl64 //DDRA = 0xff; //PORTA = 0x00; uint8_t byte = 0; uint16_t address = 6; char charPer; eeInit(); port_ini(); lcd_ini(); setPos(0, 0); str_lcd("Adress 0 = "); charPer = eeReadByte(address); setPos(11, 0); sendChar(charPer); setPos(12, 0); str_lcd(" "); setPos(0, 1); str_lcd(" "); } ////////////////////////////////// i2c_eeprom.h #define false 0 #define true 1 //#define slaveF_SCL 100000 //100 Khz #define slaveF_SCL 400000 //400 Khz #define slaveAddressConst 0b1010 //Постоянная часть адреса ведомого устройства #define slaveAddressVar 0b000 //Переменная часть адреса ведомого устройства //Разряды направления передачи данных #define READFLAG 1 //Чтение #define WRITEFLAG 0 //Запись 0 void eeInit(void); //Начальная настройка TWI uint8_t eeWriteByte(uint16_t address,uint8_t data); //Запись байта в модуль памяти EEPROM uint8_t eeReadByte(uint16_t address); //Чтение байта из модуля памяти EEPROM // TWSR values (not bits) // (taken from avr-libc twi.h - thank you Marek Michalkiewicz) // Master #define TW_START 0x08 #define TW_REP_START 0x10 // Master Transmitter #define TW_MT_SLA_ACK 0x18 #define TW_MT_SLA_NACK 0x20 #define TW_MT_DATA_ACK 0x28 #define TW_MT_DATA_NACK 0x30 #define TW_MT_ARB_LOST 0x38 // Master Receiver #define TW_MR_ARB_LOST 0x38 #define TW_MR_SLA_ACK 0x40 #define TW_MR_SLA_NACK 0x48 #define TW_MR_DATA_ACK 0x50 #define TW_MR_DATA_NACK 0x58 // Slave Transmitter #define TW_ST_SLA_ACK 0xA8 #define TW_ST_ARB_LOST_SLA_ACK 0xB0 #define TW_ST_DATA_ACK 0xB8 #define TW_ST_DATA_NACK 0xC0 #define TW_ST_LAST_DATA 0xC8 // Slave Receiver #define TW_SR_SLA_ACK 0x60 #define TW_SR_ARB_LOST_SLA_ACK 0x68 #define TW_SR_GCALL_ACK 0x70 #define TW_SR_ARB_LOST_GCALL_ACK 0x78 #define TW_SR_DATA_ACK 0x80 #define TW_SR_DATA_NACK 0x88 #define TW_SR_GCALL_DATA_ACK 0x90 #define TW_SR_GCALL_DATA_NACK 0x98 #define TW_SR_STOP 0xA0 // Misc #define TW_NO_INFO 0xF8 #define TW_BUS_ERROR 0x00 И вот ещё что показывает программатор что есть в памяти микрухи. То что не получается считать.....(
×
×
  • Создать...