Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работают два DS1820 на общей шине
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
EasyToUse
Здравствуйте, люди добрые! Помогите отладить задачку под 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);
}
}
amiller
Достаточно далек от темы, кубик не использую, просто мысли вслух:
1. Вероятно Вы проверили работоспособность каждого датчика и результаты эксперимента подтверждаются, если поменять их местами или использовать по одному?
2. Насколько я помню, измерение у этого датчика происходит как раз за время около секунды и в течение измерения нельзя дергать линию связи. Не получилось ли так, что процесс измерения одного датчика накладывается на попытку обмена с другим датчиком?
EasyToUse
Цитата(amiller @ Apr 28 2016, 14:46) *
Достаточно далек от темы, кубик не использую, просто мысли вслух:
1. Вероятно Вы проверили работоспособность каждого датчика и результаты эксперимента подтверждаются, если поменять их местами или использовать по одному?
2. Насколько я помню, измерение у этого датчика происходит как раз за время около секунды и в течение измерения нельзя дергать линию связи. Не получилось ли так, что процесс измерения одного датчика накладывается на попытку обмена с другим датчиком?


Когда сидят 2 на шине, то работает первый. Если "на горячую" отключить первый, то правильно начинает отвечать и второй. При обратном подключении первого второй затыкается, первый работает правильно.
По даташиту время преобразования 750 мс, должно хватать.
А вот готовность флагов посмотреть в кубе сложно. Уровень абстракции такой, что считается флаги проверять программисту необязательно. Хотя, наверно, через макросы и можно. SPL в этом плане по-приятней была.



Друзья, взял другие датчики и проблема исчезла! Правда новые датчики на совсем короткой линии. Проверю влияние длины линии. В результате получил практически аппаратное измерение температуры, МК ядро практически не используется.
amiller
Цитата(EasyToUse @ Apr 28 2016, 17:12) *
Когда сидят 2 на шине, то работает первый. Если "на горячую" отключить первый, то правильно начинает отвечать и второй. При обратном подключении первого второй затыкается, первый работает правильно.
По даташиту время преобразования 750 мс, должно хватать.
А вот готовность флагов посмотреть в кубе сложно. Уровень абстракции такой, что считается флаги проверять программисту необязательно. Хотя, наверно, через макросы и можно. SPL в этом плане по-приятней была.

Друзья, взял другие датчики и проблема исчезла! Правда новые датчики на совсем короткой линии. Проверю влияние длины линии. В результате получил практически аппаратное измерение температуры, МК ядро практически не используется.

Может усилить подтяжку на линии данных?
А вообще идея использовать UART для обмена с датчиком DALLAS интересная. Надо будет попробовать. Я раньше делал связь с датчиком на таймере (правда не на STM). Формирование сигнала через PWM, а считывание длительности импульса ответа через Capture. Но мне показалось, что получился слишком сложный алгоритм.
Кстати по применению библиотек:
Кто Вам мешает прямо в main прочитать значение любого регистра? Если в библиотеке объявлены символические имена регистров, можно использовать их. Или даже объявить указатель, присвоить ему адрес регистра из даташита, и читать его где угодно и как угодно в отладочных целей.
alex2103
У меня на HAL не полетело. Ту же самую идею написал через регистры и заработало. 2 шт 18b20 не пробовал, но 18b20 + 1990 работают.
kolobok0
Цитата(amiller @ Apr 28 2016, 16:33) *
..идея использовать UART для обмена с датчиком DALLAS интересная....


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

но для варианта оконного датчика для любимой собаки - да самое то...

(круглый)
PS & OFF/2
Для большего разрешения лучше использовать ds1821 = 0,01 градус вместо 0,0625 у двадцаток...
Vasily_
Цитата(kolobok0 @ Apr 28 2016, 19:54) *
Для большего разрешения лучше использовать ds1821 = 0,01 градус вместо 0,0625 у двадцаток...

Да похоже их уже сняли с производства.
kolobok0
Цитата(Vasily_ @ Apr 28 2016, 20:40) *
... сняли с производства.


да вот жешь.
пришлось свой разрабатывать с такими параметрами. сейчас в проект запускаю. правда подешевле и без 1Wire.

(круглый)
Aleksandr Baranov
Цитата(kolobok0 @ Apr 28 2016, 13:56) *
да вот жешь.
пришлось свой разрабатывать с такими параметрами. сейчас в проект запускаю. правда подешевле и без 1Wire.

(круглый)

У 18B20 разрешение до 12 разрядов.
kolobok0
Цитата(Aleksandr Baranov @ Apr 28 2016, 21:10) *
У 18B20 разрешение до 12 разрядов.


я больше практик чем теоретик. но в даташитах чёрным по ангельски приведена формула расчёта повышенной точности - рекомендую сравнить 21 и 20,
особенно с точки зрения переменных получаемых с датчика. у 20 = применена константа sm.gif посему максимальное разрешение меньше чем у 21 и равна
0,0625 градуса.


(круглый)
ЗЫ
Если Вы посчитаете разницу между формулами - Вы получите именно это значение...
PS PS
Разрешение там искусственно снижено. Т.к. там нет АЦП - то точность могла быть и больше (если технологично вытащить все получаемые погрешности -
но это уже совсем другой ценовой диапазон вышел бы)...
EasyToUse
Цитата(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 есть кажется и шинные ключи, которые могут сегментировать шину. Так что насчет перспектив я бы не согласился с Вами.
Сергей Борщ
QUOTE (EasyToUse @ Apr 28 2016, 22:03) *
Использование UART + DMA позволяет аппаратно формировать временные слоты чтения и записи. Не нужно думать, что твою посылку прервет прерывание или какая-нибудь более приоритетная задача.
Для этого необходимо и достаточно выдержать времянку в пределах одного слота, то есть достаточно только УАПП (UART).
alex2103
Цитата(EasyToUse @ Apr 28 2016, 22:03) *
Использование UART + DMA позволяет аппаратно формировать временные слоты чтения и записи. Не нужно думать, что твою посылку прервет прерывание или какая-нибудь более приоритетная задача. Задаче чтения 1820 можно присвоить самый низкий приоритет и она себе спокойно будет работать. А схемотехника вся сводится к соединению приемника и передатчика в кучу. Пробуйте! Рекомендую! EasyToUse)))
Можно читать и регистры как вы говорите. Но в HAL лучше использовать макросы.

Еще удобно режим SingleWire использовать. Тогдавнешне не надо соединять RX и TX.
kolobok0
Цитата(EasyToUse @ Apr 28 2016, 22:03) *
...насчет перспектив я бы не согласился с Вами.


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

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

(круглый)


Цитата(Сергей Борщ @ Apr 28 2016, 23:10) *
Для этого необходимо и достаточно выдержать времянку в пределах одного слота,...


скажу больше = достаточно выдержать синхро паузу между стробом чтения для принимаемых данных. при записи ещё проще.
Всё остальное - может дрейфовать в пределах десяток мс. Что для мк с частотой ядра около 1 МГц - уже не сложно решаемая задача в рукопашном режиме.

(круглый)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.