Практическая работа №03 (вывод графических примитивов)

28.10.2017 - Valentin Gubarev - Микроконтроллеры

Для выполнения практической работы потребуется отладочная плата 1986EvBrd_48_Rev3.

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

Проект аналогичен тому, что использовался в практической работе №02. Изменились файлы: graphics.h, graphics.c, main.c.

Файл graphics.h

1
2
3
4
5
6
7
8
9
10
#include "structs.h"
#include "driver_lcd.h"
#include "font_ansi_5x8.h"

void Print(unsigned row, unsigned col, char * byte);
void PointOn (int x, int y);
void PointOff(int x, int y);
void RectangleOn(int x1, int y1, int x2, int y2);
void ClearScreen(void);
void ScreenUpdate(void);

Файл main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*-------------------------------------------------------*/
/* Практическая работа 03 (вывод графических примитивов) */
/*-------------------------------------------------------*/

#include "structs.h"
#include "driver_lcd.h"
#include "graphics.h"
#include "math.h" /* Для применения функции sqrt - корень квадратный */
/* Позже будет реализация без вычисления квадратного корня */

void PortOut(struct_ports * port){
    port->OE      = 0xFF;       /* Выход                */
    port->FUNC    = 0x0000;     /* Порт                 */
    port->DIGITAL = 0xFF;       /* Цифровые             */
    port->PULL    = 0x00000000; /* Подтяжка отключена   */
    port->PD      = 0x00000000; /* Управляемый драйвер  */
    port->PWR     = 0xFFFF;     /* Фронт ~10 нс         */
    port->GFEN    = 0x0000;     /* Фильтрация отключена */
}

static void Delay(unsigned count){
    while(count--);
}

int main (void) {
    /* Включение тактирования порта F */
    *(unsigned *)(0x4002001C) |= (1<<29);
    PortOut(F);

    /* Включение тактирования порта D */
    *(unsigned *)(0x4002001C) |= (1<<24);
    PortOut(D);

    /* Включение тактирования порта A */
    *(unsigned *)(0x4002001C) |= (1<<21);
    PortOut(A);  

    LcdInit();
    LcdDispOn();
    ClearScreen();

    PointOn(15,22);
    PointOn(10,30);
    PointOn(20,30);

    RectangleOn(40,10,115,40);
    RectangleOn(45,15,110,35);

    /* Пример реализации окружности */
    int radius = 24;
    int x_center = 50;
    int y_center = 30;
    PointOn(x_center,y_center);
    for(int delta_1 = 0; delta_1 <= sqrt(radius*radius - delta_1*delta_1); ++delta_1){
        int delta_2 = sqrt(radius*radius - delta_1*delta_1);
        PointOn(x_center+delta_1,y_center+delta_2);
        PointOn(x_center+delta_2,y_center+delta_1);
        PointOn(x_center-delta_1,y_center+delta_2);
        PointOn(x_center-delta_2,y_center+delta_1);
        PointOn(x_center+delta_1,y_center-delta_2);
        PointOn(x_center+delta_2,y_center-delta_1);
        PointOn(x_center-delta_1,y_center-delta_2);
        PointOn(x_center-delta_2,y_center-delta_1);
    }

    ScreenUpdate();

    return 0;
}

Файл graphics.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "graphics.h"

/* Флаг, есть ли что выводить на экран */
static unsigned char grafic_out = 1;

/* Буфер для хранения графической информации */
/* Доступ к памяти дисплея намного медленнее */
static unsigned char screen[8][128];

/* Очистка буфера экрана */
void ClearScreen(void){
    grafic_out = 1;
    for(unsigned i = 0; i < sizeof(screen); ++i)
        screen[0][i] = 0x00;
}

/* Печать нуль терминированной строки в позицию (row, col) */
void Print(unsigned row, unsigned col, char * byte){
    grafic_out = 1;
    if (row > 7) return;
    while(*byte){
        for(unsigned i = 0; i < 5 && col < 128; ++i)
            screen[row][col++] = ansi[*byte][i];
        if (col < 128)
            screen[row][col++] = 0x00;
        ++byte;
    }
}

/* Изображение точки в буфере */
void PointOn(int x, int y){
    if (x >= 0 && x < 128 && y >= 0 && y < 64)
        screen[y>>3][x] |=  (1<<(y&0x7));
}

/* Стирание точки в буфере */
void PointOff(int x, int y){
    if (x >= 0 && x < 128 && y >= 0 && y < 64)
        screen[y>>3][x] &= ~(1<<(y&0x7));
}

/* Изображение прямоугольника, заданного координатами его противоположных вершин */
void RectangleOn(int x1, int y1, int x2, int y2){
    int x_start = x1<x2? x1:x2;
    int y_start = y1<y2? y1:y2;
    int x_finish = x1>x2? x1:x2;
    int y_finish = y1>y2? y1:y2;

    for(int x_current = x_start; x_current <= x_finish; ++x_current){
        PointOn(x_current,y_start);
        PointOn(x_current,y_finish);
    }
    for(int y_current = y_start; y_current <= y_finish; ++y_current){
        PointOn(x_start,y_current);
        PointOn(x_finish,y_current);
    }
}

/* Вывод изображения, если были изменения */
void ScreenUpdate(void){
    if (grafic_out){
        grafic_out = 0;
        LcdScreen(screen);
    }
}

Задания для самостоятельного выполнения

  1. Нарисуйте окружность вписанную в квадрат.
  2. Добавьте функцию рисующую отрезки с заданными координатами концов отрезка.
  3. Нарисуйте треугольник используя функцию из предыдущего задания.
  4. Нарисуйте домик с окном.
  5. Организуйте движение точки по дисплею.
  6. Организуйте эффект увеличивающихся и уменьшающихся окружностей.
  7. Нарисуйте круг (не окружность).
  8. Выведите синусоиду.
Лицензия Creative Commons
Code More Team - GitHub