基于Lattice XO2-4000HC FPGA核心板的SSD1306 OLED12832驱动芯片指令及工作方式详述(Verilog)

本文主要是介绍基于Lattice XO2-4000HC FPGA核心板的SSD1306 OLED12832驱动芯片指令及工作方式详述(Verilog),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • :pushpin: 前言
    • :gift: oled_driver_adc驱动顶层模块代码
    • :umbrella: OLED驱动原理简述
      • :paperclip: 结构及引脚分配
      • :game_die: MCU总线接口:4线SPI
    • :microscope: OLED驱动模块工作分析(结合代码)
      • :art: 图形显示数据RAM(GDDRAM)
        • 寻址模式
          • 页寻址模式
          • 水平模式寻址
          • 垂直模式寻址
        • 重映射及多路复用
      • :fish_cake: 代码中使用的工作方式
        • 单个字符编码
        • 字符串写入顺序
        • 多行字符串写入顺序

📌 前言

本篇文章为《基于Lattice XO2-4000HC FPGA核心板及电子森林综合训练底板的ADC数字电压表及OLED显示设计(Verilog)》一文的延伸,针对该项目中的SSD1306 OLED显示屏驱动的指令及工作(扫描)方式进行较为详细的说明,并结合原文中oled_driver_adc驱动模块的部分代码进行详细分析。

👉 注意事项及源代码参见原文。

🎁 oled_driver_adc驱动顶层模块代码

为便于后续对照代码进行说明,在此先贴出源代码,子模块的代码在原文中给出,简要而言为两个只读ROM,分别读取命令编码及字符编码。

