реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Странное поведение DS18b20
Halfback
сообщение Jan 27 2016, 17:45
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 322
Регистрация: 28-05-05
Пользователь №: 5 512



Всем доброго времени суток!
Есть проблема с датчиками DS18b20
Заказал пару штук этих датчиков во влагозащищенном исполнении.
Подключил один из них по 2-проводной схеме - т.е. красный и черный провод объединил и посадил на "землю". Желтый провод сделал PullUP (к 3,3В через 3,3кОм) посадил на передатчик USART4.
МК - STM32F103RE (отладочная плата - Махаон).
Для упрощения жизни запустил CubeMX последней версии, настроил USART4 на HalfDuplex.
И ситуация следующая: на F0 датчик отвечает E0, а вот на остальные команды не отвечает вообще никак. Ни на 0хсс 0хBE (чтение памяти 9 байт) ни на 0x33.
Собственно, результаты смотрел в отладчике Keil и осциллографом. Скорость UART меняется адекватно, оценивал длительность импульсов согласно скорости.

Код ниже:

Код
        
uint8_t TxCmdReset=0xF0;
uint8_t RxAnswReset1;
uint8_t RxData[100];
uint8_t ow_buf[8];

HAL_HalfDuplex_EnableReceiver(&huart4);
        
    MX_UART4_Init_wBoudRate(9600); //Reset
    HAL_UART_Receive_IT(&huart4,&RxAnswReset1,1);    
    HAL_UART_Transmit(&huart4, &TxCmdReset, sizeof(TxCmdReset), 2);    
    for(i=0;i<1000;i++) {__NOP();}
        
    MX_UART4_Init_wBoudRate(115200);
    HAL_UART_Receive_IT(&huart4, RxData, sizeof(RxData));
    OW_toBits(0xCC, ow_buf);
    HAL_UART_Transmit(&huart4, (uint8_t *)ow_buf, 8, 3);
    OW_toBits(0xB4, ow_buf);
    HAL_UART_Transmit(&huart4, (uint8_t *)ow_buf, 8, 3);
    HAL_Delay(2);
    while(1);


Код
void MX_UART4_Init_wBoudRate(uint32_t BoudRate)
{
  huart4.Instance = UART4;
  huart4.Init.BaudRate = BoudRate;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  
  HAL_HalfDuplex_Init(&huart4);
}


Функция преобразования байта в 8 байт для отправки заимствован. Тем не менее его в отладчике проверял - замечаний нет.

Код
void OW_toBits(uint8_t ow_byte, uint8_t *ow_bits) {
        uint8_t i;
        for (i = 0; i < 8; i++) {
               if (ow_byte & 0x01) {
                        *ow_bits = OW_1;
                } else {
                        *ow_bits = OW_0;
                }
                ow_bits++;
                ow_byte = ow_byte >> 1;
        }
}


Пробовал оба датчика - ведут себя одинаково. Значит есть надежда что ошибка в коде.
Может кто прояснит в чем я не прав?

Сообщение отредактировал Halfback - Jan 27 2016, 17:57
Go to the top of the page
 
+Quote Post
k155la3
сообщение Jan 28 2016, 07:13
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Насколько мне не изменяет (?) память, DS18B20 работают по интерфейсу OWI.
Соответствует ли формат данных фреймам символов USART - не знаю.
Но для корректной работы с датчиком временнЫе параметры запроса должны выдерживатьс.
Для начала - посмотрите осцилографом соответствие формы Вашего запроса к датчику требованиям даташита на 18B20.

По аппартаной части - есть малозаметное отличие для 18B20
DS18B20 - 3-проводное подключение.
DS18B20P - 2-проводное подключение с "паразитным" питанием.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jan 28 2016, 07:28
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Halfback @ Jan 27 2016, 20:45) *
Пробовал оба датчика - ведут себя одинаково. Значит есть надежда что ошибка в коде.
Может кто прояснит в чем я не прав?

Недавно выкладывал проверялщик DS18B20 для STM32F4DISCOVERY.
Go to the top of the page
 
+Quote Post
Halfback
сообщение Jan 28 2016, 08:33
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 322
Регистрация: 28-05-05
Пользователь №: 5 512



Спасибо что откликнулись.
Тайминги на соответствие даташиту посмотрю.

Могу вот что добавить: при запросе на преобразование 0хF0 (9600), 0xCC(115200), 0xBE(115200) при подключении по двухпроводной схеме (VCC и GND замыкаются и сажаются на землю, сигнальный на UART TX c подтяжкой к 3,3В через 3,3кОм) осциллограмма в точности как на этом рисунке

В этом случае проседание длиться ~600мс.
Если включаю по трехпроводной схеме то при таком же запросе проседания линии нет.
Что бы это могло значить?

Сообщение отредактировал Halfback - Jan 28 2016, 08:34
Go to the top of the page
 
+Quote Post
adnega
сообщение Jan 28 2016, 08:48
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Halfback @ Jan 28 2016, 11:33) *
Что бы это могло значить?

