Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F050 I2C
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
hd44780
Привет всем.

Пытаемся завести на данном проце термодатчик LM75.
Собственно до датчика дело не доходит. Не работает сам I2C.

Инициализация:

CODE

RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM2EN | RCC_APB1ENR_I2C1EN;
GPIOA->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;
//MODER 32 разрядный
// 00 - по умолчанию вход, 01(GPIO_MODER_MODER0_0) - выход, 10(GPIO_MODER_MODER0_1) - альтернативная функция
// 11(GPIO_MODER_MODER0) - аналоговый режим
GPIOA->AFR[1] |= 0x00000440;//здесь i2c
GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10;
//OTYPER 16 разрядный если 1(GPIO_OTYPER_OT_0) - открытый коллектор, а если 0 - обычный выход(по умолчанию)
GPIOA->PUPDR = GPIO_PUPDR_PUPDR9_0 | GPIO_PUPDR_PUPDR10_0;
//OPUPDR 32 разрядный
// 00 - без подтяжки(по умолчанию), 01(GPIO_PUPDR_PUPDR0_0) - подтяжка к "+", 10(GPIO_PUPDR_PUPDR0_1) - подтяжка к "-"

I2C1->CR1|=I2C_CR1_PE; //включить I2C
I2C1->CR1&=~I2C_CR1_PE; //выключить I2C
while(I2C1->CR1&I2C_CR1_PE); //ждём пока выключится I2C
//I2C1->TIMINGR|=(PRESC << 28)|(SCLL<<0)|(SCLH<<8)|(SCLDEL<<20)|(SDADEL<<16);
//PRESC=11, SCLL=199, SCLH=195, SCLDEL=4, SDADEL=2 это для 10кГц
//PRESC=11, SCLL=19, SCLH=15, SCLDEL=4, SDADEL=2 это для 100кГц
//PRESC=5, SCLL=9, SCLH=3, SCLDEL=3, SDADEL=3 это для 400кГц
//PRESC=5, SCLL=3, SCLH=1, SCLDEL=1, SDADEL=0 это для 1000кГц
I2C1->TIMINGR|=(11 << 28)|(199<<0)|(195<<8)|(4<<20)|(2<<16); //конфигурируем тайминги
I2C1->CR1|=I2C_CR1_PE; //включить I2C
I2C1->CR2 = I2C_CR2_AUTOEND | (1<<16) | I2C_CR2_RD_WRN | (0x90<<1);


Чтение температуры:

CODE

// LM75 address = 0x90
#define LM75_Addr 0x90
// Temperature Register of LM75
#define LM75_TEMP_Reg 0x00
uint16_t I2C_LM75_Temp_Read ( uint8_t addr )
{
uint16_t RegValue = 0;

// 1. Послать в LM75 адрес регистра - 0x00
// Конфигурирование адреса ведомого; количество байтов, которые будут запрограммированы (переданы); перезагрузки и генерировать старт
I2C_TransferHandling ( I2C1, addr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write );

// Подождите, пока ISR.TXIS флаг не будет установлен
// TXIS==1 - TXDR empty
while ( I2C_GetFlagStatus ( I2C1, I2C_ISR_TXIS ) == RESET );

// Отправить адрес (LM75_TEMP_Reg)
I2C_SendData ( I2C1, LM75_TEMP_Reg );

// Подождите, пока ISR.TCR флаг не будет установлен
// TCR == 1 - Заданное кол-во байт передано
while ( I2C_GetFlagStatus ( I2C1, I2C_ISR_TCR ) == RESET );

// 2. Читать ответ LM75
// Конфигурирование адреса ведомого; количество байтов, которые будут считаны; перезагрузки и генерировать старт
I2C_TransferHandling ( I2C1, addr, 2, I2C_Reload_Mode, I2C_Generate_Start_Read );

// ждать приёма байта
// ISR.RXNE == 1 - byte received
while ( I2C_GetFlagStatus ( I2C1, I2C_ISR_RXNE ) == RESET );
RegValue = I2C_ReceiveData ( I2C1 );
RegValue <<= 8;

// ждать приёма байта
// ISR.RXNE == 1 - byte received
while ( I2C_GetFlagStatus ( I2C1, I2C_ISR_RXNE ) == RESET );
RegValue |= I2C_ReceiveData ( I2C1 );

// Сгенерировать STOP
I2C_TransferHandling ( I2C1, addr, 0, I2C_Reload_Mode, I2C_Generate_Stop );

// Подождите, пока ISR.STOPF флаг не будет установлен
// STOPF == 1 - а шине действует STOP
while ( I2C_GetFlagStatus ( I2C1, I2C_ISR_STOPF ) == RESET);

// Очистить флаг STOPF
// ICR.STOPF := 1 1 - очистка флага ISR.STOPF
I2C_ClearFlag ( I2C1, I2C_ICR_STOPCF );

return RegValue;
}


