NK-980IOT测评之使用EBI驱动LCD

NK-980IOT测评之使用EBI驱动LCD特征 三个独立芯片选择引脚 可设置极性 支持三个设备 时序独立设置 数据总线和地址总线分开 每个设备支持 1MB 空间 8 16 位数据宽度 支持 8080 模式 LCD 接口 支持 PDMA 支持设置读写空闲时间 可选内部 HCLK 分频得到 MCLK 或者外部 EBI MCLK 支持地址总线和数据总线分开 配置 时钟使能 EBI CLK HCLKEN 9 复位模块

大家好,我是讯享网,很高兴认识大家。

特征

  • 三个独立芯片选择引脚,可设置极性,支持三个设备,时序独立设置
  • 数据总线和地址总线分开。
  • 每个设备支持1MB空间
  • 8/16位数据宽度
  • 支持8080模式LCD接口
  • 支持PDMA
  • 支持设置读写空闲时间
  • 可选内部HCLK分频得到MCLK或者外部EBI_MCLK
  • 支持地址总线和数据总线分开


讯享网

配置

  • 时钟使能

EBI (CLK_HCLKEN[9])

  • 复位模块

EBIRST (SYS_AHBIPRST[3])

  • 引脚

功能

地址映射

三个片选分别对应地址如下:

连接

地址总线和数据总线分开模式

读写时序


tASU:地址建立时间,CS拉低到RD或WR拉低的时间,连续读模式CACCESS=1,tASU不需要.
tACC:RD,WD拉低的时间,数据访问时间,即给对方去读数据的时间。
tAHD:数据保持时间,即RD,WR拉高后到CS拉高的时间。

寄存器

使用EBI驱动LCD设计

硬件设计

LCD选型

对应如下:

(链接就不上了,可以以图搜图搜索购买同款)

原理图和PCB设计

使用KiCAD设计了原理图和PCB



 

生产焊接


在生产时刚好淘宝下单将BOM表的物料采购下,我手里大部分都有就买了个FFC的座子,和2.54的排母。

打样加上物料30块多点就搞定了。

焊接手工,十来分钟就搞定了。

回来的PCB


焊接之后,由于手头没有洗板水所以焊接后残留很多松香渣滓,可以买点高浓度酒精97%以上清洗下。


插入到开发板

原理分析

用的CS0片选,所以地址空间为0x6000_0000 ~ 0x600F_FFFF


由于RS引脚接到了ADDR10,而且使用的是16bit模式,所以地址中的1<<11位对应ADDR10即RS。
如果是8位模式则一一对应,地址中的1<<10位对应ADDR10即RS
写地址0x | 1<<11则ADDR10为1,RS=1表示数据
写地址0x | 0<< 11则ADDR10为0,RS=0表示命令

所以读写命令或者数据只需要读写地址0x | 1<<11和0x | 0<< 11即可。

液晶屏的参数如下





根据以上
先确认HCLK时钟分频2^x次得到MCLK,x=0~7最大分频128。
sysGetClock(SYS_HCLK))可以获取HCLK单位为M
分频x则MCLK为x/HCLK uS = 1000*x/HCLK nS

nu_clocks可以打印当前时钟配置

代码编写

见lcd.c

