У меня есть контроллер STM32F2 и устройство FRAM FM24V10-G, подключенное к нему через I2C.
Обычно для связи с устройствами I2C я использую библиотеку, основанную на libopencm3. Однако использование FRAM требует немного другого порядка действий I2C (например, отправка начала, 7-битный адрес и т. Д.), Что означает, что я не могу использовать стандартные библиотечные функции, такие как чтение и запись, которые помогли мне с другими устройствами I2C. В этой библиотеке I2C реализован как класс, и в нем есть перегруженные операторы потоков для отправки этих команд I2C в нужном порядке.
Например:
I2c& I2c::operator<< (operation_t operation)
{
switch (operation) {
case Start:
i2c_send_start(_reg);
while (!checkEvent(SR2(I2C_SR2_BUSY | I2C_SR2_MSL) | I2C_SR1_SB));
break;
case Stop:
i2c_send_stop(_reg);
break;
case Wait_End:
while (!checkEvent(I2C_SR1_TxE));
break;
return *this;
}
Иногда некоторые из этих команд не выполняются, в результате чего процессор ожидает некоторый флаг (как в случае Wait_End), останавливая работу всей системы.
Итак, вот мой вопрос: есть ли способ вернуть какой-нибудь флаг тайм-аута в коде выше? Для меня очень важно, чтобы система работала постоянно, просто пропустив одну команду, если операция I2C не удалась и истекло время ожидания, все в порядке.
Спасибо всем, кто читает это!
Вы можете сделать очень простой тайм-аут, как это:
I2c& I2c::operator<< (operation_t operation)
{
int count = 0;
const int TIMEOUT = 4242;
switch (operation) {
case Start:
i2c_send_start(_reg);
while (!checkEvent(SR2(I2C_SR2_BUSY | I2C_SR2_MSL) | I2C_SR1_SB)
&& count != TIMEOUT) {
count++;
}
break;
case Stop:
i2c_send_stop(_reg);
break;
case Wait_End:
while (!checkEvent(I2C_SR1_TxE) && count != TIMEOUT) {
count++;
}
break;
}
if (count == TIMEOUT) {
//error handling
return -1;
}
return *this;
}
Конечно, если вам нужен точный тайм-аут и вы не хотите тратить время на обработку, увеличивая count
Переменная вы должны использовать аппаратные таймеры.
Других решений пока нет …