实验九--裸机LCD

一。环境

  系统:ubuntu12.04

  开发板:jz2440

  编译器:gcc

二。说明

有空补上

三。代码

Makefile:

 1 CC      = arm-linux-gcc
 2 LD      = arm-linux-ld
 3 AR      = arm-linux-ar
 4 OBJCOPY = arm-linux-objcopy
 5 OBJDUMP = arm-linux-objdump
 6
 7 CFLAGS         := -Wall -O2
 8
 9
10 export     CC LD AR OBJCOPY OBJDUMP CFLAGS
11
12 objs := head.o init.o nand.o lcddrv.o framebuffer.o main.o
13
14 lcd.bin: $(objs)
15     ${LD} -Tlcd.lds -o lcd_elf $^
16     ${OBJCOPY} -O binary -S lcd_elf [email protected]
17     ${OBJDUMP} -D -m arm lcd_elf > lcd.dis
18
19
20 %.o:%.c
21     ${CC} $(CFLAGS) -c -o [email protected] $<
22
23 %.o:%.S
24     ${CC} $(CFLAGS) -c -o [email protected] $<
25
26 clean:
27     rm -f lcd.bin lcd_elf lcd.dis *.o
28     

head.S:

 1 @******************************************************************************
 2 @ File: head.S
 3 @ 功能: 设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
 4 @******************************************************************************
 5
 6 .extern     main
 7 .text
 8 .global _start
 9 _start:
10 @******************************************************************************
11 @ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
12 @******************************************************************************
13     b   Reset
14
15 @ 0x04: 未定义指令中止模式的向量地址
16 HandleUndef:
17     b   HandleUndef
18
19 @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
20 HandleSWI:
21     b   HandleSWI
22
23 @ 0x0c: 指令预取终止导致的异常的向量地址
24 HandlePrefetchAbort:
25     b   HandlePrefetchAbort
26
27 @ 0x10: 数据访问终止导致的异常的向量地址
28 HandleDataAbort:
29     b   HandleDataAbort
30
31 @ 0x14: 保留
32 HandleNotUsed:
33     b   HandleNotUsed
34
35 @ 0x18: 中断模式的向量地址
36 HandleIRQ:
37     b   HandleIRQ
38
39 @ 0x1c: 快中断模式的向量地址
40 HandleFIQ:
41     b   HandleFIQ
42
43 Reset:
44     ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈
45     bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启
46     bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK
47     bl  memsetup            @ 设置存储控制器以使用SDRAM
48     bl  nand_init           @ 初始化NAND Flash
49
50                             @ 复制代码到SDRAM中
51     ldr r0, =0x30000000     @ 1. 目标地址 = 0x30000000,这是SDRAM的起始地址
52     mov r1, #4096           @ 2. 源地址   = 4096,运行地址在SDRAM中的代码保存在NAND Flash 4096地址开始处
53     mov r2, #16*1024        @ 3. 复制长度 = 16K,对于本实验,这是足够了
54     bl  CopyCode2SDRAM      @ 调用C函数CopyCode2SDRAM
55
56     bl  clean_bss           @ 清除bss段,未初始化或初值为0的全局/静态变量保存在bss段
57
58
59
60     msr cpsr_c, #0xdf       @ 进入系统模式
61     ldr sp, =0x34000000     @ 设置系统模式栈指针,
62
63
64
65     ldr lr, =halt_loop      @ 设置返回地址
66     ldr pc, =main           @ 调用main函数
67 halt_loop:
68     b   halt_loop

上面的sdram,时钟,nand flash等同前面的,不贴出来了

现在与lcd有关的函数:

main.c:

 1 #include "lcddrv.h"
 2 #include "framebuffer.h"
 3 #include "s3c24xx.h"
 4
 5 void delay()
 6
 7 {
 8
 9 unsigned long cnt;
10
11 for(cnt=0;cnt<100000;cnt++);
12
13 }
14
15 int main()
16 {
17     Lcd_Port_Init();                     // 设置LCD引脚
18     Tft_Lcd_Init(); // 初始化LCD控制器
19     Lcd_PowerEnable(0, 1);               // 设置LCD_PWREN有效,它用于打开LCD的电源
20     Lcd_EnvidOnOff(1);                   // 使能LCD控制器输出信号
21
22     ClearScr(0x0);  // 清屏,黑色
23     while (1)
24     {
25
26         Mire();
27     delay();
28         //Lcd_EnvidOnOff(0);
29
30     }
31
32     return 0;
33 }