module oled_driver_adc #(parameter CMD_WIDTH = 8,   		// LCD命令宽度parameter CMD_DEPTH = 5'd25, 	// LCD初始化的命令的数量parameter CHAR_WIDTH = 40,		// 一个文字的数据宽度parameter CHAR_DEPTH = 7'd123	// 文字库数量
)(input sys_clk,input rst_n,input [7:0] oled_display_digital, 	// 两位ADC数据(一位小数)output reg oled_csn,				//OLCD液晶屏使能output reg oled_rst,				//OLCD液晶屏复位output reg oled_dcn,				//OLCD数据指令控制output reg oled_clk,				//OLCD时钟信号output reg oled_data				//OLCD数据信号
);localparam IDLE = 3'b0, MAIN = 3'b1, INIT = 3'b10;localparam SCAN = 3'b11, WRITE = 3'b100, DELAY = 3'b101;localparam HIGH	= 1'b1, LOW = 1'b0;localparam DATA	= 1'b1, CMD = 1'b0;wire [CMD_WIDTH-1:0]  cmd_out;		// cmd_RAM输出的8位命令wire [CHAR_WIDTH-1:0] char_out;   	// data_RAM输出的40位文字reg [7:0] wr_reg;reg	[7:0] ypage, xpage_high, xpage_low;reg	[(8*21-1):0] char;				// 字符串reg	[4:0] char_num;   				// 文字个数 最多16reg [4:0] cmd_addr;reg [7:0] char_addr;reg	[2:0] cnt_main;reg [2:0] cnt_init;reg [3:0] cnt_scan;reg	[4:0] cnt_write;reg	[14:0]num_delay, cnt_delay;reg	[2:0] state, state_last;oled_cmd_RAM #(.RAM_WIDTH(CMD_WIDTH),.RAM_DEPTH(CMD_DEPTH),.ADDR_WIDTH(5)) CMD_RAM(.clk(sys_clk),.rst_n(rst_n),.re(oled_dcn),.addr(cmd_addr),.data(cmd_out));oled_char_RAM #(.RAM_WIDTH(CHAR_WIDTH),.RAM_DEPTH(CHAR_DEPTH),.ADDR_WIDTH(8)) CHAR_RAM(.clk(sys_clk),.rst_n(rst_n),.re(oled_dcn),.addr(char_addr),.data(char_out));always @(posedge sys_clk or negedge rst_n) beginif(!rst_n) begincnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;wr_reg <= 1'b0;ypage <= 1'b0;xpage_high <= 1'b0; xpage_low <= 1'b0;char <= 1'b0; char_num <= 1'b0;cmd_addr <= 1'b0;char_addr <= 1'b0;num_delay <= 15'd5; cnt_delay <= 1'b0; oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_data <= LOW;state <= IDLE; state_last <= IDLE;end else begincase(state)IDLE: begincnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;wr_reg <= 1'b0;ypage <= 1'b0;xpage_high <= 1'b0; xpage_low <= 1'b0;char <= 1'b0; char_num <= 1'b0; cmd_addr <= 1'b0;char_addr <= 1'b0;num_delay <= 15'd5; cnt_delay <= 1'b0; oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_data <= LOW;state <= MAIN; state_last <= MAIN;endMAIN: beginif(cnt_main >= 3'd6)cnt_main <= 3'd5;else cnt_main <= cnt_main + 1'b1;case(cnt_main)	//MAIN状态3'd0: begin state <= INIT; end3'd1: begin ypage <= 8'hb0; xpage_high <= 8'h10; xpage_low <= 8'h00; char_num <= 5'd16; char <= "ADC DATA DISPLAY";state <= SCAN; end3'd2: begin ypage <= 8'hb1; xpage_high <= 8'h10; xpage_low <= 8'h00; char_num <= 5'd16; char <= "VOLTAGE:   . V  ";state <= SCAN; end3'd3: begin ypage <= 8'hb2; xpage_high <= 8'h10; xpage_low <= 8'h00; char_num <= 5'd16; char <= "AUTHOR: ZIRU PAN";state <= SCAN; end3'd4: begin ypage <= 8'hb3; xpage_high <= 8'h10; xpage_low <= 8'h00; char_num <= 5'd16; char <= "                ";state <= SCAN; end3'd5: begin ypage <= 8'hb1; xpage_high <= 8'h15; xpage_low <= 8'h00; char_num <= 5'd1 ; char <= oled_display_digital[7:4]; state <= SCAN; end3'd6: begin ypage <= 8'hb1; xpage_high <= 8'h16; xpage_low <= 8'h00; char_num <= 5'd1 ; char <= oled_display_digital[3:0]; state <= SCAN; enddefault: state <= IDLE;endcaseendINIT: begin	//初始化状态case(cnt_init)5'd0: begin oled_rst <= LOW; cnt_init <= cnt_init + 1'b1; end	//复位有效5'd1: begin num_delay <= 15'd25000; state <= DELAY; state_last <= INIT; cnt_init <= cnt_init + 1'b1; end	//延时大于3us5'd2: begin oled_rst <= HIGH; cnt_init <= cnt_init + 1'b1; end	//复位恢复5'd3: begin num_delay <= 15'd25000; state <= DELAY; state_last <= INIT; cnt_init <= cnt_init + 1'b1; end	//延时大于220us5'd4: begin if(cmd_addr >= CMD_DEPTH) begincmd_addr <= 1'b0;cnt_init <= cnt_init + 1'b1;end else begin	cmd_addr <= cmd_addr + 1'b1; num_delay <= 15'd5;oled_dcn <= CMD; wr_reg <= cmd_out;state <= WRITE; state_last <= INIT;endend5'd5: begin cnt_init <= 1'b0; state <= MAIN; enddefault: state <= IDLE;endcaseendSCAN: beginif(cnt_scan == 4'd12) beginif(char_num) cnt_scan <= 4'd3;else cnt_scan <= cnt_scan + 1'b1;end else if(cnt_scan == 4'd13) cnt_scan <= 4'd0;else cnt_scan <= cnt_scan + 1'b1;case(cnt_scan)4'd0: begin oled_dcn <= CMD; wr_reg <= ypage; state <= WRITE; state_last <= SCAN; end    	//定位列页地址4'd1: begin oled_dcn <= CMD; wr_reg <= xpage_low; state <= WRITE; state_last <= SCAN; end	//定位行地址低位4'd2: begin oled_dcn <= CMD; wr_reg <= xpage_high; state <= WRITE; state_last <= SCAN; end	//定位行地址高位4'd3: begin char_num <= char_num - 1'b1; end4'd4: begin char_addr <= char[(char_num*8)+:8]; end4'd5: begin oled_dcn <= DATA; wr_reg <= 8'h00; state <= WRITE; state_last <= SCAN; end	//5*8点阵变成8*84'd6: begin oled_dcn <= DATA; wr_reg <= 8'h00; state <= WRITE; state_last <= SCAN; end	//5*8点阵变成8*84'd7: begin oled_dcn <= DATA; wr_reg <= 8'h00; state <= WRITE; state_last <= SCAN; end	//5*8点阵变成8*84'd8: begin oled_dcn <= DATA; wr_reg <= char_out[39:32]; state <= WRITE; state_last <= SCAN; end4'd9: begin oled_dcn <= DATA; wr_reg <= char_out[31:24]; state <= WRITE; state_last <= SCAN; end4'd10:begin oled_dcn <= DATA; wr_reg <= char_out[23:16]; state <= WRITE; state_last <= SCAN; end4'd11:begin oled_dcn <= DATA; wr_reg <= char_out[15:8] ; state <= WRITE; state_last <= SCAN; end4'd12:begin oled_dcn <= DATA; wr_reg <= char_out[7:0]  ; state <= WRITE; state_last <= SCAN; end4'd13:begin state <= MAIN; enddefault: state <= IDLE;endcaseendWRITE: begin	//WRITE状态,将数据按照SPI时序发送给屏幕if(cnt_write >= 5'd17) cnt_write <= 5'd0;else cnt_write <= cnt_write + 1'b1;case(cnt_write)5'd0: begin oled_csn <= LOW; end	//9位数据最高位为命令数据控制位5'd1: begin oled_clk <= LOW; oled_data <= wr_reg[7]; end	//先发高位数据5'd2: begin oled_clk <= HIGH; end5'd3: begin oled_clk <= LOW; oled_data <= wr_reg[6]; end5'd4: begin oled_clk <= HIGH; end5'd5: begin oled_clk <= LOW; oled_data <= wr_reg[5]; end5'd6: begin oled_clk <= HIGH; end5'd7: begin oled_clk <= LOW; oled_data <= wr_reg[4]; end5'd8: begin oled_clk <= HIGH; end5'd9: begin oled_clk <= LOW; oled_data <= wr_reg[3]; end5'd10:begin oled_clk <= HIGH; end5'd11:begin oled_clk <= LOW; oled_data <= wr_reg[2]; end5'd12:begin oled_clk <= HIGH; end5'd13:begin oled_clk <= LOW; oled_data <= wr_reg[1]; end5'd14:begin oled_clk <= HIGH; end5'd15:begin oled_clk <= LOW; oled_data <= wr_reg[0]; end	//后发低位数据5'd16:begin oled_clk <= HIGH; end5'd17:begin oled_csn <= HIGH; state <= DELAY; enddefault: state <= IDLE;endcaseendDELAY: beginif(cnt_delay >= num_delay) begincnt_delay <= 15'd0; state <= state_last; end else cnt_delay <= cnt_delay + 1'b1;enddefault: state <= IDLE;endcaseendend
endmodule