#include <rtconfig.h> #include <rtdevice.h> #include "nuc980.h" #include "nu_ebi.h" #include "nu_sys.h" #include <rthw.h> #include <drv_gpio.h> #define LCD_XSIZE 320 #define LCD_YSIZE 240 #define CMD_ADDR (0x | 0u<<11) #define DAT_ADDR (0x | 1u<<11) #define LLCD_WRITE_CMD(cmd)    *((volatile uint16_t*)CMD_ADDR)=cmd #define LLCD_WRITE_DATA(dat)   *((volatile uint16_t*)DAT_ADDR)=dat #define LLCD_READ_DATA()    *((volatile uint16_t*)DAT_ADDR) #define MCLK_DIVSET 5     /* 0~7   75m 26ns    */ #define MCLK_DIVVAL 32     /* 1~128分频 */ #define R2R         100    /* >10nS  */ #define W2X         100    /* >10nS  */ #define TAHD        100    /* >10nS  */ #define TACC        3000   /* >355nS */ void lcd_init(void) {         uint32_t hclk = sysGetClock(SYS_HCLK);       uint32_t r2r;         uint32_t w2x;       uint32_t tahd;         uint32_t tacc;       /* 1. 引脚配置 */       /* PA12背光 EBI_ADDR8 */     rt_pin_mode(NU_GET_PININDEX(NU_PA, 12), PIN_MODE_OUTPUT);         /* PA11复位 EBI_ADDR9 */     rt_pin_mode(NU_GET_PININDEX(NU_PA, 11), PIN_MODE_OUTPUT);         /* PA10 EBI_ADDR10 (LCD_RS) MFP1          PA9  EBI_nCS0            MFP1          PA8  EBI_nRE             MFP1          PA7  EBI_nWE             MFP1              PC0~PC15 EBI_DATA0~EBI_DATA15 MFP1        */         M32(REG_SYS_GPC_MFPL) = 0x; /*PC0~PC15 MFP1 */         M32(REG_SYS_GPC_MFPH) = 0x;             M32(REG_SYS_GPA_MFPL) = (M32(REG_SYS_GPA_MFPL) & 0x0FFFFFFF) | 0x; /* PA7 MFP1 */         M32(REG_SYS_GPA_MFPH) = (M32(REG_SYS_GPA_MFPH) & 0xFFFFF000) | 0x00000111; /* PA8 PA9 PA10 MFP1 */           /* 2. 时钟配置 */         M32(REG_CLK_HCLKEN) |= (1u<<9);    /* 使能时钟 */               /* 3. 复位 */           M32(REG_SYS_AHBIPRST) |= (1u<<3);  /* 复位EBI  */         M32(REG_SYS_AHBIPRST) &= ~(1u<<3); /* 结束复位 */         /* 4. 时序 */         EBI->CTL0 |= 1u<<24; /* EBI write buffer Enabled */         EBI->CTL0 = (EBI->CTL0 & (~(0x07<<8))) | (MCLK_DIVVAL<<8);         EBI->CTL0 |= 0u<<4; /* Continuous data access mode  tASU cycle is bypass. */         EBI->CTL0 |= 1u<<1; /* 16bit. */                 r2r = R2R/(1000*MCLK_DIVVAL/hclk) & 0x0F;         if(r2r==0)         {             r2r=1;         }                 w2x = W2X/(1000*MCLK_DIVVAL/hclk) & 0x0F;         if(w2x==0)         {             w2x=1;         }                 tahd = TAHD/(1000*MCLK_DIVVAL/hclk) & 0x07;         if(tahd==0)         {             tahd=1;         }                 tacc = TACC/(1000*MCLK_DIVVAL/hclk) & 0x1F;         if(tacc==0)         {             tacc=1;         }         EBI->TCTL0 = (r2r<<24) | (0 <<23) | (0<<22) | (w2x<<12) | ((tahd-1)<<8) | ((tacc-1)<<3);                         EBI->CTL0 |= 1u<<0; /* EBI function Enabled. */                 /* 5. LCD复位 */         rt_pin_write(NU_GET_PININDEX(NU_PA, 11), PIN_LOW);         /* 手册P48 延时大于10uS */         rt_thread_mdelay(1);         rt_pin_write(NU_GET_PININDEX(NU_PA, 11), PIN_HIGH);                 /* LCD寄存器初始化 */         rt_thread_mdelay(120);         //---------------------------------------------------------------------------------------------------//         LLCD_WRITE_CMD (0x11);         rt_thread_mdelay(120); //Delay 120ms         //------------------------------display and color format setting--------------------------------//         LLCD_WRITE_CMD (0x36);         LLCD_WRITE_DATA (0x00);         LLCD_WRITE_CMD (0x3a);         LLCD_WRITE_DATA (0x05);         //--------------------------------ST7789V Frame rate setting----------------------------------//         LLCD_WRITE_CMD (0xb2);         LLCD_WRITE_DATA (0x0c);         LLCD_WRITE_DATA (0x0c);         LLCD_WRITE_DATA (0x00);         LLCD_WRITE_DATA (0x33);         LLCD_WRITE_DATA (0x33);         LLCD_WRITE_CMD (0xb7);         LLCD_WRITE_DATA (0x35);         //---------------------------------ST7789V Power setting--------------------------------------//         LLCD_WRITE_CMD (0xbb);         LLCD_WRITE_DATA (0x28);         LLCD_WRITE_CMD (0xc0);         LLCD_WRITE_DATA (0x2c);         LLCD_WRITE_CMD (0xc2);         LLCD_WRITE_DATA (0x01);         LLCD_WRITE_CMD (0xc3);         LLCD_WRITE_DATA (0x0b);         LLCD_WRITE_CMD (0xc4);         LLCD_WRITE_DATA (0x20);         LLCD_WRITE_CMD (0xc6);         LLCD_WRITE_DATA (0x0f);         LLCD_WRITE_CMD (0xd0);         LLCD_WRITE_DATA (0xa4);         LLCD_WRITE_DATA (0xa1);         //--------------------------------ST7789V gamma setting---------------------------------------//         LLCD_WRITE_CMD (0xe0);         LLCD_WRITE_DATA (0xd0);         LLCD_WRITE_DATA (0x01);         LLCD_WRITE_DATA (0x08);         LLCD_WRITE_DATA (0x0f);         LLCD_WRITE_DATA (0x11);         LLCD_WRITE_DATA (0x2a);         LLCD_WRITE_DATA (0x36);         LLCD_WRITE_DATA (0x55);         LLCD_WRITE_DATA (0x44);         LLCD_WRITE_DATA (0x3a);         LLCD_WRITE_DATA (0x0b);         LLCD_WRITE_DATA (0x06);         LLCD_WRITE_DATA (0x11);         LLCD_WRITE_DATA (0x20);         LLCD_WRITE_CMD (0xe1);         LLCD_WRITE_DATA (0xd0);         LLCD_WRITE_DATA (0x02);         LLCD_WRITE_DATA (0x07);         LLCD_WRITE_DATA (0x0a);         LLCD_WRITE_DATA (0x0b);         LLCD_WRITE_DATA (0x18);         LLCD_WRITE_DATA (0x34);         LLCD_WRITE_DATA (0x43);         LLCD_WRITE_DATA (0x4a);         LLCD_WRITE_DATA (0x2b);         LLCD_WRITE_DATA (0x1b);         LLCD_WRITE_DATA (0x1c);         LLCD_WRITE_DATA (0x22);         LLCD_WRITE_DATA (0x1f);         LLCD_WRITE_CMD (0x29);                 /* 开背光 */         rt_pin_write(NU_GET_PININDEX(NU_PA, 12), PIN_HIGH); #if 0  /* 逻辑分析仪测试波形使用 */         while(1)         {                 LLCD_WRITE_CMD(0x00);                 LLCD_WRITE_CMD(0x01);                 LLCD_WRITE_CMD(0x02);                 LLCD_WRITE_CMD(0x03);                   LLCD_WRITE_DATA(0x00);                 LLCD_WRITE_DATA(0x01);                 LLCD_WRITE_DATA(0x02);                 LLCD_WRITE_DATA(0x03);                 LLCD_READ_DATA();                 rt_thread_mdelay(1);         } #endif } void lcd_setpoint(uint16_t x ,uint16_t y, uint16_t color) {     LLCD_WRITE_CMD(0x2A);     LLCD_WRITE_DATA(x>>8);     LLCD_WRITE_DATA(x&0XFF);             LLCD_WRITE_CMD(0x2B);     LLCD_WRITE_DATA(y>>8);     LLCD_WRITE_DATA(y&0XFF);         LLCD_WRITE_CMD(0x2C);       LLCD_WRITE_DATA(color); } void lcd_clear(uint16_t color) {     LLCD_WRITE_CMD(0x2A);     LLCD_WRITE_DATA(0);     LLCD_WRITE_DATA(0);         LLCD_WRITE_CMD(0x2B);     LLCD_WRITE_DATA(0);     LLCD_WRITE_DATA(0);         LLCD_WRITE_CMD(0x2C);             for(uint32_t i=0;i<LCD_XSIZE*LCD_YSIZE;i++)     {         LLCD_WRITE_DATA(color);     } }