Результат - I2C труп полный, на осцилле обе ноги единицы (pull-up-ы 10кил). Ничего не шевелится sm.gif .
Кто-то с I2C на том проце работал? Он там вообще рабочий? Или я где-то ошибся?

В ДШ на ногах I2C PA9, PA10 есть странный коммент: "This alternate feature is available on standard dies only." Стандарт умер, да здравствует стандарт laugh.gif
Спасибо.
smalcom
Примеры из библиотеки работают?
adnega
Я возможно не прав (поправьте меня), но вроде принято взводить RCC_APB2ENR_SYSCFGEN перед настройкой альтернативных функций.

PS: STM32F050 имеет статус NRND. Вы часом не новое разрабатываете?
glags
Цитата(smalcom @ Jun 17 2014, 22:57) *
Примеры из библиотеки работают?

Там в самом верху написали что не работает сам интерфейс I2C. До библиотек дело не доходит. На портах ни одного импульса. Тут только 2 варианта. 1- есть какието особые нюансы в активации I2C интерфейса и 2-он в этой микрухе не работает. sm.gif

Цитата(adnega @ Jun 17 2014, 23:09) *
Я возможно не прав (поправьте меня), но вроде принято взводить RCC_APB2ENR_SYSCFGEN перед настройкой альтернативных функций.

PS: STM32F050 имеет статус NRND. Вы часом не новое разрабатываете?


RCC->APB2ENR = RCC_APB2ENR_SYSCFGEN; сделано. Просто упустили кидая кусок кода на форум sm.gif
Это одиночное изделие и посему этот проц (так как уже куплен) вполне подходит. От него кроме SPI для дисплея (кстати работает), внутреннего календаря и I2C для датчика температуры больше ничего не надо.
andron86
Вам уже писали, запустите тупо пример от stm и посмотрите работает или нет, без своих добавок. У меня опыт был, что из за работающего таймера (pwm) и правда i2c не работал, нужно было коротко отключить pwm, включить i2c enable, и всё заработало. такие траблы. wacko.gif
hd44780
Из примеров I2C на сайте ST нашёл только это - http://www.st.com/web/en/catalog/tools/PF257886#
Там есть файл mems_eval_i2c.c - драйвер под какой-то MEMS на I2C.

Правда, оно для F0Discovery, там проц не совсем такой - F051 sad.gif

Сегодня проверим sm.gif
Alien85
Что за стиль программирования такой?

Интерфейс настраивается регистрами, а управляется библиотечными функциями.

Какой в этом тайный смысл?

И ещё: учитесь пользоваться прерываниями.
hd44780
Цитата(Alien85 @ Jun 18 2014, 11:27) *
Какой в этом тайный смысл?

Разные люди писали sm.gif
Да и отладка ... Закончим отлаживать - подчистим sm.gif

Цитата(Alien85 @ Jun 18 2014, 11:27) *
И ещё: учитесь пользоваться DMA.

А зачем тут DMA, если не секрет? Для записи в датчик одного байта и чтения 2 байтов его ответа?
Тут дай Бог, чтобы оно вообще заработало ....
Alien85
Цитата(hd44780 @ Jun 18 2014, 12:41) *
Разные люди писали sm.gif

krapula.gif

