|
|
  |
PIC16F628A + 24LC512 + HT-PICC + i2c sample, Не проходит стоп-условие |
|
|
|
Jan 10 2011, 11:07
|
Частый гость
 
Группа: Участник
Сообщений: 181
Регистрация: 26-11-10
Пользователь №: 61 198

|
Добрый день, коллеги. Подскажите, что не так я делаю? Имеется PIC16LF628A (мастер) и 24LC512 (слейв); программный i2c из примеров HT-PICC 9.80. Пытаюсь записать один байт по адресу, скажем, 0: 1. Посылаю старт-условие и управляющий байт (0b10100000); 2. Посылаю 2 байта адреса (нули); 3. Посылаю байт данных (например, 0xAA); 4. Посылаю стоп-условие. Прием байтов (пп. 1-3) слейв подтверждает, затем контроллер генерит стоп-условие, однако память почему-то в это время держит SDA в нуле, поэтому стоп условия не получает. Зациклил для наблюдений такой кусочек кода: CODE while(1){ t = i2c_WriteTo(I2C_DEVICE_ADDRESS); t = i2c_PutByte (0); t = i2c_PutByte (0); t = i2c_PutByte (0xAA); i2c_Stop(); __delay_ms(10); } Симуляция в протеусе показывает, что слейв не отпускает SDA:  В реальном железе наблюдаю настоящим осциллографом то же самое. в линиях включены резисторы по 150 Ом, со стороны контроллера "стоповый" импульс примерно 2 В, со стороны памяти совсем маленький... В даташите процесс записи нарисован так:  Вроде все правильно делаю, а работает неправильно. Прилагаю модель для протеуса и прошивку, хелп!
|
|
|
|
|
Jan 10 2011, 12:23
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(stas00n @ Jan 10 2011, 17:07)  Симуляция в протеусе показывает, что слейв не отпускает SDA: Слейв может держать SDA если хочет выдать на шину данные, либо выдать бит ACK. Так как вы туда записываете, то остается последний вариант. Может вы на шине CLK не додаете 1 такт чтоб слейв закончил выдавать acknowledge? (Т.е. он выдает ACK, а фронт по CLK который заканчивает эту операцию, слейв не получает) p.s. А подтяжка должна быть посильнее 10 кОм
|
|
|
|
|
Jan 10 2011, 13:13
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(stas00n @ Jan 10 2011, 18:58)  Такты считал - ровно 9 штук 9-й такт должен закончится нулем. В единичном состоянии CLK, слейв не имеет права менять сигнал на SDA. попробуйте дернуть CLK еще раз, посмотрите что поменяется.
|
|
|
|
|
Jan 11 2011, 07:56
|
Частый гость
 
Группа: Участник
Сообщений: 181
Регистрация: 26-11-10
Пользователь №: 61 198

|
rezident, да есть такое дело, для дергания выводами в хайтековском модуле применяются макросы SDA_HIGH(); SDA_LOW() и т.д.: CODE /* Change port as required - defaults to port b */ #define SCL RA1 /* clock on port A bit 1 */ #define SCL_DIR TRISA1 #define SDA RA0 /* data on port A bit 0 */ #define SDA_DIR TRISA0 #define I2CTRIS TRISA #define I2C_INPUT 1 /* data direction input */ #define I2C_OUTPUT 0 /* data direction output */ //.... #define SCL_HIGH() SCL = 1; SCL_DIR = I2C_OUTPUT #define SCL_LOW() SCL = 0; SCL_DIR = I2C_OUTPUT #define SDA_HIGH() SDA = 1; SDA_DIR = I2C_OUTPUT #define SDA_LOW() SDA = 0; SDA_DIR = I2C_OUTPUT
Может, стоит изменить их на такие: CODE //.... #define SCL_HIGH() SCL_DIR = I2C_INPUT #define SCL_LOW() SCL = 0; SCL_DIR = I2C_OUTPUT #define SDA_HIGH() SDA_DIR = I2C_INPUT #define SDA_LOW() SDA = 0; SDA_DIR = I2C_OUTPUT
?
Сообщение отредактировал stas00n - Jan 11 2011, 08:00
|
|
|
|
|
Jan 11 2011, 14:54
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(rezident @ Jan 11 2011, 03:13)  Кстати, напряжение половины уровня лог.1 может также свидетельствовать о некорректности реализации алгоритма I2C, когда лог.1 выдается мастером не ОК или Z-состоянием выхода SDA, а нормальной лог.1. При этом к питанию линию "тянет" транзисторный выходной каскад, а не внешний pull-up резистор. Проверьте, что это не так. В том месте мастер должен быть неактивен, а 24LC512 выводить бит ACK. Может быть там на короткий момент происходит конфликт на шине когда слейв выдает 0, а мастер тянет к логической 1. Цитата(stas00n @ Jan 11 2011, 13:56)  Может, стоит изменить их на такие: CODE //.... #define SCL_HIGH() SCL_DIR = I2C_INPUT #define SCL_LOW() SCL = 0; SCL_DIR = I2C_OUTPUT #define SDA_HIGH() SDA_DIR = I2C_INPUT #define SDA_LOW() SDA = 0; SDA_DIR = I2C_OUTPUT
Теоретически так и надо
|
|
|
|
|
Jan 11 2011, 19:16
|
Частый гость
 
Группа: Участник
Сообщений: 181
Регистрация: 26-11-10
Пользователь №: 61 198

|
Цитата(paskal @ Jan 11 2011, 19:54)  В том месте мастер должен быть неактивен, а 24LC512 выводить бит ACK. Может быть там на короткий момент происходит конфликт на шине когда слейв выдает 0, а мастер тянет к логической 1. Да нет, ACK нормально проходил, мастер переключался на вход, конфликт возникал позже, когда мастер пытался послать стоп-условие установкой выхода SDA в "1" (к тому же, как выяснилось, - некорректно), а слейв держал SDA в нуле из-за того что отрицательный фронт не поступал на SCL после передачи ACK. Сейчас все исправил, работает
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|