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

переключение контента+TimeOut I2C

Добрый день, есть функция чтение температуры из термодатчика Lm75ad во время ожидания ожидания флага передаю управления другому процессу portYIELD(); Так вот если замкнуть линии I2C то процесс чтения температуры зависает, а остальное все работает. Так вот как по феншую сделать отработку зависания ? Пока только одна идея перед каждый ожидание засекать время, и в диспетчере смотреть больше оно таймаута или нет, но мне это не нравиться тем что это надо прятать в дефайны, что не айс, или код "загромождать". Если другие способы определения ?

 

 

uint8_t OS_Lm75ad_Read(short unsigned int* dataout,const unsigned char addr){

static short unsigned int tmp[2];

static short unsigned int* dataout_temp;

//------------------------------------------------------------------------------------

LED_DEBUG_ON

dataout_temp=dataout;

while(I2C_GetFlagStatus(I2C_LM75AD, I2C_FLAG_BUSY)){portYIELD();};

LED_DEBUG_OFF

//------------------------------------------------------------------------------------

I2C_GenerateSTART(I2C_LM75AD, ENABLE);

/* check start bit flag */

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_MODE_SELECT)){portYIELD();};

LED_DEBUG_ON

//----------------------SEND_ADDR_Write-------------------------------------------------------

I2C_Send7bitAddress(I2C_LM75AD,(addr), I2C_Direction_Transmitter);

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){portYIELD();};

//----------------------POINT------------------------------------------------------------------

I2C_SendData(I2C_LM75AD,LM75AD_ADDR_REG_Temp); //Регист Temp(температура)

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_BYTE_TRANSMITTED)){portYIELD();};

LED_DEBUG_ON

//----------------------RE-START-------------------------------------------------------------------

I2C_GenerateSTART(I2C_LM75AD, ENABLE);

/* check start bit flag */

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_MODE_SELECT)){portYIELD();};

LED_DEBUG_OFF

//-------------------Send_addr_read------------------------------------------------------

I2C_Send7bitAddress(I2C_LM75AD, (addr), I2C_Direction_Receiver);

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){portYIELD();};

LED_DEBUG_ON

//------------------------------------------------------------------------------------------

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_BYTE_RECEIVED)){portYIELD();};

LED_DEBUG_OFF

tmp[0]=I2C_ReceiveData(I2C_LM75AD);

//------------------------------------------------------------------------------------------

while(!I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_BYTE_RECEIVED)){portYIELD();};

LED_DEBUG_ON

tmp[1]=I2C_ReceiveData(I2C_LM75AD);

//------------------------------------------------------------------------------------------

I2C_GenerateSTOP(I2C_LM75AD, ENABLE);

/*stop bit flag*/

I2C_AcknowledgeConfig(I2C_LM75AD, ENABLE);

while(I2C_GetFlagStatus(I2C_LM75AD, I2C_FLAG_BUSY)){portYIELD();};

LED_DEBUG_OFF

//------------------------------------------------------------------------------------------

*dataout_temp=(tmp[0]<<8)|tmp[1];

NOP;NOP;NOP;NOP;NOP;

LED_DEBUG_ON

//------------------------------------------------------------------------------------------

}

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


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

Cчeтчик с условием таймаута можно запрятать в функцию portYIELD, возвращать 0, если надо продолжать попытки, или не 0 если таймаут. Вызывать, например, так:

 

while ( !(!I2C_GetFlagStatus(I2C_LM75AD, I2C_FLAG_BUSY) || portYIELD()) );

//Если I2C_GetFlagStatus вернет 1, будет вызываться portYIELD. Цикл будет повторяться, пока portYIELD возвращает 0.

 

while( !(I2C_CheckEvent(I2C_LM75AD, I2C_EVENT_MASTER_MODE_SELECT) || portYIELD()) );

//Если I2C_CheckEvent вернет 0, будет вызываться portYIELD. Цикл будет повторяться, пока portYIELD возвращает 0.

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


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

