上海响应式网站设计seo还有未来吗
一、跟据参考的STM32代码了解初始化流程
LCD初始化函数
void LCD_Init(void);
首先是LCD的复位
void LCD_RESET(void)
{
LCD_RST_CLR; //拉低复位引脚
Delay_Ms(100); //延时100ms
LCD_RST_SET; //拉高复位引脚
Delay_Ms(50); //延时50ms
}
向LCD屏幕写入一个8位命令
void LCD_WR_REG(u8 data)
{
LCD_CS_CLR; //拉低片选引脚
LCD_RS_CLR; //拉低dc引脚
SPI_WriteByte(SPI1,data); //使用硬件SPI写入一个字节的数据
LCD_CS_SET; //拉高片选引脚
}
将8位数据写入LCD屏幕
void LCD_WR_DATA(u8 data)
{
LCD_CS_CLR; //拉低片选引脚
LCD_RS_SET; //拉高dc引脚
SPI_WriteByte(SPI1,data); //使用硬件SPI写入一个字节的数据
LCD_CS_SET; //拉高片选引脚
}
设置液晶显示屏的显示方向
void LCD_direction(u8 direction);
清屏,也就是整个屏幕的点都为白色
void LCD_Clear(u16 Color);
LCD显示窗口设置
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);
二、模块框图
三、设计状态机
1、初始化命令
初始化命令是厂家已经配置好的,直接调用这部分就行了。
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
(省略~)
LCD_WR_DATA(0xef);
LCD_WR_REG(0x11); //Exit Sleep
Delay_Ms(120);
LCD_WR_REG(0x29); //display on
2、设置LCD显示方向
为了方便省事,只考虑参考代码中液晶屏顺时针旋转方向为0的情况。
#define USE_HORIZONTAL 0//定义液晶屏顺时针旋转方向 0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转
void LCD_direction(u8 direction)函数只需要知道LCD_WriteReg(0x36,(1<<3)|(0<<6)|(0<<7));
传输到lcd_write模块的数据(最高位决定命令/数据,0为命令,1为数据)为9'h036和9'h108。
3、清屏
lcd的清屏步骤是先设置LCD的填充窗口大小(320x240)
9'h02A; //列地址设置
{1'b1,7'b0000_000,start_x[8]}; //x的开始坐标高8位
{1'b1,start_x[7:0]}; //x的开始坐标低8位
{1'b1,7'b0000_000,end_x[8]}; //x的结束坐标高8位
{1'b1,end_x[7:0]}; //x的结束坐标低8位
9'h02B; //页面地址设置
{1'b1,7'b0000_000,start_y[8]}; //y的开始坐标高8位
{1'b1,start_y[7:0]}; //y的开始坐标低8位
{1'b1,7'b0000_000,end_y[8]}; //y的结束坐标高8位
{1'b1,end_y[7:0]}; //y的结束坐标低8位
9'h02C; //存储器写入
清屏的时候设置的窗口大小(320x240)和start_x、start_y、end_x、end_y已经确定,可以直接用以下部分。
9'h02A
9'h100
9'h100
9'h100
9'h1ef
9'h02B
9'h100
9'h100
9'h101
9'h13f
9'h02C
然后在需要填充的点进行对应颜色(白色)的填充。颜色填充为16位,先传高8位,再传低8位。
一共传输320*240*2-1=153,599次。
四、波形图绘制
五、代码编写
module lcd_init
// #(//仿真时调用// parameter TIME100MS = 23'd100, //23'd5000_000 // TIME150MS = 23'd150, //23'd7500_000 // TIME120MS = 23'd120, //23'd6000_000 // TIMES4MAX = 18'd51 , //320*240*2+13(设置窗口大小)=153_613 // DATA_IDLE = 9'b0_0000_0000
// )
#(//驱动lcd时调用parameter TIME100MS = 23'd5000_000, //23'd5000_000 TIME150MS = 23'd7500_000, //23'd7500_000 TIME120MS = 23'd6000_000, //23'd6000_000 TIMES4MAX = 18'd153_613 , //320*240*2+13(设置窗口大小)=153_613 DATA_IDLE = 9'b0_0000_0000
)
(input wire sys_clk_50MHz ,input wire sys_rst_n ,input wire wr_done ,output reg lcd_rst ,output reg [8:0] init_data ,output wire en_write ,output wire init_done
);
//****************** Parameter and Internal Signal *******************//
//画笔颜色
parameter WHITE = 16'hFFFF,BLACK = 16'h0000, BLUE = 16'h001F, BRED = 16'hF81F,GRED = 16'hFFE0,GBLUE = 16'h07FF,RED = 16'hF800,MAGENTA = 16'hF81F,GREEN = 16'h07E0,CYAN = 16'h7FFF,YELLOW = 16'hFFE0,BROWN = 16'hBC40, //棕色BRRED = 16'hFC07, //棕红色GRAY = 16'h8430; //灰色//-----------------------------------------------------------------
reg [5:0] state;
parameter S0_DELAY100MS = 6'b000_001, S1_DELAY50MS = 6'b000_010,S2_WR_90 = 6'b000_100,S3_DELAY120MS = 6'b001_000,S4_WR_DIRECTION_CLEAR = 6'b010_000,DONE = 6'b100_000;reg [22:0] cnt_150ms;
reg lcd_rst_high_flag;
reg [6:0] cnt_s2_num;
reg cnt_s2_num_done;
reg [17:0] cnt_s4_num;
reg cnt_s4_num_done; //-----------------------------------------------------------------
//状态跳转
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)state <= S0_DELAY100MS;elsecase(state)S0_DELAY100MS:state <= (cnt_150ms == TIME100MS) ? S1_DELAY50MS : S0_DELAY100MS;S1_DELAY50MS:state <= (cnt_150ms == TIME150MS) ? S2_WR_90 : S1_DELAY50MS;S2_WR_90:state <= (cnt_s2_num_done) ? S3_DELAY120MS : S2_WR_90;S3_DELAY120MS:state <= (cnt_150ms == TIME120MS) ? S4_WR_DIRECTION_CLEAR : S3_DELAY120MS; S4_WR_DIRECTION_CLEAR:state <= (cnt_s4_num_done) ? DONE : S4_WR_DIRECTION_CLEAR;DONE:state <= DONE;default:state <= S0_DELAY100MS;endcase//cnt_150ms
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)cnt_150ms <= 23'd0;else if(state == S0_DELAY100MS || state == S1_DELAY50MS || state == S3_DELAY120MS )cnt_150ms <= cnt_150ms + 1'b1;elsecnt_150ms <= 23'd0;//lcd_rst_high_flag
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)lcd_rst_high_flag <= 1'b0;else if(state == S0_DELAY100MS && (cnt_150ms == TIME100MS - 1'b1))lcd_rst_high_flag <= 1'b1;elselcd_rst_high_flag <= 1'b0;//lcd_rst
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)lcd_rst <= 1'b0;else if(lcd_rst_high_flag)lcd_rst <= 1'b1;elselcd_rst <= lcd_rst;
//-----------------------------------------------------------------
//cnt_s2_num决定要传的命令/数据
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)cnt_s2_num <= 7'd0;else if(state != S2_WR_90)cnt_s2_num <= 7'd0;else if(wr_done && state == S2_WR_90)cnt_s2_num <= cnt_s2_num + 1'b1;elsecnt_s2_num <= cnt_s2_num;//cnt_s2_num_done == 1'b1则S2_WR_90完成
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)cnt_s2_num_done <= 1'b0;else if(cnt_s2_num == 7'd89 && wr_done == 1'b1)cnt_s2_num_done <= 1'b1;elsecnt_s2_num_done <= 1'b0;//init_data[8:0]
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)init_data <= DATA_IDLE;else if(state == S2_WR_90)//初始化命令/数据,直接借用厂家的case(cnt_s2_num) //init_data[8] == 1'b1写数据; == 1'b0写命令7'd0 : init_data <= 9'h0CF ; 7'd1 : init_data <= 9'h100 ; 7'd2 : init_data <= 9'h1C9 ; 7'd3 : init_data <= 9'h130 ; 7'd4 : init_data <= 9'h0ED ; 7'd5 : init_data <= 9'h164 ; 7'd6 : init_data <= 9'h103 ; 7'd7 : init_data <= 9'h112 ; 7'd8 : init_data <= 9'h181 ; 7'd9 : init_data <= 9'h0E8 ; 7'd10: init_data <= 9'h185 ; 7'd11: init_data <= 9'h110 ; 7'd12: init_data <= 9'h17A ; 7'd13: init_data <= 9'h0CB ; 7'd14: init_data <= 9'h139 ; 7'd15: init_data <= 9'h12C ; 7'd16: init_data <= 9'h100 ; 7'd17: init_data <= 9'h134 ; 7'd18: init_data <= 9'h102 ; 7'd19: init_data <= 9'h0F7 ; 7'd20: init_data <= 9'h120 ; 7'd21: init_data <= 9'h0EA ; 7'd22: init_data <= 9'h100 ; 7'd23: init_data <= 9'h100 ; 7'd24: init_data <= 9'h0C0 ; 7'd25: init_data <= 9'h11B ; 7'd26: init_data <= 9'h0C1 ; 7'd27: init_data <= 9'h100 ; 7'd28: init_data <= 9'h0C5 ; 7'd29: init_data <= 9'h130 ; 7'd30: init_data <= 9'h130 ; 7'd31: init_data <= 9'h0C7 ; 7'd32: init_data <= 9'h1B7 ; 7'd33: init_data <= 9'h036 ; 7'd34: init_data <= 9'h108 ; 7'd35: init_data <= 9'h03A ; 7'd36: init_data <= 9'h155 ; 7'd37: init_data <= 9'h0B1 ; 7'd38: init_data <= 9'h100 ; 7'd39: init_data <= 9'h11A ; 7'd40: init_data <= 9'h0B6 ; 7'd41: init_data <= 9'h10A ; 7'd42: init_data <= 9'h1A2 ; 7'd43: init_data <= 9'h0F2 ; 7'd44: init_data <= 9'h100 ; 7'd45: init_data <= 9'h026 ; 7'd46: init_data <= 9'h101 ; 7'd47: init_data <= 9'h0E0 ; 7'd48: init_data <= 9'h10F ; 7'd49: init_data <= 9'h12A ; 7'd50: init_data <= 9'h128 ; 7'd51: init_data <= 9'h108 ; 7'd52: init_data <= 9'h10E ; 7'd53: init_data <= 9'h108 ; 7'd54: init_data <= 9'h154 ; 7'd55: init_data <= 9'h1A9 ; 7'd56: init_data <= 9'h143 ; 7'd57: init_data <= 9'h10A ; 7'd58: init_data <= 9'h10F ; 7'd59: init_data <= 9'h100 ; 7'd60: init_data <= 9'h100 ; 7'd61: init_data <= 9'h100 ; 7'd62: init_data <= 9'h100 ; 7'd63: init_data <= 9'h0E1 ; 7'd64: init_data <= 9'h100 ; 7'd65: init_data <= 9'h115 ; 7'd66: init_data <= 9'h117 ; 7'd67: init_data <= 9'h107 ; 7'd68: init_data <= 9'h111 ; 7'd69: init_data <= 9'h106 ; 7'd70: init_data <= 9'h12B ; 7'd71: init_data <= 9'h156 ; 7'd72: init_data <= 9'h13C ; 7'd73: init_data <= 9'h105 ; 7'd74: init_data <= 9'h110 ; 7'd75: init_data <= 9'h10F ; 7'd76: init_data <= 9'h13F ; 7'd77: init_data <= 9'h13F ; 7'd78: init_data <= 9'h10F ; 7'd79: init_data <= 9'h02B ; 7'd80: init_data <= 9'h100 ; 7'd81: init_data <= 9'h100 ; 7'd82: init_data <= 9'h101 ; 7'd83: init_data <= 9'h13f ; 7'd84: init_data <= 9'h02A ; 7'd85: init_data <= 9'h100 ; 7'd86: init_data <= 9'h100 ; 7'd87: init_data <= 9'h100 ; 7'd88: init_data <= 9'h1ef ; 7'd89: init_data <= 9'h011 ; default: init_data <= DATA_IDLE;endcaseelse if(state == S4_WR_DIRECTION_CLEAR)case(cnt_s4_num)'d0 : init_data <= 9'h029;//设置LCD显示方向'd1 : init_data <= 9'h036;'d2 : init_data <= 9'h108;//LCD显示窗口设置'd3 : init_data <= 9'h02a;'d4 : init_data <= 9'h100;'d5 : init_data <= 9'h100;'d6 : init_data <= 9'h100;'d7 : init_data <= 9'h1ef;'d8 : init_data <= 9'h02b;'d9 : init_data <= 9'h100;'d10: init_data <= 9'h100;'d11: init_data <= 9'h101;'d12: init_data <= 9'h13f;'d13: init_data <= 9'h02c;//填充对应点的颜色,可以换用比较明显的红色,便于观察现象default : //当cnt_s4_num大于14且为偶数时,传输颜色数据的高8位if(cnt_s4_num >= 'd14 && cnt_s4_num[0] == 0)init_data <= {1'b1,WHITE[15:8]};//当cnt_s4_num大于14且为奇数时,传输颜色数据的低8位else if(cnt_s4_num >= 'd14 && cnt_s4_num[0] == 1)init_data <= {1'b1,WHITE[7:0]};elseinit_data <= DATA_IDLE;endcaseelseinit_data <= DATA_IDLE;//cnt_s4_num决定要传的命令/数据
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)cnt_s4_num <= 18'd0;else if(state != S4_WR_DIRECTION_CLEAR)cnt_s4_num <= 18'd0;else if(wr_done && state == S4_WR_DIRECTION_CLEAR)cnt_s4_num <= cnt_s4_num + 1'b1;else cnt_s4_num <= cnt_s4_num;//cnt_s4_num_done
always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)cnt_s4_num_done <= 1'b0;else if(cnt_s4_num == TIMES4MAX && wr_done == 1'b1)cnt_s4_num_done <= 1'b1;elsecnt_s4_num_done <= 1'b0; assign en_write = (state == S2_WR_90 || state == S4_WR_DIRECTION_CLEAR) ? 1'b1 : 1'b0; assign init_done = (state == DONE) ? 1'b1 : 1'b0; endmodule
六、仿真代码
`timescale 1ns/1nsmodule tb_lcd_init();reg sys_clk_50MHz;
reg sys_rst_n ;
reg wr_done ;wire lcd_rst ;
wire [8:0] init_data ;
wire en_write ;
wire init_done ;reg [1:0] cnt1;initial
beginsys_clk_50MHz <= 1'b1;sys_rst_n <= 1'b0;wr_done <= 1'b0;#100sys_rst_n <= 1'b1;
endalways #10 sys_clk_50MHz <= ~sys_clk_50MHz;always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)cnt1 <= 'd0;else if(en_write)cnt1 <= cnt1 + 1'b1;always@(posedge sys_clk_50MHz or negedge sys_rst_n)if(!sys_rst_n)wr_done <= 1'b0;else if(cnt1 == 'd3)wr_done <= 1'b1;elsewr_done <= 1'b0;lcd_init lcd_init_inst
(.sys_clk_50MHz (sys_clk_50MHz),.sys_rst_n (sys_rst_n ),.wr_done (wr_done ),.lcd_rst (lcd_rst ),.init_data (init_data ),.en_write (en_write ),.init_done (init_done )
);endmodule
七、仿真波形图