Цитата(hd44780 @ Jun 18 2014, 12:41) *
А зачем тут DMA, если не секрет? Для записи в датчик одного байта и чтения 2 байтов его ответа?
Тут дай Бог, чтобы оно вообще заработало ....

Упс... С dma ошибся, имел в виду прерывания.
jcxz
Цитата(hd44780 @ Jun 18 2014, 12:41) *
Разные люди писали sm.gif

Неужто для поднятия одного I2C нужно несколько человек???
Или это из истории:
-За день I2C запустишь?
-Да, ноу проблем.
-А за два?
-Один не справлюсь - помощник нужен...
beer.gif
hd44780
Как поётся в одной советской песне - "Вдвоём вдвойне веселей" biggrin.gif
jcxz
У граждан ДНР ещё хватает времени заниматься I2C?
glags
Смотрю тут вместо помощи одна критика. То это ни так, то сё. Лучше бы помогли ценным советом чем базар разводить. Такое впечатление что тут не помагают, а просто набирают количество сообщений.
До прерываний тут ещё далеко, зашевелился бы хотябы сам интерфейс. После команды I2C_SendData ( I2C1, LM75_TEMP_Reg ); должно на ногах хоть что-то зашевелиться, а там глухо одни еденицы. По сему подозрение на неправильный конфиг I2C.
hd44780
Цитата(jcxz @ Jun 18 2014, 14:49) *
У граждан ДНР ещё хватает времени заниматься I2C?


Да вот сижу, в окопе, пока доблестной укр армии а-ля Правый сектор не видать, дай думаю, I2C раздолбаю что-ли...

Сорри за оффтоп biggrin.gif .
smalcom
Цитата
Из примеров I2C на сайте ST нашёл только это

чо-чо!? только?

> Примеры из библиотеки работают?
Нажмите для просмотра прикрепленного файла
Axel
Цитата(glags @ Jun 18 2014, 13:58) *
...Лучше бы помогли ценным советом чем базар разводить...

Ну прям сердце разрывается... Итак:
1. ST-шный I2C работает. Проверено на разных STM32 и STM8.
2. ST-шный I2C производит впечатление недоделанного курсового. Причина ворчания (одна из) - удивительные упражнения с ACK-ом и STOP-ом в конце приема.
3. ST-шные примеры малополезны по причинам:
а) используют весьма нелюбимую мной либу
б) не облегчают понимание
в) абсолютно не гарантируют отсутствие (или уменьшение) проблем при попытке их адаптации под свои нужды
Теперь советы (естественно только ценные):
1. Детально разобраться с регистрами (по мануалу, на всякие AN-ы не заморачиваться), после чего сконфигурить порт по собственному разумению
2. Разрешить клоки на I2C (RCC->APB1ENR) и GPIO (RCC->APB2ENR). Не забыть про бит 0 в RCC->APB2ENR.
3. Начать изучать поведение пинов с команды I2C1->CR1 |= (1 << 8) (старт)
jcxz
Цитата(Axel @ Jun 19 2014, 10:34) *
Теперь советы (естественно только ценные):
...
4. Разобраться с тактированием периферии в чипе по мануалу (aka - регистрам). RCC?
5. Разобраться с конфигурированием пинов по мануалу.
6. Разобраться с контроллером прерываний по мануалу.

После этого минимума в принципе более-менее уже можно приступать к реализации обмена по I2C.
glags
Цитата(smalcom @ Jun 19 2014, 02:27) *
чо-чо!? только?

> Примеры из библиотеки работают?
Нажмите для просмотра прикрепленного файла

А можно ссылочку на эту библиотеку. sm.gif

Отвечаю сразу для Axel и jcxz на Ваши советы. sm.gif
1) С регистрами I2C более менее разобрался, но чтоб отсеять свои сомнения передачу организовал на SPL.
2) Всё сделано как надо, в первом посте всё описано.
3) Какое б не было поведение пинов на команду I2C1->CR1 |= (1 << 8) (старт), но оно должно быть. А там глухо.
На 4,5 и 6 я уже собаку съел. Тут ошибок быть не может. Тем более об 6 пункте (прерывания) рано говорить, так как оно организовывается только по приёму. На передачу оно не надо. В данном случае хотелось чтоб при передаче хотябы ноги дрыгнулись.
Может кто уже сам лично програмировал I2C на этом проце (STM32F050F4P6 корпус TSSOP20).
Организовывал I2C на 105 и 407 процах проблем не было, а тут засада какая-то. Такое впечатление что он есть только в даташите на проц, а в реалии его нет.
x893
Нет такого процессора у ST - STM32F050F4
hd44780
Та ну, нету....

А в ДШ есть - вложение.
А вот запросто может быть, что он просто получился кривым и глюкавым, что о нём поспешили забыть и заменить его на те же F031 или на F051 ..
adnega
Цитата(hd44780 @ Jun 19 2014, 12:16) *
А вот запросто может быть, что он просто получился кривым и глюкавым, что о нём поспешили забыть и заменить его на те же F031 или на F051 ..

Проц, как проц.
Просто, сейчас его называют по-другому.
Новость уже обсуждали тут (http://www.compel.ru/2014/05/29/pereimenovanie-mikrokontrollerov-stm32f0-i-stm32f3/).
Обычно кривость наблюдается у программиста, "особенности" чипа описаны в специальном документе.
Сомнительно, что такой явный и повторяемый баг туда не попал.
Axel
Цитата(glags @ Jun 19 2014, 10:19) *
1) С регистрами I2C более менее разобрался, но чтоб отсеять свои сомнения передачу организовал на SPL.

Сомнительный путь для отсева сомнений (ИМХО)... А регистры в отладчике просматривали?
Golikov A.
а че такое SPL, простите?

да я бы проверил все флаги, наверняка там для прерываний куча флагов ставиться во время работы i2C, хоть поглядеть они стараются? А может еще ноги снаружи пошевелить, вдруг вы не мастером сделали?
scifi
Цитата(Golikov A. @ Jun 19 2014, 13:09) *
а че такое SPL, простите?

Вас в гугле забанили, простите?
Golikov A.
не допер дописать STM32 SPL, а по SPL такое выдает.... я догадывался что это библиотека, просто хотел быть уверен)
glags
Цитата(Golikov A. @ Jun 19 2014, 12:09) *
а че такое SPL, простите?

да я бы проверил все флаги, наверняка там для прерываний куча флагов ставиться во время работы i2C, хоть поглядеть они стараются? А может еще ноги снаружи пошевелить, вдруг вы не мастером сделали?

Да вы правы, уже добавил I2C1->CR1|=I2C_CR1_SMBHEN | I2C_CR1_PE; //включить I2C
Огромное спасибо, минут через 30 проверю.

Кстати заметил одну особенность у этого проца. У меня на нём настроен SPI и к нему подключен єкран. от нокии 3310. Я отключил I2C и на его место включил USART. Запустил и случилось чудо - SPI загнулся, а USART работает. Принимает и передаёт данные, подключил к компу через переходник usb-usart. Написал програмулину которая принимает от порта данные и обратно выдаёт то что приняло. В терменале всё чётко, для надёжности проверки обратно в терминал выдавал то что принял +1.
Так вот к чему я веду. Может этот проц может работать только с одним аппаратным интерфейсом? Но в эррате и даташите я ничего про это не нашёл. Шас попробую SPI отключить и проверить.

Изменил инициализацию добавив CR1|=I2C_CR1_SMBHEN;
Код
RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_I2C1EN;
RCC->APB2ENR = RCC_APB2ENR_SYSCFGEN;
RCC->AHBENR = RCC_AHBENR_GPIOAEN;

