Stm32F0 и 1-wire

Я пытался в процедуре сброса определить три состояния:
1. Есть датчик OWI
2. Нет датчика
3. КЗ ни линии.
Сделать это пытался по анализу ответа на сброс.
В статье есть раздел «Сброс шины 1-wire», и сделано так (незначимая часть — опущена)
uint8_t OW_Reset(USART_TypeDef* USARTx) {
uint8_t ow_presence;
...........................
USART_ClearFlag(USARTx, USART_FLAG_TC);
USART_SendData(USARTx, 0xf0);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
ow_presence = USART_ReceiveData(USARTx);
...........................
if (ow_presence != 0xf0) {
return 1;
}
return 0;
Пока к шине никто не подключен ow_presence = USART_ReceiveData(USARTx); возвращает правильное значение 0xF0. Как только подключили датчик картина меняется кардинально — USART_ReceiveData(USARTx) возвращает строго — НОЛЬ.
Видимо импульс «неправильной» длительности сносит башню приемнику. На картинке отмечено место где должны быть переходы у «нормальной» последовательности 9600.

Может быть, промежуток времени между отпусканием линии контроллером и началом ответа датчиком воспринимается приемником как повторный старт.
В отладчике видно, что к моменту окончания передачи приемник еще не решил, принял он что-то или нет. Если поставить точку останова после строки
ow_presence = USART_ReceiveData(USARTx);
то USART_FLAG_RXNE оказывается взведен, а в регистре RDR лежат правильные данные (0хE0)
Т.е. приемник принимает решение о приеме байта позже из-за дерготни в непонятные для него моменты времени.
Лечение — элементарно. Ждем флага готовности приема.
#define OWI_USART USART1
..........................
OWI_USART->TDR = 0x0F;
while ((OWI_USART->ISR & USART_FLAG_TC) == RESET);
while ((OWI_USART->ISR & USART_FLAG_RXNE) == RESET);
ow_presence = OWI_USART->RDR;
Теперь посылаем 0x0F а принимаем 0x07. Ответ на импульс сброса — виден.
Но задачу этим я не решил. :)
Поскольку при КЗ ответа не будет никогда, т.к. на входе приемника (RxD) не будет стартового перепада, при ожидании ответа необходимо завести тайм-аут по приему. И вот этот тайм-аут покажет, что на линии КЗ.
Как организовать паузу — каждый решает самостоятельно. :)
У меня USART_CR2_MSBFIRST установлен, поэтому данные передаются старшим битом вперед. Мне так показалось нагляднее. :)
Более простое решение подсказал dadigor в комментах. Перед тем как вообще что-то делать с OWI нужно посмотреть входной пин и если там 0, то КЗ и завершаем с ошибкой.
12.11.2017 Прикрепил исходники.
- +1
- 31 октября 2015, 19:59
- SeregaB
- 1
Файлы в топике:
SRC.ZIP
У steel_ne есть развитие темы здесь. Там все коды рабочие, проверено.
Где нибудь, в моей заметке написано что код steel_ne нерабочий?
Я пытался в процедуре сброса определить три состояния:
1. Есть датчик OWI
2. Нет датчика
3. КЗ ни линии.
Не получилось по п.3 потому, что ответ, записанный в переменной ow_presence при наличии датчика всегда нулевой. Мне показалось это странным, решил понять в чем дело. Разобрался, кратенько описал.
У steel_ne и в указанной тобой библиотеке и по ссылке которую дал я очень тонко обойден этот момент. Ответ сравнивается с исходной посылкой.
Т.о., получив 0х00, при сравнении с 0xF0 все работает.
Я понимаю, после того как дописал кусок кода дальше, что я не могу получить в ответе 0х00 при КЗ в линни, поскольку не будет стартового бита. И выходить при КЗ пришлось по тайм-ауту приема. Но мне необходимо знать до начала штатной работы есть КЗ или нет (подавать умощненное питание на время преобразования или не стОит, поскольку датчики включены с фантомным питанием).
Я пытался в процедуре сброса определить три состояния:
1. Есть датчик OWI
2. Нет датчика
3. КЗ ни линии.
Не получилось по п.3 потому, что ответ, записанный в переменной ow_presence при наличии датчика всегда нулевой. Мне показалось это странным, решил понять в чем дело. Разобрался, кратенько описал.
У steel_ne и в указанной тобой библиотеке и по ссылке которую дал я очень тонко обойден этот момент. Ответ сравнивается с исходной посылкой.
if (ow_presence != 0xf0) {
return OW_OK;
}
Т.о., получив 0х00, при сравнении с 0xF0 все работает.
Я понимаю, после того как дописал кусок кода дальше, что я не могу получить в ответе 0х00 при КЗ в линни, поскольку не будет стартового бита. И выходить при КЗ пришлось по тайм-ауту приема. Но мне необходимо знать до начала штатной работы есть КЗ или нет (подавать умощненное питание на время преобразования или не стОит, поскольку датчики включены с фантомным питанием).
Что-то я не очень наверное въехал, башка сегодня ни к черту… Никак не соображу, но вроде бы КЗ можно проверить сразу, ничего вообще не передавая — USART выдает в стоповом состоянии 1, просто посмотри что на приемном входе, если 0, значит КЗ и не начинай обмен вообще.
Сейчас именно так и сделал. :) Спасибо за простое решение.
С тайм-аут выкинул за ненадобностью. Перед переинициализацией на 9600 переключаю TxD в GPIO-вход и смотрю уровень. При низком — функция OWI_Reset сразу возвращает код ошибки КЗ.
А у меня утром сегодня башка плохо варила и я пытался по приему байта 0х00 определить КЗ. :)
С тайм-аут выкинул за ненадобностью. Перед переинициализацией на 9600 переключаю TxD в GPIO-вход и смотрю уровень. При низком — функция OWI_Reset сразу возвращает код ошибки КЗ.
А у меня утром сегодня башка плохо варила и я пытался по приему байта 0х00 определить КЗ. :)
Комментарии (6)
RSS свернуть / развернуть