HAL_UART_Receive_DMA(&HUARTx, ow_buf, num_bits);
HAL_UART_Transmit_DMA(&HUARTx, ow_buf, num_bits);
Передмова
![]() |
Макет |
Створюємо проект в CubeMX або CubeIDE
Запускаємо CubeIDE, обираємо свій мікроконтролер, або дошку. Даємо назву проекту, та налаштовуємо проект:![]() |
Налаштування проекту |
- RCC - тактуємось від зовнішнього кварцу "Crystal/Ceramic resonator";
- SYS - відладка по "Serial Wire";
- USART1 або USART3 - обираємо режим "Single Wire (Half-Duplex)" та додаємо канали DMA як для прийому так і для передачі, а також вмикаємо глобальні переривання "USART global interrupt";
- USART2 - за замовчуванням, для передачі даних температури на послідовний порт комп'ютера.
В файлі DallasTemperature.h за замовчуванням, на лінії 1-Wire йде пошук, максимум 5 сенсорів. Змінити можна в рядку:
#define ONEWIRE_MAX_DEVICES 5
Схема підключення
![]() |
Схема підключення |
Демо-код
/* USER CODE BEGIN Includes */ #include "OneWire.h" #include "DallasTemperature.h" /* USER CODE END Includes */
/* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int _write(int file, char *ptr, int len) { HAL_UART_Transmit(&huart2, (uint8_t *) ptr, len, HAL_MAX_DELAY); return len; } // function to print a device address void printAddress(CurrentDeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { printf("0x%02X ", deviceAddress[i]); } } /* USER CODE END 0 */
/* USER CODE BEGIN PV */ OneWire_HandleTypeDef ow; DallasTemperature_HandleTypeDef dt; /* USER CODE END PV */
В секцію 2 додаємо перевірку чи на лінії є якісь сенсори 1-Wire, взнаємо кількість підключених до лінії сенсорів, задаємо роздільну здатність сенсорів, та прочитаємо їхню адресу і поточну роздільну здатність:
/* USER CODE BEGIN 2 */ printf("[%8lu] Debug UART2 is OK!\r\n", HAL_GetTick()); OW_Begin(&ow, &huart3); if(OW_Reset(&ow) == OW_OK) { printf("[%8lu] OneWire devices are present :)\r\n", HAL_GetTick()); } else { printf("[%8lu] OneWire no devices :(\r\n", HAL_GetTick()); } DT_SetOneWire(&dt, &ow); // arrays to hold device address CurrentDeviceAddress insideThermometer; // locate devices on the bus printf("[%8lu] Locating devices...", HAL_GetTick()); DT_Begin(&dt); printf("[%8lu] Found %d devices.\r\n", HAL_GetTick(), DT_GetDeviceCount(&dt)); if (!DT_GetAddress(&dt, insideThermometer, 0)) printf("[%8lu] Unable to find address for Device 0\r\n", HAL_GetTick()); printf("[%8lu] Device 0 Address: ", HAL_GetTick()); printAddress(insideThermometer); printf("\r\n"); // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions) DT_SetResolution(&dt, insideThermometer, 12, true); printf("[%8lu] Device 0 Resolution: %d\r\n", HAL_GetTick(), DT_GetResolution(&dt, insideThermometer)); if (!DT_GetAddress(&dt, insideThermometer, 1)) printf("[%8lu] Unable to find address for Device 1\r\n", HAL_GetTick()); printf("[%8lu] Device 1 Address: ", HAL_GetTick()); printAddress(insideThermometer); printf("\r\n"); // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions) DT_SetResolution(&dt, insideThermometer, 12, true); printf("[%8lu] Device 1 Resolution: %d\r\n", HAL_GetTick(), DT_GetResolution(&dt, insideThermometer)); /* USER CODE END 2 */
Приклад розрахований для двох DS18B20 на одній лінії. Як у вас один сенсор, видаліть код для другого сенсора з індексом 1.
А в безкінечному циклі раз на 2 секунди будемо опитувати сенсори і виводити в послідовний порт отриману температуру:
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { // call DT_RequestTemperatures(&dt) to issue a global temperature // request to all devices on the bus printf("[%8lu] Requesting temperatures...", HAL_GetTick()); DT_RequestTemperatures(&dt); // Send the command to get temperatures printf("\r\n[%8lu] DONE\r\n", HAL_GetTick()); // After we got the temperatures, we can print them here. // We use the function ByIndex, and as an example get the temperature from the first sensor only. printf("[%8lu] Temperature for the device 1 (index 0) is: %.2f\r\n", HAL_GetTick(), DT_GetTempCByIndex(&dt, 0)); printf("[%8lu] Temperature for the device 2 (index 1) is: %.2f\r\n", HAL_GetTick(), DT_GetTempCByIndex(&dt, 1)); HAL_Delay(2000); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
Щоб функція "printf" могла виводити значення типу "float" потрібно відповідно налаштувати проект в CubeIDE, а саме додати ключ "-u _printf_float":
![]() |
Налаштування друку float |
І для Atolic TrueStudio обрати "NewLib standart":
![]() |
Налаштування для друку float |
Компілюємо, заливаємо. Запускаємо будь-яку термінальну програму і спостерігаємо:
![]() |
Приклад роботи двох датчиків на лінії |
Відео-посібник
Текст коду з відео:
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" #include "OneWire.h" #include "DallasTemperature.h" /* USER CODE END Includes */ /* USER CODE BEGIN PV */ OneWire_HandleTypeDef ow1; DallasTemperature_HandleTypeDef dt1; OneWire_HandleTypeDef ow2; DallasTemperature_HandleTypeDef dt2; /* USER CODE END PV */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int _write(int file, char *ptr, int len) { HAL_UART_Transmit(&huart2, (uint8_t *) ptr, len, HAL_MAX_DELAY); return len; } // function to print a device address void printAddress(CurrentDeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { printf("0x%02X ", deviceAddress[i]); } } /* USER CODE END 0 */ /* USER CODE BEGIN 2 */ printf("[%8lu] Debug UART2 is OK!\r\n", HAL_GetTick()); OW_Begin(&ow1, &huart1); OW_Begin(&ow2, &huart3); if(OW_Reset(&ow1) == OW_OK) { printf("[%8lu] OneWire 1 line devices are present :)\r\n", HAL_GetTick()); } else { printf("[%8lu] OneWire 1 line no devices :(\r\n", HAL_GetTick()); } if(OW_Reset(&ow2) == OW_OK) { printf("[%8lu] OneWire 2 line devices are present :)\r\n", HAL_GetTick()); } else { printf("[%8lu] OneWire 2 line no devices :(\r\n", HAL_GetTick()); } DT_SetOneWire(&dt1, &ow1); DT_SetOneWire(&dt2, &ow2); // arrays to hold device address CurrentDeviceAddress insideThermometer; // locate devices on the bus printf("[%8lu] 1-line Locating devices...\r\n", HAL_GetTick()); DT_Begin(&dt1); uint8_t numDevOneLine = DT_GetDeviceCount(&dt1); printf("[%8lu] 1-line Found %d devices.\r\n", HAL_GetTick(), numDevOneLine); printf("[%8lu] 2-line Locating devices...\r\n", HAL_GetTick()); DT_Begin(&dt2); uint8_t numDevTwoLine = DT_GetDeviceCount(&dt2); printf("[%8lu] 2-line Found %d devices.\r\n", HAL_GetTick(), numDevTwoLine); for (int i = 0; i < numDevOneLine; ++i) { if (!DT_GetAddress(&dt1, insideThermometer, i)) printf("[%8lu] 1-line: Unable to find address for Device %d\r\n", HAL_GetTick(), i); printf("[%8lu] 1-line: Device %d Address: ", HAL_GetTick(), i); printAddress(insideThermometer); printf("\r\n"); // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions) DT_SetResolution(&dt1, insideThermometer, 12, true); printf("[%8lu] 1-line: Device %d Resolution: %d\r\n", HAL_GetTick(), i, DT_GetResolution(&dt1, insideThermometer)); } for (int i = 0; i < numDevTwoLine; ++i) { if (!DT_GetAddress(&dt2, insideThermometer, i)) printf("[%8lu] 2-line: Unable to find address for Device %d\r\n", HAL_GetTick(), i); printf("[%8lu] 2-line: Device %d Address: ", HAL_GetTick(), i); printAddress(insideThermometer); printf("\r\n"); // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions) DT_SetResolution(&dt2, insideThermometer, 12, true); printf("[%8lu] 2-line: Device %d Resolution: %d\r\n", HAL_GetTick(), i, DT_GetResolution(&dt2, insideThermometer)); } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus printf("[%8lu] 1-line: Requesting temperatures...", HAL_GetTick()); DT_RequestTemperatures(&dt1); // Send the command to get temperatures printf("\r\n[%8lu] 1-line: DONE\r\n", HAL_GetTick()); printf("[%8lu] 2-line: Requesting temperatures...", HAL_GetTick()); DT_RequestTemperatures(&dt2); // Send the command to get temperatures printf("\r\n[%8lu] 2-line: DONE\r\n", HAL_GetTick()); for (int i = 0; i < numDevOneLine; ++i) { // After we got the temperatures, we can print them here. // We use the function ByIndex, and as an example get the temperature from the first sensor only. printf("[%8lu] 1-line: Temperature for the device %d (index %d) is: %.2f\r\n", HAL_GetTick(), i, i, DT_GetTempCByIndex(&dt1, i)); } for (int i = 0; i < numDevTwoLine; ++i) { // After we got the temperatures, we can print them here. // We use the function ByIndex, and as an example get the temperature from the first sensor only. printf("[%8lu] 2-line: Temperature for the device %d (index %d) is: %.2f\r\n", HAL_GetTick(), i, i, DT_GetTempCByIndex(&dt2, i)); } HAL_Delay(DT_MillisToWaitForConversion(DT_GetAllResolution(&dt1))); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */