找回密码
 立即注册
查看: 972|回复: 9

AI8051U 驱动 TFT-LCD

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:519
  • 最近打卡:2025-05-01 08:15:57
已绑定手机
已实名认证

46

主题

161

回帖

474

积分

中级会员

积分
474
发表于 2024-11-14 03:17:35 | 显示全部楼层 |阅读模式
本帖最后由 lijinlei 于 2024-11-14 03:31 编辑

AI8051U 驱动 TFT 显示屏
本文主要介绍了 TFT 屏驱动原理,以及 AI8051U 驱动 TFT 显示图片。
TFT-LCD_ST7735S.png
TFT-LCD 原理
TFT (Thin Film Transistor) -LCD (Liquid Crystal Display),薄膜晶体管型液晶显示屏,像素点由薄膜晶体管驱动,具有响应速度快,色彩控制精确,成像更逼真等优点。

器件结构
TFT 屏的主要结构组成包括:背光源、导光板、扩散膜、棱镜膜、配向膜、液晶材料、薄膜晶体管等。

背光源
LCD 屏幕的光就是来自于屏幕最下面的光源。
LCD 光源可以是长条荧光灯 (CCFL), 也可以是发光二极管(LED), 通常用 LED 使屏幕更薄。

光源放置方式
1.将 LED 平铺在最下面的反光板上;
2.将LED放在屏幕的侧边。

导光板
LED放在屏幕的侧边时,会出现亮度不均匀的情况,因此需要一层导光板,其作用就是将点光源转换为面光源,使光束传播更均匀。

扩散膜
扩散膜是为了令光扩散的面积更大,且更加柔和,提高舒适度。

棱镜膜
棱镜膜的作用是将分散的光线集中到特定角度。只有符合该角度范围的光线才能从棱镜膜射出,其他角度的光线则被反射到反光板,再反射回棱镜膜,以期再次利用。
使用棱镜膜是因为光线是四处分散的,需要尽可能让光线方向聚集,也可提高亮度。

偏光片
偏光片的作用是过滤。只允许特定方向的光透过。具有两层相互垂直的偏光片用来控制屏幕的亮灭显示。

液晶
液晶层位于两层偏光片之间,液晶层的分子无外场条件下是规则排列的,当施加定向电场便会发生形变。
液晶是一种介于固体和液体之间的特殊物质,是一种有机化合物,常态下呈液态,但是它的分子排列却和固体晶体一样非常规则,因此取名液晶。
如果给液晶施加电场,会改变它的分子排列,从而改变光线的传播方向,配合偏振光片,它就具有控制光线透过率的作用,再配合彩色滤光片,改变加给液晶电压大小,就能改变某一颜色透光量的多少。

配向膜
配向膜将液晶层夹在中间,液晶沿着配向膜表面的细槽定向排列,这样透过偏光片的光线便会沿着液晶层分子排布方向发生变化,从而透过外层偏光片。

电极层
电极层产生定向电场,从而驱动液晶分子排列发生扭转。

彩色滤光膜
令不同波长的光选择性透过。

薄膜晶体管
电极层上的玻璃基板上覆盖着薄膜晶体管。

显示原理
薄膜晶体管通过控制电压可实现像素点的亮度调节,该像素点范围内的液晶分子也会受到电压产生的电场影响发生分子排列扭曲,再经过偏光片即可调整亮度,子像素由 RGB 三色组合实现各种色彩输出。

详见:TFT_LCD液晶屏 .

驱动芯片
利用 ST7735S 驱动芯片和 SPI 通信协议,实现 TFT-LCD驱动显示。

AI8051U 驱动 1.8 英寸 TFT 显示屏
使用 AI8051U 驱动 TFT-LCD 显示和刷新图片。

