дисплей чтоб не мешал фримастеру

This commit is contained in:
seklyuts 2024-08-23 13:36:06 +03:00
parent 09d1aafce3
commit aefcee53fb
4 changed files with 143 additions and 133 deletions

View File

@ -1,13 +1,12 @@
/*
* buttons.c
*
* Created on: 15 авг. 2024 г.
* Created on: 15 <EFBFBD><EFBFBD><EFBFBD>. 2024 <EFBFBD>.
* Author: sedov
*/
#include "buttons.h"
#include "f28x_project.h"
#include "i2c_init.h"
#include "vector.h"
#include "pwm_init.h"
@ -26,10 +25,10 @@ typedef enum {
MENU_TEMP,
MENU_DIAKONT,
MENU_STATUS,
MENU_ITEMS_COUNT // Количество пунктов меню
MENU_ITEMS_COUNT //количество пунктов не должно превышть 16
} MenuItem;
// Глобальная переменная для хранения текущего пункта меню
// Переменная для хранения текущего пункт
MenuItem currentMenuItem = MENU_START;
__interrupt void buttonclik_isr(void)
@ -40,26 +39,26 @@ __interrupt void buttonclik_isr(void)
}
int buttonsRead(){
int err1,err2;
err1=I2CWrite(0x25, 0, 0, false, &Button_Sost); // Перед чтением всегда должна быть запись
err2=I2CRead(0x25, 1, true, &Button_Sost); // Читаем состояние порта
err1=I2CWrite(0x25, 0, 0, false, &Button_Sost); //Для чтения с расширителя порта необходимо отправить пустышку
err2=I2CRead(0x25, 1, true, &Button_Sost); // Отправка запроса сотояния
if(err1 != 0 || err2 != 0){
return 1;
}else{
return 0;
}
}
//Функция нстройки расширителя интерфейса
void buttonsInit(void) {
uint16_t Conf0 = 0xFE;
uint16_t Conf1 = 0xFF;
I2CWrite(0x25, 6, 1, true, &Conf1); // Конфигурирование кнопок на вход
I2CWrite(0x25, 6, 1, true, &Conf1); // настраиваем расширитель
I2CWrite(0x25, 7, 1, true, &Conf1);
I2CWrite(0x25, 0, 0, false, &Button_Sost); // Перед чтением всегда должна быть запись
I2CRead(0x25, 1, true, &Button_Sost); // Читаем состояние порта
I2CWrite(0x25, 0, 0, false, &Button_Sost); // <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
I2CRead(0x25, 1, true, &Button_Sost); // читаем кнопки
// Настройка прерывания XINT3
// инициализируем внешее ппрерывание XINT3
EALLOW;
PieVectTable.XINT3_INT = &buttonclik_isr;
IER |= M_INT12;
@ -73,53 +72,55 @@ void buttonsInit(void) {
int buttonsDisp(){
if(buttonClik!=0){
//читаем состояние кнопок
//проверка на нажати кнопки
if(buttonsRead()){
//обработка ошибки чтения
//если кнопка не нажата то выходим т.к ничего нчего отобразить
return 1;
}
Button_Sost=Button_Sost&0xF;
switch(Button_Sost){
case 0xD:
case 0xD:// кнопка выбора пункта
if(button < 0XFF)
button+=0XFF;//ПУСК
button+=0XFF;
break;
case 0xB:
case 0xB://кнопка возврата в меню
if(button >= 0XFF)
button-=0XFF;//СТОП
button-=0XFF;
break;
case 0x7:
case 0x7://нопка перехода по меню вверх
if(button < 0XFF){
button++;//ВЕРХ
button++;
if(button>MENU_ITEMS_COUNT-1){
button=0;
}}
break;
case 0xE:
case 0xE://кнопка перехода по мню вниз
if(button < 0XFF)
button--;//ВЕРХ
button--;
if(button==0xFFFF){
button=MENU_ITEMS_COUNT-1;
}
break;
default:
//несколько кнопок нажали
}
SSD1306_Fill(SSD1306_COLOR_BLACK);
Button_Sost=0;
buttonClik--;
currentMenuItem=button;
SSD1306_Fill(SSD1306_COLOR_BLACK);// затираем старое меню
Button_Sost=0;// обнуляем состояние
buttonClik--;//сбрасываем флаг необходимости обработать кнопку
currentMenuItem=button;//устанавливаем выбранную функцию
}
}
//диспетчер отображения
int ScreenDisp(){
static uint16_t oldbutton=0xFFF;
if(button<=0xFF)
MenuBilder();
if(oldbutton!=button)
SSD1306_UpdateScreen();
if(oldbutton!=button){// обнавляем меню только когода нажата кнопка
if(button<=0xFF)
MenuBilder();//построение меню
SSD1306_UpdateScreen();}//отображение меню
oldbutton=button;
MenuDisp();
MenuDisp();//вывод функций
}
//Диспетчер функций меню
void MenuDisp(){
switch(button){
case 0+0xFF:
@ -214,31 +215,32 @@ void MenuDisp(){
}
}
static uint16_t topItem;
//функция построения меню
void MenuBilder(void) {
uint16_t i,yPos;
static uint16_t buff;
char tempStr[5];
topItem = (uint16_t)currentMenuItem;// Верхний видимый пункт
if (currentMenuItem > 0 && (topItem-buff)==1) {
topItem = (uint16_t)currentMenuItem;// в начальнм состоянии всегда выбран 1 пункт меню и он всегда вверху
if (currentMenuItem > 0 && (topItem-buff)==1) {//выбранный пункт +1 от начального
topItem = currentMenuItem - 1;
}else if (currentMenuItem > 0 && (topItem-buff)==2){
topItem = currentMenuItem - 2;
}else if (currentMenuItem > 0 && (topItem-buff)==2){//выбранный пункт +2 от начального
topItem = currentMenuItem - 2;//свдвигаем начальный пункт
}
buff =topItem;
// Очищаем экран
// очищаем изображение
SSD1306_Fill(SSD1306_COLOR_BLACK);
// Отрисовка заголовка
// Заголовок
SSD1306_DrawFilledRectangle(0, 0, 128, 10, SSD1306_COLOR_WHITE);
SSD1306_GotoXY(30, 1);
SSD1306_Puts("START MENU", &Font_7x10, SSD1306_COLOR_BLACK);
// Отрисовка пунктов меню
// построение 4 пунктов меню
for ( i = 0; i < 4 && (topItem + i) < MENU_ITEMS_COUNT; i++) {
yPos = 13 + i*13; // Вертикальная позиция пункта
yPos = 13 + i*13; // расчет позиции текущего пункта
// Выделение выбранного пункта
// построение рамки пунктов
if (topItem + i == currentMenuItem) {
SSD1306_DrawFilledRectangle(0, yPos, 128, 13, SSD1306_COLOR_WHITE);
} else {
@ -247,20 +249,20 @@ void MenuBilder(void) {
if(yPos==52){
yPos-=2;
}
// Вывод номера пункта
// Отрисовка нумерации
SSD1306_GotoXY(5, yPos + 3);
// Используем sprintf для преобразования числа в строку
// Преобразование числа в строку "вручную"
// Перевод чисел в строки
uint8_t num = topItem + i + 1;
tempStr[0] = '0' + (num / 10); // Десятки
tempStr[1] = '0' + (num % 10); // Единицы
tempStr[2] = '\0'; // Нуль-терминатор
tempStr[0] = '0' + (num / 10);
tempStr[1] = '0' + (num % 10);
tempStr[2] = '\0';
if (topItem + i == currentMenuItem) {
SSD1306_Puts(tempStr, &Font_7x10, SSD1306_COLOR_BLACK);
}else
SSD1306_Puts(tempStr, &Font_7x10, SSD1306_COLOR_WHITE);
SSD1306_GotoXY(20, yPos + 3); // Сдвиг для названия пункта
SSD1306_GotoXY(20, yPos + 3);
//Отрисовка текста в пункты меню
switch (topItem + i) {
case MENU_START:
SSD1306_Puts(" START", &Font_7x10, topItem + i == currentMenuItem ? SSD1306_COLOR_BLACK : SSD1306_COLOR_WHITE);

View File

@ -1,7 +1,20 @@
#ifndef SRC_BUTTONS_H_
#define SRC_BUTTONS_H_
#include "f28x_project.h"
static uint16_t topItem;//переменная хранит верний пункт меню
int buttonsRead();
void buttonsInit(void);
int buttonsDisp();
int ScreenDisp();
void MenuDisp();
void MenuBilder(void);
#endif /* SRC_BUTTONS_H_ */

View File

@ -94,21 +94,20 @@ uint8_t SSD1306_Init(void) {
#define SSD1306_COLUMNADDR 0x21
#define SSD1306_PAGEADDR 0xB0
// функция установки коретки
void SSD1306_setPosition(uint8_t column, uint8_t page) {
if (column > SSD1306_WIDTH - 1) {
column = 0; // Ограничение столбца
column = 0;
}
if (page > 7) {
page = 0; // Ограничение страницы
page = 0;
}
SSD1306_WRITECOMMAND(0x20+column);
SSD1306_WRITECOMMAND(SSD1306_PAGEADDR+page);
SSD1306_WRITECOMMAND(0x20+column); // Начальный адрес столбца
SSD1306_WRITECOMMAND(SSD1306_PAGEADDR+page); // Начальный адрес страницы
// SSD1306_WRITECOMMAND(7); // Конечный адрес страницы
}
//Функция обнавления дисплея
void SSD1306_UpdateScreen(void) {
uint8_t page;
@ -117,10 +116,9 @@ void SSD1306_UpdateScreen(void) {
for (page = 0; page < 8; page++) {
SSD1306_WRITECOMMAND(0x10);
SSD1306_WRITECOMMAND(0x00);
for (column = 0; column < SSD1306_WIDTH; column++) { //
SSD1306_setPosition(column, page); // Начало столбца - 0, страница - m
// Запись данных в буфер дисплея
I2C_TXdata[0] = 0x40; // Байт управления: данные
for (column = 0; column < SSD1306_WIDTH; column++) {
SSD1306_setPosition(column, page);
I2C_TXdata[0] = 0x40; // Команда на запись данных
for ( i = 0; i < SSD1306_WIDTH; i++) {
I2C_TXdata[i + 1] = SSD1306_Buffer[SSD1306_WIDTH*page + i];
}
@ -129,28 +127,7 @@ void SSD1306_UpdateScreen(void) {
}
}
}
void SSD1306_UpdateScreenАFAST(void) {
uint8_t page;
uint8_t column;
uint8_t data_bytes = SSD1306_WIDTH / 8;
int i;
for (page = 0; page < 1; page++) {
SSD1306_WRITECOMMAND(0x10);
SSD1306_WRITECOMMAND(0x00);
for (column = 0; column < SSD1306_WIDTH-60; column++) { //
SSD1306_setPosition(column+60, page); // Начало столбца - 0, страница - m
// Запись данных в буфер дисплея
I2C_TXdata[0] = 0x40; // Байт управления: данные
// Заполнить буфер I2C данными из буфера дисплея
I2C_TXdata[0] = 0x40; // Команда записи данных
I2C_TXdata[1] = SSD1306_Buffer[SSD1306_WIDTH*page + column];
I2CWriteOLED(I2C_SLAVE_ADDRESS, 2, true);
}
}
}
//Функция отражения изображения
void SSD1306_ToggleInvert(void) {
uint16_t i;
@ -162,7 +139,7 @@ void SSD1306_ToggleInvert(void) {
SSD1306_Buffer[i] = ~SSD1306_Buffer[i];
}
}
//Функция затирания дисплея базовым цветом
void SSD1306_Fill(SSD1306_COLOR_t color) {
/* Set memory */
memset(SSD1306_Buffer, (color == SSD1306_COLOR_BLACK) ? 0x00 : 0xFF, sizeof(SSD1306_Buffer));
@ -176,9 +153,8 @@ void SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color) {
color = (SSD1306_COLOR_t)!color;
}
// Правильно вычисляем индекс байта в буфере
uint16_t byteIndex = x + (y / 8) * SSD1306_WIDTH;
// Правильно вычисляем индекс бита в байт
uint8_t bitIndex = y % 8;
if (color == SSD1306_COLOR_WHITE) {
@ -250,30 +226,9 @@ char SSD1306_Putc(char ch, FontDef_t* Font, SSD1306_COLOR_t color) {
/* Return character written */
return ch;
}
void reverseString(char *str) {
if (str == NULL) { // Проверка на NULL указатель
return;
}
char *end = str; // Указатель на конец строки
while (*end) {
end++;
}
end--; // Перемещаем указатель на последний символ строки
char temp;
while (str < end) {
temp = *str; // Меняем местами символы
*str = *end;
*end = temp;
str++;
end--;
}
}
char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color) {
/* Write characters */
// reverseString(str);
while (*str) {
/* Write character by character */
if (SSD1306_Putc(*str, Font, color) != *str) {
@ -655,16 +610,16 @@ void I2CWriteOLED(uint16_t slaveAddr, uint16_t byteCount, bool sendStopCondition
}
}
//uint16_t PWM_Vent1;
//Функцмя перевода Unsigned long в символы
char* ulongToStr(unsigned long num, char* buffer) {
unsigned long startnum=num;
if (num == 0) {
*buffer++ = '0';
*buffer++ = '0'; // Добавляем нуль-терминатор
*buffer++ = '0'; // если 0 то выводим 00
return buffer;
}
char temp[10]; // Буфер для временного хранения цифр
char temp[10]; //переменная для вывода строки
int i = 0;
while (num > 0) {
@ -674,30 +629,29 @@ char* ulongToStr(unsigned long num, char* buffer) {
if(startnum<=9){
*buffer++ = '0';
}
// Копируем цифры в обратном порядке в основной буфер
//выгружаем сисволы чисел
while (i > 0) {
*buffer++ = temp[--i];
}
*buffer = '\0'; // Добавляем нуль-терминатор
*buffer = '\0';
return buffer;
}
// Функция для отображения времени с момента запуска
// Возвращает true, если время было обновлено, иначе false
bool displayUptime(void) {
static unsigned long lastDisplayedTime = 0; // Последнее отображённое время
// Проверяем, нужно ли обновлять дисплей
bool displayUptime(void) {
static unsigned long lastDisplayedTime = 0; //старое время
// если мы сюда попали а секунда не прошла то выходим
if (uptimeSeconds == lastDisplayedTime) {
return false; // Время не изменилось
return false;
}
// Время изменилось, обновляем дисплей
//переводим время из секунд в привычное представление
unsigned long hours = uptimeSeconds / 3600;
unsigned int minutes = (uptimeSeconds % 3600) / 60;
unsigned int seconds = uptimeSeconds % 60;
// Формируем строку времени
char timeStr[16] = "UP ";
char *ptr = timeStr + 3;
ptr = ulongToStr(hours, ptr);
@ -710,19 +664,18 @@ bool displayUptime(void) {
SSD1306_Puts(timeStr, &Font_7x10, SSD1306_COLOR_WHITE);
}
// Запоминаем последнее отображённое время
// обновляем буффер времеи
lastDisplayedTime = uptimeSeconds;
SSD1306_UpdateScreen();
return true; // Время было обновлено
return true;
}
//Функция отображения температуры
void displayTemp(void) {
static int OldeqepTemperature = 0;
uint16_t temp, eqepTemperature = geteqepTemperature();
temp= eqepTemperature;
char temp_str[11];
//int seconds = 30; // Пример значения секунд
// Заполняем первые 6 символов вручную
temp_str[0] = 'T';
temp_str[1] = 'E';
temp_str[2] = 'M';
@ -735,19 +688,17 @@ void displayTemp(void) {
temp_str[9] = ' ';
temp_str[10] = ' ';
// Заполняем последние 2 символа секундами через цикл for
// Преобразуем сотни
// Флаг для отслеживания вывода цифр
int i=5;
bool startedOutput = false;
// Преобразование сотен
if (temp >= 100 || startedOutput) {
temp_str[i] = (temp / 100) + '0';
i++;
startedOutput = true;
}
temp %= 100;
// Преобразование десятков
if (temp >= 10 || startedOutput) {
temp_str[i] = (temp / 10) + '0';
startedOutput = true;
@ -756,7 +707,6 @@ void displayTemp(void) {
temp_str[i] = temp%10 + '0';
i++;
// Отображаем температуру
SSD1306_Puts(temp_str, &Font_11x18, SSD1306_COLOR_WHITE);
OldeqepTemperature = eqepTemperature;

View File

@ -16,7 +16,7 @@ typedef unsigned char uint8_t;
#define GPIO_PIN_SCLA 1 // GPIO number for I2C SCLA
//Макрос для отправки команды на OLED-дисплей
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> OLED-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define SSD1306_WRITECOMMAND(cmd) \
do { \
I2C_TXdata[0] = 0x00; \
@ -43,7 +43,52 @@ typedef enum {
SSD1306_COLOR_WHITE = 0x01 /*!< Pixel is set. Color depends on LCD */
} SSD1306_COLOR_t;
uint8_t SSD1306_Init(void);
int buttonsDisp();
int ScreenDisp();
void SSD1306_setPosition(uint8_t column, uint8_t page);
void SSD1306_UpdateScreen(void);
void SSD1306_ToggleInvert(void);
void SSD1306_Fill(SSD1306_COLOR_t color);
void SSD1306_DrawPixel(uint16_t x, uint16_t y, SSD1306_COLOR_t color);
void ssd1306_DrawBitmap(uint8_t x, uint8_t y, const unsigned char* bitmap, uint8_t w, uint8_t h, SSD1306_COLOR_t color) ;
void SSD1306_GotoXY(uint16_t x, uint16_t y);
char SSD1306_Putc(char ch, FontDef_t* Font, SSD1306_COLOR_t color);
void reverseString(char *str);
char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color);
void SSD1306_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, SSD1306_COLOR_t c);
void SSD1306_DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c);
void SSD1306_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, SSD1306_COLOR_t c);
void SSD1306_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color);
void SSD1306_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, SSD1306_COLOR_t color);
void SSD1306_DrawCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c);
void SSD1306_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, SSD1306_COLOR_t c);
void SSD1306_ON(void);
void SSD1306_OFF(void);
void I2CMaster_Init(uint16_t I2C_OwnAddress, uint16_t I2CSlave_Address);
void I2CWriteOLED(uint16_t slaveAddr, uint16_t byteCount, bool sendStopCondition) ;
char* ulongToStr(unsigned long num, char* buffer);
bool displayUptime(void);
void displayTemp(void);