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

 
 
> Странное поведение 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
 
Start new topic
Ответов
Halfback
сообщение Jan 29 2016, 13:52
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 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
k155la3
сообщение Jan 31 2016, 14:56
Сообщение #3


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

Группа: Свой
Сообщений: 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
Леонид Иванович
сообщение Feb 4 2016, 22:09
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 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
jcxz
сообщение Feb 5 2016, 06:09
Сообщение #5


Гуру
******

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



Цитата(Леонид Иванович @ Feb 5 2016, 04:09) *
Прерывания надо запрещать только в промежутке от окончания импульса сброса до момента поллинга "presence pulse" (это 75 мкс), а также от начала тайм-слота до считывания бита (это примерно 60 мкс). Остальное время прерывания могут как угодно растягивать процесс обмена - ни на что это не повлияет.

За 75 или 60 мкс у Вас успеет потеряться к примеру один байт в UART-е работающем без FIFO на скорости 230400.
Прерывания вообще запрещать не нужно. Вся работа идёт в ISR. Процесс приёма бита:
1.Мастер включает pull down шины; программирует таймер на выдержку 15 мкс; выходит из ISR.
2.Получив прерывание таймера: выключает pull down шины; программирует таймер в режим capture с прерыванием/защёлкиванием значения таймера от фронта сигнала на шине; также программируется таймер на отслеживание таймаута
(на случай если удалённая сторона померла или линия залипла в "pull down"); выходит из ISR.
3.Получив прерывание таймера (таймаут): детектирует состояние ошибки обмена с датчиком - завершает процедуру обмена; выходит из ISR.
4.Получив прерывание таймера (обнаружен фронт на шине): считывает защёлкнутое значение таймера, вычисляет прошедшее время - определяет значение бита, сохраняет его; декрементирует счётчик оставшихся бит, если не 0 - программирует таймер на выдержку интервала времени до начала след. бита согласно требуемой и допустимой скорости обмена по шине; выходит из ISR.
5.Переход к п.1.

Всё! Ни одного запрета прерывания! Тем более на огромные интервалы порядка десятков мкс.
Можно немного упростить алгоритм, если не использовать режим capture таймера, а работать на обычных выдержках с принятием решений по границам состояний бит '0' и '1'. Но правильнее будет с capture.
Алгоритм передачи ещё проще, даже описывать смысла нет.
Go to the top of the page
 
+Quote Post
Леонид Иванович
сообщение Feb 5 2016, 10:55
Сообщение #6


Местный
***

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



Цитата(jcxz @ Feb 5 2016, 09:09) *
За 75 или 60 мкс у Вас успеет потеряться


Есть множество проектов, где запрещение прерываний на десятки мкс не является критичным. Тогда можно делать чисто программную реализуцию 1-Wire, которая намного проще для понимания, чем вариант с таймером.


--------------------
Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 5 2016, 16:22
Сообщение #7


Гуру
******

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



Цитата(Леонид Иванович @ Feb 5 2016, 16:55) *
Есть множество проектов, где запрещение прерываний на десятки мкс не является критичным. Тогда можно делать чисто программную реализуцию 1-Wire, которая намного проще для понимания, чем вариант с таймером.

Здесь раздел для начинающих. Т.е. - для тех кто должен учиться. Учиться делать правильно. Чтобы это потом можно было использовать в других проектах, наращивать функциональность проектов добавляя новые интерфейсы например и функции.
Да и опыта надо набираться начинающим. Как раз вот на таких примитивных интерфейсах это и можно делать.
Я считаю - если сейчас он делает тяп-ляп, лишь бы кое-как, то и потом с него толка не будет.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Halfback   Странное поведение DS18b20   Jan 27 2016, 17:45
- - k155la3   Насколько мне не изменяет (?) память, DS18B20 рабо...   Jan 28 2016, 07:13
- - adnega   Цитата(Halfback @ Jan 27 2016, 20:45) Про...   Jan 28 2016, 07:28
- - Halfback   Спасибо что откликнулись. Тайминги на соответствие...   Jan 28 2016, 08:33
|- - adnega   Цитата(Halfback @ Jan 28 2016, 11:33) Что...   Jan 28 2016, 08:48
- - AHTOXA   Цитата(Halfback @ Jan 27 2016, 22:45) Для...   Jan 28 2016, 10:13
- - k155la3   Вот подвернулось тут. Работа с DS18B20 По ссылке, ...   Jan 29 2016, 06:27
|- - adnega   Цитата(Halfback @ Jan 29 2016, 16:52) Час...   Jan 29 2016, 14:04
||- - jcxz   Цитата(Halfback @ Jan 29 2016, 19:52) Реш...   Feb 1 2016, 05:16
||- - rx3apf   Цитата(jcxz @ Feb 1 2016, 08:16) И причём...   Feb 1 2016, 10:39
|- - adnega   Цитата(k155la3 @ Jan 31 2016, 17:56) Запр...   Jan 31 2016, 17:30
||- - k155la3   Цитата(adnega @ Jan 31 2016, 20:30) ))) О...   Feb 3 2016, 10:54
|- - Сергей Борщ   Цитата(jcxz @ Feb 5 2016, 08:09) Алгоритм...   Feb 5 2016, 07:50
|- - CrimsonPig   Цитата(jcxz @ Feb 5 2016, 16:22) Здесь ра...   Feb 5 2016, 16:39
|- - adnega   Цитата(CrimsonPig @ Feb 5 2016, 19:39) Мо...   Feb 5 2016, 18:55
|- - jcxz   Цитата(CrimsonPig @ Feb 5 2016, 22:39) Во...   Feb 6 2016, 09:15
- - ILYAUL   Самый простой способ работать с 1-wire через UART ...   Feb 9 2016, 16:49


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

 


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


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