GPIOA->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;
GPIOA->AFR[1] |= 0x00000440;//I2C - 4
GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10;

    I2C1->CR1|=I2C_CR1_PE;          //включить I2C
    I2C1->CR1&=~I2C_CR1_PE;         //выключить I2C
    while(I2C1->CR1&I2C_CR1_PE);    //ждём пока выключится I2C
    //I2C1->TIMINGR|=(PRESC << 28)|(SCLL<<0)|(SCLH<<8)|(SCLDEL<<20)|(SDADEL<<16);
    //PRESC=11, SCLL=199, SCLH=195, SCLDEL=4, SDADEL=2 это для 10кГц
    //PRESC=11, SCLL=19, SCLH=15, SCLDEL=4, SDADEL=2 это для 100кГц
    //PRESC=5, SCLL=9, SCLH=3, SCLDEL=3, SDADEL=3 это для 400кГц
    //PRESC=5, SCLL=3, SCLH=1, SCLDEL=1, SDADEL=0 это для 1000кГц
    I2C1->TIMINGR|=(11 << 28)|(199<<0)|(195<<8)|(4<<20)|(2<<16); //конфигурируем тайминги
    I2C1->CR1|=I2C_CR1_SMBHEN | I2C_CR1_PE;          //включить I2C
    I2C1->CR2 =  I2C_CR2_AUTOEND | (1<<16) | I2C_CR2_RD_WRN | (0x90<<1);


И случилось не вероятное передача заработала, но приём пока нет. Огромаднейшее СПАСИБО Golikov A.. Теперь щас повоюю с приёмом, может с адресом слейва намутил. sm.gif
Сергей Борщ
Цитата(glags @ Jun 19 2014, 10:19) *
На 4,5 и 6 я уже собаку съел. Тут ошибок быть не может.
Ну-ну. И после этого вы пишете

Цитата(glags @ Jun 19 2014, 13:55) *
Код
GPIOA->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;
...
GPIOA->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_10;
Рекомендую съесть еще одну собаку. В этом коде поведение может быть каким угодно и очень часто совсем не таким, какого вы ожидали. Не удивительно, что у вас
Цитата(glags @ Jun 19 2014, 13:55) *
Запустил и случилось чудо - SPI загнулся, а USART работает
glags
Цитата(Сергей Борщ @ Jun 19 2014, 14:34) *
Ну-ну. И после этого вы пишете

Рекомендую съесть еще одну собаку. В этом коде поведение может быть каким угодно и очень часто совсем не таким, какого вы ожидали. Не удивительно, что у вас

Вы имеете "логическое ИЛИ" ?. Так я это делаю чтоб SWD порт не потерять. В отладчике на регистры смотрел, то там всё ОК.
Axel
Так вроде I2C_CR1_SMBHEN (3-й бит в CR1) здесь не при делах (если Вы действительно говорите про I2C, а не про SMBUS). Рекомендация по поводу собаки видится по-прежнему актуальной...
glags
Цитата(Axel @ Jun 19 2014, 15:20) *
Так вроде I2C_CR1_SMBHEN (3-й бит в CR1) здесь не при делах (если Вы действительно говорите про I2C, а не про SMBUS). Рекомендация по поводу собаки видится по-прежнему актуальной...