由main函数可以看出,本程序只是驱动lcd来画同心圆,参考代码是韦东山先生的,此处作了较大的删改:

framebuffer.c:

 1 /*
 2  * FILE: framebuffer.c
 3  * 实现在framebuffer上画点、画线、画同心圆、清屏的函数
 4  */
 5
 6 #include "framebuffer.h"
 7
 8 extern unsigned int fb_base_addr;
 9 extern unsigned int bpp;
10 extern unsigned int xsize;
11 extern unsigned int ysize;
12
13 /*
14  * 画点
15  * 输入参数:
16  *     x、y : 象素坐标
17  *     color: 颜色值
18  *         对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
19  *     需要转换为5:6:5格式
20  *         对于8BPP: color为调色板中的索引值,
21  *     其颜色取决于调色板中的数值
22  */
23 void PutPixel(unsigned int x, unsigned int y, unsigned int color)
24 {
25     unsigned char red,green,blue;
26
27     switch (bpp){
28         case 16:
29         {
30             unsigned short *addr = (unsigned short *)fb_base_addr + (y * xsize + x);
31             red   = (color >> 19) & 0x1f;
32             green = (color >> 10) & 0x3f;
33             blue  = (color >>  3) & 0x1f;
34             color = (red << 11) | (green << 5) | blue; // 格式5:6:5
35             *addr = (unsigned short) color;
36             break;
37         }
38
39
40         default:
41             break;
42     }
43 }
44
45 /*
46  * 绘制同心圆
47  */
48 void Mire(void)
49 {
50     unsigned int x,y;
51     unsigned int color;
52     unsigned char red,green,blue,alpha;
53
54     for (y = 0; y < ysize; y++)
55         for (x = 0; x < xsize; x++){
56             color = ((x-xsize/2)*(x-xsize/2) + (y-ysize/2)*(y-ysize/2))/64;
57             red   = (color/8) % 256;
58             green = (color/4) % 256;
59             blue  = (color/2) % 256;
60             alpha = (color*2) % 256;
61
62             color |= ((unsigned int)alpha << 24);
63             color |= ((unsigned int)red   << 16);
64             color |= ((unsigned int)green << 8 );
65             color |= ((unsigned int)blue       );
66
67             PutPixel(x,y,color);
68         }
69 }
70
71 /*
72  * 将屏幕清成单色
73  * 输入参数:
74  *     color: 颜色值
75  *         对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
76  *     需要转换为5:6:5格式
77  *         对于8BPP: color为调色板中的索引值,
78  *     其颜色取决于调色板中的数值
79  */
80 void ClearScr(unsigned int color)
81 {
82     unsigned int x,y;
83
84     for (y = 0; y < ysize; y++)
85         for (x = 0; x < xsize; x++)
86             PutPixel(x, y, color);
87 }

