реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F100C6T6 и I2C1, работать не хочет
ivainc1789
сообщение Apr 12 2012, 14:36
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



По примеру в IAR EWARM написал небольшую программу инициализации интерфейса I2C для работы через прерывания:
CODE
void I2C_Ini(void){
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// I2C RCC
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
// I2C GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);// SCL=B8,SDA=B9
PININI(SCL,GPIO_Mode_AF_OD,GPIO_Speed_50MHz);PINLOCK(SCL); // макросы проверены, ошибок нет
PININI(SDA,GPIO_Mode_AF_OD,GPIO_Speed_50MHz);PINLOCK(SDA);// макросы проверены, ошибок нет
// I2C config
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0xAA;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1,&I2C_InitStructure);
I2C_Cmd(I2C1,ENABLE);
// I2C NVIC
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
NVIC_Init(&NVIC_InitStructure);
I2C_ITConfig(I2C1,I2C_IT_EVT,ENABLE); // enable event IRQ
I2C_ITConfig(I2C1,I2C_IT_ERR,ENABLE); // enable error IRQ
I2C_ITConfig(I2C1,I2C_IT_BUF,ENABLE); // enable buffer IRQ
}


Странно, но результатом ее выполнения является установка бита BUSY, хотя осцилл показывает, что линии SCL и SDA находятся в высоком уровне. По описанию этого бита, его установка свидетельствует о низком уровне хотя бы одной линии. Что же тут не так?
Дальнейшая выдача START бессмысленна, т. к. судя по всему интерфейс неправильно инициализирован...

Сообщение отредактировал IgorKossak - Apr 12 2012, 17:43
Причина редактирования: [codebox]!!!
Go to the top of the page
 
+Quote Post
Aaron
сообщение Apr 13 2012, 11:31
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 243
Регистрация: 5-10-06
Из: Зеленоград
Пользователь №: 21 007



попробуйте поменять местами команды включения и инициализации, и добавить ещё один вызов:
Код
I2C_Cmd(I2C1,ENABLE);
I2C_Init(I2C1,&I2C_InitStructure);
I2C_AcknowledgeConfig(I2C1, ENABLE);

по крайней мере я сегодня I2C код на базе примеров написал, всё заработало с первого раза. И у меня именно так команды стоят.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 13 2012, 13:06
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата
I2C_Cmd(I2C1,ENABLE);
I2C_Init(I2C1,&I2C_InitStructure);


Странная последовательность. Надо бы наоборот. А то разрешается I2C, которая еще не проинициализирована.

P.S. @ivainc1789: в своем коде нашел такое замечание: // ATTENTION: some forums say, first init I2C, then GPIO... У Вас же сначала инициализируется GPIO, потом I2C. Я бы тоже так сделал по логике вещей, но мой работающий код следует-таки замечанию:
Код
    I2C_INIT(I2C_DEVICE, I2C_InitStruct); // (sets PE, too)
    GPIO_Configuration(I2CGPIOs,  sizeof(I2CGPIOs));
#ifdef I2C1_REMAPPED

    GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);
#endif
    IRQ_INIT(NVIC_I2CInitStructure);
    IRQ_INIT(NVIC_I2CErrStructure);

(всякие макросы использованы, но суть остается).


Сообщение отредактировал KnightIgor - Apr 13 2012, 13:15
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Apr 13 2012, 13:32
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Цитата(KnightIgor @ Apr 13 2012, 17:06) *
Странная последовательность. Надо бы наоборот. А то разрешается I2C, которая еще не проинициализирована.
Я того же мнения, хотя в примерах от IAR именно так и сделано: разрешается работа того, что еще не настроено... )))

Цитата
в своем коде нашел такое замечание: // ATTENTION: some forums say, first init I2C, then GPIO...
вот это фундаментальное наблюдение! Я тоже сложа руки не сидел, но пришел к другому выводу. Для того, чтобы мой код из первого поста заработал, достаточно строку:
Код
// I2C RCC
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

опустить ниже секции инициализации GPIO - и все начинает работать! Т. е. хочется сделать вывод, что сначала все же настраиваем GPIO (в том числе ремаппинг, если есть) и только потом подаем тактирование и инициализируем переферийный модуль! Причем в примерах у IAR все работать может только потому, что не используется ремаппинг... Короче, в ref manual прямо про эти тонкости не сказано, а проблема вроде бы существует: как все же правильно инициализировать?
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 13 2012, 15:00
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(ivainc1789 @ Apr 13 2012, 14:32) *
как все же правильно инициализировать?

Правильно так, как заработает. Я, как уже писал, подсмотрел в форуме самого ST то самое замечание, сделал, - работает. Больше над темой не задумывался. Может правы Вы: у меня такт на GPIO подается где-то в начале всей программы (чтобы привести ноги в танцевальную позицию номер 5 максимально быстро), а уж потом в разных подмодулях начинается инициализация периферий. Кстати, что я еще себе за правило взял: перед XXX_Init() я вызываю XXX_DeInit() на случай, если вздумаю вызвать переинициализацию подмодулей изнутри уже работающей программы, а не только единожды после RESET.

Сообщение отредактировал KnightIgor - Apr 13 2012, 15:01
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Apr 13 2012, 15:03
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Я сначала инициализирую GPIO, а потом - I2C. Иначе иногда инициализированный I2C во время инициализации GPIO заклинивает


--------------------
ASB
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 13 2012, 15:44
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Aleksandr Baranov @ Apr 13 2012, 16:03) *
Я сначала инициализирую GPIO, а потом - I2C. Иначе иногда инициализированный I2C во время инициализации GPIO заклинивает

Попробовал и я: "наплевал" на собственное предостережение и сделал инициализацию пинов GPIO для I2C перед самим I2C (как, собственно, логика и подсказывает). Работает и так. Правда, тактирование на GPIO порт и AFIO к этому моменту уже имеется, и я лишь задаю режимы требуемых пинов в данном подмодуле. Поэтому я предположу, что автор темы прав и раскопал верную особенность: дай такт на GPIO, поставь ноги прямо и лишь потом запускай периферию.
Go to the top of the page
 
+Quote Post
smk
сообщение Apr 18 2012, 13:50
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Спасибо автору, что обратил внимание на эту тонкость. У меня както так повелось, что всегда первыми инициализируются GPIO, может потому и не наступил на эти грабли.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 09:55
Рейтинг@Mail.ru


Страница сгенерированна за 0.0141 секунд с 7
ELECTRONIX ©2004-2016