代码

  1. /*
  2. AI8051U
  3. 0.96inch TFT_ST7735 screen
  4. IRC rate 24MHz
  5. */
  6. #include <AI8051U.h>
  7. #include <absacc.h>
  8. #include <intrins.h>
  9. #include <string.h>
  10. #include "BMP.h"
  11. typedef unsigned char u8;
  12. typedef unsigned int u16;
  13. typedef unsigned long u32;
  14. #define MAIN_Fosc 24000000UL // main frequency
  15. //--------------------------- TFT 液晶屏接线说明 -------------------------------------//
  16. sbit bl        =P2^2;//接模块BL引脚,背光可以采用IO控制或者PWM控制,也可以直接接到高电平常亮
  17. sbit scl       =P2^7;//接模块CLK引脚,接裸屏Pin9_SCL
  18. sbit sda       =P2^6;//接模块DIN/MOSI引脚,接裸屏Pin8_SDA
  19. sbit rs        =P2^5;//接模块D/C引脚,接裸屏Pin7_A0
  20. sbit cs        =P2^4;//接模块CE引脚,接裸屏Pin12_CS
  21. sbit reset     =P2^1;//接模块RST引脚,接裸屏Pin6_RES
  22. //--------------------------- End of 液晶屏接线 ---------------------------------//
  23. //定义常用颜色
  24. #define RED                  0xf800
  25. #define GREEN                0x07e0
  26. #define BLUE                 0x001f
  27. #define WHITE                0xffff
  28. #define BLACK                0x0000
  29. #define YELLOW  0xFFE0
  30. #define GRAY0   0xEF7D   
  31. #define GRAY1   0x8410             
  32. #define GRAY2   0x4208   
  33. code unsigned char gImage_AIC_LOGO_RGB[];
  34. /**********************************
  35. ----------Image2LCD取模选项设置---------
  36. 水平扫描
  37. 16位
  38. 80*160
  39. 不包含图像头数据
  40. 自左至右
  41. 自顶至底
  42. 低位在前
  43. **********************************/
  44. void GPIO_Init();
  45. void delay_ms(u16 time);
  46. void lcd_initial();
  47. void showimage(const unsigned char *p);
  48. void showimageFull(const unsigned char *p);
  49. void main(void)
  50. {
  51.         GPIO_Init();
  52.         //P3M1 = 0x00;P3M0 = 0x00;
  53.         lcd_initial();
  54.         bl=1;
  55.     showimageFull(gImage_AIC_LOGO_RGB);
  56.   while(1)
  57.   {
  58.                 showimageFull(gImage_AIC_LOGO_RGB);
  59.                 delay_ms(200);
  60.   }
  61. }
  62. /*-------------- GPIO initialize ------------------*/
  63. void GPIO_Init()
  64. {
  65.         P0M1 = 0x00;   P0M0 = 0x00;
  66.   P1M1 = 0x00;   P1M0 = 0x00;
  67.   P2M1 = 0x00;   P2M0 = 0x00;
  68.   P3M1 = 0x00;   P3M0 = 0x00;
  69.   P4M1 = 0x00;   P4M0 = 0x00;
  70.   P5M1 = 0x00;   P5M0 = 0x00;
  71.         P6M1 = 0x00;   P6M0 = 0x00;
  72.   P7M1 = 0x00;   P7M0 = 0x00;
  73. }
  74. void delay_ms(u16 time)
  75. {
  76. u16 i;
  77.         do
  78.         {
  79.                 i = MAIN_Fosc / 6000;
  80.                 while(--i);
  81.         }
  82.         while(--time);
  83. }
  84. //向SPI总线传输一个8位数据
  85. void  SPI_WriteData(u8 Data)
  86. {
  87.         unsigned char i=0;
  88.         for(i=8;i>0;i--)
  89.         {
  90.                 if(Data&0x80)       
  91.                 sda=1; //输出数据
  92.                 else sda=0;
  93.                 scl=0;
  94.                 scl=1;
  95.                 Data<<=1;
  96.         }
  97. }
  98. //向液晶屏写一个8位指令
  99. void  Lcd_WriteIndex(u8 Data)
  100. {
  101.                
  102.                 cs=0;
  103.                 rs=0;
  104.                 SPI_WriteData(Data);                
  105.                 cs=1;
  106. }
  107. //向液晶屏写一个8位数据
  108. void  Lcd_WriteData(u8 Data)
  109. {       
  110.                 unsigned char i=0;
  111.                 cs=0;
  112.                 rs=1;
  113.                 SPI_WriteData(Data);        
  114.                 cs=1;
  115. }
  116. //向液晶屏写一个16位数据
  117. void  LCD_WriteData_16Bit(unsigned int Data)
  118. {
  119.         unsigned char i=0;
  120.         cs=0;
  121.         rs=1;
  122.         SPI_WriteData(Data>>8);         //写入高8位数据
  123.         SPI_WriteData(Data);                         //写入低8位数据
  124.         cs=1;
  125. }
  126. void Reset()
  127. {
  128.     reset=0;
  129.     delay_ms(100);
  130.     reset=1;
  131.     delay_ms(100);
  132. }
  133. //液晶屏初始化 for S6D02A1
  134. void lcd_initial()
  135. {        Reset();//Reset before LCD Init.
  136.                
  137.         //LCD Init For 1.44Inch LCD Panel with ST7735R.
  138.         Lcd_WriteIndex(0x11);//Sleep exit
  139.         delay_ms (120);
  140.        
  141.         Lcd_WriteIndex(0x21); // normal : 0x20;  inverse color: 0x21;
  142. Lcd_WriteIndex(0xB1);
  143. Lcd_WriteData(0x05);
  144. Lcd_WriteData(0x3A);
  145. Lcd_WriteData(0x3A);
  146. Lcd_WriteIndex(0xB2);
  147. Lcd_WriteData(0x05);
  148. Lcd_WriteData(0x3A);
  149. Lcd_WriteData(0x3A);
  150. Lcd_WriteIndex(0xB3);
  151. Lcd_WriteData(0x05);  
  152. Lcd_WriteData(0x3A);
  153. Lcd_WriteData(0x3A);
  154. Lcd_WriteData(0x05);
  155. Lcd_WriteData(0x3A);
  156. Lcd_WriteData(0x3A);
  157. Lcd_WriteIndex(0xB4);
  158. Lcd_WriteData(0x03);
  159. Lcd_WriteIndex(0xC0);
  160. Lcd_WriteData(0x62);
  161. Lcd_WriteData(0x02);
  162. Lcd_WriteData(0x04);
  163. Lcd_WriteIndex(0xC1);
  164. Lcd_WriteData(0xC0);
  165. Lcd_WriteIndex(0xC2);
  166. Lcd_WriteData(0x0D);
  167. Lcd_WriteData(0x00);
  168. Lcd_WriteIndex(0xC3);
  169. Lcd_WriteData(0x8D);
  170. Lcd_WriteData(0x6A);   
  171. Lcd_WriteIndex(0xC4);
  172. Lcd_WriteData(0x8D);
  173. Lcd_WriteData(0xEE);
  174. Lcd_WriteIndex(0xC5);  /*VCOM*/
  175. Lcd_WriteData(0x0E);   
  176. Lcd_WriteIndex(0xE0);
  177. Lcd_WriteData(0x10);
  178. Lcd_WriteData(0x0E);
  179. Lcd_WriteData(0x02);
  180. Lcd_WriteData(0x03);
  181. Lcd_WriteData(0x0E);
  182. Lcd_WriteData(0x07);
  183. Lcd_WriteData(0x02);
  184. Lcd_WriteData(0x07);
  185. Lcd_WriteData(0x0A);
  186. Lcd_WriteData(0x12);
  187. Lcd_WriteData(0x27);
  188. Lcd_WriteData(0x37);
  189. Lcd_WriteData(0x00);
  190. Lcd_WriteData(0x0D);
  191. Lcd_WriteData(0x0E);
  192. Lcd_WriteData(0x10);
  193. Lcd_WriteIndex(0xE1);
  194. Lcd_WriteData(0x10);
  195. Lcd_WriteData(0x0E);
  196. Lcd_WriteData(0x03);
  197. Lcd_WriteData(0x03);
  198. Lcd_WriteData(0x0F);
  199. Lcd_WriteData(0x06);
  200. Lcd_WriteData(0x02);
  201. Lcd_WriteData(0x08);
  202. Lcd_WriteData(0x0A);
  203. Lcd_WriteData(0x13);
  204. Lcd_WriteData(0x26);
  205. Lcd_WriteData(0x36);
  206. Lcd_WriteData(0x00);
  207. Lcd_WriteData(0x0D);
  208. Lcd_WriteData(0x0E);
  209. Lcd_WriteData(0x10);
  210. Lcd_WriteIndex(0x3A);
  211. Lcd_WriteData(0x05);
  212. Lcd_WriteIndex(0x36);
  213. Lcd_WriteData(0xC8);
  214. Lcd_WriteIndex(0x29);
  215. }
  216. /*************************************************
  217. 函数名:LCD_Set_Region
  218. 功能:设置lcd显示区域,在此区域写点数据自动换行
  219. 入口参数:xy起点和终点
  220. 返回值:无
  221. *************************************************/
  222. void Lcd_SetRegion(unsigned int x_start,unsigned int y_start,unsigned int x_end,unsigned int y_end)
  223. {       
  224.         Lcd_WriteIndex(0x2a);
  225.         Lcd_WriteData(0x00);
  226.         Lcd_WriteData(x_start+0x1A);
  227.         Lcd_WriteData(0x00);
  228.         Lcd_WriteData(x_end+0x1A);
  229.         Lcd_WriteIndex(0x2b);
  230.         Lcd_WriteData(0x00);
  231.         Lcd_WriteData(y_start+1);
  232.         Lcd_WriteData(0x00);
  233.         Lcd_WriteData(y_end+1);       
  234.         Lcd_WriteIndex(0x2c);
  235. }
  236. void dsp_single_colour(int color)
  237. {
  238.         u8 i,j;
  239.         Lcd_SetRegion(0,0,80-1,160-1);
  240.         for (i=0;i<160;i++)
  241.             for (j=0;j<80;j++)
  242.                 LCD_WriteData_16Bit(color);
  243. }
  244. //取模方式 水平扫描 从左到右 低位在前
  245. void showimageFull(const unsigned char *p) //显示128*64
  246. {
  247.         int i,j,k;
  248.         unsigned char picH,picL;
  249.         dsp_single_colour(WHITE); //清屏  
  250.        
  251.         for(k=0;k<1;k++)//纵坐标图片数量
  252.         {
  253.                    for(j=0;j<1;j++)//横坐标图片数量
  254.                 {       
  255.                         Lcd_SetRegion(80*j,160*k,80*j+79,160*k+159); //坐标设置
  256.                     for(i=0;i<80*160;i++)
  257.                          {       
  258.                                  picL=*(p+i*2);        //数据低位在前
  259.                                 picH=*(p+i*2+1);                               
  260.                                 LCD_WriteData_16Bit(picH<<8|picL);                                                 
  261.                          }       
  262.                  }
  263.         }               
  264. }
