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

I2c Slave


pvg_79

Рекомендуемые сообщения

uint8_t transmitI2C[12];
uint8_t receiveI2C[7];

void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
    if(HAL_I2C_EnableListen_IT(hi2c) != HAL_OK)
    {
       //Error
    }
}

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
  UNUSED(AddrMatchCode);
  if(hi2c->Instance == I2C1)
  {
    switch (TransferDirection)
        {
            case I2C_DIRECTION_TRANSMIT:
                if (HAL_I2C_Slave_Seq_Receive_DMA(hi2c, receiveI2C, 7, I2C_FIRST_AND_LAST_FRAME) != HAL_OK) //I2C_FIRST_FRAME
                {
                    //Error;
                }
                while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_BUSY_RX_LISTEN); //HAL_I2C_STATE_LISTEN //HAL_I2C_STATE_BUSY_RX_LISTEN
            break;
            case I2C_DIRECTION_RECEIVE:
                if (HAL_I2C_Slave_Seq_Transmit_DMA(hi2c, transmitI2C, 12,  I2C_LAST_FRAME) != HAL_OK)
                {
                    // Error here!!! (HAL_BUSY)
                    //Error;
                }
                while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_BUSY_TX_LISTEN); //HAL_I2C_STATE_READY //HAL_I2C_STATE_BUSY_TX_LISTEN
            break;
        }
  }
}

Доброго всем вечера.

Помогите с программированием I2C на stm32f373cc, а именно не могу получить количество полученных байт, я использую библиотеку HAL.

Вопрос заключается в следующем, при передачи МАСТЕРОМ  данных СЛЕЙВ их принимает через функцию  HAL_I2C_Slave_Seq_Receive_DMA, Слейв перестает принимать после обнаружения СТОП бита, а вот количество переданных байт МАСТЕРОМ неизвестно, как узнать количество переданных байт. Данные попадают в массив receiveI2C.

Мой код:

 

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

02.10.2020 в 18:56, pvg_79 сказал:

вот количество переданных байт МАСТЕРОМ неизвестно, как узнать количество переданных байт. Данные попадают в массив receiveI2C.

тут не совсем понятно что вы хотите, даже(!), потому что количество переданных мастером байт и количество принятых Слейвом байт, вообще говоря может отличаться!

И Слейв может посчитать только количество принятых байт, как оно считается и/или в каком регистре его взять после окончания приема ищите в документации на переферию процессора.

Если вы про Мастера, то как может быть неизвестно сколько он собственных байт отослал я вообще понять не могу!

Можно сделать все! Но чем больше можно, тем больше нельзя!

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

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

3 hours ago, pvg_79 said:

количество байт принятых слейвом?

У ДМА есть регистр DMA_CNDTRx, в который записывается число байтов, которые необходимо принять. Функция HAL_I2C_Slave_Seq_Receive_DMA() записывает в этот регистр число 7 в данном случае.

Можно в любой момент прочитать этот регистр и получить значение - сколько байтов осталось для приёма. Если 0, то значит все 7 байтов приняты.

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

22 часа назад, Yurkin2015 сказал:

У ДМА есть регистр DMA_CNDTRx

Спасибо, кнопки благодарности почему-то я не нахожу.

Подскажи, в дебрях функции HAL_I2C_Slave_Seq_Receive_DMA() я добавил строчку кода  "hi2c->XfreeSize      = hi2c->hdmarx->Instance->CNDTR;" и затем обращаюсь к переменной так 

"sst = (uint32_t)7 - (uint32_t)(hi2c1.XfreeSize);" и получаю число принятых байт. А если напрямую обращаюсь "sst = (uint32_t)7 - (uint32_t)hi2c1.hdmarx->Instance->CNDTR;"  то значение 0, хоть и в отладчике показывает значение 7 - 4 а результат 0. 

Я с такими конструкциями ни когда не работал, можно оставить первый вариант и результат правильный но при генерации кода из CubeMX исчезают мои изменения.

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

10 часов назад, pvg_79 сказал:

А если напрямую обращаюсь "sst = (uint32_t)7 - (uint32_t)hi2c1.hdmarx->Instance->CNDTR;"  то значение 0, хоть и в отладчике показывает значение 7 - 4 а результат 0. 

Так I2c и слейв здесь не при чем! это проблема или с ДМА или с С-кодом, надо разбираться почему у вас значение из регистра не читается или не сохраняется, возможно переменная sst зануляется каким то образом.

Весь код функции надо смотреть где вы добавляете строчку с которой работает.

10 часов назад, pvg_79 сказал:

hi2c->hdmarx

а почему сдесь hi2c, а здесь:

10 часов назад, pvg_79 сказал:

(uint32_t)hi2c1.hdmarx

hi2c1 ????????????

Изменено пользователем ruhi

Можно сделать все! Но чем больше можно, тем больше нельзя!

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

Вот почему здесь hi2c, потому, что это в функции

HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions)
{
...
	hi2c->XfreeSize	  = hi2c->hdmarx->Instance->CNDTR;
...
}

А здесь 

11 часов назад, ruhi сказал:

hi2c1 ????????????