☔️ OLED驱动原理简述

📎 结构及引脚分配

该部分参看SSD1306 OLED驱动芯片 详细介绍、百度云:SSD1306 英文手册(提取码csdn,由于CSDN存在相同资源但是不免费)及百度文库:SSD1306 中文手册,在此不做详述。

🎲 MCU总线接口:4线SPI

关于SSD1306的总线接口,在上述参考链接中均有说明,在此对原文FPGA核心板中所使用的4线SPI接口做详细说明。

FPGA GPIO与OLED(其实是与SSD1306,该驱动集成在显示屏背部)结构连接电路图如下图所示,包括VCC、串行时钟(SCLK)、串行数据(SDIN)、数据/命令控制(D/C)、片选(CS#)及一复位(RES)。
FPGA GPIO与OLED连接电路原理图
在SCLK每个上升沿,SDIN上的数据按MSB~LSB顺序移位到一个8位移位寄存器中。每八个时钟对D/C进行一次采样,移位寄存器中的8位数据根据D/C的采样结果决定写入到图形显示数据RAM(GDDRAM)或命令寄存器。其写时序如下图所示:
4线SPI下的写时序
根据上述4线SPI接口的工作原理,即:片选有效后,命令解码模块根据D/C#确定输入数据是被解释为数据还是命令。D/C#引脚为HIGH,SDIN输入的D[7:0]则被解释为写入图形显示数据RAM (Graphic Display Data RAM, GDDRAM)的显示数据。如果是LOW,则D[7:0]被解释为命令,然后被解码并写入相应的命令寄存器。

代码中,在INIT状态下5’d4处cmd_addr <= cmd_addr + 1'b1; oled_dcn <= CMD; wr_reg <= cmd_out;即指定D/C#为低电平,而后输入的cmd_out则被解释为命令编码,并存入相应寄存器中。

SCAN状态中,oled_dcn <= DATA则指定D/C#为高电平,而后输入wr_reg的数据为字符编码的一个八位,连续输入5次,则代表一个字母的全部显示编码,这杯解释为图形显示数据,则存入GDDRAM中。

🔬 OLED驱动模块工作分析(结合代码)

🎨 图形显示数据RAM(GDDRAM)

GDDRAM是一个位映射静态RAM,保存要显示的位模式。内存大小为128×64位,分成8页,从PAGE0到PAGE7,用于黑白128×64点阵显示,如下图所示。
SSD1306 GDDRAM的页结构
注:重映射在后文说明。

当一个数据字节被写入GDDRAM时,当前列同页的所有行图像数据被填充(即列地址指针指向的整个列(8位)被填充)。数据位D0被写入顶部行。数据位D7写入底部一行。
数据填充方式

寻址模式

在SSD1306中有3种不同的内存寻址模式:页寻址模式、水平寻址模式和垂直寻址模式。设置寻址模式需要两个字节的命令:

  1. 20H,00H:水平寻址模式;
  2. 20H,01H,垂直寻址模式;
  3. 20H,02H,页寻址模式(复位);
  4. 20H,03H,无效。
页寻址模式

页面寻址模式(A[1:0]-10xb)页寻址模式。当GDDRAM被读写后,列地址指针自动增加1。如果列地址指针到达列结束地址,列地址指针将重置为列起始地址,页地址指针不变。用户必须设置新的页面和列地址,以便访问下一页RAM内容。页寻址模式的页和列地址的移动顺序如下图所示。
地址指针移动页面寻址模式
在正常GDDRAM读写和页寻址模式下,需要定义启动RAM访问指针的位置:

  1. 通过命令B0H~B7H设置目标显示位置的页面起始地址;
  2. 通过命令00H~0FH设置指针的较低列地址,高4位恒定为00H,低4位为要设置的起始列地址的低4位;
  3. 通过命令10H~1FH设置指针的较高列地址,高4位恒定为01H,低4位为要设置的起始列地址的高4位;
  4. *例如:设定B0H、00H、15H,则指针在PAGE1,COL80(50H = 80D)的COM0处。

例如,页面地址设置为B2H,较低列地址为03H,较高列地址为10H。这意味着起始列是PAGE2的SEG3。内存访问指针的位置如下图所示,输入数据字节将被写入RAM第3列的位置。
在页寻址模式下设置GDDRAM访问指针的示例
代码中,MIAN状态下设置了要显示的字符串,其中ypage指定了页,xpage_lowxpage_high指定了低与高列地址。由于该OLED屏幕为128×32,因此分为4页(page)和SEG0~SEG127,则ypage = 8'hb0~8'hb3

由于每个字符为5×8,保持恰当的字间距使之扩充为8×8,因此一行可以显示16个字符,对于代码中需要不断动态刷新的一行字符串 “VOLTAGE:空空空.空V空空”,两个不断更新的数字需要在第三和第四个“空”字处,因此单独设置这两个字符的访问指针为:

ypage <= 8'hb1; xpage_high <= 8'h15; xpage_low <= 8'h00; // 50H = 80(COL)
ypage <= 8'hb1; xpage_high <= 8'h16; xpage_low <= 8'h00; // 60H = 96(COL)

对于满满一行字符串,则设置高低列地址均为00H,则指针在该页COL0处。

水平模式寻址

在水平寻址模式下,当GDDRAM被读写后,列地址指针自动增加1。如果列地址指针到达列结束地址。列地址指针被重置为列起始地址,页地址指针增加1。

水平寻址模式下,页面和列地址的移动顺序如下图所示。当列地址指针和页地址指针都到达结束地址时,指针被重置为列起始地址和页起始地址(图中虚线)。
水平寻址模式下地址指针的移动

垂直模式寻址

在垂直寻址模式下,当GDDRAM被读写后,页面地址指针自动增加1。如果页面地址指针到达页面结束地址,页面地址指针被重置为页面开始地址,列地址指针加1。

垂直寻址方式下,页面和列地址的移动顺序如下图所示。当列地址指针和页地址指针都到达结束地址时,指针被重置为列起始地址和页起始地址(图中虚线)。
垂直寻址模式下地址指针的移动

重映射及多路复用
  1. A0/A1,设置段映射:
  • A0H:列地址0映射到SEG0(复位状态);
  • A1H:列地址127映射到SEG0,即原本:SEG0对应COL0→SEG127对应COL127,现在映射为:SEG0对应COL127→SEG127对应COL0。
  1. A8 + A[5:0] (00H~3FH),设置多路复用率(MUX Ratio)为N+1:A[5:0]从0到14的取值都是无效的。代码中,命令RAM中8'ha8后接8'h1F,则指定复用率(MUX Ratio) = 1FH + 1 = 20H,则复用率为20H。

  2. C0/C8,设置COM输出扫描方向:

  • C0:正常模式(复位状态),从COM0→COM[N-1];
  • C1:重映射模式,扫描从COM[N-1]→COM0,其中N为复用率。上述复用率设置为20H,代码中指定为C0,则从COM0→COM31进行扫描。
  1. DA + A[5:4] (02H/12H/22H/32H):设置COM引脚的硬件配置(以复用率为64为例):
  • A[5:4] = 00H:顺序COM引脚配置,禁止COM左右重映射,当扫描方向为COM0→COM63,COM的配置如下图;当扫描方向为COM63→COM0,为第二幅图。
    A[5:4] = 00H 正向扫描
    A[5:4] = 00H 反向扫描

  • A[5:4] = 10H:顺序COM引脚配置,允许COM左右重映射,当扫描方向为COM0→COM63,COM配置如下图,当扫描方向为COM63→COM0,为第二幅图。
    A[5:4] = 10H 正向扫描
    A[5:4] = 10H 反向扫描

  • A[5:4] = 01H:备用COM引脚配置(奇偶间隔),禁止COM左右重映射,当扫描方向为COM0→COM63,COM配置如下图,当扫描方向为COM63→COM0,为第二幅图。
    A[5:4] = 01H 正向扫描
    A[5:4] = 01H 反向扫描

  • A[5:4] = 11H:备用COM引脚配置(奇偶间隔),允许COM左右重映射,当扫描方向为COM0→COM63,COM配置如下图,当扫描方向为COM63→COM0,为第二幅图。
    A[5:4] = 11H 正向扫描
    A[5:4] = 11H 反向扫描
    代码中,命令RAM中8'hda后接8'h02,则指定A[5:4] = 00H,顺序配置COM引脚,禁止引脚左右重映射,扫描方向为COM31→COM0。

🍥 代码中使用的工作方式

OLED屏幕上显示出字符的方式不唯一,这与OLED屏幕加载的命令、输入字符编码的顺序等均有关系。

⚠️ 注意:经作者实验,OLED屏幕正面看右上角可能为每一页的COL0、ROW0处;从上至下依次为PAGE3/2/1/0。

单个字符编码

首先考虑代码中,oled_char_RAM中储存的字符编码是怎么一回事。例如:

Mem[ 50] = {8'h42, 8'h61, 8'h51, 8'h49, 8'h46};   // 50  2

无段映射(SEG与COL一致,SEG0)、扫描方向为正向(COM0→COM7),写入GDDRAM时先写入字符编码高位WRITE状态下先写入一个字节编码的高位时表示字符“2”的字符编码为如下图所示:
字符2的编码显示-1
为正常显示,需要改变扫描方向和SEG重映射:
字符2的编码显示-2

字符串写入顺序

字符串由多个字符组成,因此相较于单个字符存在字符扫描顺序问题。该问题取决于页选址模式小节中GDDRAM访问指针的位置。

无段映射(SEG与COL一致,A0H)、扫描方向为正向(COM0→COM7,C0H),写入GDDRAM时先写入字符编码高位正序读入字符串时字符串“27”显示的效果为:
字符串27编码显示-1
指针从右上方红色箭头处开始朝下扫描。

而原文所提供的代码其字符串扫描顺序如下图所示,具体方式说明见后:
字符串27编码显示-2
指针从左下方红色箭头处开始朝上扫描。

oled_cmd_RAM中设置了段重映射,因此SEG0对应COL127→SEG127对应COL0;设置反向扫描,因此每一页(page)从下往上填充一个八位编码。

在读入显示数据(D/C = 1)时,先需要在D/C = 0下输入3个字节的命令以决定RAM访问指针起始位置:ypage(设置页起始地址)、xpage_lowxpage_high(共同设置COL地址)。

SCAN状态下,记录字符个数的计数器char_num是倒序的,由于char_addr <= char[(char_num*8)+:8],字符串从最左侧(高位)开始取字符编码(示例中先扫描“2”)。程序中,由于字符编码为5×8,需要扩充至8×8才可在每个字符间保持恰当的间距,因此先输入3列8'h00(空白),而后再读入字符编码。读入字符编码时,程序中先读入字符“2”的高位(8’h42)→低位(8’h46),并且写入COM中的一个八位编码(8’h42)顺序为:01000010。

多行字符串写入顺序

多行字符串写入需要增加PAGE的控制。具体体现在代码中,由于是页寻址模式,扫描每一行字符串需要设置不同的ypagexpage_lowxpage_high

这篇关于基于Lattice XO2-4000HC FPGA核心板的SSD1306 OLED12832驱动芯片指令及工作方式详述(Verilog)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/262257

相关文章

虚拟机与物理机的文件共享方式

《虚拟机与物理机的文件共享方式》文章介绍了如何在KaliLinux虚拟机中实现物理机文件夹的直接挂载,以便在虚拟机中方便地读取和使用物理机上的文件,通过设置和配置,可以实现临时挂载和永久挂载,并提供... 目录虚拟机与物理机的文件共享1 虚拟机设置2 验证Kali下分享文件夹功能是否启用3 创建挂载目录4

linux报错INFO:task xxxxxx:634 blocked for more than 120 seconds.三种解决方式

《linux报错INFO:taskxxxxxx:634blockedformorethan120seconds.三种解决方式》文章描述了一个Linux最小系统运行时出现的“hung_ta... 目录1.问题描述2.解决办法2.1 缩小文件系统缓存大小2.2 修改系统IO调度策略2.3 取消120秒时间限制3

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux

Mybatis官方生成器的使用方式

《Mybatis官方生成器的使用方式》本文详细介绍了MyBatisGenerator(MBG)的使用方法,通过实际代码示例展示了如何配置Maven插件来自动化生成MyBatis项目所需的实体类、Map... 目录1. MyBATis Generator 简介2. MyBatis Generator 的功能3

Python数据处理之导入导出Excel数据方式

《Python数据处理之导入导出Excel数据方式》Python是Excel数据处理的绝佳工具,通过Pandas和Openpyxl等库可以实现数据的导入、导出和自动化处理,从基础的数据读取和清洗到复杂... 目录python导入导出Excel数据开启数据之旅:为什么Python是Excel数据处理的最佳拍档

SpringBoot项目启动后自动加载系统配置的多种实现方式

《SpringBoot项目启动后自动加载系统配置的多种实现方式》:本文主要介绍SpringBoot项目启动后自动加载系统配置的多种实现方式,并通过代码示例讲解的非常详细,对大家的学习或工作有一定的... 目录1. 使用 CommandLineRunner实现方式:2. 使用 ApplicationRunne

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

MYSQL行列转置方式

《MYSQL行列转置方式》本文介绍了如何使用MySQL和Navicat进行列转行操作,首先,创建了一个名为`grade`的表,并插入多条数据,然后,通过修改查询SQL语句,使用`CASE`和`IF`函... 目录mysql行列转置开始列转行之前的准备下面开始步入正题总结MYSQL行列转置环境准备:mysq

Linux(Centos7)安装Mysql/Redis/MinIO方式

《Linux(Centos7)安装Mysql/Redis/MinIO方式》文章总结:介绍了如何安装MySQL和Redis,以及如何配置它们为开机自启,还详细讲解了如何安装MinIO,包括配置Syste... 目录安装mysql安装Redis安装MinIO总结安装Mysql安装Redis搜索Red

Java文件上传的多种实现方式

《Java文件上传的多种实现方式》文章主要介绍了文件上传接收接口的使用方法,包括获取文件信息、创建文件夹、保存文件到本地的两种方法,以及如何使用Postman进行接口调用... 目录Java文件上传的多方式1.文件上传接收文件接口2.接口主要内容部分3.postman接口调用总结Java文件上传的多方式1