|
Странное поведение DS18b20 |
|
|
|
Jan 27 2016, 17:45
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 14)
|
Jan 28 2016, 08:33
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 29 2016, 13:52
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 31 2016, 14:56
|
Профессионал
    
Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848

|
Цитата(Halfback @ Jan 29 2016, 17:52)  Частично разобрался. Решил пока забить на UART и сделал долбатню пином. Все временные выдерки взял согласно даташиту на датчик. Всё четко как в аптеке. Свою задержку 1us замерял осциллом. . . . . Буду ли ковыряться с UART - не знаю. Слишком много времени убил на этот датчик. Работа с датчиком в таком режиме предполагает отсутствие всех прерываний. Возможно, чтобы не ограничиваться в этом, и "замутили" работу через UART. Запретить прерывания можно только на время цикла обмена с DS18B20. цена вопроса пара миллисекунд (кажется) И все будет феншуй.
|
|
|
|
|
Jan 31 2016, 17:30
|
Гуру
     
Группа: Свой
Сообщений: 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, а это в разы сложнее мастера, да еще на таком "жирном" МК.
|
|
|
|
|
Feb 1 2016, 05:16
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Halfback @ Jan 29 2016, 19:52)  Решил пока забить на UART и сделал долбатню пином. И причём там UART???  А почему не на 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, а это в разы сложнее мастера, да еще на таком "жирном" МК. Таких "программистов" гнать в шею надо из команды.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|