lcddrv.c:

  1 /*
  2  * FILE: lcddrv.c
  3  * 提供操作LCD控制器、调色板等的底层函数
  4  */
  5
  6 #include "s3c24xx.h"
  7 #include "lcddrv.h"
  8
  9 #define GPB0_tout0  (2<<(0*2))
 10 #define GPB0_out    (1<<(0*2))
 11 #define GPB1_out    (1<<(1*2))
 12
 13 #define GPB0_MSK    (3<<(0*2))
 14 #define GPB1_MSK    (3<<(1*2))
 15
 16
 17 unsigned int fb_base_addr;
 18 unsigned int bpp;
 19 unsigned int xsize;
 20 unsigned int ysize;
 21
 22
 23 /*
 24  * 初始化用于LCD的引脚
 25  */
 26 void Lcd_Port_Init(void)
 27 {
 28     GPCUP   = 0xffffffff;   // 禁止内部上拉
 29     GPCCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
 30     GPDUP   = 0xffffffff;   // 禁止内部上拉
 31     GPDCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[23:8]
 32       GPBCON &= ~(GPB0_MSK);  // Power enable pin
 33     GPBCON |= GPB0_out;
 34     GPBDAT &= ~(1<<0);            // Power off
 35
 36 }
 37
 38 /*
 39  * 初始化LCD控制器
 40  * 输入参数:
 41  * type: 显示模式
 42  *      MODE_TFT_8BIT_240320  : 240*320 8bpp的TFT LCD
 43  *      MODE_TFT_16BIT_240320 : 240*320 16bpp的TFT LCD
 44  *      MODE_TFT_8BIT_640480  : 640*480 8bpp的TFT LCD
 45  *      MODE_TFT_16BIT_640480 : 640*480 16bpp的TFT LCD
 46  */
 47 void Tft_Lcd_Init()
 48 {
 49
 50         /*
 51          * 设置LCD控制器的控制寄存器LCDCON1~5
 52          * 1. LCDCON1:
 53          *    设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
 54          *    选择LCD类型: TFT LCD
 55          *    设置显示模式: 16BPP
 56          *    先禁止LCD信号输出
 57          * 2. LCDCON2/3/4:
 58          *    设置控制信号的时间参数
 59          *    设置分辨率,即行数及列数
 60          * 现在,可以根据公式计算出显示器的频率:
 61          * 当HCLK=100MHz时,
 62          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
 63          *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
 64          *              {2x(CLKVAL+1)/(HCLK)}]
 65          *            = 60Hz
 66          * 3. LCDCON5:
 67          *    设置显示模式为16BPP时的数据格式: 5:6:5
 68          *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
 69          *    半字(2字节)交换使能
 70          */
 71         LCDCON1 = (4<<8) | (LCDTYPE_TFT<<5) |  72                   (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
 73         LCDCON2 = (1<<24) | (271<<14) |  74                   (1<<6) | (9);
 75         LCDCON3 = (1<<19) | (479<<8) | (1);
 76         LCDCON4 = 40;
 77         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) |  78                   (HWSWP<<1);
 79
 80         /*
 81          * 设置LCD控制器的地址寄存器LCDSADDR1~3
 82          * 帧内存与视口(view point)完全吻合,
 83          * 图像数据格式如下:
 84          *         |----PAGEWIDTH----|
 85          *    y/x  0   1   2       239
 86          *     0   rgb rgb rgb ... rgb
 87          *     1   rgb rgb rgb ... rgb
 88          * 1. LCDSADDR1:
 89          *    设置LCDBANK、LCDBASEU
 90          * 2. LCDSADDR2:
 91          *    设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
 92          * 3. LCDSADDR3:
 93          *    OFFSIZE等于0,PAGEWIDTH等于(240*2/2)
 94          */
 95         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
 96         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+  97                     (480)*(272)*2)>>1);
 98         LCDSADDR3 = (0<<11) | (480*2/2);
 99
100         /* 禁止临时调色板寄存器 */
101         TPAL = 0;
102
103         fb_base_addr = LCDFRAMEBUFFER;
104         bpp = 16;
105         xsize = 480;
106         ysize = 272;
107
108
109 }
110
111
112 /*
113  * 设置是否输出LCD电源开关信号LCD_PWREN
114  * 输入参数:
115  *     invpwren: 0 - LCD_PWREN有效时为正常极性
116  *               1 - LCD_PWREN有效时为反转极性
117  *     pwren:    0 - LCD_PWREN输出有效
118  *               1 - LCD_PWREN输出无效
119  */
120 void Lcd_PowerEnable(int invpwren, int pwren)
121 {
122     GPGCON = (GPGCON & (~(3<<8))) | (3<<8);   // GPG4用作LCD_PWREN
123     GPGUP  = (GPGUP & (~(1<<4))) | (1<<4);    // 禁止内部上拉
124
125     LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5);  // 设置LCD_PWREN的极性: 正常/反转
126     LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3);     // 设置是否输出LCD_PWREN
127 }
128
129 /*
130  * 设置LCD控制器是否输出信号
131  * 输入参数:
132  * onoff:
133  *      0 : 关闭
134  *      1 : 打开
135  */
136 void Lcd_EnvidOnOff(int onoff)
137 {
138     if (onoff == 1)
139     {
140         LCDCON1 |= 1;         // ENVID ON
141         GPBDAT |= (1<<0);            // Power on
142     }
143     else
144     {
145         LCDCON1 &= 0x3fffe;  // ENVID Off
146         GPBDAT &= ~(1<<0);     // Power off
147     }
148 }    

