<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統 > 設計應用 > 圖片顯示系統設計

          圖片顯示系統設計

          作者:時間:2023-12-18來源:電子森林收藏

          實驗任務

          • 任務:基于底板 完成圖片顯示系統設計并觀察調試結果
          • 要求:將小腳丫的Logo轉換成單色圖片數據,驅動底板上1.8寸彩色液晶屏顯示出來
          • 解析:將單色圖片的數據存儲到rom中,驅動1.8寸將圖片刷到液晶屏上。

          實驗目的

          擴展板卡上集成了1.8寸彩色液晶屏TFT_LCD模塊,大家可以驅動LCD顯示文字、圖片或動態的波形。本實驗主要學習1.8寸串行彩色液晶屏的驅動設計,然后將小腳丫Logo處理顯示,完成圖片顯示系統的總體設計。

          本文引用地址:http://www.ex-cimer.com/article/202312/453982.htm
          • 了解1.8寸串行采樣液晶屏的原理及驅動設計
          • 完成圖片顯示系統設計實現

          設計框圖

          根據前面的實驗解析我們可以得知,該設計可以拆分成兩個功能模塊實現,

          • LCDRGB:1.8寸串行液晶屏驅動模塊。 * LCDRAM:用于存儲單色圖片數據。

          Top-Down層次設計

           

          模塊結構設計

          實驗原理

          液晶屏介紹

          液晶屏規格書

          查看底板上集成的1.8寸串行彩色液晶屏規格書,屏幕采用ST7735S的驅動芯片,接下來我們主要根據ST7735S的芯片手冊來了解其工作原理和驅動方法。

          ST7735S為132RGB x 162像素點 262K 控制器/驅動器,芯片可以直接跟外部處理器連接,支持串行SPI通信和8/9/16/18位并行通信(本液晶屏集成ST7735S時沒有留并行接口,所以只能使用串行通信),詳細參數請參考數據手冊。

          液晶屏驅動芯片原理示意

          ST7735S支持不同位寬的并行通信格式。

          ST7735S通信格式

          在控制器給屏幕刷屏時,根據MV、MX、MY的配置支持8種不同方向的刷屏模式。

          ST7735S部分刷屏模式

          支持大量功能指令,部分系統功能指令列表如下

          ST7735S部分功能指令

          更多的內容這里就不一一介紹了,感興趣的同學可以詳細閱讀ST7735S芯片手冊。

          液晶屏硬件連接

          底板上的1.8寸串行彩色液晶屏模塊電路:

          底板上的1.8寸串行彩色液晶屏電路和VGA顯示電路復用部分FPGA管腳,兩者不能同時使用,當使用1.8寸串行彩色液晶屏時,DISPSEL信號置高,驅動1.8寸串行彩色液晶屏使能同時點亮背光,DISP2~ DISP_5分別對應RESET、D/C、SDA、SCK管腳,最后FPGA驅動1.8寸液晶屏完成屏顯示控制即可。

          液晶屏驅動設計

          要驅動液晶屏需要先了解液晶屏的驅動流程,可以從液晶屏驅動芯片ST7735S的芯片手冊上獲取,也可以到網上找找有沒有別人使用同類液晶屏的案例,或者向賣方問問有沒有相關資料提供,這里我們找到了一個用51單片機驅動的程序例程,例程僅供參考,需要根據例程中的配置到芯片手冊中查找確認,不可以直接套用。

          首先完成液晶屏初始化操作,51程序流程如下:

          void  ST7735_LAIBAO177_INITIAL ()
          { 
          //-----------ST7735R Reset Sequence----------------// 
          RES =1; delay (1);        //Delay 1ms 
          RES =0; delay (1);        //Delay 1ms 
          RES =1; delay (120);      //Delay 120ms 
          //----------End ST7735R Reset Sequence ------------// 
          LCD_WriteCommand(0x11);   //Sleep out 
          delay(120);               //Delay 120ms 
          //---------ST7735S Frame Rate-------------------// 
          LCD_WriteCommand(0xB1); LCD_WriteData(0x05); 
          LCD_WriteData(0x3C); LCD_WriteData(0x3C); 
          LCD_WriteCommand(0xB2); 
          LCD_WriteData(0x05); 
          LCD_WriteData(0x3C); 
          LCD_WriteData(0x3C); 
          LCD_WriteCommand(0xB3); 
          LCD_WriteData(0x05); 
          LCD_WriteData(0x3C); 
          LCD_WriteData(0x3C); 
          LCD_WriteData(0x05); 
          LCD_WriteData(0x3C); 
          LCD_WriteData(0x3C); 
          //-----------End ST7735S Frame Rate---------------// 
          LCD_WriteCommand(0xB4); //Dot inversion 
          LCD_WriteData(0x03); 
          //-----------ST7735S Power Sequence---------------// 
          LCD_WriteCommand(0xC0); 
          LCD_WriteData(0x28); 
          LCD_WriteData(0x08); 
          LCD_WriteData(0x04); 
          LCD_WriteCommand(0xC1); 
          LCD_WriteData(0XC0); 
          LCD_WriteCommand(0xC2); 
          LCD_WriteData(0x0D); 
          LCD_WriteData(0x00); 
          LCD_WriteCommand(0xC3); 
          LCD_WriteData(0x8D); 
          LCD_WriteData(0x2A); 
          LCD_WriteCommand(0xC4); 
          LCD_WriteData(0x8D); 
          LCD_WriteData(0xEE); 
          //----------End ST7735S Power Sequence----------// 
          LCD_WriteCommand(0xC5); //VCOM 
          LCD_WriteData(0x18);    //1a
          LCD_WriteCommand(0x36); //MX, MY, RGB mode 
          LCD_WriteData(0xC0); 
          //-----------ST7735S Gamma Sequence-----------// 
          LCD_WriteCommand(0xE0); 
          LCD_WriteData(0x04); LCD_WriteData(0x22); LCD_WriteData(0x07); 
          LCD_WriteData(0x0A); LCD_WriteData(0x2E); LCD_WriteData(0x30); 
          LCD_WriteData(0x25); LCD_WriteData(0x2A); LCD_WriteData(0x28); 
          LCD_WriteData(0x26); LCD_WriteData(0x2E); LCD_WriteData(0x3A); 
          LCD_WriteData(0x00); LCD_WriteData(0x01); LCD_WriteData(0x03); 
          LCD_WriteData(0x13); 
          LCD_WriteCommand(0xE1); 
          LCD_WriteData(0x04); LCD_WriteData(0x16); LCD_WriteData(0x06); 
          LCD_WriteData(0x0D); LCD_WriteData(0x2D); LCD_WriteData(0x26); 
          LCD_WriteData(0x23); LCD_WriteData(0x27); LCD_WriteData(0x27); 
          LCD_WriteData(0x25); LCD_WriteData(0x2D); LCD_WriteData(0x3B); 
          LCD_WriteData(0x00); LCD_WriteData(0x01); LCD_WriteData(0x04); 
          LCD_WriteData(0x13); 
          //------------End ST7735S Gamma Sequence----------// 
          LCD_WriteCommand(0x3A); //65k mode 
          LCD_WriteData(0x05); 
          LCD_WriteCommand(0x29); //Display on 
          }

          創建存儲器,將初始化過程中寫的所有指令和數據存儲,同時存儲的還有指令或數據標志,例如初始化第1條指令為8'h11,我們增加最高位1‘b0組成9位位寬數據。存儲器部分指令和數據如下:

          initial begin //LCD初始化的命令及數據
              reg_init[ 0]    =   {1'b0,8'h11}; //最高位為0,表示低8位為指令
              reg_init[ 1]    =   {1'b0,8'hb1}; 
              reg_init[ 2]    =   {1'b1,8'h05}; //最高位為1,表示低8位為數據
              reg_init[ 3]    =   {1'b1,8'h3c}; 
              reg_init[ 4]    =   {1'b1,8'h3c};

          從51例程中可以看到,整個初始化過程都在給液晶屏寫指令或數據,通過查看寫指令或寫數據的時序發現,唯一不同的就是對A0(對應底板液晶屏模塊中的D/C信號)的控制,程序實現如下:

          void  LCD_WriteXXX(uint dat)
          {  int i;
              A0=0; //寫指令,如果寫數據 A0=1;
              CSB=0; //液晶屏使能
              for(i=0;i<8;i++)
              {
                  if(dat &0x80) SDA=1;
                  else SDA=0;
                  SCL=0; SCL=1;
                  dat <<=1;
              }
              CSB=1;  
              }

          FPGA驅動液晶屏的設計使用狀態機完成,將寫數據與寫指令的SPI時序整合成一個狀態,另加一位指令數據控制位,程序實現如下:

          WRITE:begin //WRITE狀態,將數據按照SPI時序發送給屏幕
                  if(cnt_write >= 6'd17) cnt_write <= 1'b0;
                  else cnt_write <= cnt_write + 1'b1;
                  case(cnt_write)
                      6'd0:   begin lcd_dc <= data_reg[8]; end    //9位數據最高位為命令數據控制位
                      6'd1:   begin lcd_clk <= LOW; lcd_din <= data_reg[7]; end   //先發高位數據
                      6'd2:   begin lcd_clk <= HIGH; end
                      6'd3:   begin lcd_clk <= LOW; lcd_din <= data_reg[6]; end
                      6'd4:   begin lcd_clk <= HIGH; end
                      6'd5:   begin lcd_clk <= LOW; lcd_din <= data_reg[5]; end
                      6'd6:   begin lcd_clk <= HIGH; end
                      6'd7:   begin lcd_clk <= LOW; lcd_din <= data_reg[4]; end
                      6'd8:   begin lcd_clk <= HIGH; end
                      6'd9:   begin lcd_clk <= LOW; lcd_din <= data_reg[3]; end
                      6'd10:  begin lcd_clk <= HIGH; end
                      6'd11:  begin lcd_clk <= LOW; lcd_din <= data_reg[2]; end
                      6'd12:  begin lcd_clk <= HIGH; end
                      6'd13:  begin lcd_clk <= LOW; lcd_din <= data_reg[1]; end
                      6'd14:  begin lcd_clk <= HIGH; end
                      6'd15:  begin lcd_clk <= LOW; lcd_din <= data_reg[0]; end   //后發低位數據
                      6'd16:  begin lcd_clk <= HIGH; end
                      6'd17:  begin lcd_clk <= LOW; state <= DELAY; end   //
                      default: state <= IDLE;
                  endcase
              end

          初始化指令和數據都放到存儲器中了,數據寫入的SPI串行時序也已經設計成了一個狀態,初始化狀態只需要在復位后將存儲器中的指令或數據通過WRITE狀態發送給液晶屏,程序實現如下:

          INIT:begin  //初始化狀態
                  if(cnt_init==3'd4) begin
                      if(cnt==INIT_DEPTH) cnt_init <= 1'b0;
                      else cnt_init <= cnt_init;
                  end else cnt_init <= cnt_init + 1'b1;
                  case(cnt_init)
                      3'd0:   lcd_res <= 1'b0;    //復位有效
                      3'd1:   begin num_delay<=16'd3000; state<=DELAY; state_back<=INIT; end 
                      3'd2:   lcd_res <= 1'b1;    //復位恢復
                      3'd3:   begin num_delay<=16'd3000; state<=DELAY; state_back<=INIT; end 
                      3'd4:   if(cnt>=INIT_DEPTH) begin //當62條指令及數據發出后,配置完成
                                  cnt <= 16'd0;  state <= MAIN;
                              end else begin
                                  cnt <= cnt + 16'd1;  data_reg <= reg_init[cnt];  
                                  if(cnt==16'd0) num_delay <= 16'd50000; //第一條指令需要較長延時
                                  else num_delay <= 16'd50;
                                  state <= WRITE; state_back <= INIT;
                              end
                      default: state <= IDLE;
                  endcase
              end

          初始化完成,進入刷屏狀態,刷屏數據寫入前首先進行區域坐標的定位,然后刷寫數據,圖片采用單色顯示,圖片ram中每位數表示一個液晶屏一個像素點的亮還是滅,彩色液晶屏本實驗采用16bit格式,即需要16bit數據決定像素的顏色,16bit數據分兩次發送,最終從ram模塊中獲取的數據每位數據都要轉換成16bit的數據,0轉換成背景色對應的數據,1轉換成頂層色對應的數據,程序實現如下:

          SCAN:begin  //刷屏狀態,從RAM中讀取數據刷屏
              case(cnt_scan)
                  3'd0: if(cnt >= 11) begin //確定刷屏的區域坐標,這里為全屏
                              cnt <= 16'd0;
                              cnt_scan <= cnt_scan + 1'b1;
                          end else begin
                              cnt <= cnt + 16'd1;
                              data_reg <= reg_setxy[cnt];
                              num_delay <= 16'd50;
                              state <= WRITE; state_back <= SCAN;
                          end
                  3'd1: begin ram_clk_en<=HIGH;ram_addr<=y_cnt;cnt_scan<=cnt_scan+1'b1; end   
                  3'd2: begin cnt_scan <= cnt_scan + 1'b1; end  //延時一個時鐘
                  3'd3: begin ram_clk_en<=LOW;ram_data_r<=ram_data;cnt_scan<=cnt_scan+1'b1; end
                  3'd4: begin //每個像素點需要16bit的數據,SPI每次傳8bit,兩次分別傳送高8位和低8位
                             if(x_cnt>=LCD_W) begin  //當一個數據(一行屏幕)寫完后,
                                  x_cnt <= 8'd0;  
                                  if(y_cnt>=LCD_H) begin y_cnt <= 8'd0; cnt_scan <= cnt_scan + 1'b1; end  //如果是最后一行就跳出循環
                                  else begin y_cnt <= y_cnt + 1'b1; cnt_scan <= 3'd1; end     //否則跳轉至RAM時鐘使能,循環刷屏
                              end else begin
                                  if(high_word) 
                                      //根據相應bit的狀態判定顯示頂層色或背景色,根據high_word的狀態判定寫高8位或低8位
                                      data_reg <= {1'b1,(ram_data_r[x_cnt]? color_t[15:8]:color_b[15:8])};    
                                  else begin 
                                      data_reg <= {1'b1,(ram_data_r[x_cnt]? color_t[7:0]:color_b[7:0])}; 
                                      x_cnt <= x_cnt + 1'b1; 
                                  end //
                                  high_word <= ~high_word;    //high_word的狀態翻轉
                                  num_delay <= 16'd50;    //設定延時時間
                                  state <= WRITE; //跳轉至WRITE狀態
                                  state_back <= SCAN; //執行完WRITE及DELAY操作后返回SCAN狀態
                              end
                          end
                  3'd5:   begin cnt_scan <= 1'b0; state <= MAIN; end
                  default: state <= IDLE;
                  endcase 
                  end
          系統總體實現

          液晶屏驅動模塊的數據來源于圖片數據的ram模塊,這些數據由圖片取模得到,使用圖片取模軟件,將圖片載入軟件,輸出數據類型選擇C語言數組,根據液晶屏驅動實際情況配置對應的掃描模式,輸出灰度選擇單色,調整最大寬度和高度符合液晶屏要求,最后點擊保存生成需要的文件。

          取模軟件參數配置

          打開生成的文件,數據格式如下,是C語言的格式

          const unsigned char gImage_11[1990] = { 0X10,0X01,0X00,0X80,0X00,0X7C,
          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X00,

          使用編輯器的查找替換功能,將數據處理成下圖格式

          132'h00000000000000000000000000000000,
          132'h00000000000000000000000000000000,
          132'h00000000000000000000000000000000,
          132'h0000000000000000F800000000000000,
          132'h0000000000000007FF00000000000000,

          創建ram模塊,將圖片數據初始化到ram中,程序實現圖下:

          module LCD_RAM (input wire [7:0] Address, output reg [131:0] Q);
          always @ (*)
              case(Address)
                  8'd0  : Q = 132'h00000000000000000000000000000000;
                  8'd1  : Q = 132'h00000000000000000000000000000000;
                  8'd2  : Q = 132'h00000000000000000000000000000000;
                  8'd3  : Q = 132'h0000000000000000F800000000000000;
                  8'd4  : Q = 132'h0000000000000007FF00000000000000;

          存儲圖片數據的ram本實驗采用分布式ram搭建,前面波形信號發生器實驗中講過ram IP核的例化及使用方法,有興趣的同學可以自己嘗試一下。

          在頂層模塊中,將兩個模塊例化并連接,最終完成圖片顯示系統的總體設計。

          實驗步驟

          1. 雙擊打開Quartus Prime工具軟件;
          2. 新建工程:File → New Project Wizard(工程命名,工程目錄選擇,設備型號選擇,EDA工具選擇);
          3. 新建文件:File → New → Verilog HDL File,鍵入設計代碼并保存;
          4. 設計綜合:雙擊Tasks窗口頁面下的Analysis & Synthesis對代碼進行綜合;
          5. 管腳約束:Assignments → Assignment Editor,根據項目需求分配管腳;
          6. 設計編譯:雙擊Tasks窗口頁面下的Compile Design對設計進行整體編譯并生成配置文件;
          7. 程序燒錄:點擊Tools → Programmer打開配置工具,Program進行下載;
          8. 觀察設計運行結果。

          實驗現象

          將設計加載到FPGA中,觀察底板液晶屏顯示,小腳丫的Logo被顯示出來了,前面說了1.8寸串行液晶屏支持不同的刷新方向,大家可以調整圖片顯示的方向

          實驗現象



          評論


          相關推薦

          技術專區

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();