потому, что в главном цикле ( Main ... while(1))

То что это не связано с I2C понятно, это что-то с синтаксисом.

Вот кусок кода из цикла WHILE:

I2C_HandleTypeDef hi2c1;

if (transferAdres == 1)
			  {
				  	switch (transferDirection)
					{
						case I2C_DIRECTION_TRANSMIT:
							if (HAL_I2C_Slave_Seq_Receive_DMA(&hi2c1, receiveI2C, 7, I2C_FIRST_FRAME) != HAL_OK) //I2C_FIRST_FRAME  I2C_FIRST_AND_LAST_FRAME
							{
								//Error;
							}
							//sst = (uint32_t)7 - (uint32_t)(hi2c1.XfreeSize);
							sst = (uint32_t)7 - (uint32_t)hi2c1.hdmarx->Instance->CNDTR;
							while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_LISTEN); //HAL_I2C_STATE_LISTEN //HAL_I2C_STATE_BUSY_RX_LISTEN
						break;
						case I2C_DIRECTION_RECEIVE:
							if (HAL_I2C_Slave_Seq_Transmit_DMA(&hi2c1, transmitI2C, 12,  I2C_LAST_FRAME) != HAL_OK)
							{
								// Error here!!! (HAL_BUSY)
								//Error;
							}
							while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY); //HAL_I2C_STATE_READY //HAL_I2C_STATE_BUSY_TX_LISTEN
						break;
					}
				  transferAdres = 0;
			  }

 

uint32_t sst = 0; переменная объявлена до цикла и нигде не используется.

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

17 часов назад, pvg_79 сказал:

case I2C_DIRECTION_TRANSMIT: if (HAL_I2C_Slave_Seq_Receive_DMA(&hi2c1, receiveI2C, 7, I2C_FIRST_FRAME)

А почему кейс для TRANSMIT, а структура передается для receiveI2C??? Перепутано???

И если это ошибка то могу объяснить почему в дебаге видно значение - потому что в кейс заходим когда его нет, а поскольку вы прерываете работу программы в дебаге, а железо продолжает работать, значение в регистре появляется уже(!), когда вы его смотрите в дебаге.

Изменено пользователем ruhi

Можно сделать все! Но чем больше можно, тем больше нельзя!

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

6 часов назад, ruhi сказал:

А почему кейс для TRANSMIT, а структура передается для receiveI2C??? Перепутано???

Нет не перепутано, но почему так я не знаю?

Разобрался почему не работало, я считывал значение из регистра CNDTR сразу после функции, и сразу отнимал "7 - CNDTR" и получал 0 т.к. в регистре было реально значение 7. 

в отладчике показывало что значение 4 и я стал считывать значение после while т.е. с задержкой.

Вод рабочий код:

if (transferAdres == 1)
			  {
				  	switch (transferDirection)
					{
						case I2C_DIRECTION_TRANSMIT:
							if (HAL_I2C_Slave_Seq_Receive_DMA(&hi2c1, receiveI2C, 7, I2C_FIRST_FRAME) != HAL_OK) //I2C_FIRST_FRAME  I2C_FIRST_AND_LAST_FRAME
							{
								//Error
							}
							while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_LISTEN); //HAL_I2C_STATE_LISTEN //HAL_I2C_STATE_BUSY_RX_LISTEN
							sst = (uint32_t)7 -(uint32_t) hi2c1.hdmarx->Instance->CNDTR;
						break;
						case I2C_DIRECTION_RECEIVE:
							if (HAL_I2C_Slave_Seq_Transmit_DMA(&hi2c1, transmitI2C, 12,  I2C_LAST_FRAME) != HAL_OK)
							{
								// Error here!!! (HAL_BUSY)
								//Error;
							}
							while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY); //HAL_I2C_STATE_READY //HAL_I2C_STATE_BUSY_TX_LISTEN
						break;
					}
				  transferAdres = 0;
			  }

 

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

Какой еще задержкой, зачем тебе тогда ДМА? Почему именно 7 что за глупости еще. Напиши нормальную функцию передачи пакета данных по ДМА на шине и2ц и все. Я имею в виду универсальную.

А слейв ну тогда приема данных и кто его знает какой там у тебя алгоритм, протокол.

Сделай так в CNT ДМА впиши масимальный размер приемного буфера. По стопу, прерыванию от и2ц останавливай ДМА и лезь читать его счетчик отнимай и все.

Изменено пользователем MasterElectric
Ссылка на комментарий
Поделиться на другие сайты

Я использую библиотеку HAL функция HAL_I2C_Slave_Seq_Receive_DMA(&hi2c1, receiveI2C, 7, I2C_FIRST_FRAME), здесь я указал число 7 это и есть максимальный размер приемного буфера и данная функция это число записывает в регистр CNDTR, а вот как считать это значение после приема данных, в этой библиотеке я не нашел. Отсюда и число 7, отнимаю (7-CNDTR = 0) 

Вот и мучаюсь уже почти 3 недели, не могу получить количество принятых байт. Никто не может подсказать как это значение получить, так сказать рабочую строчку выложить.

Это моя первая программа на STM. 

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...