复制代码
AI8051U 驱动 0.96 英寸 TFT 显示屏
TFT_80x160.jpg

Image2LCD
Image2LCD 软件设置

打开目标图片 - 选择输出类型 - 扫描方式 - 输出灰度 - 宽度和高度 - 保存

Image2LCD.png
代码

AI8051U 驱动 80*160 像素图片的显示

  1. #include <AI8051U.h>
  2. #include <intrins.h>
  3. #include <sys.h>
  4. #include <lcd.h>
  5. #include <font.h>
  6. void showimageF()
  7. {
  8.           int i,j,k;
  9.         for(k=0;k<1;k++)
  10.         {
  11.                    for(j=0;j<3;j++)
  12.                 {       
  13.                         Address_set(128*j,160*k,128*j+127,160*k+159);
  14.                     for(i=0;i<20480;i++)
  15.                          {                               
  16.                                    LCD_WR_DATA8(image_fire[i*2+1]);
  17.                                  LCD_WR_DATA8(image_fire[i*2]);                                       
  18.                          }       
  19.                  }
  20.         }
  21.                
  22. }
  23. void main()
  24. {
  25.         GPIO_Init();
  26.         Lcd_Init();
  27.         LCD_Clear(WHITE);
  28.         BACK_COLOR=BLACK;;POINT_COLOR=WHITE;
  29.         while(1)
  30.         {
  31.                 LCD_Clear(WHITE);
  32.                 BACK_COLOR=BLACK;;POINT_COLOR=WHITE;
  33.                 showimageF();
  34.                 delayms(200);
  35.   }
  36. }
