//===================================================================
// ПРОСТОЙ ТЕСТ ДИСПЛЕЯ ILI9341 ДЛЯ BLUE PILL (ARDUINO IDE)
// Мигает разными цветами, всё в одном файле
//===================================================================
// Адреса периферии
#define RCC_BASE 0x40021000
#define GPIOA_BASE 0x40010800
#define GPIOB_BASE 0x40010C00
#define SPI1_BASE 0x40013000
// Регистры RCC
#define RCC_APB2ENR (*(volatile unsigned long*)(RCC_BASE + 0x18))
#define RCC_APB2ENR_IOPAEN (1 << 2)
#define RCC_APB2ENR_IOPBEN (1 << 3)
#define RCC_APB2ENR_SPI1EN (1 << 12)
// Регистры GPIOA
#define GPIOA_CRL (*(volatile unsigned long*)(GPIOA_BASE + 0x00))
#define GPIOA_BSRR (*(volatile unsigned long*)(GPIOA_BASE + 0x10))
// Регистры GPIOB
#define GPIOB_CRL (*(volatile unsigned long*)(GPIOB_BASE + 0x00))
#define GPIOB_CRH (*(volatile unsigned long*)(GPIOB_BASE + 0x04))
#define GPIOB_BSRR (*(volatile unsigned long*)(GPIOB_BASE + 0x10))
// Регистры SPI1
#define SPI1_CR1 (*(volatile unsigned long*)(SPI1_BASE + 0x00))
#define SPI1_SR (*(volatile unsigned long*)(SPI1_BASE + 0x08))
#define SPI1_DR (*(volatile unsigned long*)(SPI1_BASE + 0x0C))
// Биты SPI
#define SPI_CR1_MSTR (1 << 2)
#define SPI_CR1_BR (2 << 3) // fPCLK/8
#define SPI_CR1_SSI (1 << 8)
#define SPI_CR1_SSM (1 << 9)
#define SPI_CR1_SPE (1 << 6)
#define SPI_SR_TXE (1 << 1)
#define SPI_SR_BSY (1 << 7)
// Пины дисплея ILI9341
#define PIN_SCLK 5 // PA5
#define PIN_MOSI 7 // PA7
#define PIN_RES 0 // PB0
#define PIN_DC 1 // PB1
#define PIN_CS 10 // PB10
// Цвета (RGB565)
#define BLACK 0x0000
#define RED 0xF800
#define GREEN 0x07E0
#define BLUE 0x001F
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// Макросы для управления пинами
#define CS_LOW() (GPIOB_BSRR = (1 << (PIN_CS + 16)))
#define CS_HIGH() (GPIOB_BSRR = (1 << PIN_CS))
#define DC_LOW() (GPIOB_BSRR = (1 << (PIN_DC + 16)))
#define DC_HIGH() (GPIOB_BSRR = (1 << PIN_DC))
#define RES_LOW() (GPIOB_BSRR = (1 << (PIN_RES + 16)))
#define RES_HIGH() (GPIOB_BSRR = (1 << PIN_RES))
// Простая задержка (переименована, чтобы избежать конфликта с Arduino)
void myDelay(volatile unsigned int count) {
while(count--) {
__asm__("nop");
}
}
// Отправка байта по SPI
void spi_send(uint8_t data) {
while(!(SPI1_SR & SPI_SR_TXE));
SPI1_DR = data;
while(!(SPI1_SR & SPI_SR_TXE));
while(SPI1_SR & SPI_SR_BSY);
}
// Отправка команды дисплею
void send_cmd(uint8_t cmd) {
DC_LOW();
CS_LOW();
spi_send(cmd);
CS_HIGH();
}
// Отправка данных дисплею
void send_data(uint8_t data) {
DC_HIGH();
CS_LOW();
spi_send(data);
CS_HIGH();
}
// Отправка 16-битного цвета
void send_color(uint16_t color) {
DC_HIGH();
CS_LOW();
spi_send(color >> 8); // Старший байт
spi_send(color & 0xFF); // Младший байт
CS_HIGH();
}
// Установка окна для заливки
void set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
send_cmd(0x2A); // Column Address Set
send_data(x0 >> 8);
send_data(x0);
send_data(x1 >> 8);
send_data(x1);
send_cmd(0x2B); // Page Address Set
send_data(y0 >> 8);
send_data(y0);
send_data(y1 >> 8);
send_data(y1);
send_cmd(0x2C); // Memory Write
}
// Заливка всего экрана цветом
void fill_screen(uint16_t color) {
set_window(0, 0, 239, 319); // ILI9341 240x320
DC_HIGH();
CS_LOW();
// Отправляем цвет для каждого пикселя
for(int i = 0; i < 240 * 320; i++) {
while(!(SPI1_SR & SPI_SR_TXE));
SPI1_DR = color >> 8;
while(!(SPI1_SR & SPI_SR_TXE));
SPI1_DR = color & 0xFF;
}
while(SPI1_SR & SPI_SR_BSY);
CS_HIGH();
}
// Инициализация SPI
void spi_init(void) {
// Включаем тактирование
RCC_APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_SPI1EN;
myDelay(1000);
// Настройка PA5 (SCLK) как альтернативная функция push-pull
GPIOA_CRL &= ~(0xF << 20); // Очистка битов для PA5
GPIOA_CRL |= (0xB << 20); // 1011 = Alternate function push-pull 50MHz
// Настройка PA7 (MOSI) как альтернативная функция push-pull
GPIOA_CRL &= ~(0xF << 28); // Очистка битов для PA7
GPIOA_CRL |= (0xB << 28); // 1011 = Alternate function push-pull 50MHz
// Настройка PB0 (RES), PB1 (DC), PB10 (CS) как выходы
// PB0 (CRL биты 0-3)
GPIOB_CRL &= ~0xF;
GPIOB_CRL |= 0x3; // 0011 = Push-pull output 50MHz
// PB1 (CRL биты 4-7)
GPIOB_CRL &= ~(0xF << 4);
GPIOB_CRL |= (0x3 << 4);
// PB10 (CRH биты 8-11)
GPIOB_CRH &= ~(0xF << 8);
GPIOB_CRH |= (0x3 << 8);
// Установка начального состояния
CS_HIGH();
DC_HIGH();
RES_HIGH();
// Настройка SPI
SPI1_CR1 = SPI_CR1_MSTR | SPI_CR1_BR | SPI_CR1_SSI | SPI_CR1_SSM;
SPI1_CR1 |= SPI_CR1_SPE;
}
// Инициализация дисплея ILI9341
void ili9341_init(void) {
// Сброс дисплея
RES_LOW();
myDelay(100000);
RES_HIGH();
myDelay(100000);
send_cmd(0x01); // Software Reset
myDelay(100000);
send_cmd(0x36); // Memory Access Control
send_data(0x48); // Ориентация
send_cmd(0x3A); // Pixel Format Set
send_data(0x55); // 16-bit color
send_cmd(0x11); // Sleep Out
myDelay(100000);
send_cmd(0x29); // Display On
myDelay(10000);
}
// Главная функция
int main(void) {
// Инициализация
spi_init();
ili9341_init();
// Основной цикл - мигаем разными цветами
while(1) {
fill_screen(RED); // Красный
myDelay(2000000);
fill_screen(GREEN); // Зеленый
myDelay(2000000);
fill_screen(BLUE); // Синий
myDelay(2000000);
fill_screen(YELLOW); // Желтый
myDelay(2000000);
fill_screen(CYAN); // Голубой
myDelay(2000000);
fill_screen(MAGENTA); // Пурпурный
myDelay(2000000);
fill_screen(WHITE); // Белый
myDelay(2000000);
fill_screen(BLACK); // Черный
myDelay(2000000);
}
return 0;
}