Easyelectronics.ru

Электроника для всех
Текущее время: 22 сен 2018, 14:36

Часовой пояс: UTC + 5 часов



    • JLCPCB - Прототипы 10 PCBs всего за 2$ (100*100mm, 2-layer)
    • Как мы делаем платы, смотрите на YouTube
    • Крупнейшая китайская фабрика прототипов. 300000+ заказчиков и 10000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин комплектующих.

Начать новую тему Ответить на тему  [ Сообщений: 6 ] 
Автор Сообщение
 Заголовок сообщения: STM32F207. I2C модуль. Зависание при отправке
СообщениеДобавлено: 09 июл 2018, 17:50 
Только пришел

Зарегистрирован: 30 окт 2017, 18:12
Сообщения: 28
Добрый день, уважаемы форумчане!

Имеется камень из темы, который работает по шине I2C в режиме ведомого (slave). Процесс чтения работает без проблем, но при запросе от мастера данных происходит зависание интерфейса, а именно установка флагов TRA и BUSY (по идеи флаги сбрасываются при отправке данных), в результате чего линия тактирования SDL оказывается подтянута к земле. Выручает программный сброс модуля, но хотелось бы избавиться от этого костыля.

Инициализация модуля:
Код:
/**************Инициализация I2C***********/
void I2C_Setup(void)
{
 
  __HAL_RCC_I2C1_CLK_ENABLE();          //тактирование
 
   
    I2C1->CCR |= 0x2EE;
    I2C1->CR1=0;                                                        //обновим после сброса
    I2C1->CR1 |= I2C_CR1_PE | I2C_CR1_ACK;                              //вкл + АСК 
    I2C1->CR2 |= I2C_CR2_ITEVTEN |I2C_CR2_ITBUFEN |I2C_CR2_ITERREN | 30; //Прерывания + скорость
    I2C1->OAR1 |= I2C_OAR1_ADD2 ;                                       //адрес устройства (2)
   
    HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);                                   //разрешим прерывания
    HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
}



Работа с модулем:
Код:
void I2C1_EV_IRQHandler(void)
{
uint32_t temp1,temp2;
if((I2C1->SR1 >>I2C_SR1_ADDR_Pos)&1)    //если получили адрес 
{
  temp1 = I2C1->SR1;    //прочитаем 1 регистр
  temp2 = I2C1->SR2;    //прочитаем 2 регистр
}
if((I2C1->SR1 >>I2C_SR1_RXNE_Pos)&1)    //что-то в буфере на прием
{
  data1[cntt++]=I2C1->DR;               //пишем в кольцевой
 
  if(cntt==999)
    cntt=0;
}
if((I2C1->SR1 >>I2C_SR1_TXE_Pos)&1)    //запрос на отправку
{
  I2C1->DR=0;  //отправим бит   
  //и тут устанавливаются флаги
  //и происходит зависание
}
if((I2C1->SR1 >>I2C_SR1_STOPF_Pos)&1)   //стоп бит
{
  temp1 = I2C1->SR1;
  I2C1->CR1 |= I2C_CR1_PE | I2C_CR1_ACK;
}


}



Корявый костыль, который хочется удалить. Крутится в основном цикле.
Код:
//Костыль от зависания I2C
    if((I2C1->SR2 >>I2C_SR2_BUSY_Pos)&1 && (I2C1->SR2 >>I2C_SR2_TRA_Pos)&1)     //если установлены оба флага, ждем отправки
    {
      while((I2C1->SR1 >>I2C_SR1_TXE_Pos)&1);  //ждем пока не отправятся данные
      I2C1->CR1 |= I2C_CR1_SWRST;              //перезагрузим I2C
      I2C_Setup();
    }



PS (I2C1->SR2 >>I2C_SR2_BUSY_Pos)&1 - мне кажется, что эта конструкция не очень красивый способ опроса одного бита. Как сделать более корректно?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32F207. I2C модуль. Зависание при отправке
СообщениеДобавлено: 09 июл 2018, 19:21 
Заглядывает иногда