复制代码


显示效果
80x160_static_switch_pic.gif
1.8inchTFT.jpg
局部刷新
根据前面的测试结果,发现循环延迟刷新画面会导致画面抖动失帧,因此对于多数情况仅需要进行局部数据的修改即可,可极大减少主控负担和代码体积。

目标
让炉子上方的火苗动起来

方案
使用 PhotoShop 软件,打开原始图片,选中目标火苗区域,复制到多个新建图层,调整设置扭曲滤镜(波纹)的幅度值,控制火苗的形变,幅值最好是连续等间隔,最后裁剪火苗并存储为 BMP 图片。

Fires.jpg
代码

0.96 英寸 TFT 显示屏代码

  1. void main(void)
  2. {
  3.         GPIO_Init();
  4.         lcd_initial();
  5.         bl=1;
  6.         showimageFull(gImage_bg);
  7.   while(1)
  8.   {
  9.                 showimagePart(gImage_fire_0);
  10.                 delay_ms(50);
  11.                 showimagePart(gImage_fire_N100);
  12.                 delay_ms(50);
  13.                 showimagePart(gImage_fire_N200);
  14.                 delay_ms(50);
  15.                 showimagePart(gImage_fire_N100);
  16.                 delay_ms(50);
  17.                 showimagePart(gImage_fire_0);
  18.                 delay_ms(50);
  19.                 showimagePart(gImage_fire_P100);
  20.                 delay_ms(50);
  21.                 showimagePart(gImage_fire_P200);
  22.                 delay_ms(50);
  23.                 showimagePart(gImage_fire_P100);
  24.                 delay_ms(50);
  25.   }
复制代码


对于 1.8 inch TFT 使用代码如下

  1. #include <AI8051U.h>
  2. #include <intrins.h>
  3. #include "sys.h"
  4. #include "LCD.h"
  5. #include "font.h"
  6. #include "bmp.h"
  7. void main()
  8. {
  9.         GPIO_Init();
  10.         Lcd_Init();
  11.         LCD_Clear(WHITE);
  12.         BACK_COLOR=BLACK;;POINT_COLOR=WHITE;
  13.         showimageFull();//显示整张图片
  14.         while(1)
  15.         {//开始局部刷新循环
  16.                 showimagePart(57,52,56,41,gImage_fire_0);
  17.                 delayms(50);
  18.                 //showimagePart(57,52,56,41,gImage_fire_N100);
  19.                 //delayms(50);
  20.                 showimagePart(57,52,56,41,gImage_fire_N200);
  21.                 delayms(50);
  22.                 //showimagePart(57,52,56,41,gImage_fire_N100);
  23.                 //delayms(50);
  24.                 showimagePart(57,52,56,41,gImage_fire_0);
  25.                 delayms(50);
  26.                 //showimagePart(57,52,56,41,gImage_fire_P100);
  27.                 //delayms(50);
  28.                 showimagePart(57,52,56,41,gImage_fire_P200);
  29.                 delayms(50);
  30.                 //showimagePart(57,52,56,41,gImage_fire_P100);
  31.                 //delayms(50);
  32.   }
  33. }
复制代码


这里为了减小数组体积,避免报错,注释了中间部分过渡帧画面;加上过渡部分效果更连贯,动画更细腻。

显示效果
0.96 英寸 TFT-LCD 显示效果
Burner_Fire_dynamic_80x160.gif
1.8 英寸 TFT-LCD 显示效果
AIC_Fire_dynamic.gif

使用的开发板为基于 AI8051U 芯片的学习板,PCB工程见:Ai8051U多功能学习板 - 立创开源硬件平台

具体工程见附件(包含代码和显示BMP图片)。


















128x160_fresh.gif

Code_Project.zip

231.02 KB, 下载次数: 60

1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
MCU开发者和爱好者
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:238
  • 最近打卡:2025-05-01 13:11:43

22

主题

283

回帖

901

积分

高级会员

积分
901
发表于 2024-11-14 11:26:19 来自手机 | 显示全部楼层
REMOVEUNUSED
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:29
  • 最近打卡:2025-04-26 08:37:49

2

主题

56

回帖

546

积分

高级会员

积分
546
发表于 2024-11-14 14:48:47 | 显示全部楼层
有驱动3.5寸TFT屏的代码吗?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2024-11-14 15:20:51 | 显示全部楼层
{:5_332:}
三天不学习,赶不上刘少奇~
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:162
  • 最近打卡:2025-05-01 06:56:44
已绑定手机

56

主题

1319

回帖

2938

积分

荣誉版主

无情的代码机器

积分
2938
发表于 2024-11-14 22:40:39 | 显示全部楼层
来交作业{:5_351:}


三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:123
  • 最近打卡:2025-04-19 16:12:35
已绑定手机

60

主题

777

回帖

4001

积分

论坛元老

自定义头衔

积分
4001
发表于 2024-11-15 00:14:05 来自手机 | 显示全部楼层
TFT液晶面板的原理,和TFT驱动芯片的应用方法基本没有关系

哈哈哈开头的铺垫太像我们的教科书了
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:519
  • 最近打卡:2025-05-01 08:15:57
已绑定手机
已实名认证

46

主题

161

回帖

474

积分

中级会员

积分
474
发表于 2024-11-15 00:56:30 | 显示全部楼层
VC*** 发表于 2024-11-15 00:14
TFT液晶面板的原理,和TFT驱动芯片的应用方法基本没有关系

哈哈哈开头的铺垫太像我们的教科书了 ...

我是光学专业的,所以更专注于显示原理部分,电路设计、驱动芯片原理只能查询硬件手册解决了
MCU开发者和爱好者
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:342
  • 最近打卡:2025-04-30 08:26:34
已绑定手机

6

主题

202

回帖

810

积分

高级会员

积分
810
发表于 2024-11-15 07:11:05 | 显示全部楼层
非常不错!!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:504
  • 最近打卡:2025-05-01 07:50:30

9

主题

193

回帖

552

积分

高级会员

积分
552
发表于 2024-12-12 10:20:59 | 显示全部楼层

刷新速度还可以啊,这么快

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:120
  • 最近打卡:2025-05-01 10:54:51
已绑定手机

83

主题

286

回帖

391

积分

中级会员

积分
391
发表于 前天 16:11 | 显示全部楼层
感谢分享。
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-1 20:52 , Processed in 0.476629 second(s), 127 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表