Bit 21 SMBDEN: SMBus Device Default address enable
0: Device default address disabled. Address 0b1100001x is NACKed.
1: Device default address enabled. Address 0b1100001x is ACKed.
Вы какой мануал смотрите sm.gif
Сергей Борщ
Цитата(glags @ Jun 19 2014, 14:49) *
Вы имеете "логическое ИЛИ" ?. Так я это делаю чтоб SWD порт не потерять.
А если в битах для конфигурируемых ног уже были единицы в ненужных местах? Некоторые ноги при включении питания содержат отнюдь не нули в этих регистрах. Вы их пытаетесь перевести в режим альтернативной функции, но если он был перед этим настроен на вывод - вы переведете его в аналоговый режим. То есть даже если сейчас все и заработает, то потом дописав настройку этой ноги на вывод где-то в начале (не знаю зачем - например для организации сброса зависшего автомата ведомого выдачей 9 тактов ручным маханием ногами) вы получите эффект отваливания I2C в совершенно другом, никак не связанном с этим дописанным кодом месте. Мы ведь не знаем, что у вас там в начале программы творится, просто видим лежащую на ровном месте граблю, которую подложил себе человек, съевший собаку.
Я, честно говоря, не понимаю - что мешает прописать весь регистр один раз целиком, задав одной записью необходимое состояние сразу всех ног? Аналогично и с остальными регистрами при инициализации - вы же знаете, что было записано в этот регистр (или вам не нужно предыдущее состояние в начале инициализации). Так запишите еще раз этот регистр полностью, но с измененными нужными битами. А вот если потребовалось изменить группу битов в регистре, состояние которого не может быть известно точно - тогда надо позаботиться о правильном состоянии всех битов. И не двумя операциями - сбросом и установкой, ведь в этом случае вы между этими операциями переводите регистр в совершенно ненужное состояние, а считыванием во временную переменную, изменением группы бит в этой переменной и записью назад в регистр за один раз уже конечного результата.
glags
Цитата(Сергей Борщ @ Jun 19 2014, 16:13) *
А если в битах для конфигурируемых ног уже были единицы в ненужных местах? Некоторые ноги при включении питания содержат отнюдь не нули в этих регистрах. Вы их пытаетесь перевести в режим альтернативной функции, но если он был перед этим настроен на вывод - вы переведете его в аналоговый режим. То есть даже если сейчас все и заработает, то потом дописав настройку этой ноги на вывод где-то в начале (не знаю зачем - например для организации сброса зависшего автомата ведомого выдачей 9 тактов ручным маханием ногами) вы получите эффект отваливания I2C в совершенно другом, никак не связанном с этим дописанным кодом месте. Мы ведь не знаем, что у вас там в начале программы творится, просто видим лежащую на ровном месте граблю, которую подложил себе человек, съевший собаку.
Я, честно говоря, не понимаю - что мешает прописать весь регистр один раз целиком, задав одной записью необходимое состояние сразу всех ног? Аналогично и с остальными регистрами при инициализации - вы же знаете, что было записано в этот регистр (или вам не нужно предыдущее состояние в начале инициализации). Так запишите еще раз этот регистр полностью, но с измененными нужными битами. А вот если потребовалось изменить группу битов в регистре, состояние которого не может быть известно точно - тогда надо позаботиться о правильном состоянии всех битов. И не двумя операциями - сбросом и установкой, ведь в этом случае вы между этими операциями переводите регистр в совершенно ненужное состояние, а считыванием во временную переменную, изменением группы бит в этой переменной и записью назад в регистр за один раз уже конечного результата.

Здесь я с Вами полностью согласен и поддерживаю. Я раньше так и делал, но пару раз по ошибке запорол SWD и после этого я делаю инит всех устройств в начале проги учитывая состояние регистров по умолчанию из даташита. При чём я не пользуюсь при этой методе сторонними библиотеками, а всегда пишу свои. По этому я знаю какой бит в каком регистре установлен. И в своих библиотеках я не делаю инициализации устройств, она у меня всегда в начале программы и если мне надо что-то с устройствами сделать, то я лезу туда. sm.gif
Golikov A.
Цитата
И не двумя операциями - сбросом и установкой, ведь в этом случае вы между этими операциями переводите регистр в совершенно ненужное состояние, а считыванием во временную переменную, изменением группы бит в этой переменной и записью назад в регистр за один раз уже конечного результата.


Интересное замечание, всегда делал через 2 операции. Надо будет запомнить, спасибо...
glags
Интерфейс наконец то ожил.
Но стопор получается после передачи номера регистра.
Код
    uint_fast16_t I2C(void)
    {   uint32_t i;
        while ((I2C1->ISR & I2C_ISR_TXE)==0);    //while TXE ==0, buffer is full
        // Задать адрес приёмника и длину данных
        i=I2C1->CR2;
        i &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
        i |= ((0x90 & I2C_CR2_SADD) | ((1 << 16 ) & I2C_CR2_NBYTES) | I2C_CR2_RELOAD | I2C_CR2_START);
        I2C1->CR2=i;
        while ( (I2C1 -> ISR & I2C_ISR_TXIS) == 0);
         I2C1->TXDR = 0;//Передача номера регистра для чтения из STLM75
         while ((I2C1->ISR & I2C_ISR_TCR)==0);//ждём окончание передачи
    i=I2C1->CR2;
    i &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
    i |= ((0x90 & I2C_CR2_SADD) | ((2 << 16 ) & I2C_CR2_NBYTES) | I2C_CR2_RELOAD | I2C_CR2_RD_WRN | I2C_CR2_START);
    I2C1->CR2=i;
    while ( ( I2C1 -> ISR & I2C_ISR_RXNE ) == 0);//Виснет ТУТ!!!!!!!!!!!!
    i=I2C1->RXDR;
     i<<=8;
     while ( ( I2C1 -> ISR & I2C_ISR_RXNE ) == 0);
    i |=I2C1->RXDR;
         I2C1->CR2|=(90<<0)|(1<<16)| I2C_CR2_RELOAD;    //address SLAVE 7bits
         I2C1->CR2 &=~ I2C_CR2_RD_WRN;  //write
         I2C1->CR2 |= I2C_CR2_STOP; // Stop Transmit
        while ( ( I2C1 -> ISR & I2C_ISR_STOPF ) == 0 );
        I2C1 -> ICR = I2C_ICR_STOPCF;
        return i;}