讯享网

硬件/时序调试

焊接完后要先确认是否有短路,再上电。

讯享网 #if 0  /* 逻辑分析仪测试波形使用 */         while(1)         {                 LLCD_WRITE_CMD(0x00);                 LLCD_WRITE_CMD(0x01);                 LLCD_WRITE_CMD(0x02);                 LLCD_WRITE_CMD(0x03);                   LLCD_WRITE_DATA(0x00);                 LLCD_WRITE_DATA(0x01);                 LLCD_WRITE_DATA(0x02);                 LLCD_WRITE_DATA(0x03);                 LLCD_READ_DATA();                 rt_thread_mdelay(1);         } #endif

刷屏测试

#if LCD_TEST lcd_clear(0xF800); rt_thread_mdelay(1000); lcd_clear(0x07E00); rt_thread_mdelay(1000); lcd_clear(0x0001F); rt_thread_mdelay(1000); #endif

源码

NK-980IOT-TEST: NK-980IOT-TEST

LCD相关资料在lcd-pcb目录下。

总结

EBI接口驱动8080接口的LCD非常方便,本次设计也比较顺利,一次就成功,其中逻辑分析仪非常重要,用来分析时序没有他不行,另外嘉立创的打样活动非常不错,可以去看看。
下次测试下性能,优化下时序,将时序尽可能提高到最快,尽可能提高刷屏速度。
后面再移植GUI,暂时选定lvgl或者emwin。
后面再添加ADC测评,添加驱动支持。

小讯
上一篇 2025-04-05 23:54
下一篇 2025-01-09 12:02

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/51633.html