Cледуюшим шагом моих эксперементов стал датчик ds18b20, а именно вывод его показаний на экран встроенного LCD.
Как я уже писал в предыдущей статье ,на плате STM32L-DISСOVERY, свободных от "board function" пинов (Free I/O) - 5 шт (PA5,PA11,PA12,PC13,PD2) ,причем PA11,PA12 аппаратный USB.Я решил подключать датчик на PD2,этот пин согласно мануала толерантен к 5В.Впрочем забегу наперед ,схема работает как от 5В,так и от 3,3В.
В сети есть библиотеки для работы с этими датчиками,но они в основном "заточены" под использование USART.Я же поставил перед собой задачу использовать для вывода информации с датчика - LCD, который идет в комплекте с STM32L-DISСOVERY.А при его использовании, на плате просто не остается свободного USART,все доступные пины заняты на работу с LCD.
На одном из китайских сайтов была найдена подходящая библиотека,и я решил адаптировать ее под свою задачу и под stm32l .Библиотекa имеет два файла : DS18B20.c и DS18B20.h ( скачать).В файле DS18B20.c прописываем пин и порт на который подключен ds18b20:
#define DS_PORT GPIOD //DS18B20 разъем
#define DS_DQIO GPIO_Pin_2 //GPIOD2
#define DS_RCC_PORT RCC_AHBPeriph_GPIOD
Вообще из всего порта D в нашем микроконтролере физически присутствует только пин PD2 .Поэтому я сконфигурировал все пины порта одинаково (выход с открытым стоком):
void DS18B20_Configuration(void)
{
RCC_AHBPeriphClockCmd(DS_RCC_PORT, ENABLE);
//================ GPIOD CONFIGURATION ================
GPIOD->MODER=0x55555555;
GPIOD->OTYPER=0x0000FFFF;
GPIOD->PUPDR=0x00000000;
GPIOD->OSPEEDR=0xFFFFFFFF;
GPIOD->AFR[0]=0x00000000;
GPIOD->AFR[1]=0x00000000;
}
При использовании других пинов .естественно нужно вносить изменения в void DS18B20_Configuration(void).
В стандартном наборе библиотек для STM32L152 идут библиотечные файлы
stm32l1xx_lcd.h и stm32l1xx_lcd.c.
Эти файлы были подключены к проекту без изменений. В них расположены макросы для настроек индикатора, а также функция записи значений в ячейки памяти, отведенные под данные для LCD. Также были использованы библиотечные файлы из демонстрационной программы для STM32L-DISCOVERY
stm32l_discovery_lcd.h и stm32l_discovery_lcd.c.
Здесь как раз и определены массивы значений для букв и цифр (алфавит, естественно, латинский). А также функция, конвертирующая числа из этого массива в другие значения, которые зависят от того, в какую позицию индикатора символ нужно вывести (подробней - http://chipspace.ru/stm32l-discovery-lcd-2/).
Основной проблемой ,для меня ,оказалось вывести значение датчика float на экран LCD при помощи библиотеки stm32l_discovery_lcd.Решение было найдено в разбивке значения float на целую и дробную части (десятая доля):
int t_int = t; //здесь будет целая часть
int t_float = ((t*10)-(t_int*10)); //здесь будет дробная часть
int t_str = (t_int*10) + t_float;
t_str = t_str*100;
Полный текст программы:
#include "stm32l1xx_conf.h"
#include "stm32l1xx.h"
#include "lcd_gpio_init.h"
#include "stm32l_discovery_lcd.h"
uint16_t strDisp[6]; //Массив символов для вывода на дисплей
static volatile float t;
void ds18b20_init(void);
float ds18b20_read(void);
void convert_into_char(uint32_t number, uint16_t *p_tab);
int main(void)
{
gpio_init(); //Настройка портов ввода/вывода под работу с LCD
lcd_init(); //Здесь конфигурируем LCD контроллер
ds18b20_init();
while(1)
{
t = ds18b20_read();
int t_int = t; //здесь будет целая часть
int t_float = ((t*10)-(t_int*10)); //здесь будет дробная часть
int t_str = (t_int*10) + t_float;
t_str = t_str*100;
/*Конвертируем результат преобразования в массив символов.
Результат сохраняется в элементах массива 1..4*/
convert_into_char(t_str, strDisp);
strDisp[3] = ' '; //Третье знакоместо дисплея оставляем пустым
strDisp[4] = '°'; //знакт "градус"
strDisp[5] = 'C'; //В последнее знакоместо дисплея выводим букву C
strDisp[1] |= DOT; //Десятичная точка
/*Следующая функция выводит на экран массив strDisp. Еще она позволяет выводить на
экран десятичную точку или двоеточие в любой позиции экрана.
В данном случае команда strDisp[1] |= DOT выводит точку после второй цифры*/
LCD_GLASS_DisplayStrDeci(strDisp);
}
}
//************************************************************************************************
//Здесь обрабатывается неудачный результат функций assert_param() из стандартных библиотек
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{
}
}
#endif
//***********************************************************************
//Эта функция конвертирует результат преобразования в массив символов
void convert_into_char(uint32_t number, uint16_t *p_tab)
{
uint16_t units=0, tens=0, hundreds=0, thousands=0, misc=0;
units = (((number%10000)%1000)%100)%10;
tens = ((((number-units)/10)%1000)%100)%10;
hundreds = (((number-tens-units)/100))%100%10;
thousands = ((number-hundreds-tens-units)/1000)%10;
misc = ((number-thousands-hundreds-tens-units)/10000);
*(p_tab+4) = units + 0x30;
*(p_tab+3) = tens + 0x30;
*(p_tab+2) = hundreds + 0x30;
*(p_tab+1) = thousands + 0x30;
*(p_tab) = misc + 0x30;
}
В итоге получаем такую картинку
Проект для Em::Blocks 2.20. - http://radiomanoff.at.ua/load/ds18b20_lcd/1-1-0-23