现在贴出重要的头文件做为理解用:

lcddrv.h:

 1 /*
 2  * FILE: lcddrv.h
 3  * 操作LCD控制器、调色板等的底层函数接口
 4  */
 5
 6 #ifndef __LCDDRV_H__
 7 #define __LCDDRV_H__
 8
 9
10 #define LOWER21BITS(n)  ((n) & 0x1fffff)
11
12 #define BPPMODE_16BPP   0xC
13
14
15 #define LCDTYPE_TFT     0x3
16
17 #define ENVID_DISABLE   0
18 #define ENVID_ENABLE    1
19
20 #define FORMAT8BPP_5551 0
21 #define FORMAT8BPP_565  1
22
23 #define HSYNC_NORM      0
24 #define HSYNC_INV       1
25
26 #define VSYNC_NORM      0
27 #define VSYNC_INV       1
28
29 #define VDEN_NORM        0
30 #define VDEN_INV        1
31
32 #define BSWP            1
33 #define HWSWP           1
34
35 #define LCDFRAMEBUFFER 0x30400000
36
37 /*
38  * 初始化用于LCD的引脚
39  */
40 void Lcd_Port_Init(void);
41
42 /*
43  * 初始化LCD控制器
44  * 输入参数:
45  * type: 显示模式
46  *      MODE_TFT_8BIT_640480  : 640*640 8bpp的TFT LCD
47  *      MODE_TFT_16BIT_640480 : 640*640 16bpp的TFT LCD
48  */
49 void Tft_Lcd_Init();
50
51 void Lcd_EnvidOnOff(int onoff);
52
53 /*
54  * 设置是否输出LCD电源开关信号LCD_PWREN
55  * 输入参数:
56  *     invpwren: 0 - LCD_PWREN有效时为正常极性
57  *               1 - LCD_PWREN有效时为反转极性
58  *     pwren:    0 - LCD_PWREN输出有效
59  *               1 - LCD_PWREN输出无效
60  */
61 void Lcd_PowerEnable(int invpwren, int pwren);
62
63
64 #endif /*__LCDDRV_H__*/

自然不难看出,仍然有不少冗余项,这里先不做深究。

上面代码经过烧写验证,没有问题。

代码删减了串口,中断,以及print函数的硬件重定向等内容,以便更直观理解lcd驱动。

关于代码中重要函数,有时间补上。

时间: 2024-10-20 07:01:08

实验九--裸机LCD的相关文章

王爽汇编实验九

1 ;实验九 2 assume cs:code,ds:data 3 data segment 4 db 'welcome to masm!' 5 data ends 6 7 code segment 8 start : 9 mov ax,data 10 mov ds,ax;定义数据段 11 12 mov ax,0B800h 13 mov es,ax;定义显示段 14 15 mov cx,16 16 mov si,0 17 mov di,10*160+80 ;将输出显示放在第10行中间 18 19

Packet Tracer 5.0实验(九) 路由器RIP动态路由配置

Packet Tracer 5.0实验(九) 路由器RIP动态路由配置 一.实验目标 掌握RIP协议的配置方法: 掌握查看通过动态路由协议RIP学习产生的路由: 熟悉广域网线缆的连接方式: 二.实验背景 假设校园网通过一台三层交换机连到校园网出口路由器上,路由器再和校园外的另一台路由器连接.现要做适当配置,实现校园网内部主机与校园网外部主机之间的相互通信.为了简化网管的管理维护工作,学校决定采用RIP V2协议实现互通. 三.技术原理 RIP(Routing Information Protoc

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验九:PS/2模块③ — 键盘与多组合键

实验九:PS/2模块③ — 键盘与多组合键 笔者曾经说过,通码除了单字节以外,也有双字节通码,而且双字节通码都是 8’hE0开头,别名又是 E0按键.常见的的E0按键有,<↑>,<↓>,<←>,<→>,<HOME>,<PRTSC> 等编辑键.除此之外,一些组合键也是E0按键,例如 <RCtrl> 或者 <RAlt> .所以说,当我们设计组合键的时候,除了考虑“左边”的组合键以外,我们也要考虑“右边”的组合键.&

Linux基础入门(新版)(实验九-实验十二)

实验九 简单文本入门 一.常用的文本处理命令 二.文本处理命令 1.tr 命令 tr 命令可以用来删除一段文本信息中的某些文字.或者将其进行转换. 使用方式: tr [option]...SET1 [SET2]   常用的选项有: 选项 说明 -d 删除和set1匹配的字符,注意不是全词匹配也不是按字符顺序匹配 -s 去除set1指定的在输入文本中连续并重复的字符 操作举例: # 删除 "hello shiyanlou" 中所有的'o','l','h' $ echo 'hello sh

CCNP实验九:OSPF 帧中继实验系列2:BMA模式

一,帧中继配置 r1(config)#inter lo 0 r1(config-if)#ip add 1.1.1.1 255.255.255.0 r1(config-if)#ip ospf network point-to-p r1(config-if)#inter s1/2 r1(config-if)#en frame-relay r1(config-if)#ip add 178.1.1.1 255.255.255.0 r1(config-if)#no frame-relay inverse-

20155201 网络攻防技术 实验九 Web安全基础

20155201 网络攻防技术 实验九 Web安全基础 一.实践内容 本实践的目标理解常用网络攻击技术的基本原理.Webgoat实践下相关实验. 二.报告内容: 1. 基础问题回答 1)SQL注入攻击原理,如何防御 SQL注入即是指web应用程序对用户输入数据的合法性没有判断,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息. SQL注入攻击的典型手段:判断应用程序是否存在注入漏洞,收集信息

20155222卢梓杰 实验九 Web安全基础

实验九 Web安全基础 今天不多bb,打开webgoat就是干好吧 1.简单字符串sql注入 可以看到这个实验说明是 "下表允许用户查看其信用卡号码.尝试插入一个SQL字符串,以显示所有信用卡号码." 下面已经显示了后台使用的sql语句是 SELECT * FROM user_data WHERE last_name = 'Your Name' 既然我们的目的是要显示所有信用卡的记录,所以我们会想到让SELECT * FROM user_data WHERE后面的表达式为永真,所以我们

2017-2018-2 20155225《网络对抗技术》实验九 Web安全基础

2017-2018-2 20155225<网络对抗技术>实验九 Web安全基础 WebGoat 1.String SQL Injection 题目是想办法得到数据库所有人的信用卡号,用Smith登录后,得到Smith的两个信用卡号,如图 但如何才能得到所有人的信用卡号呢? 只需要输入' or 1 = ' 1,这样构造可以将引号闭合,再or上一个永真式,就能屏蔽掉前面的条件. 2.Log Spoofing 在User Name中以这种格式注入:Use CR (%0d) and LF (%0a)

20155313 杨瀚 《网络对抗技术》实验九 Web安全基础

20155313 杨瀚 <网络对抗技术>实验九 Web安全基础 一.实验目的 本实践的目标理解常用网络攻击技术的基本原理.Webgoat实践下相关实验. 二.基础问题回答 1.SQL注入攻击原理,如何防御 2.XSS攻击的原理,如何防御 3.CSRF攻击原理,如何防御 三.实验内容 第一阶段 原文地址:https://www.cnblogs.com/bonsai/p/9097562.html