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

Нюанс при передачи байта в функцию с отправкой его по I2c

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

Суть такая, имеется код для работы с внешним АЦП MCP3421 по I2c.

Вот тут я его инициализирую его (посылаю cfg байт):

uint8_t cfg_MCP3421_18bit_PGA8 = 0x1F;
// Ждем готовности на шине I2c
while(HAL_I2C_IsDeviceReady(&hi2c3, 0xD0, 1, HAL_MAX_DELAY) != HAL_OK);
// Шлем конфигурационный байт
HAL_I2C_Master_Transmit_IT(&hi2c3, 0xD0, &cfg_MCP3421_18bit_PGA8, 1);

И дальше принимаем 4 байта данных (4й - подтверждение введенного конфига). В такой редакции все работает.

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

uint8_t cfg_MCP3421_18bit_PGA8 = 0x1F;
// Функция инициализации АЦП
Init_I2c_MCP3421(&hi2c3, cfg_MCP3421_18bit_PGA8);

// Сама функция
void Init_I2c_MCP3421(I2C_HandleTypeDef *hi2c, uint8_t cfg)
{
	// ждем готовности на шине I2c  
	while(HAL_I2C_IsDeviceReady(hi2c, 0xD0, 1, HAL_MAX_DELAY) != HAL_OK);
  	// Шлем конфигурационный байт
	HAL_I2C_Master_Transmit_IT(hi2c, 0xD0, (uint8_t*)&cfg, 1);
}

// Структура фунц. приема: "HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)"

В чем разница этих двух подходов понять не могу. Передаю в функцию обычный байт, он там принимается, cfg становится равный cfg_MCP3421_18bit_PGA8 = 0x1F - это видно при отладке, но по I2c улетает фиг знает что.

Еще работает, если в функции, перед отправкой по I2c, байт cfg предварительно перезаписать в любую глобальную переменную, и её уже в свою очередь отправлять. Если объявить буферную переменную, как локальную внутри функции, то работать уже не будет.

uint8_t CFG = 0;
void Init_I2c_MCP3421(I2C_HandleTypeDef *hi2c, uint8_t cfg)
{
	CFG = cfg;
	// I2c_Transmited_Block(&hi2c3, addr_MCP3421_Write, cfg_MCP3421_18bit_PGA1);
	// I2c_Transmited_Mem(&hi2c3, addr_MCP3421_Write, cfg_MCP3421_18bit_PGA1);
	while(HAL_I2C_IsDeviceReady(hi2c, addr_MCP3421_Write, 1, HAL_MAX_DELAY) != HAL_OK);
	HAL_I2C_Master_Transmit_IT(hi2c, addr_MCP3421_Write, (uint8_t*)&CFG, 1);
}

Думал, может компилятор голову морочит, но на разных режимах оптимизации и полностью без неё (NONE) результат один. Пишу на HAL в Cube IDE.

Вред ли это проблема с HAL, скорее что-то чисто СИ-шное :)

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


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

В 01.07.2022 в 19:24, Salk сказал:

В чем разница этих двух подходов понять не могу. Передаю в функцию обычный байт, он там принимается, cfg становится равный cfg_MCP3421_18bit_PGA8 = 0x1F - это видно при отладке, но по I2c улетает фиг знает что.

В том, что:

в 1-м случае вы функции HAL_I2C_Master_Transmit_IT() передаёте указатель на переменную в глобальной памяти;

а во 2-м - указатель на переменную в автоматической памяти (на стеке).

И если эта функция - не блокирующая (завершает выполнение не завершив использование данных по переданному указателю), то после выхода из вашей Init_I2c_MCP3421() переданная в HAL_I2C_Master_Transmit_IT() переменная будет разрушена.

 

В 01.07.2022 в 19:24, Salk сказал:

Пишу на HAL в Cube IDE.

Вот в этом-то и беда... всего этого кубокодерства.... 100500 раз уже писалось.....  :unknw:

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


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

On 7/1/2022 at 7:40 PM, jcxz said:

Вот в этом-то и беда... всего этого кубокодерства.... 100500 раз уже писалось.....

Проблема не в Кубе, а в знании С.

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


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

Что-то не то.

Цитата

HAL_I2C_Master_Transmit_IT(hi2c, 0xD0, cfg, 1);

Init_I2c_MCP3421(&hi2c3, cfg_MCP3421_18bit_PGA8);

void Init_I2c_MCP3421(I2C_HandleTypeDef *hi2c, uint8_t cfg)
{
	while(HAL_I2C_IsDeviceReady(hi2c, addr_MCP3421_Write, 1, HAL_MAX_DELAY) != HAL_OK);
	HAL_I2C_Master_Transmit_IT(hi2c, addr_MCP3421_Write, cfg, 1);
}
// Получаю предупреждение "passing argument 3 of 'HAL_I2C_Master_Transmit_IT' makes pointer from integer without a cast "

И не работает.

Цитата

а во 2-м - указатель на переменную в автоматической памяти (на стеке).

Какой тогда выход? Я действительно в ступоре, куда хоть копать скажите, что искать. Только не кидайтесь всей книгой по СИ целиком :)

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


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

В 01.07.2022 в 20:40, Salk сказал:

Какой тогда выход? Я действительно в ступоре, куда хоть копать скажите, что искать. Только не кидайтесь всей книгой по СИ целиком :)

Во-первых: внимательно изучить требования функции HAL_I2C_Master_Transmit_IT() которую используете (раз уж предпочитаете жить не своим умом). В её описании должно быть упоминание о характере работы функции (блокирующая/неблокирующая) и о требованиях к времени жизни данных передаваемых в неё по указателю. Если описания нет - изучить код функции и всех других, которые она вызывает.

Во-вторых: обеспечить требования к данным переданным в функцию. Если функция неблокирующая - значит должен быть какой-то способ ожидания завершения использования ею переданных ей данных. (ожидания заверешния транзакции).

Или найти другую функцию (либо блокирующую либо которой можно передать данные в динамической памяти и которыми она владеет с момента передачи). Или ещё как. Способов может быть 100500.

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


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

On 7/1/2022 at 7:40 PM, jcxz said:

Вот в этом-то и беда... всего этого кубокодерства.... 100500 раз уже писалось.....

Проблема не в Кубе, а в понимании работы процессора на основе написанных текстов.

А главное не менять cfg пока не будет вызван callback

Первый способ - неправильный.

Второй - правильный
 

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


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

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

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

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

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

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

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

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

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

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