{"id":315961,"date":"2021-01-04T21:00:21","date_gmt":"2021-01-04T21:00:21","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=315961"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=315961","title":{"rendered":"\u041f\u0438\u0448\u0435\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440\u0430 \u0434\u043b\u044f Raspberry Pi \u0441 LCD"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\n<p>\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0432 \u043c\u043e\u043d\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0435\u0440\u0438\u044e <a href=\"https:\/\/habr.com\/ru\/post\/163689\/\">\u0441\u0442\u0430\u0442\u0435\u0439<\/a> \u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 LCD \u044d\u043a\u0440\u0430\u043d\u0430 \u043a \u0440\u043e\u0443\u0442\u0435\u0440\u0443 \u043c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u043d\u043e\u0433\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430 (openwrt, stm32, usb) \u0432 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0438 \u0441 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0445 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u0434\u0430 <del>\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043b\u043e\u0445\u043e \u0438\u0441\u043a\u0430\u043b<\/del> \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u0438\u043b\u043e \u0437\u0430\u0434\u0430\u0447\u0443. \u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043c\u0430\u043b\u043e\u0433\u043e \u2014 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e framebuffer \u0434\u043b\u044f raspberry \u0438 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0440\u0435\u0434\u0443 raspberry \u043d\u0430 LCD. \u0427\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0412\u043e\u043e\u0431\u0449\u0435-\u0442\u043e \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u044b \u0434\u043b\u044f LCD (\u043f\u0440\u043e\u0435\u043a\u0442 tbtft), \u043d\u043e \u043c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0441\u0432\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a \u0432\u0441\u0435 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e.<\/p>\n<p>  <\/p>\n<h2 id=\"lcd\">LCD<\/h2>\n<p>  <\/p>\n<p>LCD 320&#215;240 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u043c ILI9341. \u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e 8 \u0431\u0438\u0442\u043d\u043e\u0439 \u0448\u0438\u043d\u0435.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/nj\/yy\/ms\/njyymskmhmnhsglyzoaoo-dw8ga.jpeg\"><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/2u\/ts\/jl\/2utsjlzmawr5geq6vmwjd4bsrdc.jpeg\"><\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0438\u0441\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 LCD \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c <a href=\"https:\/\/cdn-shop.adafruit.com\/datasheets\/ILI9341.pdf\" rel=\"nofollow\">(\u0441\u0442\u0440.28)<\/a>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/04\/t3\/zb\/04t3zbpzsifvkcndgx4h8clw3l4.png\"><\/p>\n<p>  <\/p>\n<p>1 \u043d\u0430 RD \u0438 1 \u043d\u0430 RESET \u043f\u043e\u0441\u043b\u0435 \u0441\u0442\u0430\u0440\u0442\u0430 LCD \u0434\u0435\u0440\u0436\u0438\u043c \u0432\u0441\u0435 \u0432\u0440\u0435\u043c\u044f. \u041f\u0435\u0440\u0435\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0434\u0430\u0435\u043c 0 \u043d\u0430 CS, \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c 8 \u0431\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0448\u0438\u043d\u0435, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c 1 \u0438\u043b\u0438 0 \u043d\u0430 RS (D\/CX \u043d\u0430 \u0433\u0440\u0430\u0444\u0438\u043a\u0435) \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u2014 \u0434\u0430\u043d\u043d\u044b\u0435 \/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430, \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c WR \u0432 0, \u0437\u0430\u0442\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432 1. \u041f\u043e\u0441\u043b\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c CS \u0432 1.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \/ \u043a\u043e\u043c\u0430\u043d\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b lcd.c *\/ void LCD_write(u8 VAL) {     LCD_CS_CLR;     DATAOUT(VAL);     LCD_WR_CLR;     LCD_WR_SET;     LCD_CS_SET; }  \/* \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b *\/ void LCD_WR_REG(u8 data) {     LCD_RS_CLR;     LCD_write(data); }  \/* \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 *\/ void LCD_WR_DATA(u8 data) {     LCD_RS_SET;     LCD_write(data); }  \/* \u0437\u0430\u043f\u0438\u0441\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 *\/ void LCD_WriteReg(u8 LCD_Reg, u8 LCD_RegValue) {     LCD_WR_REG(LCD_Reg);     LCD_WR_DATA(LCD_RegValue); }  \/* \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 16 \u0431\u0438\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 *\/ void Lcd_WriteData_16Bit(u16 Data) {     LCD_RS_SET;     LCD_CS_CLR;     DATAOUT((u8)(Data&gt;&gt;8));     LCD_WR_CLR;     LCD_WR_SET;     DATAOUT((u8)Data);     LCD_WR_CLR;     LCD_WR_SET;     LCD_CS_SET; }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f LCD (\u0434\u043b\u044f STM32), \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0432\u0437\u044f\u0442 <a href=\"http:\/\/www.lcdwiki.com\/2.8inch_Arduino_Display\" rel=\"nofollow\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a> \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f raspberry. \u0426\u0432\u0435\u0442 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u043d\u0430 LCD \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f 16 \u0431\u0438\u0442\u0430\u043c\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 RGB565 (5 \u0431\u0438\u0442 \u043d\u0430 \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u0446\u0432\u0435\u0442, 6 \u043d\u0430 \u0437\u0435\u043b\u0435\u043d\u044b\u0439, 5 \u043d\u0430 \u0441\u0438\u043d\u0438\u0439).<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f LCD<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b lcd.h *\/ #define LCD_W 320 #define LCD_H 240  \/* \u0444\u0430\u0439\u043b lcd.c *\/ \/* \u0438\u043d\u0434\u0438\u043a\u0430\u0446\u0438\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0430\u043b\u0435\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0432\u0438\u0434\u0435\u043e\u0431\u0443\u0444\u0435\u0440\u0430 *\/ void LCD_WriteRAM_Prepare(void) {     LCD_WR_REG(0x2C); }  \/* \u0437\u0430\u0434\u0430\u0435\u043c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c *\/ void LCD_SetWindows(u16 xStart, u16 yStart,u16 xEnd,u16 yEnd) {     LCD_WR_REG(0x2A);     LCD_WR_DATA(xStart&gt;&gt;8);     LCD_WR_DATA(0x00FF&amp;xStart);     LCD_WR_DATA(xEnd&gt;&gt;8);     LCD_WR_DATA(0x00FF&amp;xEnd);      LCD_WR_REG(0x2B);     LCD_WR_DATA(yStart&gt;&gt;8);     LCD_WR_DATA(0x00FF&amp;yStart);     LCD_WR_DATA(yEnd&gt;&gt;8);     LCD_WR_DATA(0x00FF&amp;yEnd);      LCD_WriteRAM_Prepare(); }  \/* \u0440\u0435\u0441\u0435\u0442 \u044d\u043a\u0440\u0430\u043d\u0430 *\/ void LCD_RESET(void) {     LCD_RST_CLR;     delay(100);     LCD_RST_SET;     delay(50); }  \/* \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0440\u0430\u043d\u0430 *\/ void LCD_Init(void) {     LCD_RESET();     LCD_WR_REG(0xCF);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0xC9);     LCD_WR_DATA(0X30);     LCD_WR_REG(0xED);     LCD_WR_DATA(0x64);     LCD_WR_DATA(0x03);     LCD_WR_DATA(0X12);     LCD_WR_DATA(0X81);     LCD_WR_REG(0xE8);     LCD_WR_DATA(0x85);     LCD_WR_DATA(0x10);     LCD_WR_DATA(0x7A);     LCD_WR_REG(0xCB);     LCD_WR_DATA(0x39);     LCD_WR_DATA(0x2C);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x34);     LCD_WR_DATA(0x02);     LCD_WR_REG(0xF7);     LCD_WR_DATA(0x20);     LCD_WR_REG(0xEA);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_REG(0xC0);         LCD_WR_DATA(0x1B);        LCD_WR_REG(0xC1);         LCD_WR_DATA(0x00);        LCD_WR_REG(0xC5);         LCD_WR_DATA(0x30);        LCD_WR_DATA(0x30);        LCD_WR_REG(0xC7);        LCD_WR_DATA(0XB7);     LCD_WR_REG(0x36);         LCD_WR_DATA(0x08);     LCD_WR_REG(0x3A);     LCD_WR_DATA(0x55);     LCD_WR_REG(0xB1);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x1A);     LCD_WR_REG(0xB6);         LCD_WR_DATA(0x0A);     LCD_WR_DATA(0xA2);     LCD_WR_REG(0xF2);         LCD_WR_DATA(0x00);     LCD_WR_REG(0x26);         LCD_WR_DATA(0x01);     LCD_WR_REG(0xE0);         LCD_WR_DATA(0x0F);     LCD_WR_DATA(0x2A);     LCD_WR_DATA(0x28);     LCD_WR_DATA(0x08);     LCD_WR_DATA(0x0E);     LCD_WR_DATA(0x08);     LCD_WR_DATA(0x54);     LCD_WR_DATA(0XA9);     LCD_WR_DATA(0x43);     LCD_WR_DATA(0x0A);     LCD_WR_DATA(0x0F);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_REG(0XE1);         LCD_WR_DATA(0x00);     LCD_WR_DATA(0x15);     LCD_WR_DATA(0x17);     LCD_WR_DATA(0x07);     LCD_WR_DATA(0x11);     LCD_WR_DATA(0x06);     LCD_WR_DATA(0x2B);     LCD_WR_DATA(0x56);     LCD_WR_DATA(0x3C);     LCD_WR_DATA(0x05);     LCD_WR_DATA(0x10);     LCD_WR_DATA(0x0F);     LCD_WR_DATA(0x3F);     LCD_WR_DATA(0x3F);     LCD_WR_DATA(0x0F);     LCD_WR_REG(0x2B);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x01);     LCD_WR_DATA(0x3f);     LCD_WR_REG(0x2A);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0x00);     LCD_WR_DATA(0xef);     LCD_WR_REG(0x11);      delay(120);     LCD_WR_REG(0x29);      LCD_WriteReg(0x36,(1&lt;&lt;3)|(1&lt;&lt;5)|(1&lt;&lt;6));  }  \/* \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u044d\u043a\u0440\u0430\u043d \u043e\u0434\u043d\u0438\u043c \u0446\u0432\u0435\u0442\u043e\u043c *\/ void LCD_Clear(u16 Color) {     unsigned int i;     LCD_SetWindows(0,0,LCD_W-1,LCD_H-1);     for(i=0;i&lt;LCD_H*LCD_W;i++)     {         Lcd_WriteData_16Bit(Color);     } }  \/* \u0440\u0438\u0441\u0443\u0435\u043c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 \u0438\u0437 raw \u0444\u0430\u0439\u043b\u0430 (\u0432 \u043d\u0435\u043c \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0442 \u0446\u0432\u0435\u0442\u0430 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 RGB565) *\/ void LCD_draw_image(char *file){     int fd = open(file, O_RDWR);     if(fd &lt; 0){         perror(&quot;Open file&quot;);         exit(1);     }     u16 buffer[128];     LCD_SetWindows(0,0,LCD_W-1,LCD_H-1);     while(1){         int nread = read(fd, buffer, 256);         if(nread == 0 || nread &lt; 0)             break;         \/* buffer[i] - 2 \u0431\u0430\u0439\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0438\u0448\u0435\u043c nread\/2 \u0440\u0430\u0437 *\/         for(int i=0; i &lt; nread\/2; i++){             Lcd_WriteData_16Bit(buffer[i]);         }     }     close(fd); }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h2 id=\"raspberry\">Raspberry<\/h2>\n<p>  <\/p>\n<p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e raspberry pi 3 \u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c raspbian lite (\u0432\u0435\u0440\u0441\u0438\u044f \u044f\u0434\u0440\u0430 4.14). GUI \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 lxde \u0438 xinit.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">sudo apt-get install lxde xinit<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"raspolozhenie-gpio\">\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 GPIO<\/h3>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/g7\/tc\/1g\/g7tc1g883sfphg2xk5xdhofygre.png\"><\/p>\n<p>  <\/p>\n<h3 id=\"podklyuchenie-lcd-k-raspberry\">\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 LCD \u043a raspberry<\/h3>\n<p>  <\/p>\n<ul>\n<li>LCD Data 0 -&gt; GPIO 12<\/li>\n<li>LCD Data 1 -&gt; GPIO 13<\/li>\n<li>&#8230;<\/li>\n<li>LCD Data 7 -&gt; GPIO 19<\/li>\n<li>LCD CS -&gt; GPIO 20<\/li>\n<li>LCD RS -&gt; GPIO 21<\/li>\n<li>LCD RST -&gt; GPIO 22<\/li>\n<li>LCD WR -&gt; GPIO 23<\/li>\n<li>LCD RD -&gt; GRPIO 24<\/li>\n<li>LCD 5V -&gt; 5V<\/li>\n<li>LCD GND -&gt; Ground<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"upravlenie-gpio\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 GPIO<\/h3>\n<p>  <\/p>\n<p>\u0412 raspberry GPIO \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u044f\u043c\u043e\u0435 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u0430\u043c\u044f\u0442\u0438. \u0418\u0437 \u043c\u0430\u043d\u0443\u0430\u043b\u0430 \u043a <a href=\"https:\/\/cs140e.sergio.bz\/docs\/BCM2837-ARM-Peripherals.pdf\" rel=\"nofollow\">BCM 2837<\/a> 32 \u0431\u0438\u0442\u043d\u044b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b GPFSEL0-5 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0435\u0436\u0438\u043c\u0430 GPIO. \u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 GPIO \u043f\u0438\u043d \u043e\u0442\u0432\u043e\u0434\u0438\u0442\u0441\u044f 3 \u0431\u0438\u0442\u0430. \u041f\u0438\u043d\u0443 0 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0431\u0438\u0442\u044b 2-0 \u0432 GPFSEL0, \u043f\u0438\u043d\u0443 1 \u0431\u0438\u0442\u044b 5-3 \u0438 \u0442.\u0434. \u041a\u0430\u0436\u0434\u044b\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 10 GPIO. \u0411\u0438\u0442\u044b 000 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u0435\u0436\u0438\u043c\u0443 input, \u0431\u0438\u0442\u044b 001 \u0440\u0435\u0436\u0438\u043c\u0443 output. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0440\u0435\u0436\u0438\u043c\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b rpi_gpio.h *\/ \/* \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 input \u0440\u0435\u0436\u0438\u043c\u0430 *\/ #define INP_GPIO(g) *(gpio+((g)\/10)) &amp;= ~(7&lt;&lt;(((g)%10)*3)) \/* \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 output \u0440\u0435\u0436\u0438\u043c\u0430 *\/ #define OUT_GPIO(g) *(gpio+((g)\/10)) |=  (1&lt;&lt;(((g)%10)*3))<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u0438\u043d\u043e\u0432 0 \u2014 31 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 output \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 1 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 GPSET0. \u0427\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c GPIO n \u0432 1, \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0447\u0438\u0441\u043b\u043e, n-\u044b\u0439 \u0431\u0438\u0442 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0432\u0435\u043d 1. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 1 \u0432 GPIO 10 \u0438 11 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 GPSET0 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0447\u0438\u0441\u043b\u043e 0b11 &lt;&lt; 10.<\/p>\n<p>  <\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 0 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 GPCLR0.<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">\/* \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c 1 \u043d\u0430 GPIO, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 1 \u043d\u0430 GPIO 10 - GPIO_SET = 1&lt;&lt;10 *\/ #define GPIO_SET *(gpio+7) \/*  \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c 0 \u043d\u0430 GPIO, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, 0 \u043d\u0430 GPIO 10 - GPIO_CLR = 1&lt;&lt;10 *\/ #define GPIO_CLR *(gpio+10)<\/code><\/pre>\n<p>  <\/p>\n<p>gpio \u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u0434\u0440\u0435\u0441 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430 0x3F200000 (\u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c mmap \u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430). *gpio \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a GPFSEL0. *(gpio+7) \u043a GPSET0. *(gpio+10) \u043a GPCLR0.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 gpio<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b rpi_gpio.c *\/ int setup_rpi_gpio() {     unsigned int gpio_base_addr = 0x3F200000;     \/* open \/dev\/mem *\/    if ((mem_fd = open(&quot;\/dev\/mem&quot;, O_RDWR|O_SYNC) ) &lt; 0) {       printf(&quot;can't open \/dev\/mem \\n&quot;);       return -1;    }     \/* mmap GPIO *\/    gpio_map = mmap(       NULL,             \/\/Any adddress in our space will do       BLOCK_SIZE,       \/\/Map length       PROT_READ|PROT_WRITE,\/\/ Enable reading &amp; writting to mapped memory       MAP_SHARED,       \/\/Shared with other processes       mem_fd,           \/\/File to map       gpio_base_addr    \/\/Offset to GPIO peripheral    );     close(mem_fd); \/\/No need to keep mem_fd open after mmap     if (gpio_map == MAP_FAILED) {       printf(&quot;mmap error %d\\n&quot;, (int)gpio_map);\/\/errno also set!       return -1;    }     \/\/ Always use volatile pointer!    gpio = (volatile uint32_t *)gpio_map;    return 0; }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"upravlenie-lcd-c-raspberry\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 LCD c raspberry<\/h3>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0438\u043d\u0430\u043c\u0438 LCD \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b lcd.h *\/ #define BIT_BASE 12 #define CS   20 #define RS   21 #define RST  22 #define WR   23 #define RD   24  #define LCD_CS_SET  GPIO_SET=(1&lt;&lt;CS) #define LCD_RS_SET  GPIO_SET=(1&lt;&lt;RS) #define LCD_RST_SET GPIO_SET=(1&lt;&lt;RST) #define LCD_WR_SET  GPIO_SET=(1&lt;&lt;WR) #define LCD_RD_SET  GPIO_SET=(1&lt;&lt;RD)  #define LCD_CS_CLR  GPIO_CLR=(1&lt;&lt;CS) #define LCD_RS_CLR  GPIO_CLR=(1&lt;&lt;RS) #define LCD_RST_CLR GPIO_CLR=(1&lt;&lt;RST) #define LCD_WR_CLR  GPIO_CLR=(1&lt;&lt;WR) #define LCD_RD_CLR  GPIO_CLR=(1&lt;&lt;RD)  #define DATAOUT(x) GPIO_SET=(x&lt;&lt;BIT_BASE);GPIO_CLR=(x&lt;&lt;BIT_BASE)^(0xFF&lt;&lt;BIT_BASE)<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"proverka-raboty-s-lcd-v-user-space\">\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 LCD \u0432 user space<\/h3>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u0431\u0440\u043e\u0441\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0443\u0447\u0438\u043d\u0443 kernel, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 LCD \u0432 user space. \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 image.jpg \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 raw 320&#215;240. \u0412 output.raw \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0449\u0438\u0435 16 \u0431\u0438\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u0430 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f (RGB565):<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">mogrify -format bmp -resize 320 -crop 320x240 image.jpg ffmpeg -vcodec bmp -i image.bmp -vcodec rawvideo -f rawvideo -pix_fmt rgb565 output.raw<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u0432\u0435\u0434\u0435\u043c output.raw \u043d\u0430 LCD:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b main.c *\/ int main(int argc , char *argv[]){     if( setup_rpi_gpio() ) {         printf(&quot;Cannot map GPIO memory, probably use &lt;sudo&gt;\\n&quot;);         return -1;     }     for(int i = BIT_BASE; i &lt;= RD; i++){         INP_GPIO(i);         OUT_GPIO(i);     }     \/\/set BITS_BASE - RD to 1     GPIO_SET = 0xFFF&lt;&lt;12;     GPIO_SET = 1 &lt;&lt; RD;     LCD_Init();      if(argc &gt;= 2){         LCD_draw_image(argv[1]);     } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">gcc main.c rpi_gpio.c lcd.c -o main sudo .\/main output.raw<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/jt\/tw\/km\/jttwkm8dwr2sixhvhdei6vio82i.jpeg\"><\/p>\n<p>  <\/p>\n<h3 id=\"podgotovka-okruzheniya\">\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u044f\u0434\u0440\u0430 \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u044f\u0434\u0440\u0430 \u0432 raspbian \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043a\u0430\u0447\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 linux, \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u044f\u0434\u0440\u043e, \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0441\u043e \u0441\u043a\u0440\u0438\u043f\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 reference \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0443 <a href=\"https:\/\/www.raspberrypi.org\/documentation\/linux\/kernel\/building.md\" rel=\"nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>. \u0412\u0435\u0440\u0441\u0438\u044f \u0441\u043e\u0440\u0446\u043e\u0432 \u044f\u0434\u0440\u0430 \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043d\u0430 \u043f\u043e\u0434 \u043c\u043e\u044e \u0432\u0435\u0440\u0441\u0438\u044e raspbian. <\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">git clone --depth=1 -b rpi-4.14.y https:\/\/github.com\/raspberrypi\/linux.git cd linux KERNEL=kernel7 make bcm2709_defconfig make -j4 zImage modules dtbs sudo make modules_install sudo cp arch\/arm\/boot\/dts\/*.dtb \/boot\/ sudo cp arch\/arm\/boot\/dts\/overlays\/*.dtb* \/boot\/overlays\/ sudo cp arch\/arm\/boot\/dts\/overlays\/README \/boot\/overlays\/ sudo cp arch\/arm\/boot\/zImage \/boot\/$KERNEL.img <\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 make, \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0432 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 Makefile:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">Makefile<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"bash\">ifeq ($(KERNELRELEASE),)      KERNELDIR ?= \/lib\/modules\/$(shell uname -r)\/build         PWD := $(shell pwd)  modules:     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules  modules_install:     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install  clean:     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions  .PHONY: modules modules_install clean  else     # \u0438\u043c\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430, \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c vfb.c, \u0437\u0430\u043c\u0435\u043d\u0438\u043c \u043d\u0430 vfb.o         obj-m := lcd_drv_simple.o endif<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"drayver-freymbufera\">\u0414\u0440\u0430\u0439\u0432\u0435\u0440 \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440\u0430<\/h3>\n<p>  <\/p>\n<p>\u0422\u0435\u043e\u0440\u0438\u044f \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440\u043e\u0432 \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0430 <a href=\"https:\/\/habr.com\/ru\/post\/163689\/\">\u0437\u0434\u0435\u0441\u044c<\/a> \u0438 <a href=\"https:\/\/habr.com\/ru\/post\/213775\/\">\u0437\u0434\u0435\u0441\u044c<\/a>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440\u0430 (vfb.c). \u041e\u043d \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0438\u0448\u0435\u0442 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u0432 \/dev\/fbX (X \u2014 \u043d\u043e\u043c\u0435\u0440 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430). \u042d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 cat \/dev\/fbX. \u042d\u0442\u043e\u0442 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0443\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e).<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u0434 \u0431\u0435\u0440\u0435\u043c <a href=\"https:\/\/elixir.bootlin.com\/linux\/v3.12.43\/source\/drivers\/video\/vfb.c\" rel=\"nofollow\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a>. \u0414\u0430\u043b\u0435\u0435<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">make sudo cp vfb.ko \/lib\/modules\/$(uname -r)\/extra\/ # \u043f\u0440\u043e\u0441\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 sudo depmod # \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440 sudo modprobe vfb_enable=1 # \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u044d\u043a\u0440\u0430\u043d\u0430 \u0438 \u0433\u043b\u0443\u0431\u0438\u043d\u0443 \u0446\u0432\u0435\u0442\u0430 (16 \u0431\u0438\u0442, \u0440\u0435\u0436\u0438\u043c RGB565) fbset -fb \/dev\/fb1 -g 320 240 320 240 16<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u043e\u0432\u043e\u0435 framebuffer \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e (\/dev\/fb1). \u0417\u0430\u043f\u0438\u0448\u0435\u043c \u0432 \u043d\u0435\u0433\u043e \u043a\u0430\u043a\u043e\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435,<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">sudo apt-get install fbi # fbi \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0437 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u043e\u0434 ssh \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c sudo \u0438 -T 1 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u043a\u043e\u043d\u0441\u043e\u043b\u0438  sudo fbi -a -d \/dev\/fb1 -T 1 image.jpg<\/code><\/pre>\n<p>  <\/p>\n<p>\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0435\u0433\u043e <\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cat \/dev\/fb1 &gt; scrn.raw<\/code><\/pre>\n<p>  <\/p>\n<p>\u0438 \u043e\u0442\u043a\u0440\u043e\u0435\u043c \u0432 gimp \u043a\u0430\u043a \u0444\u0430\u0439\u043b raw rgb565. \u0423\u0431\u0435\u0434\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0435\u0441\u0442\u044c.<\/p>\n<p>  <\/p>\n<h3 id=\"prostoy-drayver\">\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440<\/h3>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0443 LCD. \u0412\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \u043d\u0435 \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0435\u043c, \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u0431\u0435\u0440\u0435\u043c \u043a\u043e\u0434 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0438\u0437 \u0442\u043e\u0439 \u0436\u0435 <a href=\"https:\/\/habr.com\/ru\/post\/163689\/\">\u0441\u0442\u0430\u0442\u044c\u0438<\/a>. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043c \u0441\u0435\u0431\u0435 \u0436\u0438\u0437\u043d\u044c \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u0432 LCD \u043f\u0438\u0448\u0435\u043c \u0432\u0435\u0441\u044c \u0432\u0438\u0434\u0435\u043e\u0431\u0443\u0444\u0435\u0440, \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u043a\u0443\u0441\u043e\u0447\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0440\u0435\u0436\u0438\u043c\u0430 \u0438 \u0443\u0440\u043e\u0432\u043d\u044f (1\/0) \u043f\u0438\u043d\u043e\u0432 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c (\u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u044f\u043c\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a I\/O \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 \u044f\u0434\u0440\u0435 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442):<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b lcd_drv_simple.c *\/ static void inp_gpio(u32 g){     u32 *addr = gpio+g\/10;     u32 val = readl(addr);     u32 tmp =  ~(7&lt;&lt;((g%10)*3));     val &amp;= tmp;     writel(val,addr); } static void out_gpio(u32 g){     u32 *addr = gpio+g\/10;     u32 val = readl(addr);     u32 tmp =  (1&lt;&lt;(((g)%10)*3));     val |= tmp;     writel(val,addr); } static void GPIO_SET(u32 val){     writel(val,gpio+7); } static void GPIO_CLR(u32 val){     writel(val,gpio+10); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410\u0434\u0440\u0435\u0441 gpio \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u043c ioremap:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">gpio = ioremap(PORT, RANGE);<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u0445:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">u32 *gpio; static unsigned PORT = 0x3F200000; static unsigned RANGE =  0x40;  #define W 320 #define H 240  static struct fb_fix_screeninfo ili9341_fix  = {         .type        = FB_TYPE_PACKED_PIXELS,         .visual      = FB_VISUAL_TRUECOLOR,         .accel       = FB_ACCEL_NONE,         .line_length = W * 2, };  static struct fb_var_screeninfo ili9341_var  = {         .xres        = W,         .yres        = H,         .xres_virtual    = W,         .yres_virtual    = H,         .width        = W,         .height        = H,         .bits_per_pixel = 16,         .red         = {11, 5, 0}, \/* \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 11 \u0431\u0438\u0442, 5 \u0431\u0438\u0442\u043e\u0432 \u043d\u0430 \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 *\/         .green         = {5, 6, 0}, \/* \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 5 \u0431\u0438\u0442, 6 \u0431\u0438\u0442\u043e\u0432 \u043d\u0430 \u0437\u0435\u043b\u0435\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 *\/         .blue         = {0, 5, 0}, \/* \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 0 \u0431\u0438\u0442, 5 \u0431\u0438\u0442\u043e\u0432 \u043d\u0430 \u0441\u0438\u043d\u0438\u0439 \u0446\u0432\u0435\u0442 *\/         .activate     = FB_ACTIVATE_NOW,         .vmode     = FB_VMODE_NONINTERLACED, };  \/* \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0441 \u0444\u0440\u0435\u0439\u043c\u0431\u0443\u0444\u0435\u0440\u043e\u043c *\/ static struct fb_ops ili9341_fbops = {         .owner        = THIS_MODULE,         .fb_write     = fb_sys_write,         .fb_fillrect  = sys_fillrect,         .fb_copyarea  = sys_copyarea,         .fb_imageblit = sys_imageblit,         .fb_setcolreg   = ili9341_setcolreg, };  \/* \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 probe \u0438 remove *\/ struct platform_driver ili9341_driver = {         .probe = ili9341_probe,         .remove = ili9341_remove,         .driver = { .name = &quot;my_fb_driver&quot; } };  \/* \u0437\u0430\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e ili9341_update, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u044e\u0449\u0443\u044e \u044d\u043a\u0440\u0430\u043d (\u0447\u0430\u0441\u0442\u043e\u0442\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 delay) *\/ static struct fb_deferred_io ili9341_defio = {         .delay          = HZ \/ 25,         .deferred_io    = &amp;ili9341_update, };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">static int  ili9341_probe(struct platform_device *dev) {     int ret = 0;     struct ili9341 *item;     struct fb_info *info;     unsigned char  *videomemory;     printk(&quot;ili9341_probe\\n&quot;);      \/*\u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 *\/     item = kzalloc(sizeof(struct ili9341), GFP_KERNEL);     if (!item) {         printk(KERN_ALERT &quot;unable to kzalloc for ili9341\\n&quot;);         ret = -ENOMEM;         goto out;     }      \/* \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0435 *\/     item-&gt;dev = &amp;dev-&gt;dev;     dev_set_drvdata(&amp;dev-&gt;dev, item);      \/* \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 fb_info *\/     info = framebuffer_alloc(0, &amp;dev-&gt;dev);     if (!info) {         ret = -ENOMEM;         printk(KERN_ALERT &quot;unable to framebuffer_alloc\\n&quot;);         goto out_item;     }     item-&gt;info = info;      \/* \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 fb_info \u043d\u0430\u0448\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 *\/     info-&gt;par = item;     info-&gt;dev = &amp;dev-&gt;dev;     info-&gt;fbops = &amp;ili9341_fbops;     info-&gt;flags = FBINFO_FLAG_DEFAULT;     info-&gt;fix = ili9341_fix;     info-&gt;var = ili9341_var;     info-&gt;fix.smem_len = VIDEOMEM_SIZE; \/\/ \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0443\u0444\u0435\u0440\u0430 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438     info-&gt;pseudo_palette = &amp;pseudo_palette;      \/* \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u043e\u0434 \u0432\u0438\u0434\u0435\u043e\u0431\u0443\u0444\u0435\u0440, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0438\u0448\u0443\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 \/dev\/fbX *\/     videomemory=vmalloc(info-&gt;fix.smem_len);     if (!videomemory)     {         printk(KERN_ALERT &quot;Can not allocate memory for framebuffer\\n&quot;);         ret = -ENOMEM;         goto out_info;     }      \/* \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 fb_info \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 ili9341 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f *\/     info-&gt;fix.smem_start =(unsigned long)(videomemory);     info-&gt;screen_base = (char __iomem *)info-&gt;fix.smem_start;     item-&gt;videomem = videomemory;      \/* \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 *\/     info-&gt;fbdefio = &amp;ili9341_defio;     fb_deferred_io_init(info);      \/* \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 fb_info \u044f\u0434\u0440\u0443 *\/     ret = register_framebuffer(info);     if (ret &lt; 0) {         printk(KERN_ALERT &quot;unable to register_frambuffer\\n&quot;);         goto out_pages;     }      if (ili9341_setup(item)) goto out_pages;     return ret;      out_pages:     kfree(videomemory);     out_info:     framebuffer_release(info);     out_item:     kfree(item);     out:     return ret; }  int ili9341_setup(struct ili9341 *item) {     int i;      \/* \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0440\u0442\u0430\u043c\u0438 GPIO \u0432 gpio *\/     gpio = ioremap(PORT, RANGE);     if(gpio == NULL){         printk(KERN_ALERT &quot;ioremap error\\n&quot;);         return 1;     }      \/* \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c LCD *\/     for(i = BIT_BASE; i &lt;= RD; i++){         inp_gpio(i);         out_gpio(i);     }     GPIO_SET(0xFFF&lt;&lt;12);     GPIO_SET(1 &lt;&lt; RD);     LCD_Init();     printk(&quot;ili9341_setup\\n&quot;);     return 0; } static void ili9341_update(struct fb_info *info, struct list_head *pagelist) {     \/* \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043d\u0430\u0448\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044f\u043c\u0438 *\/     struct ili9341 *item = (struct ili9341 *)info-&gt;par;     \/* \u0430\u0434\u0440\u0435\u0441 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 *\/     u16 *videomemory = (u16 *)item-&gt;videomem;     int i, j, k;      \/* \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d *\/     LCD_SetWindows(0,0,LCD_W-1,LCD_H-1);         for(i = 0; i &lt; LCD_W * LCD_H; i++){         \/* \u0447\u0438\u0442\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u043e\u043f\u0438\u043a\u0441\u0435\u043b\u044c\u043d\u043e \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u0445 \u0432 LCD *\/         Lcd_WriteData_16Bit(readw(videomemory));         videomemory++;     } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"zapuskaem-graficheskuyu-obolochku-na-lcd\">\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 \u043d\u0430 LCD<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430. \u0421\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u0435\u0433\u043e<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">make sudo cp lcd_drv_simple.ko \/lib\/modules\/$(uname -r)\/extra\/ sudo depmod sudo modprobe lcd_drv_simple<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u0432\u0435\u0434\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cat \/dev\/urandom &gt; \/dev\/fb1<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u0432\u0435\u0434\u0435\u043c \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \/dev\/fbX \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 \u0438\u043b\u0438 \u0432\u0438\u0434\u0435\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">sudo fbi -a -d \/dev\/fb1 -T 1 image.jpg mplayer -vo fbdev:\/dev\/fb1 video.mp4<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 \u043d\u0430 LCD. \u0415\u0441\u043b\u0438 Desktop environment (DE) \u0435\u0449\u0435 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 raspbian), \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">sudo apt-get install lxde<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b \/etc\/X11\/xorg.conf:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">Section &quot;Device&quot;     Identifier &quot;FBDEV&quot;     Driver &quot;fbdev&quot;     Option &quot;fbdev&quot; &quot;\/dev\/fb1&quot; EndSection <\/code><\/pre>\n<p>  <\/p>\n<p>\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \/etc\/rc.local:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">\/sbin\/modprobe lcd_drv_simple<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 LCD \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0430.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/cc\/7z\/yl\/cc7zylvl6csmdovq8r0tc8vlvxm.jpeg\"><\/p>\n<p>  <\/p>\n<h3 id=\"uskoryaem-rabotu-drayvera\">\u0423\u0441\u043a\u043e\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u043f\u0440\u043e\u0441\u0442, \u043d\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440. \u041f\u043e\u043b\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u0437\u0430\u043c\u0435\u0442\u043d\u0430. Deferred_io \u0445\u043e\u0440\u043e\u0448\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u044f\u0434\u0440\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e ili9341_update \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435. \u0422.\u0435. \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u044d\u043a\u0440\u0430\u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c 4096 \u0431\u0430\u0439\u0442\u0430\u043c (\u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043c\u044f\u0442\u0438). <\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u0435\u0440\u0432\u044b\u0435 4096 \u0431\u0430\u0439\u0442\u043e\u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043f\u043e\u043b\u043d\u044b\u043c 6 \u043b\u0438\u043d\u0438\u044f\u043c \u0438 128 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u043c 7\u043e\u0439 \u043b\u0438\u043d\u0438\u0438, \u0442.\u043a. 4096 = 320*2*6 + 128*2 (2 \u0431\u0430\u0439\u0442\u0430 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c)<\/li>\n<li>\u0412\u0442\u043e\u0440\u044b\u0435 4096 \u0431\u0430\u0439\u0442\u043e\u0432 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441 129 \u043f\u0438\u043a\u0441\u0435\u043b\u044f 7\u043e\u0439 \u043b\u0438\u043d\u0438\u0438, \u0442\u0440\u0435\u0431\u0443\u044e\u0442 384 \u0431\u0430\u0439\u0442\u0430 \u0434\u043b\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043b\u0438\u043d\u0438\u0438 (128*2 + 384 = 640), \u0437\u0430\u0442\u0435\u043c \u0438\u0434\u0443\u0442 5 \u043f\u043e\u043b\u043d\u044b\u0445 \u043b\u0438\u043d\u0438\u0439 \u0438 256 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0432 6 \u043b\u0438\u043d\u0438\u0438 (4096 = 384 + 640*5 + 512).<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u043c \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f \u0434\u0430\u043b\u044c\u0448\u0435, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0435 5 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c 5 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043c\u044f\u0442\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439 \u043d\u043e\u043c\u0435\u0440 37, \u0442.\u043a. \u043e\u043d\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 2048 \u0431\u0430\u0439\u0442\u043e\u0432:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b lcd_drv_fast.c *\/  \/* \u0434\u0430\u043b\u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e \u0444\u0430\u043a\u0442\u0443 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0443\u0436\u043d\u044b, \u0442.\u043a. \u043c\u0435\u0442\u043e\u0434 ili9341_touch \u043d\u0430 raspberry \u043d\u0438 \u0440\u0430\u0437\u0443 \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u0441\u044f (\u0442.\u0435. \u043d\u0435\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0445 toUpdate \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e *\/  static void ili9341_update(struct fb_info *info, struct list_head *pagelist) {     struct ili9341 *item = (struct ili9341 *)info-&gt;par;     struct page *page;     int i;         \/* \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0432\u044b\u0447\u0438\u0442\u0430\u0435\u043c 1 \u0438\u0437 toUpdate \u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e, toUpdate \u0434\u043b\u044f \u044d\u0442\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 -2 *\/      list_for_each_entry(page, pagelist, lru)     {         atomic_dec(&amp;item-&gt;videopages[page-&gt;index].toUpdate);     }     for (i=0; i&lt;FP_PAGE_COUNT; i++)     {         \/* \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c toUpdate \u043d\u0430 1. \u0415\u0441\u043b\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0435\u043d\u0430, \u0442\u043e \u0432\u044b\u0447\u0442\u0435\u043c 1 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c -1. \u0415\u0441\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430, \u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043c -1 \u043f\u043e\u0441\u043b\u0435 \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430, \u043d\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0449\u0435 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b *\/         if(atomic_inc_and_test(&amp;item-&gt;videopages[i].toUpdate)){             atomic_dec(&amp;item-&gt;videopages[i].toUpdate);         }         else         {             draw(item, i);                   }     }  } static void draw(struct ili9341 *item, int page){     int xs,ys,i;     \/* \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 \u0432\u0438\u0434\u0435\u043e\u043f\u0430\u043c\u044f\u0442\u0438 *\/     u16 *videomemory = (u16*)(item-&gt;videomem + PAGE_SIZE*page);      \/* \u0441\u0442\u0440\u043e\u043a\u0430 LCD, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 *\/     ys = (((unsigned long)(PAGE_SIZE*page)&gt;&gt;1)\/W);      \/* \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043f\u0430\u043c\u044f\u0442\u0438, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e *\/     if (page == 37){         \/\/ write PAGE_SIZE \/ 2;         \/\/write 128 bytes         LCD_SetWindows(256, ys, LCD_W-1, ys);         for(i = 0; i &lt; 128 \/ 2; i++){             Lcd_WriteData_16Bit(readw(videomemory));             videomemory++;         }         \/\/write 3 lines         LCD_SetWindows(0, ys+1, LCD_W-1, ys+6);         for(i = 0; i &lt; 640 * 3 \/ 2; i++){             Lcd_WriteData_16Bit(readw(videomemory));             videomemory++;         }      }     else{         switch (page % 5){         \/\/xs = 0. write full six lines and 256 bytes         \/\/640 * 6 + 256         case 0:             \/\/write 6 lines             LCD_SetWindows(0,ys,LCD_W-1,ys + 5);             for(i = 0; i &lt; 640 * 6 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 256 bytes             LCD_SetWindows(0, ys+6, 256\/2-1, ys + 6); \/\/7th line from x = 0 to x = 256\/2             for(i = 0; i &lt; 256 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             break;         \/\/xs = 128 (256 bytes). write 384 bytes, 5 full lines and 512 bytes         \/\/384 + 640 * 5 + 512         case 1:             \/\/write 384 bytes             LCD_SetWindows(256\/2, ys, LCD_W-1, ys);             for(i = 0; i &lt; 384 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 5 lines             LCD_SetWindows(0, ys+1, LCD_W-1, ys+5);             for(i = 0; i &lt; 640 * 5 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 512 bytes             LCD_SetWindows(0, ys+6, 512\/2-1, ys+6);             for(i = 0; i &lt; 512 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             break;         \/\/xs = 256 (512 bytes). write 128 bytes, then 6 full lines and 128 bytes         \/\/128 + 640*6 + 128         case 2:             \/\/write 128 bytes             LCD_SetWindows(256, ys, LCD_W-1, ys);             for(i = 0; i &lt; 128 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 6 lines             LCD_SetWindows(0, ys+1, LCD_W-1, ys+6);             for(i = 0; i &lt; 640 * 6 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 128 bytes             LCD_SetWindows(0, ys+7, 128\/2-1, ys+7);             for(i = 0; i &lt; 128 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             break;         \/\/xs = 64 (128 \/2). write 512 bytes, then 5 lines and 384 bytes         \/\/512 + 640*5 + 384         case 3:             \/\/write 512 bytes             LCD_SetWindows(64, ys, LCD_W-1, ys);             for(i = 0; i &lt; 512 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 5 lines             LCD_SetWindows(0, ys+1, LCD_W-1, ys+5);             for(i = 0; i &lt; 640 * 5 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             \/\/write 384 bytes             LCD_SetWindows(0, ys+6, 384\/2-1, ys+6);             for(i = 0; i &lt; 384 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             break;         \/\/xs = 384\/2. write 256 bytes, then 6 full lines         \/\/256 + 640*6         case 4:             \/\/write 256 bytes             LCD_SetWindows(384\/2, ys, LCD_W-1, ys);             for(i = 0; i &lt; 256 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             LCD_SetWindows(0, ys+1, LCD_W-1, ys+6);             for(i = 0; i &lt; 640 * 6 \/ 2; i++){                 Lcd_WriteData_16Bit(readw(videomemory));                 videomemory++;             }             break;         default: break;          }     } } <\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 ili9341 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 ili9341_probe:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">struct videopage {     atomic_t                toUpdate; }; struct ili9341 {     struct device *dev;     struct fb_info *info;     unsigned char *videomem;     \/* \u0437\u0434\u0435\u0441\u044c \u043e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u043f\u0430\u043c\u044f\u0442\u0438 *\/     struct videopage videopages[FP_PAGE_COUNT]; }; static int  ili9341_probe(struct platform_device *dev){     ...     \/* \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043f\u0430\u043c\u044f\u0442\u0438 *\/     for(i=0;i&lt;FP_PAGE_COUNT;i++)     {         atomic_set(&amp;item-&gt;videopages[i].toUpdate, -1);           } } <\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 ili9341_fbops \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u0430\u043a \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043c\u0435\u0447\u0430\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 ili9341_touch. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u044f\u0434\u0440\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438, \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 ili9341_fbops, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0430\u043c\u044f\u0442\u0438 \u0432 ili9341_update \u043d\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0438 \u0438\u0445 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u0435\u0447\u0430\u0442\u044c. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0436\u0435, \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 raspbian \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">static struct fb_ops ili9341_fbops = {         .owner        = THIS_MODULE,         .fb_write     = ili9341_write,         .fb_fillrect  = ili9341_fillrect,         .fb_copyarea  = ili9341_copyarea,         .fb_imageblit = ili9341_imageblit,         .fb_setcolreg   = ili9341_setcolreg, };  static ssize_t ili9341_write(struct fb_info *p, const char __user *buf, size_t count, loff_t *ppos){     ssize_t retval;     printk(&quot;ili9341_write\\n&quot;);     retval=fb_sys_write(p, buf, count, ppos);     ili9341_touch(p, 0, 0, p-&gt;var.xres, p-&gt;var.yres);     return retval; } static void ili9341_fillrect(struct fb_info *p, const struct fb_fillrect *rect) {     printk(&quot;ili9341_fillrect\\n&quot;);     sys_fillrect(p, rect);     ili9341_touch(p, rect-&gt;dx, rect-&gt;dy, rect-&gt;width, rect-&gt;height); } static void ili9341_imageblit(struct fb_info *p, const struct fb_image *image) {     printk(&quot;ili9341_imageblit\\n&quot;);     sys_imageblit(p, image);     ili9341_touch(p, image-&gt;dx, image-&gt;dy, image-&gt;width, image-&gt;height); }  static void ili9341_copyarea(struct fb_info *p, const struct fb_copyarea *area) {     printk(&quot;ili9341_copyarea\\n&quot;);     sys_copyarea(p, area);     ili9341_touch(p, area-&gt;dx, area-&gt;dy, area-&gt;width, area-&gt;height); } static void ili9341_touch(struct fb_info *info, int x, int y, int w, int h) {      struct ili9341 *item = (struct ili9341 *)info-&gt;par;     int firstPage;     int lastPage;     int i;     printk(&quot;touch x %d, y %d, w %d, h %d&quot;,x,y,w,h);     firstPage=((y*W)+x)*BYTE_DEPTH\/PAGE_SIZE-1;     lastPage=(((y+h)*W)+x+w)*BYTE_DEPTH\/PAGE_SIZE+1;      if(firstPage&lt;0)         firstPage=0;     if(lastPage&gt;FP_PAGE_COUNT)         lastPage=FP_PAGE_COUNT;      for(i=firstPage;i&lt;lastPage;i++)         atomic_dec(&amp;item-&gt;videopages[i].toUpdate);      schedule_delayed_work(&amp;info-&gt;deferred_work, info-&gt;fbdefio-&gt;delay); }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"sistema-s-dvumya-ekranami\">\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0441 \u0434\u0432\u0443\u043c\u044f \u044d\u043a\u0440\u0430\u043d\u0430\u043c\u0438<\/h3>\n<p>  <\/p>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u044d\u043a\u0441\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c. \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u043a raspberry \u0434\u0432\u0430 \u044d\u043a\u0440\u0430\u043d\u0430. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u044d\u043a\u0440\u0430\u043d \/ \u0442\u0435\u043b\u0435\u0432\u0438\u0437\u043e\u0440, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0439 \u043a HDMI. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c LCD.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043e\u043a\u043e\u0448\u0435\u043a \u043c\u0435\u0436\u0434\u0443 \u044d\u043a\u0440\u0430\u043d\u0430\u043c\u0438 \u0431\u044b\u043b\u043e \u043b\u0443\u0447\u0448\u0435 \u0432\u0438\u0434\u043d\u043e, \u044f &quot;\u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043b&quot; \u0440\u0430\u0437\u043c\u0435\u0440 \u044d\u043a\u0440\u0430\u043d\u0430 LCD, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0438\u0434\u0438\u0442 linux \u0434\u043e 640&#215;480. \u0412 \u044f\u0434\u0440\u0435 \u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e \u044d\u043a\u0440\u0430\u043d 640&#215;480, \u043e\u0434\u043d\u0430\u043a\u043e \u043d\u0430 \u0441\u0430\u043c LCD \u043f\u0438\u0448\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u0432\u0442\u043e\u0440\u043e\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u0438 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u044e \u043a\u0430\u0436\u0434\u0443\u044e \u0432\u0442\u043e\u0440\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 ili9341_update:<\/p>\n<p>  <\/p>\n<pre><code class=\"cpp\">\/* \u0444\u0430\u0439\u043b lcd_drv_simple_640_480.c *\/  #define W 320*2 #define H 240*2  \/* \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 ili9341_update \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 *\/ for(j = 0; j &lt; H; j++){     if (j % 2 == 1){ \/\/skip         videomemory += W;     }     else{         for(i = 0; i &lt; W; i += 2){             Lcd_WriteData_16Bit(readw(videomemory));             videomemory += 2;                        }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0432\u0443\u043c\u044f \u044d\u043a\u0440\u0430\u043d\u0430\u043c\u0438 \u0433\u043b\u0443\u0431\u0438\u043d\u0430 \u0446\u0432\u0435\u0442\u0430 \u043d\u0430 \u043d\u0438\u0445 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0439. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \/boot\/config.txt:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">[all] framebuffer_depth=16<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0442\u0430\u0432\u0438\u043c xinerama \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u044f \u043e\u043a\u043e\u043d \u043c\u0435\u0436\u0434\u0443 \u044d\u043a\u0440\u0430\u043d\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">sudo apt-get install libxinerama-dev<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \/etc\/X11\/xorg.conf<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">xorg.conf<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"bash\">Section &quot;Device&quot;         Identifier      &quot;LCD&quot;         Driver          &quot;fbdev&quot;         Option          &quot;fbdev&quot; &quot;\/dev\/fb1&quot;         Option          &quot;ShadowFB&quot; &quot;off&quot;         Option          &quot;SwapbuffersWait&quot; &quot;true&quot; EndSection  Section &quot;Device&quot;         Identifier      &quot;HDMI&quot;         Driver          &quot;fbdev&quot;         Option          &quot;fbdev&quot; &quot;\/dev\/fb0&quot;         Option          &quot;ShadowFB&quot; &quot;off&quot;         Option          &quot;SwapbuffersWait&quot; &quot;true&quot; EndSection  Section &quot;Monitor&quot;         Identifier      &quot;LCD-monitor&quot;         Option          &quot;RightOf&quot; &quot;HDMI-monitor&quot; EndSection  Section &quot;Monitor&quot;         Identifier      &quot;HDMI-monitor&quot;         Option          &quot;Primary&quot; &quot;true&quot;         EndSection  Section &quot;Screen&quot;         Identifier      &quot;screen0&quot;         Device          &quot;LCD&quot;         Monitor         &quot;LCD-monitor&quot; EndSection  Section &quot;Screen&quot;         Identifier      &quot;screen1&quot;         Device          &quot;HDMI&quot;          Monitor         &quot;HDMI-monitor&quot; EndSection  Section &quot;ServerLayout&quot;         Identifier      &quot;default&quot;         Option          &quot;Xinerama&quot; &quot;on&quot;         Option          &quot;Clone&quot; &quot;off&quot;         Screen 0        &quot;screen0&quot; RightOf &quot;screen1&quot;         Screen 1        &quot;screen1&quot;  EndSection<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/iq\/vz\/sh\/iqvzshzaxqoddbmjdeu6tf9iwjm.jpeg\"><\/p>\n<p>  <\/p>\n<h2 id=\"zaklyuchenie\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e. \u041a\u043e\u0434 \u043d\u0430 <a href=\"https:\/\/github.com\/dsoastro\/framebuffer_driver_rpi\" rel=\"nofollow\">github<\/a>.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/536110\/\"> https:\/\/habr.com\/ru\/post\/536110\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\">\n<p>\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0432 \u043c\u043e\u043d\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0435\u0440\u0438\u044e <a href=\"https:\/\/habr.com\/ru\/post\/163689\/\">\u0441\u0442\u0430\u0442\u0435\u0439<\/a> \u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 LCD \u044d\u043a\u0440\u0430\u043d\u0430 \u043a \u0440\u043e\u0443\u0442\u0435\u0440\u0443 \u043c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u043d\u043e\u0433\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430 (openwrt, stm32, usb) \u0432 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0438 \u0441 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435\u043c \u043f\u043e\u043b\u043d\u044b\u0445 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u0434\u0430 <del>\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043b\u043e\u0445\u043e \u0438\u0441\u043a\u0430\u043b<\/del> \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u0438\u043b\u043e \u0437\u0430\u0434\u0430\u0447\u0443. \u042f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043c\u0430\u043b\u043e\u0433\u043e \u2014 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e framebuffer \u0434\u043b\u044f raspberry \u0438 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0440\u0435\u0434\u0443 raspberry \u043d\u0430 LCD. \u0427\u0442\u043e \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e \u0434\u0430\u043b\u0435\u0435.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-315961","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/315961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=315961"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/315961\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=315961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=315961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=315961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}