Форум РадиоКот • Просмотр темы - Помогите запустить дисплей SP14Q002-A (320*240)
Сообщения без ответов | Активные темы
Страница 1 из 1
[ Сообщений: 2 ]
Автор
Сообщение
Evgeny1
Заголовок сообщения: Помогите запустить дисплей SP14Q002-A (320*240)
Добавлено: Ср сен 17, 2025 17:21:30
Друг Кота
Карма: 13
Рейтинг сообщений: 79
Зарегистрирован: Пн авг 10, 2009 01:18:55Сообщений: 4100Откуда: Электросталь
Рейтинг сообщения: 0
Привет!
имеется такой вот дисплей SP14Q002-A, весьма себе замечательный и еще и размеров приличных
даташит
https://datasheet.octopart.com/SP14Q002 ... 835662.pdf дисплей подключен так
Arduino Due -> (LCD Display)
D2 -> (CP)
D3 -> (LOAD)
D4 -> (FRAME)
D5 -> (DISP_OFF)
D6 -> (D0)
D7 -> (D1)
D8 -> (D2)
D9 -> (D3)
т.к. в программировании я особо не силен, уже несколько дней пытаюсь застравить чат жпт и дипсик помочь мне с этим делом.
В итоге имеем 2 скетча, но картинка форматируется неверно
Код:
// ---------- // Arduino Due -> 4-bit LCD Display // Исправленный порядок бит, тестовые паттерны // ---------- // Пины подключения #define CP_PIN 2 #define LOAD_PIN 3 #define FRAME_PIN 4 #define DISP_OFF_PIN 5 #define D0_PIN 6 #define D1_PIN 7 #define D2_PIN 8 #define D3_PIN 9 // Разрешение дисплея #define X_RES 320 #define Y_RES 240 #define BYTES_PER_LINE 80 // 4 пикселя на байт // Прямой доступ к портам #define PORT_CP (g_APinDescription[CP_PIN].pPort->PIO_ODSR) #define PORT_LOAD (g_APinDescription[LOAD_PIN].pPort->PIO_ODSR) #define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort->PIO_ODSR) #define PORT_D0 (g_APinDescription[D0_PIN].pPort->PIO_ODSR) #define PORT_D1 (g_APinDescription[D1_PIN].pPort->PIO_ODSR) #define PORT_D2 (g_APinDescription[D2_PIN].pPort->PIO_ODSR) #define PORT_D3 (g_APinDescription[D3_PIN].pPort->PIO_ODSR) #define MASK_CP (g_APinDescription[CP_PIN].ulPin) #define MASK_LOAD (g_APinDescription[LOAD_PIN].ulPin) #define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin) #define MASK_D0 (g_APinDescription[D0_PIN].ulPin) #define MASK_D1 (g_APinDescription[D1_PIN].ulPin) #define MASK_D2 (g_APinDescription[D2_PIN].ulPin) #define MASK_D3 (g_APinDescription[D3_PIN].ulPin) // ---------- // Frame buffer uint8_t frameBuffer[Y_RES][BYTES_PER_LINE]; // ---------- // Мини-задержка ~150ns inline void shortDelay() { asm volatile( "nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n" ); } // Быстрый тактовый импульс CP inline void pulseCP() { PORT_CP &= ~MASK_CP; shortDelay(); PORT_CP |= MASK_CP; shortDelay(); } // Быстрый импульс LOAD H->L inline void pulseLOAD() { PORT_LOAD &= ~MASK_LOAD; shortDelay(); PORT_LOAD |= MASK_LOAD; shortDelay(); } // ---------- // Работа с пикселями void setAllBlack() { for (int y = 0; y < Y_RES; y++) for (int x = 0; x < BYTES_PER_LINE; x++) frameBuffer[y][x] = 0x00; } // Установка пикселя с правильным порядком бит void setPixel(int x, int y, bool state) { if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return; int byteIndex = x / 4; int bitPosition = 3 - (x % 4); // D0 = старший бит первого пикселя if (state) frameBuffer[y][byteIndex] |= (1 << bitPosition); else frameBuffer[y][byteIndex] &= ~(1 << bitPosition); } // ---------- // Тестовые паттерны void drawGrid() { setAllBlack(); // Вертикальные линии каждые 32 пикселя for (int x = 0; x < X_RES; x += 32) for (int y = 0; y < Y_RES; y++) setPixel(x, y, true); // Горизонтальные линии каждые 32 пикселя for (int y = 0; y < Y_RES; y += 32) for (int x = 0; x < X_RES; x++) setPixel(x, y, true); // Угловые маркеры setPixel(0, 0, true); setPixel(X_RES-1, 0, true); setPixel(0, Y_RES-1, true); setPixel(X_RES-1, Y_RES-1, true); // Центральный крест for (int x = X_RES/2-16; x < X_RES/2+16; x++) setPixel(x, Y_RES/2, true); for (int y = Y_RES/2-16; y < Y_RES/2+16; y++) setPixel(X_RES/2, y, true); } void drawPatternTest() { for (int y = 0; y < Y_RES; y++) for (int x = 0; x < X_RES; x++) setPixel(x, y, ((x/7 + y/8) % 2) == 0); } // ---------- // Отправка 4 бит на D0-D3 void send4Bits(uint8_t data) { if (data & 0x01) PORT_D0 |= MASK_D0; else PORT_D0 &= ~MASK_D0; if (data & 0x02) PORT_D1 |= MASK_D1; else PORT_D1 &= ~MASK_D1; if (data & 0x04) PORT_D2 |= MASK_D2; else PORT_D2 &= ~MASK_D2; if (data & 0x08) PORT_D3 |= MASK_D3; else PORT_D3 &= ~MASK_D3; pulseCP(); } // ---------- // Отправка кадра void displayFrame() { PORT_FRAME |= MASK_FRAME; // FRAME высокий для первой строки shortDelay(); for (int y = 0; y < Y_RES; y++) { for (int x = 0; x < BYTES_PER_LINE; x++) send4Bits(frameBuffer[y][x]); pulseLOAD(); // фиксация линии if (y == 0) PORT_FRAME &= ~MASK_FRAME; } } // ---------- // Arduino setup void setup() { pinMode(CP_PIN, OUTPUT); pinMode(LOAD_PIN, OUTPUT); pinMode(FRAME_PIN, OUTPUT); pinMode(DISP_OFF_PIN, OUTPUT); pinMode(D0_PIN, OUTPUT); pinMode(D1_PIN, OUTPUT); pinMode(D2_PIN, OUTPUT); pinMode(D3_PIN, OUTPUT); PORT_CP |= MASK_CP; PORT_LOAD |= MASK_LOAD; PORT_FRAME &= ~MASK_FRAME; digitalWrite(DISP_OFF_PIN, HIGH); // Выберите тестовый паттерн drawGrid(); //drawPatternTest(); } // ---------- // Arduino loop void loop() { displayFrame(); // непрерывное обновление }
формирует тестовые паттерны сетку и шахматку
но работает неочень и выглядит вот так
сетка не совсем сетка
и шахматка не совсем шахматка
и 2й скетч пытается выводить надпись hello world
Код:
// ---------- // Arduino Due -> 4-bit LCD Display // HELLO WORLD жирным шрифтом, корректное отображение // ---------- #define CP_PIN 2 #define LOAD_PIN 3 #define FRAME_PIN 4 #define DISP_OFF_PIN 5 #define D0_PIN 6 #define D1_PIN 7 #define D2_PIN 8 #define D3_PIN 9 #define X_RES 320 #define Y_RES 240 #define BYTES_PER_LINE 80 // 4 пикселя на байт #define PORT_CP (g_APinDescription[CP_PIN].pPort->PIO_ODSR) #define PORT_LOAD (g_APinDescription[LOAD_PIN].pPort->PIO_ODSR) #define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort->PIO_ODSR) #define PORT_D0 (g_APinDescription[D0_PIN].pPort->PIO_ODSR) #define PORT_D1 (g_APinDescription[D1_PIN].pPort->PIO_ODSR) #define PORT_D2 (g_APinDescription[D2_PIN].pPort->PIO_ODSR) #define PORT_D3 (g_APinDescription[D3_PIN].pPort->PIO_ODSR) #define MASK_CP (g_APinDescription[CP_PIN].ulPin) #define MASK_LOAD (g_APinDescription[LOAD_PIN].ulPin) #define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin) #define MASK_D0 (g_APinDescription[D0_PIN].ulPin) #define MASK_D1 (g_APinDescription[D1_PIN].ulPin) #define MASK_D2 (g_APinDescription[D2_PIN].ulPin) #define MASK_D3 (g_APinDescription[D3_PIN].ulPin) uint8_t frameBuffer[Y_RES][BYTES_PER_LINE]; // ---------- // Мини-задержка ~150ns inline void shortDelay() { asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); } // Быстрый тактовый импульс CP inline void pulseCP() { PORT_CP &= ~MASK_CP; shortDelay(); PORT_CP |= MASK_CP; shortDelay(); } // Быстрый импульс LOAD H->L inline void pulseLOAD() { PORT_LOAD &= ~MASK_LOAD; shortDelay(); PORT_LOAD |= MASK_LOAD; shortDelay(); } // ---------- // Работа с пикселями void setAllBlack() { for (int y = 0; y < Y_RES; y++) for (int x = 0; x < BYTES_PER_LINE; x++) frameBuffer[y][x] = 0x00; } void setPixel(int x, int y, bool state) { if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return; int byteIndex = x / 4; int bitPosition = 3 - (x % 4); // D0 = старший бит первого пикселя if (state) frameBuffer[y][byteIndex] |= (1 << bitPosition); else frameBuffer[y][byteIndex] &= ~(1 << bitPosition); } // ---------- // Отправка 4 бит на D0-D3 void send4Bits(uint8_t data) { if (data & 0x01) PORT_D0 |= MASK_D0; else PORT_D0 &= ~MASK_D0; if (data & 0x02) PORT_D1 |= MASK_D1; else PORT_D1 &= ~MASK_D1; if (data & 0x04) PORT_D2 |= MASK_D2; else PORT_D2 &= ~MASK_D2; if (data & 0x08) PORT_D3 |= MASK_D3; else PORT_D3 &= ~MASK_D3; pulseCP(); } // ---------- // Отправка кадра void displayFrame() { PORT_FRAME |= MASK_FRAME; shortDelay(); for (int y = 0; y < Y_RES; y++) { for (int x = 0; x < BYTES_PER_LINE; x++) send4Bits(frameBuffer[y][x]); pulseLOAD(); if (y == 0) PORT_FRAME &= ~MASK_FRAME; } } // ---------- // Жирный шрифт 16x16, горизонтальные байты для LCD // Каждая строка = 16 бит, потом разбиваем на 4-битные пиксели // Для примера: только буквы HELLO WORLD и пробел const uint16_t font_H[16] = { 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111111111111111, 0b1111111111111111, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001, 0b1111000111110001 }; const uint16_t font_E[16] = { 0b1111111111111111, 0b1111111111111111, 0b1111000000000000, 0b1111000000000000, 0b1111111111111110, 0b1111111111111110, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111111111111111, 0b1111111111111111, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000 }; const uint16_t font_L[16] = { 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111000000000000, 0b1111111111111111, 0b1111111111111111, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000 }; const uint16_t font_O[16] = { 0b0111111111111110, 0b1111111111111111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111111111111111, 0b0111111111111110, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000 }; const uint16_t font_W[16] = { 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111000000001111, 0b1111001100111111, 0b1111001100111111, 0b1111010010111111, 0b1111010010111111, 0b1111100001111111, 0b1111100001111111, 0b1111000000001111, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000 }; const uint16_t font_R[16] = { 0b1111111111111000, 0b1111111111111100, 0b1111000000001110, 0b1111000000000111, 0b1111000000000111, 0b1111111111111100, 0b1111111111111000, 0b1111001000000000, 0b1111000100000000, 0b1111000010000000, 0b1111000001111000, 0b1111000001111100, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000 }; const uint16_t font_D[16] = { 0b1111111111110000, 0b1111111111111000, 0b1111000000011100, 0b1111000000001100, 0b1111000000000110, 0b1111000000000110, 0b1111000000000110, 0b1111000000000110, 0b1111000000001100, 0b1111000000011000, 0b1111111111111000, 0b1111111111110000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000, 0b0000000000000000 }; const uint16_t font_space[16] = {0}; // ---------- // Рисуем символ на LCD void drawChar16x16_LCD(int x0, int y0, const uint16_t* bitmap) { for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { bool pixel = bitmap[y] & (1 << (15 - x)); setPixel(x0 + x, y0 + y, pixel); // Жирный: дублируем пиксель справа setPixel(x0 + x + 1, y0 + y, pixel); } } } // ---------- // Рисуем строку HELLO WORLD void drawHelloWorld_LCD(int x0, int y0) { const uint16_t* chars[] = {font_H, font_E, font_L, font_L, font_O, font_space, font_W, font_O, font_R, font_L, font_D}; int px = x0; for (int i = 0; i < 11; i++) { drawChar16x16_LCD(px, y0, chars[i]); px += 18; // шаг между символами } } // ---------- // Setup & loop void setup() { pinMode(CP_PIN, OUTPUT); pinMode(LOAD_PIN, OUTPUT); pinMode(FRAME_PIN, OUTPUT); pinMode(DISP_OFF_PIN, OUTPUT); pinMode(D0_PIN, OUTPUT); pinMode(D1_PIN, OUTPUT); pinMode(D2_PIN, OUTPUT); pinMode(D3_PIN, OUTPUT); PORT_CP |= MASK_CP; PORT_LOAD |= MASK_LOAD; PORT_FRAME &= ~MASK_FRAME; digitalWrite(DISP_OFF_PIN, HIGH); setAllBlack(); drawHelloWorld_LCD(50, 100); // координаты для центрирования } void loop() { displayFrame(); }
ну и тут с отображением все не так как надо
и + ко всему картинка и там и там дико мерцает
подскажите как пофиксить
Вернуться наверх
Реклама
Evgeny1
Заголовок сообщения: Re: Помогите запустить дисплей SP14Q002-A (320*240)
Добавлено: Пт сен 19, 2025 20:36:21
Друг Кота
Карма: 13
Рейтинг сообщений: 79
Зарегистрирован: Пн авг 10, 2009 01:18:55Сообщений: 4100Откуда: Электросталь
Рейтинг сообщения: 0
Ну куда все умные коты подевались?
подскажите чего не так
Код:
// ---------- // Arduino Due -> Hitachi SP14Q002-A1 // 4 части экрана с надписями // Исправлена синхронизация // ---------- #define CP_PIN 2 #define LOAD_PIN 3 #define FRAME_PIN 4 #define DISP_OFF_PIN 5 #define D0_PIN 6 #define D1_PIN 7 #define D2_PIN 8 #define D3_PIN 9 #define X_RES 320 #define Y_RES 240 #define BYTES_PER_LINE (X_RES / 8) // Прямое управление портами для максимальной скорости #define PORT_CP (g_APinDescription[CP_PIN].pPort) #define PORT_LOAD (g_APinDescription[LOAD_PIN].pPort) #define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort) #define PORT_D0 (g_APinDescription[D0_PIN].pPort) #define PORT_D1 (g_APinDescription[D1_PIN].pPort) #define PORT_D2 (g_APinDescription[D2_PIN].pPort) #define PORT_D3 (g_APinDescription[D3_PIN].pPort) #define MASK_CP (g_APinDescription[CP_PIN].ulPin) #define MASK_LOAD (g_APinDescription[LOAD_PIN].ulPin) #define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin) #define MASK_D0 (g_APinDescription[D0_PIN].ulPin) #define MASK_D1 (g_APinDescription[D1_PIN].ulPin) #define MASK_D2 (g_APinDescription[D2_PIN].ulPin) #define MASK_D3 (g_APinDescription[D3_PIN].ulPin) // Буфер для всего экрана uint8_t frameBuffer[Y_RES][BYTES_PER_LINE]; // ---------- // Ультрабыстрые функции для работы с пинами inline void setCP(bool state) { if (state) PORT_CP->PIO_SODR = MASK_CP; else PORT_CP->PIO_CODR = MASK_CP; asm volatile("nop\n nop\n"); } inline void setLOAD(bool state) { if (state) PORT_LOAD->PIO_SODR = MASK_LOAD; else PORT_LOAD->PIO_CODR = MASK_LOAD; asm volatile("nop\n nop\n"); } inline void setFRAME(bool state) { if (state) PORT_FRAME->PIO_SODR = MASK_FRAME; else PORT_FRAME->PIO_CODR = MASK_FRAME; asm volatile("nop\n nop\n"); } inline void setDataPinsFast(uint8_t data) { uint32_t portState = PORT_D0->PIO_ODSR; portState = (portState & ~(MASK_D0 | MASK_D1 | MASK_D2 | MASK_D3)) | ((data & 0x01) ? MASK_D0 : 0) | ((data & 0x02) ? MASK_D1 : 0) | ((data & 0x04) ? MASK_D2 : 0) | ((data & 0x08) ? MASK_D3 : 0); PORT_D0->PIO_ODSR = portState; asm volatile("nop\n nop\n"); } // ---------- // Быстрая отправка 4 пикселей inline void send4PixelsFast(uint8_t pixels) { setDataPinsFast(pixels); setCP(false); asm volatile("nop\n nop\n"); setCP(true); asm volatile("nop\n nop\n"); } // ---------- // Быстрая отправка байта inline void sendByteFast(uint8_t byteData) { send4PixelsFast((byteData >> 4) & 0x0F); send4PixelsFast(byteData & 0x0F); } // ---------- // Инициализация дисплея void initDisplay() { for (int i = 2; i <= 9; i++) { pinMode(i, OUTPUT); digitalWrite(i, LOW); } digitalWrite(DISP_OFF_PIN, LOW); delay(100); digitalWrite(CP_PIN, HIGH); digitalWrite(LOAD_PIN, HIGH); digitalWrite(FRAME_PIN, LOW); digitalWrite(DISP_OFF_PIN, HIGH); delay(50); } // ---------- // Очистка экрана void clearScreen() { memset(frameBuffer, 0, sizeof(frameBuffer)); } // ---------- // Установка пикселя void setPixel(int x, int y, bool state) { if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return; int byteIndex = x / 8; int bitPos = 7 - (x % 8); if (state) { frameBuffer[y][byteIndex] |= (1 << bitPos); } else { frameBuffer[y][byteIndex] &= ~(1 << bitPos); } } // ---------- // Рисование линии void drawLine(int x1, int y1, int x2, int y2, bool state) { int dx = abs(x2 - x1); int dy = abs(y2 - y1); int sx = (x1 < x2) ? 1 : -1; int sy = (y1 < y2) ? 1 : -1; int err = dx - dy; while (true) { setPixel(x1, y1, state); if (x1 == x2 && y1 == y2) break; int e2 = 2 * err; if (e2 > -dy) { err -= dy; x1 += sx; } if (e2 < dx) { err += dx; y1 += sy; } } } // ---------- // Рисование прямоугольника void drawRect(int x1, int y1, int x2, int y2, bool state) { drawLine(x1, y1, x2, y1, state); drawLine(x2, y1, x2, y2, state); drawLine(x2, y2, x1, y2, state); drawLine(x1, y2, x1, y1, state); } // ---------- // Простой шрифт 5x7 const uint8_t font_5x7[][5] = { {0x00,0x00,0x00,0x00,0x00}, // space {0x00,0x00,0x5F,0x00,0x00}, // ! {0x00,0x07,0x00,0x07,0x00}, // " {0x14,0x7F,0x14,0x7F,0x14}, // # {0x24,0x2A,0x7F,0x2A,0x12}, // $ {0x23,0x13,0x08,0x64,0x62}, // % {0x36,0x49,0x55,0x22,0x50}, // & {0x00,0x05,0x03,0x00,0x00}, // ' {0x00,0x1C,0x22,0x41,0x00}, // ( {0x00,0x41,0x22,0x1C,0x00}, // ) {0x14,0x08,0x3E,0x08,0x14}, // * {0x08,0x08,0x3E,0x08,0x08}, // + {0x00,0x50,0x30,0x00,0x00}, // , {0x08,0x08,0x08,0x08,0x08}, // - {0x00,0x60,0x60,0x00,0x00}, // . {0x20,0x10,0x08,0x04,0x02}, // / {0x3E,0x51,0x49,0x45,0x3E}, // 0 {0x00,0x42,0x7F,0x40,0x00}, // 1 {0x42,0x61,0x51,0x49,0x46}, // 2 {0x21,0x41,0x45,0x4B,0x31}, // 3 {0x18,0x14,0x12,0x7F,0x10}, // 4 {0x27,0x45,0x45,0x45,0x39}, // 5 {0x3C,0x4A,0x49,0x49,0x30}, // 6 {0x01,0x71,0x09,0x05,0x03}, // 7 {0x36,0x49,0x49,0x49,0x36}, // 8 {0x06,0x49,0x49,0x29,0x1E}, // 9 {0x00,0x36,0x36,0x00,0x00}, // : {0x00,0x56,0x36,0x00,0x00}, // ; {0x08,0x14,0x22,0x41,0x00}, // < {0x14,0x14,0x14,0x14,0x14}, // = {0x00,0x41,0x22,0x14,0x08}, // > {0x02,0x01,0x51,0x09,0x06}, // ? {0x32,0x49,0x79,0x41,0x3E}, // @ {0x7E,0x11,0x11,0x11,0x7E}, // A {0x7F,0x49,0x49,0x49,0x36}, // B {0x3E,0x41,0x41,0x41,0x22}, // C {0x7F,0x41,0x41,0x22,0x1C}, // D {0x7F,0x49,0x49,0x49,0x41}, // E {0x7F,0x09,0x09,0x09,0x01}, // F {0x3E,0x41,0x49,0x49,0x7A}, // G {0x7F,0x08,0x08,0x08,0x7F}, // H {0x00,0x41,0x7F,0x41,0x00}, // I {0x20,0x40,0x41,0x3F,0x01}, // J {0x7F,0x08,0x14,0x22,0x41}, // K {0x7F,0x40,0x40,0x40,0x40}, // L {0x7F,0x02,0x0C,0x02,0x7F}, // M {0x7F,0x04,0x08,0x10,0x7F}, // N {0x3E,0x41,0x41,0x41,0x3E}, // O {0x7F,0x09,0x09,0x09,0x06}, // P {0x3E,0x41,0x51,0x21,0x5E}, // Q {0x7F,0x09,0x19,0x29,0x46}, // R {0x46,0x49,0x49,0x49,0x31}, // S {0x01,0x01,0x7F,0x01,0x01}, // T {0x3F,0x40,0x40,0x40,0x3F}, // U {0x1F,0x20,0x40,0x20,0x1F}, // V {0x3F,0x40,0x38,0x40,0x3F}, // W {0x63,0x14,0x08,0x14,0x63}, // X {0x07,0x08,0x70,0x08,0x07}, // Y {0x61,0x51,0x49,0x45,0x43}, // Z }; void drawChar5x7(int x, int y, char c) { if (c < 32 || c > 90) c = ' '; // только заглавные буквы и цифры const uint8_t* glyph = font_5x7[c - 32]; for (int i = 0; i < 5; i++) { for (int j = 0; j < 7; j++) { if (glyph[i] & (1 << j)) { setPixel(x + i, y + j, true); } } } } void drawText(int x, int y, const char* text) { int startX = x; while (*text) { if (*text == '\n') { y += 8; x = startX; } else { drawChar5x7(x, y, *text); x += 6; } text++; } } // ---------- // Создаем 4 части экрана с надписями void createFourQuadrants() { clearScreen(); // Центральные линии, делящие экран на 4 части drawLine(X_RES/2, 0, X_RES/2, Y_RES-1, true); drawLine(0, Y_RES/2, X_RES-1, Y_RES/2, true); // Толстые границы drawRect(2, 2, X_RES-3, Y_RES-3, true); drawRect(4, 4, X_RES-5, Y_RES-5, true); // Надписи в каждой четверти drawText(30, 30, "TOP-LEFT"); drawText(X_RES/2 + 30, 30, "TOP-RIGHT"); drawText(30, Y_RES/2 + 30, "BOT-LEFT"); drawText(X_RES/2 + 30, Y_RES/2 + 30, "BOT-RIGHT"); // Дополнительные элементы для визуализации for (int i = 0; i < 4; i++) { int qx = (i % 2) * (X_RES/2); int qy = (i / 2) * (Y_RES/2); // Угловые маркеры drawRect(qx + 10, qy + 10, qx + 20, qy + 20, true); drawRect(qx + X_RES/2 - 20, qy + 10, qx + X_RES/2 - 10, qy + 20, true); drawRect(qx + 10, qy + Y_RES/2 - 20, qx + 20, qy + Y_RES/2 - 10, true); drawRect(qx + X_RES/2 - 20, qy + Y_RES/2 - 20, qx + X_RES/2 - 10, qy + Y_RES/2 - 10, true); // Диагональные линии в каждой четверти drawLine(qx + 5, qy + 5, qx + X_RES/2 - 5, qy + Y_RES/2 - 5, true); } } // ---------- // Правильная отправка кадра с исправленной синхронизацией void displayFrameCorrect() { // Начало кадра - FRAME pulse (должен быть ДО первой строки) setFRAME(true); asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n"); for (int y = 0; y < Y_RES; y++) { // Отправляем всю строку for (int x = 0; x < BYTES_PER_LINE; x++) { sendByteFast(frameBuffer[y][x]); } // Завершение строки - LOAD pulse setLOAD(false); asm volatile("nop\n nop\n nop\n nop\n"); setLOAD(true); asm volatile("nop\n nop\n"); // Сбрасываем FRAME после отправки первой строки if (y == 0) { setFRAME(false); asm volatile("nop\n nop\n nop\n nop\n"); } } } // ---------- // Setup & loop void setup() { initDisplay(); createFourQuadrants(); delay(1000); } void loop() { displayFrameCorrect(); // Мигание центральной точки для индикации работы static unsigned long lastBlink = 0; static bool blinkState = false; if (millis() - lastBlink > 500) { blinkState = !blinkState; setPixel(X_RES/2, Y_RES/2, blinkState); lastBlink = millis(); } delayMicroseconds(500); }
и вот
Код:
// ---------- // Arduino Due -> Hitachi SP14Q002-A1 // Исправлено: вывод текста на весь экран // Тест: вывод "HELLO WORLD" // ---------- #define CP_PIN 2 #define LOAD_PIN 3 #define FRAME_PIN 4 #define DISP_OFF_PIN 5 #define D0_PIN 6 #define D1_PIN 7 #define D2_PIN 8 #define D3_PIN 9 #define X_RES 320 #define Y_RES 240 #define HALF_X_RES 160 // одна половина строки #define NIBBLES_PER_LINE (HALF_X_RES / 4) #define BYTES_PER_LINE (NIBBLES_PER_LINE / 2) // Правильные определения для работы с портами #define PORT_CP (g_APinDescription[CP_PIN].pPort) #define PORT_LOAD (g_APinDescription[LOAD_PIN].pPort) #define PORT_FRAME (g_APinDescription[FRAME_PIN].pPort) #define PORT_D0 (g_APinDescription[D0_PIN].pPort) #define PORT_D1 (g_APinDescription[D1_PIN].pPort) #define PORT_D2 (g_APinDescription[D2_PIN].pPort) #define PORT_D3 (g_APinDescription[D3_PIN].pPort) #define MASK_CP (g_APinDescription[CP_PIN].ulPin) #define MASK_LOAD (g_APinDescription[LOAD_PIN].ulPin) #define MASK_FRAME (g_APinDescription[FRAME_PIN].ulPin) #define MASK_D0 (g_APinDescription[D0_PIN].ulPin) #define MASK_D1 (g_APinDescription[D1_PIN].ulPin) #define MASK_D2 (g_APinDescription[D2_PIN].ulPin) #define MASK_D3 (g_APinDescription[D3_PIN].ulPin) // ---------- // Буфер для **всего экрана** uint8_t frameBuffer[Y_RES][HALF_X_RES/4]; // храним половину строки, будем дублировать при отправке // ---------- // Мини-задержка ~200ns inline void shortDelay() { asm volatile("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n"); } // ---------- // Установка состояния пина inline void setPin(Pio* port, uint32_t mask, bool state) { if (state) { port->PIO_SODR = mask; } else { port->PIO_CODR = mask; } } // ---------- // Отправка 4 пикселей (D0..D3) inline void send4Pixels(uint8_t pixels) { setPin(PORT_D0, MASK_D0, pixels & 0x01); setPin(PORT_D1, MASK_D1, pixels & 0x02); setPin(PORT_D2, MASK_D2, pixels & 0x04); setPin(PORT_D3, MASK_D3, pixels & 0x08); shortDelay(); setPin(PORT_CP, MASK_CP, false); shortDelay(); setPin(PORT_CP, MASK_CP, true); shortDelay(); } // ---------- // Очистка экрана void setAllBlack() { for (int y = 0; y < Y_RES; y++) { for (int x = 0; x < HALF_X_RES/4; x++) { frameBuffer[y][x] = 0x00; } } } // ---------- // Установка пикселя (координаты 0..319) void setPixel(int x, int y, bool state) { if (x < 0 || x >= X_RES || y < 0 || y >= Y_RES) return; // Переводим координаты в индекс буфера половины строки int x_half = x % HALF_X_RES; int byteIndex = x_half / 8; int bitPos = 7 - (x_half % 8); if (byteIndex < BYTES_PER_LINE) { if (state) frameBuffer[y][byteIndex] |= (1 << bitPos); else frameBuffer[y][byteIndex] &= ~(1 << bitPos); } } // ---------- // Отправка кадра void displayFrame() { setPin(PORT_FRAME, MASK_FRAME, true); shortDelay(); shortDelay(); for (int y = 0; y < Y_RES; y++) { for (int half = 0; half < 2; half++) { // левая и правая половины for (int x = 0; x < BYTES_PER_LINE; x++) { uint8_t byteData = frameBuffer[y][x]; send4Pixels((byteData >> 4) & 0x0F); send4Pixels(byteData & 0x0F); } } shortDelay(); setPin(PORT_LOAD, MASK_LOAD, false); shortDelay(); shortDelay(); setPin(PORT_LOAD, MASK_LOAD, true); shortDelay(); if (y == 0) { shortDelay(); setPin(PORT_FRAME, MASK_FRAME, false); } } } // ---------- // Шрифты 8x16 const uint8_t font_H[16] = {0b11111111,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b11111111}; const uint8_t font_E[16] = {0b11111111,0b11111111,0b11000000,0b11000000,0b11000000,0b11111110,0b11111110,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b00000000,0b00000000}; const uint8_t font_L[16] = {0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b00000000,0b00000000}; const uint8_t font_O[16] = {0b01111110,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b01111110,0b00000000,0b00000000}; const uint8_t font_W[16] = {0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11011011,0b11011011,0b11111111,0b11100111,0b11100111,0b11000011,0b00000000,0b00000000,0b00000000,0b00000000}; const uint8_t font_R[16] = {0b11111110,0b11111111,0b11000011,0b11000011,0b11000011,0b11111111,0b11111110,0b11011100,0b11001110,0b11000111,0b11000011,0b11000001,0b00000000,0b00000000,0b00000000,0b00000000}; const uint8_t font_D[16] = {0b11111100,0b11111110,0b11000111,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000011,0b11000111,0b11111110,0b11111100,0b00000000,0b00000000,0b00000000,0b00000000}; const uint8_t font_space[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // ---------- // Рисуем символ 8x16 void drawChar8x16(int x0, int y0, const uint8_t* bitmap) { for (int y = 0; y < 16; y++) { for (int x = 0; x < 8; x++) { bool pixel = (bitmap[y] >> (7 - x)) & 0x01; setPixel(x0 + x, y0 + y, pixel); } } } // ---------- // Рисуем строку void drawString(const char* str, int x0, int y0) { int px = x0; for (int i = 0; str[i]; i++) { const uint8_t* glyph = font_space; switch (str[i]) { case 'H': glyph = font_H; break; case 'E': glyph = font_E; break; case 'L': glyph = font_L; break; case 'O': glyph = font_O; break; case 'W': glyph = font_W; break; case 'R': glyph = font_R; break; case 'D': glyph = font_D; break; case ' ': glyph = font_space; break; } drawChar8x16(px, y0, glyph); px += 10; } } // ---------- // Рисуем тестовую сетку для отладки void drawTestPattern() { setAllBlack(); for (int x = 0; x < X_RES; x++) { setPixel(x, 0, true); setPixel(x, Y_RES-1, true); } for (int y = 0; y < Y_RES; y++) { setPixel(0, y, true); setPixel(X_RES-1, y, true); setPixel(HALF_X_RES, y, true); } drawString("HELLO WORLD", 20, 100); } // ---------- // Setup & loop void setup() { pinMode(CP_PIN, OUTPUT); pinMode(LOAD_PIN, OUTPUT); pinMode(FRAME_PIN, OUTPUT); pinMode(DISP_OFF_PIN, OUTPUT); pinMode(D0_PIN, OUTPUT); pinMode(D1_PIN, OUTPUT); pinMode(D2_PIN, OUTPUT); pinMode(D3_PIN, OUTPUT); digitalWrite(CP_PIN, HIGH); digitalWrite(LOAD_PIN, HIGH); digitalWrite(FRAME_PIN, LOW); digitalWrite(DISP_OFF_PIN, HIGH); drawTestPattern(); } void loop() { displayFrame(); delay(20); }
даташит
https://datasheet.octopart.com/SP14Q002 ... 835662.pdf
Вернуться наверх
Реклама
Страница 1 из 1
[ Сообщений: 2 ]
Кто сейчас на форуме
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения