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

Проблема с передачей данных от слейва мастеру I2C STM32

Пытаюсь разобраться с коммуникацией по I2C, есть плата, которая шлёт мне 16 байт, и в ответ ожидает от меня 3 байта, с обработкой пришедших байт всё нормально, однако при отправке, байты отправляются в неправильном порядке, я ожидаю, что байты уйдут в последовательности 0x01 0x02 0x03, сижу битый час безрезультатно, возможно кто-то может подсказать в чём ошибка.

Мой обработчик прерываний I2C:

void I2C2_IRQHandler(void)
{
  /* USER CODE BEGIN I2C2_IRQn 0 */
    TXBUF[0] = 0x01;
    TXBUF[1] = 0x02;
    TXBUF[2] = 0x03;
    
  /* USER CODE END I2C2_IRQn 0 */
    if(I2C2->ISR & I2C_ISR_RXNE)
    {
        BUF[CNT] = I2C2->RXDR;
        CNT++;
    }
    
    if(I2C2->ISR & I2C_ISR_ADDR)
    {
        CNT=0;
        TXCNT=0;
        I2C2->ICR |= I2C_ICR_ADDRCF;
    }
    
    if(I2C2->ISR & I2C_ISR_STOPF)
    {
        I2C2->ICR |= I2C_ICR_STOPCF;
    }
    
   
   if(I2C2->ISR & I2C_ISR_NACKF)
   {
        I2C2->ICR |= I2C_ICR_NACKCF;
   }
   
   if(I2C2->ISR & I2C_ISR_TXIS)
   {
        if(TXCNT >= 3)
        {
            I2C2->CR2 |= I2C_CR2_STOP;
        }
        else
        {
            I2C2->TXDR = TXBUF[TXCNT];
            TXCNT++;
        }
   }
   
  /* USER CODE BEGIN I2C2_IRQn 1 */   

  /* USER CODE END I2C2_IRQn 1 */
}

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

void MX_I2C2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    __HAL_RCC_I2C2_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF6_I2C2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
   
   
    CLEAR_BIT(I2C2->CR1, I2C_CR1_PE);
    I2C2->TIMINGR = 0x0010061A;    
    I2C2->OAR1 &= ~I2C_OAR1_OA1EN;
    I2C2->OAR1 |= (I2C_OAR1_OA1EN | 0x78);
    I2C2->CR2  |= (I2C_CR2_AUTOEND | I2C_CR2_NACK); 
    I2C2->CR1  |= I2C_CR1_PE;

   
    I2C2->CR1 |= I2C_CR1_RXIE;
    I2C2->CR1 |= I2C_CR1_STOPIE;  
    I2C2->CR1 |= I2C_CR1_NACKIE; 
    I2C2->CR1 |= I2C_CR1_TXIE;    
    I2C2->CR1 |= I2C_CR1_ADDRIE;
    NVIC_EnableIRQ(I2C2_IRQn);
    NVIC_SetPriority(I2C2_IRQn,0);
}

То, что уходит по шине 

image.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 18.08.2022 в 13:59, PadenieShtanov сказал:

Пытаюсь разобраться с коммуникацией по I2C, есть плата, которая шлёт мне 16 байт, и в ответ ожидает от меня 3 байта, с обработкой пришедших байт всё нормально, однако при отправке, байты отправляются в неправильном порядке, я ожидаю, что байты уйдут в последовательности 0x01 0x02 0x03, сижу битый час безрезультатно, возможно кто-то может подсказать в чём ошибка.

Чтобы вам могли ответить что-то вменяемое, СЛЕДУЕТ УКАЗЫВАТЬ О КАКОМ МК ИДЁТ РЕЧЬ!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

28 minutes ago, PadenieShtanov said:

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

Прикольная солянка из ХАЛа и прямой работы с регистрами. Уж пишите или на регистрах, указав МК, или на ХАЛе, чтоб было пофиг на тип МК.

Давно не встречал паскалевского стиля написания имён переменных заглавными буквами. Так-то в С другой стиль написания рекомендуют.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

35 минут назад, jcxz сказал:

Чтобы вам могли ответить что-то вменяемое, СЛЕДУЕТ УКАЗЫВАТЬ О КАКОМ МК ИДЁТ РЕЧЬ!

Совсем забыл, речь об мк stm32g030c6

25 минут назад, tonyk_av сказал:

Прикольная солянка из ХАЛа и прямой работы с регистрами. Уж пишите или на регистрах, указав МК, или на ХАЛе, чтоб было пофиг на тип МК.

Давно не встречал паскалевского стиля написания имён переменных заглавными буквами. Так-то в С другой стиль написания рекомендуют.

Пытаюсь поскорее слезть с халовской иглы, как видите пока на полпути), а МК stm32g030c6

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Зачем вы везде читаете I2C2->ICR??? Ref.manual говорит, что этот регистр "write only".

В 18.08.2022 в 14:56, PadenieShtanov сказал:

Пытаюсь поскорее слезть с халовской иглы, как видите пока на полпути

Слезание стоит начать с чтения ref.manual-а. Судя по операциям с I2C2->ICR вы его ещё даже не открывали.

 

Также непонятно - на кой многократно читать один и тот же I2C2->ISR?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, jcxz сказал:

Зачем вы везде читаете I2C2->ICR??? Ref.manual говорит, что этот регистр "write only".

Слезание стоит начать с чтения ref.manual-а. Судя по операциям с I2C2->ICR вы его ещё даже не открывали.

Я думал, что этими операциями сбрасываю флаг прерывания, имею на это основания, так как убрав, например I2C2->ICR |= I2C_ICR_ADDRCF, коммуникация прекращается и висит флаг ADDR

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А неверный порядок думаю из-за того, что в первом прерывании TXCNT указывает на последний байт буфера. Видимо первое прерывание происходит без флага I2C_ISR_ADDR, а больше вы нигде TXCNT не обнуляете (перед началом транзакции). Хотя при отсутствии половины кода можно только гадать....

В 18.08.2022 в 16:27, PadenieShtanov сказал:

Я думал, что этими операциями сбрасываю флаг прерывания, имею на это основания, так как убрав, например I2C2->ICR |= I2C_ICR_ADDRCF, коммуникация прекращается и висит флаг ADDR

Советую наконец-то открыть мануал и прочитать описание регистров! А не "думать".

Согласно мануалу, сброс бита в ICR должен выглядеть как: I2C2->ICR = I2C_ICR_ADDRCF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 часов назад, jcxz сказал:

А неверный порядок думаю из-за того, что в первом прерывании TXCNT указывает на последний байт буфера. Видимо первое прерывание происходит без флага I2C_ISR_ADDR, а больше вы нигде TXCNT не обнуляете (перед началом транзакции). Хотя при отсутствии половины кода можно только гадать....

Советую наконец-то открыть мануал и прочитать описание регистров! А не "думать".

Согласно мануалу, сброс бита в ICR должен выглядеть как: I2C2->ICR = I2C_ICR_ADDRCF

А как возможно прерывание TXIS без предварительного прерывания ADDR?

image.thumb.png.99b811c15de0c8f4a5115107f7bc7f37.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 19.08.2022 в 11:03, PadenieShtanov сказал:

А как возможно прерывание TXIS без предварительного прерывания ADDR?

А почему оно невозможно? Буфер передатчика пуст? Пуст. Значит прерывание возможно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Какое начальное значение CNT, TXCNT? В приведённом коде начальной инициализации нет.

Отсутствие обнуления TXCNT по достижению условия — так задумано?

Как правильно подсказывают форумчане, стоит один раз считать ISR, затем его или обработать, потом погасить, или наоборот, зачем на шину лазать каждый раз :-)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...