Высказывания и цитаты:

…Спите бойцы, спите спокойным сном
Пусть вам приснятся нивы родные,
отчий далекий дом.
Пусть погибли вы в боях с врагами
Подвиг ваш к борьбе нас зовет
Кровью народной омытое знамя
Мы понесем вперед.

  • 02Дек

    Урок 5. Что меня заинтересовало в демо-прошивке — так именно отображение графических элементов, а именно окошек, похожих на Windows, графиков и картинок. Работая с этими элементами, мы можем делать удобные панели HMI (human-machine interface), которые будут интуитивно понятны любому человеку, и у которых не будет множества неизвестных кнопочек, лампочек и тумблеров.
    К счастью, для нас уже создали библиотеки графических примитивов, которые позволяют использовать buttons, checkbuttons, radiobuttons и другое в наших целях. Одной из таких библиотек является stm32_embedded_GUI_Library (размер около 10 Мб), которая включает в себя программу для Windows — ResourceEditorGUI и проекты с исходными кодами для микроконтроллера. О возможностях этой библиотеки, будет посвящена другая статья.

    Аналог графических элементов Windows я нашел и в других самоделках. С них мы и начнем, потому что любой элемент можно вытащить из одного проекта и вставить в другой, что очень удобно, потому что элементы можно добавлять по мере надобности.

    Первый графический элемент —  Button (кнопка).

    Я написал проект TouchPanel_rus_symbol.rar в Keil для платы Hy-Mini STM32 на основе примера из Урока №2. Итак, при подаче питания на дисплее появляется следующее меню с четырьмя кнопками и маленькой картинкой (качественное изображение мой телефон сделать не смог):

    IMG00671

    По нажатии на любую из кнопок  открывается новый экран. Choose color — выбираем цвет заднего фона, Start Game — управление движением квадратика на поле, Draw — рисование по точкам, Calibrate — калибровка Touch.

    А теперь расскажу как добавить в проект элемент Button. Открываем файл GLCD.h и добавляем в /* Private function prototypes */ строку

    void LCD_Button(uint16_t x, uint16_t y, uint16_t longx, uint16_t longy, uint8_t p, uint8_t* text, uint16_t ink, uint16_t bkcolor);

    где x — отступ слева в пикселях по горизонтали, y -по вертикали, longx и longy — ширина и высота кнопки. p — параметр, определяющий, нажата кнопка или нет. если не нажата = 0, если нажата = 1. Это необходимо для спецэффекта нажатие. text — надпись на кнопке, ink -цвет текста, bkcolor — цвет кнопки.

    В GLCD.c вставляем функцию
    void LCD_Button(uint16_t x, uint16_t y, uint16_t longx, uint16_t longy, uint8_t p, uint8_t* text, uint16_t ink, uint16_t bkcolor){
    int f;
    LCD_DrawLine(x+1, y, x+longx-1, y, ink ); /*horizontal alta externa*/
    LCD_DrawLine(x, y+1, x, y+longy, ink ); /*vertical izquierda externa*/
    LCD_DrawLine(x+1, y+longy, x+longx-1, y+longy, ink ); /*horizontal baja externa*/
    LCD_DrawLine(x+longx-1, y+longy-1, x+longx-1, y, ink ); /*vertical derecha externa*/
    for(f=1;f<longy;f++) { LCD_DrawLine(x+1, y+f, x+longx-1, y+f, bkcolor); }
    LCD_DrawLine(x+3,y+3, x+longx-3, y+3, ink); /*horizontal alta interna*/
    LCD_DrawLine(x+3,y+3, x+3, y+longy-2, ink); /*vertical izquierda interna*/
    LCD_DrawLine(x+3,y+longy-3, x+longx-3, y+longy-3, ink); /*horizontal baja interna*/
    LCD_DrawLine(x+longx-4,y+3, x+longx-4, y+longy-3, ink); /*vertical derecha interna*/
    if(p==0) /*botуn en estado normal*/
    {
    LCD_DrawLine(x+3,y+longy-4, x+longx-3, y+longy-4, ink); /*sombra horizontal interior baja*/
    LCD_DrawLine(x+longx-5,y+longy-3, x+longx-5, y+2, ink); /*sombra vertical interior derecha*/
    LCD_DrawLine(x+3,y+longy-2, x+longx-2, y+longy-2, ink); /*sombra horizontal baja*/
    LCD_DrawLine(x+longx-3,y+longy-2, x+longx-3, y+2, ink); /*sombra vertical derecha*/
    GUI_Text(x+4,y+(longy/2)-8, text, ink, bkcolor); /*texto normal*/
    }
    if(p==1) /*botуn es estado pulsado*/
    {
    LCD_DrawLine(x+2,y+4, x+longx-3, y+4, ink); /*sombra horizontal interior alta*/
    LCD_DrawLine(x+4,y+longy-3, x+4, y+2, ink); /*sombra vertical interior izquierda*/
    LCD_DrawLine(x+3,y+2, x+longx-3, y+2, ink); /*sombra horizontal alta*/
    LCD_DrawLine(x+2,y+longy-3, x+2, y+1, ink); /*sombra vertical izquierda*/
    GUI_Text(x+6,y+(longy/2)-6, text, ink, bkcolor); /*texto desplazado*/
    }
    }

    После чего в файле main.c можно добавить функцию
    void PrintDisplayALL(void){
    LCD_Button(20,40,200,30,0," Choose color ",Red,White); // красный текст, белый фон
    LCD_Button(20,80,200,30,0," Start Game ",Red,White);
    LCD_Button(20,120,200,30,0,"Draw",Red,White);
    LCD_Button(20,160,200,30,0,"Calibrate",Red,White); }

    и у нас появятся четыре кнопки. Хочу обратить внимание, что элемент Button использует два других элемента для себя  —  LCD_DrawLine и GUI_Text. Если их у Вас нет, то необходимо добавить их также. Все они есть в моем примере.

    Если наша кнопка просто будет находиться на экране, толку от нее не будет. Кнопка должна постоянно ожидать нажатие на нее. Опрос Touch всего экрана должен происходить постоянно, поэтому делаем опрос в цикле while (1).

    while (1)
    {
    p=LCD_TouchRead(&display); // если было нажатие =1, если не было =0
    x=display.x;
    y=display.y;
    if(p==1){ // если было нажатие
    // условие для того, чтобы определить, находится ли точка касания в пределах кнопки
    if((beb1==0)&&(x>20)&&(x<220)&&(y>40)&&(y<70)){beb1=1,oper=1;} // Choose color
    if((beb2==0)&&(x>20)&&(x<220)&&(y>80)&&(y<110)){beb2=1,oper=1;} // Start Game
    if((beb3==0)&&(x>20)&&(x<220)&&(y>120)&&(y<150)){beb3=1,oper=1;} // About рисование будет
    if((beb4==0)&&(x>20)&&(x<220)&&(y>160)&&(y<190)){beb4=1,oper=1;} // Calibrate
    // if((beb5==0)&&(x>120)&&(x<165)&&(y>200)&&(y<230)){beb5=1,oper=1;} // UP
    // if((beb6==0)&&(x>180)&&(x<225)&&(y>200)&&(y<230)){beb6=1,oper=1;} // Down
    if(oper==1) { // начало oper1
    // здесь реализуем эффект нажатия - кнопка перерисовывается в другом виде
    if (beb1==1) {LCD_Button(20,40,200,30,1," Choose color ", White, Red); } // Choose color
    if (beb2==1) {LCD_Button(20,80,200,30,1," Start Game ", White, Red); } // Start Game
    if (beb3==1) {LCD_Button(20,120,200,30,1,"Draw", White, Red);} // About
    if (beb4==1) {LCD_Button(20,160,200,30,1,"Calibrate", White, Red);} // Calibrate
    // if (beb5==1) {LCD_Button(120,200,45,30,0," UP ", White, Red);} // UP
    // if (beb6==1) {LCD_Button(180,200,45,30,0,"Down", White, Red);} // Down
    delay_ms(50); // задержка, чтобы разглядеть эффект нажатия, иначе мы его не заметим
    // новый экран калибровка
    if (beb4==1) {
    TouchPanel_Calibrate(1);
    PrintDisplayALL();
    delay_ms(1000);
    }
    // новый экран  рисование
    if (beb3==1) {
    LCD_Clear(Black);
    LCD_RectangleFill(110,300,20,20,0x0AFC);
    do {
    getDisplayPoint(&display, Read_Ads7846(), &matrix ) ; // получить точку
    TP_DrawPoint(display.x,display.y); // нарисовать точку
    x=display.x; y=display.y;
    }
    while (!((x>110)&&(x<130)&&(y>300)&&(y<320)));
    LCD_Clear(my_color);
    PrintDisplayALL();
    delay_ms(250);
    } // как коснется квадратика так выход из программы
    // новый экран  палитра цветовая. Цветовые переходы здесь резкие, дело в том, что в RGB кодирование цвета происходит немного по-другому принципу, это добавим в следующий раз.
    // новый экран  Выбор цвета
    if (beb1==1) {
    LCD_Clear(Black);
    GUI_Text(30,20,"Choose a back colour",White,Black);
    // начальное значение цвета, рисуем цвета в прямоугольнике от 0000 до FFFF
    ir=0;
    for(y1=40;y1<294;y1++) //
    {
    for(x1=10;x1<230;x1++) //
    {
    ir=ir+1;
    LCD_SetPoint(x1,y1,ir);
    }
    }
    // делаем запрос - получить цвет
    do {
    getDisplayPoint(&display, Read_Ads7846(), &matrix ) ; // получить точку
    x=display.x; y=display.y;
    }
    while (!((x>10)&&(x<230)&&(y>40)&&(y<294)));
    // теперь получаем цвет, который выбрали для этого зная координаты находим цвет
    ir=((y-40)*294+(x-10));
    my_color=ir;
    LCD_RectangleFill(110,300,20,20,my_color);
    delay_ms(2000);
    LCD_Clear(my_color);
    PrintDisplayALL();
    } // конец выбора цвета
    // новый экран Игра
    if (beb2==1)
    { LCD_Clear(Black);
    LCD_RectangleFill(20,20,200,100,my_color); //
    // здесь кнопки
    PrintPoint(xp,yp,Red);
    LCD_Button(20,190,45,30,0," UP ",Red,White); //
    LCD_Button(75,190,45,30,0,"Down",Red,White);
    LCD_Button(130,190,45,30,0,"Left",Red,White);
    LCD_Button(185,190,45,30,0,"Right",Red,White);
    LCD_RectangleFill(110,300,20,20,0x0AFC);
    m1: p=LCD_TouchRead(&display);
    x=display.x;
    y=display.y;
    if (p==1)
    {
    if((eeb1==0)&&(x>20)&&(x<65)&&(y>190)&&(y<220)){eeb1=1,oper2=1;}
    if((eeb2==0)&&(x>75)&&(x<120)&&(y>190)&&(y<220)){eeb2=1,oper2=1;}
    if((eeb3==0)&&(x>130)&&(x<175)&&(y>190)&&(y<220)){eeb3=1,oper2=1;}
    if((eeb4==0)&&(x>185)&&(x<230)&&(y>190)&&(y<220)){eeb4=1,oper2=1;}
    if ((x>110)&&(x<130)&&(y>300)&&(y<320)) {over=1;}
    if (oper2==1)
    {
    if(eeb1==1){LCD_Button(20,190,45,30,1," UP ", White, Red);}
    if(eeb2==1){LCD_Button(75,190,45,30,1,"Down", White, Red);}
    if(eeb3==1){LCD_Button(130,190,45,30,1,"Left", White,Red);}
    if(eeb4==1){LCD_Button(185,190,45,30,1,"Right", White,Red);}
    if((eeb1==1)&&(yp>20)){PrintPoint(xp,yp,my_color);yp=yp-2;PrintPoint(xp,yp,Red);}
    if((eeb2==1)&&(yp<120)){PrintPoint(xp,yp,my_color);yp=yp+2;PrintPoint(xp,yp,Red);}
    if((eeb3==1)&&(xp>20)){PrintPoint(xp,yp,my_color);xp=xp-2;PrintPoint(xp,yp,Red);}
    if((eeb4==1)&&(xp<220)){PrintPoint(xp,yp,my_color);xp=xp+2;PrintPoint(xp,yp,Red);}
    oper2=0;
    } }
    if (p==0)
    {
    if(eeb1==1){LCD_Button(20,190,45,30,0," UP ",Red,White);eeb1=0;} // черный текст белый фон
    if(eeb2==1){LCD_Button(75,190,45,30,0,"Down",Red,White);eeb2=0;}
    if(eeb3==1){LCD_Button(130,190,45,30,0,"Left",Red,White);eeb3=0;}
    if(eeb4==1){LCD_Button(185,190,45,30,0,"Right",Red,White);eeb4=0;}
    }
    if (over==0) {goto m1;} // все верно
    LCD_Clear(my_color);
    PrintDisplayALL();
    over=0;
    delay_ms(250);
    } // конец игры меню2
    } // конец операции oper из меню1
    } // конец если было нажатие из меню1
    if (p==0) {beb1=0; beb2=0; beb3=0; beb4=0;}
    }

    Для контроля за тем, какой экран в данный момент активный, используются флаги состояния beb, eeb и другие, без них реализовать экранный режим бы не получилось.

1 комментарий

WP_Cloudy
  • Сергей пишет:

    Чем вы конвертировали картинку?
    Все перепробовал,но такого формата не получил.
    На экране только цветные полоски.
    Файл pictures.h

Ваш ответ

Внимание: Модератор оставляет за собой право редактировать или удалять комментарии.

Подтвердите, что Вы не бот — выберите человечка с поднятой рукой: