В STM32F103C8T6 есть встроенный датчик температуры, (по видимому состоящий из двух диодов, включенных последовательно), который подключен к одному из каналов АЦП. Что-то похожее есть в некоторых моделях МК AVR.
Датчик не калиброванный и с одной и той же прошивкой, может показывать разную температуру в различных экземплярах МК. Поэтому для точных измерений (без калибровки) он не подходит, но как пример работы с АЦП подойдет.
В даташите написано про датчик не очень много. Это вся информация (поместилась на половине страницы даташита).
Для расчета температуры служит формула.
Temperature = (V_25-V_sense)/Avg_Slope + 25
Где V_25 и Avg_Slope это данные из даташита, а V_sense - измеренное напряжение на датчике температуры. Все напряжения должны быть в вольтах. Температура будет рассчитана в градусах по Цельсию.
После расчета данные будут выводится с МК через USB и отобраюатся в компьютерной программе. Почему так? Мне так проще, а заодно узнаем как работать с USB.
Создаем проекты EmBitz и STM32CubeMX как писал ранее.
Теперь в STM32CubeMX настроим периферию МК. Нужно выбрать тактовый генератор, настроить тактиование отдельных модулей МК, а так же сконфигурировать АЦП и USB.
На вкладке "Pinout" начнем по порядку сверху вниз конфигурировать модули. Открываем раздел ADC1 и выбираем канал датчика температуры.
Далее в разделе RCC нужно включить внешний высокочастотный резонатор.
Дальше в разделе USB нужно включить этот модуль.
Теперь нужно в разделе "USB Device" выбрать тип USB устройства. Нам нужен HID.
Скриншот всех изменений, который были сделаны.
Теперь переходим на вкладку "Clock configuration".
Задача проста. Настроить тактирование таким образом чтобы ядро и модули МК тактировались от внешнего резонатора. На модуль USB поступала частота 48 МГц, а так же на других модулях частота на была больше или меньше допустимой (подсвечивается красным).
Должно получится примерно так.
Теперь переходим на вкладку "Сonfiguration", где можно настроить выбранные модули.
Сначала настроим АЦП. Кликаем по кнопке "ADC1".
Откроется окно. Настраиваем все также.
Теперь кликаем по кнопке "USB_Device". Откроется окно.
То что находится в разделе "Basic parameters" изменять не нужно - подойдут параметры по умолчанию.
Параметр USBD_CUSTOM_HID_REPORT_DESC_SIZE это размер дескриптора HID_Report (о нем поговорим позже). Его размер в данной программе 33 байта.
Параметр USBD_CUSTOMHID_OUTREPORT_BUF_SIZE определяет размер буфера приема данных из компьютера.
Переходим на вкладку "Device descriptor". Настраиваем как на скриншоте.
Сохраняем настройки нажав на кнопку OK.
Теперь генерируем код и экспортируем его в EmBitz.
В EmBitz открываем файл "usbd_custom_hid_if.c", находящийся в папке Sources\Src проекта.
В нем находим массив CUSTOM_HID_ReportDesc_FS и вставляем в него код HID дескриптора. Должно получится.
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END = { /* USER CODE BEGIN 0 */ 0x06 , 0x00 , 0xFF, // Usage_page(vendor Defined Page 1) 0x09 , 0x01, // Usage(vendor Usage 1) 0xA1 , 0x02, // Collection(logical) // Описание конечной точки, типа Input 0x09 , 0x01, // Usage(pointer) 0x15 , 0x00, // Logical_minimum(0) 0x25 , 0xFF, // Logical_maximum(255) 0x75 , 0x08, // Report_size(8) 0x95 , 0x02, // Report_count(2) 0x81 , 0x02, // Input( , Var , Abs) // Описание конечной точки, типа Output 0x09 , 0x01, // Usage(pointer) 0x15 , 0x00, // Logical_minimum(0) 0x26 , 0xFF , 0, // Logical_maximum(255) 0x75 , 0x08, // Report_size(8) 0x95 , 0x02, // Report_count(2) 0x91 , 0x02, // Output(data , Var , Abs) /* USER CODE END 0 */ 0xC0 /* END_COLLECTION */ };
Сохраняем файл.
Теперь открываем файл main.c , находящийся в папке Sources\Src проекта.
В него нужно добавить идентификатор USB
USBD_HandleTypeDef *hUsbDevice_0;
а также константы из даташита, для датчика температуры.
#define tV_25 1.34f // Напряжение (в вольтах) на датчике при температуре 25 °C. #define tSlope 0.0043f // Изменение напряжения (в вольтах) при изменении температуры на градус. #define Vref 3.3f // Образцовое напряжение АЦП (в вольтах).
Теперь в функции main нужно до цикла while добавить объявление переменных.
int16_t Result=0; float temp;
а в цикле while, код чтения данных с АЦП, преобразования его в температуру и передачи в компьютер.
HAL_Delay(1000); // Задержка 1000 мс. HAL_ADC_Start(&hadc1); // Запуск АЦП. if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) // Ожидание завершения преобразования. { Result = HAL_ADC_GetValue(&hadc1); // Считывание с АЦП. temp = (float) Result/4096*Vref; // Напряжение в вольтах на датчике. temp = (tV_25-temp)/tSlope + 25; // Температура в градусах. temp = temp * 16; // Приводим данные к формату DS18B20. Result = (int16_t) temp; USBD_CUSTOM_HID_SendReport(hUsbDevice_0, &Result, 2); // Передача данных компьютеру. } HAL_ADC_Stop(&hadc1); // Остановка АЦП.
Программа написана. Как видим, большинство кода было сгенерировано программной STM32CubeMX. Нам же понадобилось добавить HID_Report, пару переменных и констант, а также несколько строк кода, считывающих температуру с АЦП и передающих ее в компьютер.
Программа написана так, что работает с компьютерной программой из другого проекта.
Скриншот программы.
Судя по начальной температуре, и по той что измерена через несколько минут работы, температура кристалла на 8 градусов выше температуры воздуха.
Файлы (программа для компьютера с исходником в папке PC). http://pure-basic.narod.ru/forum_files/ … rmoADC.zip
Разработка программы МК велась в EmBitz 0.42 и STM32CubeMX 4.14.0.