Зарегистрирован: 22 авг 2014, 12:29
Сообщения: 89
((I2C1->SR2 & I2C_SR2_BUSY) == 0) или ((I2C1->SR2 & I2C_SR2_BUSY) != 0) или ((I2C1->SR2 & I2C_SR2_BUSY) == I2C_SR2_BUSY) проверь в stm32F207xx.h описание бит в первых версиях были ошибки . Не вижу в прерывание его сброса .


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32F207. I2C модуль. Зависание при отправке
СообщениеДобавлено: 10 июл 2018, 12:39 
Только пришел

Зарегистрирован: 30 окт 2017, 18:12
Сообщения: 28
Цитата:
Не вижу в прерывание его сброса


Сброса какого бита? BUSY и TXE вроде же аппаратно должен сбрасываться? Или я ошибаюсь?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32F207. I2C модуль. Зависание при отправке
СообщениеДобавлено: 11 июл 2018, 00:36 
Заглядывает иногда

Зарегистрирован: 22 авг 2014, 12:29
Сообщения: 89
Вы включили во сколько источников прерывания . часть из них сбрасываются в ручную у вас нету сбросов если на столе заработает то в жизни прога будет висеть . Плюс надо смотреть уровни оптимизации. Там половина будет выкинута компилятором . например вот это будет оптимизировано .
if((I2C1->SR1 >>I2C_SR1_ADDR_Pos)&1) //если получили адрес
{
temp1 = I2C1->SR1; //прочитаем 1 регистр
temp2 = I2C1->SR2; //прочитаем 2 регистр
}
Это возможно будет оптимизировано
не знаю ставили вы модификаторы или нет при инициализации .

data1[cntt++]=I2C1->DR; //пишем в кольцевой
if(cntt==999)
cntt=0;

в конце я бы поставил барьер на выполнение команд .



Bit 10 ITBUFEN: Buffer interrupt enable
0: TxE = 1 or RxNE = 1 does not generate any interrupt.
1: TxE = 1 or RxNE = 1 generates Event Interrupt (whatever the state of DMAEN)Inter-integrated circuit (I2C) interface RM0033

Bit 9 ITEVTEN: Event interrupt enable
0: Event interrupt disabled
1: Event interrupt enabled
This interrupt is generated when:
– SB = 1 (Master)
– ADDR = 1 (Master/Slave)
– ADD10= 1 (Master)
– STOPF = 1 (Slave)
– BTF = 1 with no TxE or RxNE event
– TxE event to 1 if ITBUFEN = 1
– RxNE event to 1if ITBUFEN = 1
ITERREN: Error interrupt enable
0: Error interrupt disabled
1: Error interrupt enabled
This interrupt is generated when:
– BERR = 1
– ARLO = 1
– AF = 1
– OVR = 1
– PECERR = 1
– TIMEOUT = 1
– SMBALERT = 1


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32F207. I2C модуль. Зависание при отправке
СообщениеДобавлено: 11 июл 2018, 21:23 
Старожил
Аватара пользователя

Зарегистрирован: 04 окт 2011, 10:19
Сообщения: 1468
При любой оптимизации можно посмотреть код и понять, что выкинули.
И вообще полезно смотреть код, что бы он получался оптимальным.
Это я про
if ((...->SR >> n) & 1)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32F207. I2C модуль. Зависание при отправке
СообщениеДобавлено: 11 июл 2018, 21:47 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 382
x893 писал(а):
И вообще полезно смотреть код, что бы он получался оптимальным.
Мне кажется для начала надо просто перестать мудрить. Если хочется проверить бит, то просто проверяй его и компилятор сам всё сделает.

x893 писал(а):
Это я про
if ((...->SR >> n) & 1)
Задумка то хорошая, а вот реализация... Если не мудрить, то компилятор сам почти так и сделает, только влево.
Код:
while(!(TIM6->SR & TIM_SR_UIF));
===============================
        LDR.N    R0,??DataTable2_1  ;; 0x40001010
??XXX:
        LDR      R1,[R0, #+0]
        LSLS     R2,R1,#+31
        BPL.N    ??XXX


Так что, для начала надо научиться просто не мешать компилятору.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: redixin2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB