|
|
  |
Не работают два DS1820 на общей шине, Как подружить HAL_USART_DMA c DS1820? |
|
|
|
Apr 28 2016, 10:23
|
Группа: Участник
Сообщений: 12
Регистрация: 8-12-14
Из: Смоленск
Пользователь №: 84 036

|
Здравствуйте, люди добрые! Помогите отладить задачку под FreeRTOS. Задачка запускает измерение температуры двумя датчиками DS18S20 и через 1000мс читает значение температуры из каждого датчика, используя его адрес. Значения записываются в очередь, из которой другая задачка берет их и отображает на индикаторе. Датчики сидят на одной шине, а шиной управляет USART. Использую HAL от Cube. Когда подключены два датчика на шине, то правильно работает только первый, второй отвечает FF-ми. Вот сама задача CODE
uint8_t dma_rec[8]; uint8_t dma_trans[8]; uint8_t ow_rec[20]; uint8_t ow_trans[20]; extern UART_HandleTypeDef huart2; extern char* empty_str;
//***************************************************************************** void OneWire_Task (void){ TTemp Temp; uint8_t adr_DS1[8]; uint8_t adr_DS2[8]; restore_adr(EEPROM_ADR_DS1, adr_DS1); restore_adr(EEPROM_ADR_DS2, adr_DS2); while(1){ if(OW_Reset() == OW_OK){ ow_trans[0] = 0xCC; ow_trans[1] = 0x44; OW_Send(2); vTaskDelay(1000); DS1820_getConvertedValue(adr_DS1, &Temp.t1); DS1820_getConvertedValue(adr_DS2, &Temp.t2); xQueueOverwrite(Temp_QueueHandle, &Temp); } else{ vTaskDelay(1000); } } }
Функция сброса и обнаружения импульса присутствия CODE uint8_t OW_Reset(void){ uint8_t ow_presence; huart2.Init.BaudRate = 9600; HAL_UART_Init(&huart2); ow_trans[0] = 0xF0; HAL_UART_Receive_DMA(&huart2, ow_rec, 1); HAL_UART_Transmit_DMA(&huart2, ow_trans, 1); xSemaphoreTake(OW_Complete_BinarySemHandle, portMAX_DELAY); ow_presence = ow_rec[0]; huart2.Init.BaudRate = 115200; HAL_UART_Init(&huart2); if (ow_presence != 0xF0) return OW_OK; else return OW_NO_DEVICE; } Отправка N байт по шине 1-wire CODE void OW_Send(uint8_t kol){ uint8_t i; uint8_t rec_byte; for(i = 0; i < kol; i++){ OW_convert(ow_trans[i],dma_trans); HAL_UART_Receive_DMA(&huart2, dma_rec, 8); HAL_UART_Transmit_DMA(&huart2, dma_trans, 8); xSemaphoreTake(OW_Complete_BinarySemHandle, portMAX_DELAY); rec_byte = OW_restore(dma_rec); ow_rec[i] = rec_byte; } }
вот эта функция работает неправильно при втором вызове CODE uint8_t DS1820_getConvertedValue(uint8_t* adr, float* t){ uint8_t i; float sign; float a; uint8_t ml_byte; uint8_t st_byte; uint8_t count_remain; uint8_t count_per_c; uint16_t temp_read; uint8_t err = 0; uint8_t crc;
OW_Reset();
ow_trans[0] = 0x55; OW_Send(1); vTaskDelay(5);
for(i = 0; i < 8; i++){ ow_trans[i] = *(adr + i); } OW_Send(8); vTaskDelay(5); ow_trans[0] = 0xBE; OW_Send(1); vTaskDelay(5); for(i = 0; i < 9; i++){ ow_trans[i] = 0xFF; } OW_Send(9); vTaskDelay(5); ml_byte = ow_rec[0]; st_byte = ow_rec[1]; count_remain = ow_rec[6]; count_per_c = ow_rec[7]; crc = ow_rec[8];
temp_read = (((uint16_t)st_byte << 8) + (uint16_t)ml_byte) / 2; if(temp_read & 0xFF00) sign = -1.0; else sign = 1.0; if(sign == -1.0){ temp_read = ~temp_read + 1; a = sign * (float)temp_read; } else{ a = (float)temp_read; } a = a - 0.25 + ((float)count_per_c - (float)count_remain) / (float)count_per_c; *t = a;
return err; } каждый бит кодируем байтом CODE void OW_convert(uint8_t ow_byte, uint8_t* buf){ uint8_t i; for(i = 0; i < 8; i++){ if((ow_byte >> i) & 0x01){ *(buf + i) = OW_1; } else{ *(buf + i) = OW_0; } } } из 8 байт по USART делаем один CODE uint8_t OW_restore(uint8_t* buf){ uint8_t ow_byte; uint8_t i; ow_byte = 0; for(i = 0; i < 8; i++){ ow_byte >>= 1; if(buf[i] == OW_R_1) ow_byte |= 0x80; else ow_byte &= (~0x80); } return ow_byte; }
CODE читаем адрес датчика температуры void DS1820_readROM(void){ uint8_t i; OW_Reset(); ow_trans[0] = 0x33; OW_Send(1); vTaskDelay(5); for(i = 0; i < 8; i++){ ow_trans[i] = 0xFF; } OW_Send(8); }
после приема N байт по USART_DMA отдаем семафор void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ static portBASE_TYPE xHigherPriorityTaskWoken; xHigherPriorityTaskWoken = pdFALSE; if(huart == &huart2){ xSemaphoreGiveFromISR(OW_Complete_BinarySemHandle, &xHigherPriorityTaskWoken); portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); } }
Не хотел работать HAL_USART_DMA в режиме NORMAL. Не вызывался колбек. Пришлось подправить. [code]static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) { UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; /* DMA Normal mode*/ if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) { huart->TxXferCount = 0;
/* Disable the DMA transfer for transmit request by setting the DMAT bit in the UART CR3 register */ CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */ //__HAL_UART_ENABLE_IT(huart, UART_IT_TC); huart->State = HAL_UART_STATE_READY; HAL_UART_TxCpltCallback(huart); } /* DMA Circular mode */ else { HAL_UART_TxCpltCallback(huart); } }
Сообщение отредактировал EasyToUse - Apr 28 2016, 12:21
|
|
|
|
|
Apr 28 2016, 13:12
|
Группа: Участник
Сообщений: 12
Регистрация: 8-12-14
Из: Смоленск
Пользователь №: 84 036

|
Цитата(amiller @ Apr 28 2016, 14:46)  Достаточно далек от темы, кубик не использую, просто мысли вслух: 1. Вероятно Вы проверили работоспособность каждого датчика и результаты эксперимента подтверждаются, если поменять их местами или использовать по одному? 2. Насколько я помню, измерение у этого датчика происходит как раз за время около секунды и в течение измерения нельзя дергать линию связи. Не получилось ли так, что процесс измерения одного датчика накладывается на попытку обмена с другим датчиком? Когда сидят 2 на шине, то работает первый. Если "на горячую" отключить первый, то правильно начинает отвечать и второй. При обратном подключении первого второй затыкается, первый работает правильно. По даташиту время преобразования 750 мс, должно хватать. А вот готовность флагов посмотреть в кубе сложно. Уровень абстракции такой, что считается флаги проверять программисту необязательно. Хотя, наверно, через макросы и можно. SPL в этом плане по-приятней была. Друзья, взял другие датчики и проблема исчезла! Правда новые датчики на совсем короткой линии. Проверю влияние длины линии. В результате получил практически аппаратное измерение температуры, МК ядро практически не используется.
|
|
|
|
|
Apr 28 2016, 13:33
|
Частый гость
 
Группа: Участник
Сообщений: 176
Регистрация: 20-02-14
Из: Томск
Пользователь №: 80 612

|
Цитата(EasyToUse @ Apr 28 2016, 17:12)  Когда сидят 2 на шине, то работает первый. Если "на горячую" отключить первый, то правильно начинает отвечать и второй. При обратном подключении первого второй затыкается, первый работает правильно. По даташиту время преобразования 750 мс, должно хватать. А вот готовность флагов посмотреть в кубе сложно. Уровень абстракции такой, что считается флаги проверять программисту необязательно. Хотя, наверно, через макросы и можно. SPL в этом плане по-приятней была.
Друзья, взял другие датчики и проблема исчезла! Правда новые датчики на совсем короткой линии. Проверю влияние длины линии. В результате получил практически аппаратное измерение температуры, МК ядро практически не используется. Может усилить подтяжку на линии данных? А вообще идея использовать UART для обмена с датчиком DALLAS интересная. Надо будет попробовать. Я раньше делал связь с датчиком на таймере (правда не на STM). Формирование сигнала через PWM, а считывание длительности импульса ответа через Capture. Но мне показалось, что получился слишком сложный алгоритм. Кстати по применению библиотек: Кто Вам мешает прямо в main прочитать значение любого регистра? Если в библиотеке объявлены символические имена регистров, можно использовать их. Или даже объявить указатель, присвоить ему адрес регистра из даташита, и читать его где угодно и как угодно в отладочных целей.
|
|
|
|
|
Apr 28 2016, 16:54
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(amiller @ Apr 28 2016, 16:33)  ..идея использовать UART для обмена с датчиком DALLAS интересная.... идея использовать аппаратный уровень конечно-же подкупает. но с точки зрения использования при разработках, в пром. вариантах - малоперспективна. Да и один провод на кучу датчиков - тормоза, гимор пусконаладчиков, описанные глюкало типа "дрейф-разогрев" и т.п. детские болезни. но для варианта оконного датчика для любимой собаки - да самое то... (круглый) PS & OFF/2 Для большего разрешения лучше использовать ds1821 = 0,01 градус вместо 0,0625 у двадцаток...
Сообщение отредактировал kolobok0 - Apr 28 2016, 17:02
|
|
|
|
|
Apr 28 2016, 18:10
|
Частый гость
 
Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118

|
Цитата(kolobok0 @ Apr 28 2016, 13:56)  да вот жешь. пришлось свой разрабатывать с такими параметрами. сейчас в проект запускаю. правда подешевле и без 1Wire.
(круглый) У 18B20 разрешение до 12 разрядов.
--------------------
ASB
|
|
|
|
|
Apr 28 2016, 18:26
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(Aleksandr Baranov @ Apr 28 2016, 21:10)  У 18B20 разрешение до 12 разрядов. я больше практик чем теоретик. но в даташитах чёрным по ангельски приведена формула расчёта повышенной точности - рекомендую сравнить 21 и 20, особенно с точки зрения переменных получаемых с датчика. у 20 = применена константа  посему максимальное разрешение меньше чем у 21 и равна 0,0625 градуса. (круглый) ЗЫ Если Вы посчитаете разницу между формулами - Вы получите именно это значение... PS PS Разрешение там искусственно снижено. Т.к. там нет АЦП - то точность могла быть и больше (если технологично вытащить все получаемые погрешности - но это уже совсем другой ценовой диапазон вышел бы)...
Сообщение отредактировал kolobok0 - Apr 28 2016, 18:29
|
|
|
|
|
Apr 28 2016, 19:03
|
Группа: Участник
Сообщений: 12
Регистрация: 8-12-14
Из: Смоленск
Пользователь №: 84 036

|
Цитата(amiller @ Apr 28 2016, 16:33)  Может усилить подтяжку на линии данных? А вообще идея использовать UART для обмена с датчиком DALLAS интересная. Надо будет попробовать. Я раньше делал связь с датчиком на таймере (правда не на STM). Формирование сигнала через PWM, а считывание длительности импульса ответа через Capture. Но мне показалось, что получился слишком сложный алгоритм. Кстати по применению библиотек: Кто Вам мешает прямо в main прочитать значение любого регистра? Если в библиотеке объявлены символические имена регистров, можно использовать их. Или даже объявить указатель, присвоить ему адрес регистра из даташита, и читать его где угодно и как угодно в отладочных целей. Использование UART + DMA позволяет аппаратно формировать временные слоты чтения и записи. Не нужно думать, что твою посылку прервет прерывание или какая-нибудь более приоритетная задача. Задаче чтения 1820 можно присвоить самый низкий приоритет и она себе спокойно будет работать. А схемотехника вся сводится к соединению приемника и передатчика в кучу. Пробуйте! Рекомендую! EasyToUse))) Можно читать и регистры как вы говорите. Но в HAL лучше использовать макросы. Цитата(alex2103 @ Apr 28 2016, 17:30)  У меня на HAL не полетело. Ту же самую идею написал через регистры и заработало. 2 шт 18b20 не пробовал, но 18b20 + 1990 работают. И у меня в начале на HAL не полетело. Оказалось UART+DMA не хотел работать в NORMAL режиме. У индусов там какая-то ерунда написана. Видимо посмотрели, что в CIRCULAR работает - ну и ладно. Пришлось немножно подправить. После генерации кода кубом нужно лезть в библиотеку и ремить их функцию, а ставить свою. Писать на регистрах это чем-то будет напоминать программирование на ассемблере. Я все-таки за бОльшую абстракцию))) Хотя везде есть плюсы и минусы. Цитата(kolobok0 @ Apr 28 2016, 19:54)  идея использовать аппаратный уровень конечно-же подкупает. но с точки зрения использования при разработках, в пром. вариантах - малоперспективна. Да и один провод на кучу датчиков - тормоза, гимор пусконаладчиков, описанные глюкало типа "дрейф-разогрев" и т.п. детские болезни.
но для варианта оконного датчика для любимой собаки - да самое то...
(круглый) PS & OFF/2 Для большего разрешения лучше использовать ds1821 = 0,01 градус вместо 0,0625 у двадцаток... Причем в данном случае за аппаратный уровень не надо платить))) Вы имеете ввиду, что к устройствам надо обращаться по адресу, а для этого на шине надо оставить один датчик, считать его имя и запомнить? Есть некоторые неудобства. Радует, что это надо делать лишь раз. Еще есть хитрая процедура поиска всех адресов на шине. Но потом все равно устройство нужно связать с его расположением. У DALLAS есть кажется и шинные ключи, которые могут сегментировать шину. Так что насчет перспектив я бы не согласился с Вами.
Сообщение отредактировал EasyToUse - Apr 28 2016, 19:06
|
|
|
|
|
Apr 29 2016, 14:33
|
Частый гость
 