А где перезапустить счетчик ? Что бы для последующих ожиданий флагов был новый отсчет таймаута.

 

 

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


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

А где перезапустить счетчик ? Что бы для последующих ожиданий флагов был новый отсчет таймаута.

 

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

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


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

firew0rker, спасибо за помощь примерно то что я и хотел.

 

Только теперь возникла другая проблема, как можно повторно узнать о наличии аварии точнее о переходе из аварии в норму ?

 

Дело вот в чем, помимо термодатчика на I2C у меня еще подключен LCD через расширитель порта(только линия DATA), управляющие выводы идут напрямую от процессора, так вот в момент замыкания происходит следующее:

1) в момент замыкания (при маленьком таймауте 2-5ms) на расширитель идет полная фигня, по этому он выдает на выходе нули т.е на LCD приходит Data=0,а так как управляющие выводы работают от процессора то LCD их и принимает, и выводит "корябозябру".

 

Если увеличивать таймаут больше периода обновления LCD то такого естественно не происходит. Но я хочу что бы момент замыкания не было видно и он максимально быстро отрабатывался.

 

PS: Флаг BERR и BUSY не помогают. BUSY ставиться только при замыкании на ноль, а BERR вообше не разу не выставился сколько бы не замыкал линию.

 

BERR – ошибка шины. Устанавливается при обнаружении сигнала start или stop в ”неуместном” месте. Для сброса BERR необходимо записать в него 0.

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

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


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

Подключите линию Е через расширитель. При КЗ на линии Е будет 0 и ЖКИ не среагирует.

 

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

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


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

"Подключите линию Е через расширитель. При КЗ на линии Е будет 0 и ЖКИ не среагирует."

Все линии там уже заняты. =(

 

Повторный опрос это только с датчиком =(

 

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


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

Если ваш ЖК-модуль на основе контроллера HD44780, то в DDRAM символы с кодами 00...07 - это переопределяемые символы. При инициализации занулите их, т. е. сделайте пробелами, чтобы при получении кода 0 выводился пробел а не крякозабра.

 

Что надо обнаруживать: наличие и исправность датчика, или КЗ на I2C?

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


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

Если ваш ЖК-модуль на основе контроллера HD44780, то в DDRAM символы с кодами 00...07 - это переопределяемые символы. При инициализации занулите их, т. е. сделайте пробелами, чтобы при получении кода 0 выводился пробел а не крякозабра.
так и есть в 0 ячейка стоит символ градуса, по нему и сужу что там 0 на дате приходит =))

 

Что надо обнаруживать: наличие и исправность датчика, или КЗ на I2C?

Что бы вся периферия на I2C работала гарантированно и после КЗ что бы нечего не зависало, и в случае какой либо помехи,её не было заметно.

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

(над последним пока ещё думаю как это сделать,пока останавливаюсь на том что, если много раз зависал в одной функции то перейти на более медленный опрос этой функции раз в 10 секунд, или вообще выключить её опрос)

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


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

(1) . . .. , и в случае выхода одного из строя что бы все остальное работало.

(2) . . . .если много раз зависал в одной функции то перейти на более медленный опрос этой функции раз в 10 секунд, или вообще выключить её опрос)

(1) если датчик закоротит одну из линий I2C - то естественно, "ляжет" вся шина. И с этим ничего не сделаешь.

Шина I2C - внутрисхемный интерфейс, и если датчик висит на проводе более 10 см - готовьтесь к проблемам.

Чтоб ОНО таки работало, проверьте подтягивающие резисторы I2C. Они должны быть (для надежной рабты периферии, в соотв-ии с миним. требованиями стандарта)

R = 4.7 ... 10 кОм. ОНО будет, конечно, работать и на 100к, но помехоустойчивать будет приближаться к 0.

Снижать вниз R нельзя, можно попалить выходные узлы как мастера, так и слейвов.

Экранируйте провод линии - если они внешние для прибора.

Для работы с длинной внешней шиной I2C есть спец. микросхемы-драйверы.

(2)

не используйте

while( USCI_I2C_RDY_ ) { }  - прямой путь к завесам в нем.

лучше так

MyTimer.Start(1000);
while( USCI_I2C_RDY )  // бит периферийного узла I2C
{ 
   if( MyTimer.IsElaps() ) 
   {
        RetCode = eI2C_ERR_RDY; 
        break; 
   }
}

Завесы при работе с периферией I2C вполне возможны. slave может войти в "ступор" (ожидание) и ваш софт получит коллизию - навечно, до второго пришествия

Reset. Вывести шину из этого состояния софтово можно принудительной подачей 9 clk (узел I2C отключить. ногодрыг SCK)

 

Вообще, если что-то не работает или "глючит" - 99 проц. - вина аффтара софта и железа :)

Не устраняйте последствия, найдите и устраните причину сбойной работы.

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


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

Согласна с написанным k155la3 и ещё добавлю: чтобы освободить шину от зависшего slave, может быть мало 9 импульсов CLK (a может быть и много). Лучше после каждого проверять уровень на линии (slave отпустил — хватит дёргать). И ещё несколько раз сформировать СТОП-условие на шине.

Можно предусмотреть сброс всех, или только глючных устройств шины по питанию. Если у них есть вход "reset", то дергать им, если нет - то подавать питание через ключ и выключать его при зависании.

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


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

Вообще, если что-то не работает или "глючит" - 99 проц. - вина аффтара софта и железа :)

Не устраняйте последствия, найдите и устраните причину сбойной работы.

Т.е. - заменить автора? :biggrin:

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


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

(1) если датчик закоротит одну из линий I2C - то естественно, "ляжет" вся шина. И с этим ничего не сделаешь.

С этим понятно я имел ввиду то что он по адресу не будет отвечать.

Вообще, если что-то не работает или "глючит" - 99 проц. - вина аффтара софта и железа sm.gif

Не устраняйте последствия, найдите и устраните причину сбойной работы.

Да да автор виноват ибо нефиг пинцетом в шину тыкать, да на землю и питание её замыкать. :biggrin: :biggrin: :biggrin:

Reset. Вывести шину из этого состояния софтово можно принудительной подачей 9 clk (узел I2C отключить. ногодрыг SCK)

Клоки есть, но надо ещё сделать проверку уровня на линии после клока как посоветовал firew0rker.

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


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

Т.е. - заменить автора?

Нет. Пока мы тут "бухтим как косм. корабли бороздят Большой Театр" ОН должен "расти на собой".

Это не к ТС или к кому либо :)

 

С этим понятно я имел ввиду то что он по адресу не будет отвечать. . . .

При холодном старте

1. Проверка на "залипший" слейв. Если залипло - попытка сброса залипа. Если неудачно - LCD_Display("I2C fault", __LINE__);

2. Проверки на наличие и исправность всх имеющихся на шине slave

for(. . . )
{
    if( I2C_SlaveIsConnect( slave_list[i] ) 
           continue;
    else
    {
            LCD_Display("Slave error", i);
            while(1)  {}
    }
}

3. Надежность работы конечно зависит от типа-марки-произовдителя slave. Мне пока достаточно I2C_SlaveIsConnect( ADDR )

так как небыло необходимости.

4. Таймауты готовности slave (в смысле его внутреннего состояния). К примеру если это EEPROM в том или ином виде - то надо при последоватьельной записи

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

- читать регистры статуса напредмет готовности.

 

ps - "Так вот если замкнуть линии I2C то процесс чтения температуры зависает, ... "

Это понятно, на шине любое изменение (фронт, спад) отслеживается автоматами как master так и slave.

Можно завесить все - если при этом вошел в коллизию (фактически из-за помехи) автомат master-а, или "зависнет" какой либо слейв - ожидая неизвестно чего,

напр. после ложного "старта".

Проверяйте HW - если глючек в нем, то копаться в софте бессмыслено.

 

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

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


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

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

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

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

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

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

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

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

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

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