Ниже привожу осцилограмку жёлтый данные, а синий синхро.
smalcom
>> Но стопор получается после передачи номера регистра.
все статусы проверяете. не догоню жёлтый луч - это датчик ACK не дал?

Цитата(glags @ Jun 19 2014, 10:19) *
А можно ссылочку на эту библиотеку. sm.gif

угу http://www.st.com/web/en/catalog/tools/PF257884# => http://www.st.com/st-web-ui/static/active/...dperiph_lib.zip
glags
Цитата(smalcom @ Jun 19 2014, 22:33) *
>> Но стопор получается после передачи номера регистра.
все статусы проверяете. не догоню жёлтый луч - это датчик ACK не дал?


угу http://www.st.com/web/en/catalog/tools/PF257884# => http://www.st.com/st-web-ui/static/active/...dperiph_lib.zip


Синий лучь в конце в низу это датчик синхру не отпускает. Я проверял отпаивая датчик.
Расшифровывая осцилограмку передаётся 0х90-адрес устройства и вслед 00-номер регистра. Точнее 0х9000. А дальше *опа, датчик держит линию синхронизации.
smalcom
>> Ниже привожу осцилограмку жёлтый данные, а синий синхро.
оказывается я очень внимательный человек.

хм, а точно датчик держит?
glags
Цитата(smalcom @ Jun 20 2014, 00:09) *
>> Ниже привожу осцилограмку жёлтый данные, а синий синхро.
оказывается я очень внимательный человек.

хм, а точно датчик держит?

Ну я ж написал, что точно. Я его отпаял и синхра поднялась. Как мне ещё объяснить?
hd44780
Да. Датчик. Когда его убирали физически, этого нет, обе линии в 1 возвращаются.
Сергей Борщ
Сейчас почитаю описание датчика, а пока небольшое замечание по стию.
Вот такую конструкцию
Цитата(glags @ Jun 19 2014, 22:26) *
Код
        while ((I2C1->ISR & I2C_ISR_TXE)==0);    //while TXE ==0, buffer is full
я всегда пишу так:

Код
        while ((I2C1->ISR & I2C_ISR_TXE)==0)     //while TXE ==0, buffer is full
            ;
Это и нагляднее и гораздо меньше вероятность допустить ошибку добавляя в этот цикл, скажем, тестовое махание ногой. Точка с запятой в вашем варианте не бросается в глаза (а именно она является ключевым моментом этого цикла), ее можно забыть поставить или убрать и в цикл случайно попадет следующее выражение или наоборот оно случайно окажется за циклом.

Цитата(glags @ Jun 19 2014, 22:26) *
Интерфейс наконец то ожил.
И в чем была причина? Во-первых нам любопытно, а во вторых, возможно, когда-нибудь на это обсуждение набредет кто-то с точно такой же проблемой и, разумеется, будет рад за вас, но ему информация "наконец-то ожил" не поможет никак. А ведь он будет тратить время, читать ветку... Представляете как ему будет обидно за потраченное на бесполезное чтение время?