Группа: Свой
Сообщений: 135
Регистрация: 7-03-07
Из: г. Запорожье
Пользователь №: 25 945

|
Цитата(EasyToUse @ Apr 28 2016, 22:03)  Использование UART + DMA позволяет аппаратно формировать временные слоты чтения и записи. Не нужно думать, что твою посылку прервет прерывание или какая-нибудь более приоритетная задача. Задаче чтения 1820 можно присвоить самый низкий приоритет и она себе спокойно будет работать. А схемотехника вся сводится к соединению приемника и передатчика в кучу. Пробуйте! Рекомендую! EasyToUse))) Можно читать и регистры как вы говорите. Но в HAL лучше использовать макросы. Еще удобно режим SingleWire использовать. Тогдавнешне не надо соединять RX и TX.
|
|
|
|
|
Apr 29 2016, 16:49
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(EasyToUse @ Apr 28 2016, 22:03)  ...насчет перспектив я бы не согласился с Вами. про согласие либо нет - тут как-бы дело каждого личное. Но если Вы имеете штук 6 термодатчиков контролируемых мозгами, в какой-нить установке - то шинная топология накладывает кучу действий средне-квалифицированного персонала. В случае радиального подключения - время переключения-подключения составляет несколько секунд. Причём других настроечных-подключаемых телодвижений делать не требуется - софт вполне себе может разрулить всё на автомате за доли секунды. Что существенно при обслуживании парков таких устройств, а не отдельно стоящего в поле. всё это требует временных(как минимум) затрат, ну и постулат время=деньги думаю приводить тут перебор. если заказчик ставит задачу обязательно использовать отвёртки, супер-пупер инструкции по программированию и настройки при переключении только одного датчика (а их на установке может быть гораздо больше) - то да, шинная топология будет смотреться пафоснее и необходимее. (круглый) Цитата(Сергей Борщ @ Apr 28 2016, 23:10)  Для этого необходимо и достаточно выдержать времянку в пределах одного слота,... скажу больше = достаточно выдержать синхро паузу между стробом чтения для принимаемых данных. при записи ещё проще. Всё остальное - может дрейфовать в пределах десяток мс. Что для мк с частотой ядра около 1 МГц - уже не сложно решаемая задача в рукопашном режиме. (круглый)
Сообщение отредактировал kolobok0 - Apr 29 2016, 16:50
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|