При паразитном питании во время преобразования линию DQ нужно тащить к VCC активно: через ключ, а не пассивной подтяжкой резистором.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 28 2016, 10:13
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Halfback @ Jan 27 2016, 22:45) *
Для упрощения жизни запустил CubeMX последней версии, настроил USART4 на HalfDuplex.

Не надо HalfDuplex, приём должен идти одновременно с передачей.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
k155la3
сообщение Jan 29 2016, 06:27
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Вот подвернулось тут. Работа с DS18B20
По ссылке, любезно предоставленной Евгенич:
тут
http://karve.in/?p=1408
http://www.shelezyakin.ru/?p=104

Go to the top of the page
 
+Quote Post
Halfback
сообщение Jan 29 2016, 13:52
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 322
Регистрация: 28-05-05
Пользователь №: 5 512



Частично разобрался.
Решил пока забить на UART и сделал долбатню пином. Все временные выдерки взял согласно даташиту на датчик. Всё четко как в аптеке. Свою задержку 1us замерял осциллом.

Собственно основной цикл:
Код
#define ONEWIRE_LOW()     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET)
#define ONEWIRE_HIGH() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET)
#define ONEWIRE_INPUT()  MX_GPIO_P10_Init(2) // IN NoPull
#define ONEWIRE_OUTPUT_PP() MX_GPIO_P10_Init(1) // OUT PP
#define ONEWIRE_OUTPUT_OD() MX_GPIO_P10_Init(0) // OUT OD
#define ONEWIRE_READPIN() HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_10)
#define DELAY_1us() {__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\
                                        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\
                                        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\
                                        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\
                                        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\
                                        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();}
#define ONEWIRE_DELAY(delay_us) {for(volatile uint16_t i=0;i<delay_us-1;i++) DELAY_1us();}
......
volatile uint8_t ResetAnsw=0x55;
uint8_t RxByte[9]={0,0,0,0,0,0,0,0,0};
volatile uint8_t Temperature=0;
....
ResetAnsw=TM_OneWire_Reset();
      TM_OneWire_WriteByte(0xcc); // skip ROM command
      TM_OneWire_WriteByte(0x44); // convert T command
      ONEWIRE_OUTPUT_PP();
      ONEWIRE_HIGH();
      HAL_Delay(800); // at least 750 ms for the default 12-bit resolution
      ResetAnsw=TM_OneWire_Reset();
      TM_OneWire_WriteByte(0xcc); // skip ROM command
      TM_OneWire_WriteByte(0xbe); // read scratchpad command    
        for(uint8_t t=0;t<10;t++) RxByte[t]=TM_OneWire_ReadByte();
        Temperature = ((RxByte[1]&7)<<4)|(RxByte[0]>>4);


Но на самом деле дъявол кроется в этих функциях:
CODE
void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

void MX_GPIO_P10_Init(uint8_t PC10_Mode) // 0- Out OD, 1- Out PP, 2- In
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */
__GPIOD_CLK_ENABLE();
__GPIOC_CLK_ENABLE();

HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);

/*Configure GPIO pin : PC10 */
if(PC10_Mode==0) {GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; }
else if(PC10_Mode==1) {GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;}
else if(PC10_Mode==2) {GPIO_InitStruct.Mode = GPIO_MODE_INPUT;}


GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

uint8_t TM_OneWire_Reset(void) {
uint8_t i;

ONEWIRE_OUTPUT_OD();
ONEWIRE_LOW();
ONEWIRE_DELAY(480);
ONEWIRE_HIGH();
ONEWIRE_INPUT();
ONEWIRE_DELAY(70);
i = ONEWIRE_READPIN();
ONEWIRE_DELAY(410);
ONEWIRE_OUTPUT_OD();
return i;
}

void TM_OneWire_WriteByte(uint8_t byte) {
uint8_t i = 8;

ONEWIRE_OUTPUT_OD();
for(i=0;i<8;i++) {
if((byte&0x01)==0x01) {
ONEWIRE_LOW(); // Drive bus low
ONEWIRE_DELAY(2);
ONEWIRE_HIGH();
ONEWIRE_DELAY(55); //sample time slot for the slave
//ONEWIRE_DELAY(2); //recovery time slot
}
else {
ONEWIRE_LOW(); // Drive bus low
ONEWIRE_DELAY(90);
ONEWIRE_HIGH();
ONEWIRE_DELAY(2); //recovery time slot
}
byte=byte>>1;
ONEWIRE_HIGH();
}
}

uint8_t TM_OneWire_ReadByte(void) {
uint8_t i = 8, byte = 0;

while (i--) {
ONEWIRE_OUTPUT_OD();
ONEWIRE_LOW();
ONEWIRE_DELAY(2);
ONEWIRE_INPUT();
ONEWIRE_DELAY(6);
byte >>= 1;
byte |= (ONEWIRE_READPIN() << 7);
ONEWIRE_DELAY(50);
}
return byte;
}


Буду ли ковыряться с UART - не знаю. Слишком много времени убил на этот датчик.

Сообщение отредактировал Herz - Jan 31 2016, 17:43
Go to the top of the page
 
+Quote Post
adnega
сообщение Jan 29 2016, 14:04
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Halfback @ Jan 29 2016, 16:52) *
Частично разобрался.
...
Буду ли ковыряться с UART - не знаю. Слишком много времени убил на этот датчик.

А самое интересное еще впереди (сделать работу по прерываниям, поддерживать несколько датчиков на шине с поиском ROM и т.п.).
Go to the top of the page
 
+Quote Post
k155la3
сообщение Jan 31 2016, 14:56
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(Halfback @ Jan 29 2016, 17:52) *
Частично разобрался.
Решил пока забить на UART и сделал долбатню пином. Все временные выдерки взял согласно даташиту на датчик. Всё четко как в аптеке. Свою задержку 1us замерял осциллом.
. . . .
Буду ли ковыряться с UART - не знаю. Слишком много времени убил на этот датчик.


Работа с датчиком в таком режиме предполагает отсутствие всех прерываний.
Возможно, чтобы не ограничиваться в этом, и "замутили" работу через UART.
Запретить прерывания можно только на время цикла обмена с DS18B20. цена вопроса пара миллисекунд (кажется)
И все будет феншуй.
Go to the top of the page
 
+Quote Post
adnega
сообщение Jan 31 2016, 17:30
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(k155la3 @ Jan 31 2016, 17:56) *
Запретить прерывания можно только на время цикла обмена с DS18B20. цена вопроса пара миллисекунд (кажется)
И все будет феншуй.

)))
Обычно такой подход подразумевает вызов функции get_temp(), которая со всеми задержками и ожиданиями преобразования длится под секунду.
Да, можно разрешать и запрещать прерывания внутри get_temp(), но это никак не поможет работе всему, что до и после get_temp().
Напомню, что у ТС контроллер, типа STM32... а такой подход у меня вызывает сильнейшее негодование))
Уверен, что есть куча библиотек для STM32, где используются UART, TIMER и/или DMA - нужно только хорошо поискать и/или написать самому.

PS. Я на паршивеньком STM32F030F4 делал эмулятор DS18B20, а это в разы сложнее мастера, да еще на таком "жирном" МК.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 1 2016, 05:16
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Halfback @ Jan 29 2016, 19:52) *
Решил пока забить на UART и сделал долбатню пином.

И причём там UART??? wacko.gif А почему не на SPI зацепили?
DS18B20 вроде по 1-Wire работают. Этот интерфейс легко эмулируется на одном таймере + GPIO.

Цитата(adnega @ Jan 29 2016, 20:04) *
А самое интересное еще впереди (сделать работу по прерываниям, поддерживать несколько датчиков на шине с поиском ROM и т.п.).

С таким подходом
Цитата
#define DELAY_1us() {__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP()
;\
...
это невозможно.

Цитата(adnega @ Jan 31 2016, 23:30) *
Напомню, что у ТС контроллер, типа STM32... а такой подход у меня вызывает сильнейшее негодование))
Уверен, что есть куча библиотек для STM32, где используются UART, TIMER и/или DMA - нужно только хорошо поискать и/или написать самому.
PS. Я на паршивеньком STM32F030F4 делал эмулятор DS18B20, а это в разы сложнее мастера, да еще на таком "жирном" МК.

Таких "программистов" гнать в шею надо из команды.
Go to the top of the page
 
+Quote Post
rx3apf
сообщение Feb 1 2016, 10:39
Сообщение #13


Гуру
******

Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047



Цитата(jcxz @ Feb 1 2016, 08:16) *
И причём там UART??? wacko.gif А почему не на SPI зацепили?
DS18B20 вроде по 1-Wire работают. Этот интерфейс легко эмулируется на одном таймере + GPIO.

И на UART тоже (в старых аппликухах от Dallas как раз через UART цепляли). В остальном - согласен.
Go to the top of the page
 
+Quote Post
k155la3
сообщение Feb 3 2016, 10:54
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(adnega @ Jan 31 2016, 20:30) *
)))
Обычно такой подход подразумевает вызов функции get_temp(), которая со всеми задержками и ожиданиями преобразования длится под секунду.
. . . . .


Да. Я забыл, что при полной разрядности по температуре преобразование 750 ms. sad.gif
Go to the top of the page
 
+Quote Post
Леонид Иванович
сообщение Feb 4 2016, 22:09
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986



Цитата(k155la3 @ Jan 31 2016, 18:56) *
Запретить прерывания можно только на время цикла обмена с DS18B20. цена вопроса пара миллисекунд (кажется)


Прерывания надо запрещать только в промежутке от окончания импульса сброса до момента поллинга "presence pulse" (это 75 мкс), а также от начала тайм-слота до считывания бита (это примерно 60 мкс). Остальное время прерывания могут как угодно растягивать процесс обмена - ни на что это не повлияет.


--------------------
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th August 2025 - 10:21
Рейтинг@Mail.ru


Страница сгенерированна за 0.01522 секунд с 7
ELECTRONIX ©2004-2016