Цитата(hd44780 @ Jun 20 2014, 07:00) *
Да. Датчик. Когда его убирали физически, этого нет, обе линии в 1 возвращаются.
Этого не может быть, потому что не может быть никогда:
Цитата
The LM75 operates as a slave on the I2C bus, so the SCL line is an input (no clock is generated by the LM75) and the SDA line is a bi-directional serial data path.


Вы случаем на датчике SDA и SCL не перепутали?
smalcom
Однако вселенная любит пошутить.
У меня сейчас на столе mega168+I2C 24C256C.
Правда память без блокировочных конденсаторов. Пишет по 64 байта только, при отправляемых 128, а при чтении в какойто момент зажимает SDA на землю.
Axel
Цитата(smalcom @ Jun 21 2014, 11:28) *
Однако вселенная любит пошутить.

Дык вселенная здесь не при чем. Источник шуток наверняка располагается где-то между стулом и клавиатурой. Вас не смущает, что у 24С256 размер страницы 64 байта?
smalcom
я её и не обвиняю. действительно, прочитал внимательнее всё, т.к. тестил на разных: у 512/256/128 разный размер страниц.
спасибо sm.gif

ОФФ:
ps. наврано даже на сайте атмел в описании 128-й
на страничке написано, что размер страницы 256 байт, а в доке - 64 байта.
Axel
Цитата(smalcom @ Jun 21 2014, 13:20) *
sm.gif

rolleyes.gif
smalcom
По теме с "зажиманием" сигналов. Столкнулся с похожей ситуацией на АВР. Может и здесь подойдёт.
На самом деле никто и ничего не зажимает. Наступает неопределённое состояние контроллера из-за несвоевременной отправки STOP.
Причиной оказалась опечатка. Последний байт необходимо читать выставив NOACK, а по ошибке устанавливалось ACK. Контроллер
видя это неподобство просто складывал с себя полномочия.
Golikov A.
Цитата
И в чем была причина? Во-первых нам любопытно, а во вторых, возможно,

как я понял не был выставлен режим мастера для I2C...
glags
Привет всем. sm.gif
Ну что господа, родил я код. Привожу ниже, может кому пригодится. А то я сам намучался, хочу и другим облегчить жизнь.
Код
    uint_fast16_t I2CLM75(void)
    {   uint32_t i;
        while ((I2C1->ISR & I2C_ISR_TXE)==0);    //while TXE ==0, buffer is full
        // Задать адрес приёмника и длину данных
        i=I2C1->CR2;
        i &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
        i |= ((0x90 & I2C_CR2_SADD) | ((1 << 16 ) & I2C_CR2_NBYTES) | I2C_CR2_RELOAD | I2C_CR2_START);
        I2C1->CR2=i;
        while ( (I2C1 -> ISR & I2C_ISR_TXIS) == 0);
         I2C1->TXDR = 0;//Передача номера регистра для чтения из STLM75
         while ((I2C1->ISR & I2C_ISR_TCR)==0);//ждём окончание передачи
         I2C1->CR2 |= I2C_CR2_STOP;//Делаем стоп :) здесь собака зарыта
         i=I2C1->CR2;
         i &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
         i |= ((0x90 & I2C_CR2_SADD) | ((2 << 16 ) & I2C_CR2_NBYTES) | I2C_CR2_RD_WRN | I2C_CR2_START);
         I2C1->CR2=i;
         while ( ( I2C1 -> ISR & I2C_ISR_RXNE ) == 0);
         i=I2C1->RXDR;
         i<<=8;
         while ( ( I2C1 -> ISR & I2C_ISR_RXNE ) == 0);
         i |=I2C1->RXDR;
         I2C1->CR2|=(90<<0)|(1<<16)| I2C_CR2_RELOAD;    //address SLAVE 7bits
         I2C1->CR2 &=~ I2C_CR2_RD_WRN;  //write
         I2C1->CR2 |= I2C_CR2_STOP; // Stop Transmit
        while ( ( I2C1 -> ISR & I2C_ISR_STOPF ) == 0 );
        I2C1 -> ICR = I2C_ICR_STOPCF;
        return i;}

PS: Всем огромаднейшее спасибо за поддержку!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.