实验九--裸机LCD
一。环境
系统:ubuntu12.04
开发板:jz2440
编译器:gcc
二。说明
有空补上
三。代码
Makefile:
CC = arm-linux-gcc
LD = arm-linux-ld
AR = arm-linux-ar
OBJCOPY = arm-linux-objcopy
OBJDUMP = arm-linux-objdump CFLAGS := -Wall -O2 export CC LD AR OBJCOPY OBJDUMP CFLAGS objs := head.o init.o nand.o lcddrv.o framebuffer.o main.o lcd.bin: $(objs)
${LD} -Tlcd.lds -o lcd_elf $^
${OBJCOPY} -O binary -S lcd_elf $@
${OBJDUMP} -D -m arm lcd_elf > lcd.dis %.o:%.c
${CC} $(CFLAGS) -c -o $@ $< %.o:%.S
${CC} $(CFLAGS) -c -o $@ $< clean:
rm -f lcd.bin lcd_elf lcd.dis *.o
head.S:
@******************************************************************************
@ File: head.S
@ 功能: 设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@****************************************************************************** .extern main
.text
.global _start
_start:
@******************************************************************************
@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
@******************************************************************************
b Reset @ 0x04: 未定义指令中止模式的向量地址
HandleUndef:
b HandleUndef @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
b HandleSWI @ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
b HandlePrefetchAbort @ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
b HandleDataAbort @ 0x14: 保留
HandleNotUsed:
b HandleNotUsed @ 0x18: 中断模式的向量地址
HandleIRQ:
b HandleIRQ @ 0x1c: 快中断模式的向量地址
HandleFIQ:
b HandleFIQ Reset:
ldr sp, = @ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
bl clock_init @ 设置MPLL,改变FCLK、HCLK、PCLK
bl memsetup @ 设置存储控制器以使用SDRAM
bl nand_init @ 初始化NAND Flash @ 复制代码到SDRAM中
ldr r0, =0x30000000 @ . 目标地址 = 0x30000000,这是SDRAM的起始地址
mov r1, # @ . 源地址 = ,运行地址在SDRAM中的代码保存在NAND Flash 4096地址开始处
mov r2, #* @ . 复制长度 = 16K,对于本实验,这是足够了
bl CopyCode2SDRAM @ 调用C函数CopyCode2SDRAM bl clean_bss @ 清除bss段,未初始化或初值为0的全局/静态变量保存在bss段 msr cpsr_c, #0xdf @ 进入系统模式
ldr sp, =0x34000000 @ 设置系统模式栈指针, ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop
上面的sdram,时钟,nand flash等同前面的,不贴出来了
现在与lcd有关的函数:
main.c:
#include "lcddrv.h"
#include "framebuffer.h"
#include "s3c24xx.h" void delay() { unsigned long cnt; for(cnt=;cnt<;cnt++); } int main()
{
Lcd_Port_Init(); // 设置LCD引脚
Tft_Lcd_Init(); // 初始化LCD控制器
Lcd_PowerEnable(, ); // 设置LCD_PWREN有效,它用于打开LCD的电源
Lcd_EnvidOnOff(); // 使能LCD控制器输出信号 ClearScr(0x0); // 清屏,黑色
while ()
{ Mire();
delay();
//Lcd_EnvidOnOff(0); } return ;
}
由main函数可以看出,本程序只是驱动lcd来画同心圆,参考代码是韦东山先生的,此处作了较大的删改:
framebuffer.c:
/*
* FILE: framebuffer.c
* 实现在framebuffer上画点、画线、画同心圆、清屏的函数
*/ #include "framebuffer.h" extern unsigned int fb_base_addr;
extern unsigned int bpp;
extern unsigned int xsize;
extern unsigned int ysize; /*
* 画点
* 输入参数:
* x、y : 象素坐标
* color: 颜色值
* 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
* 需要转换为5:6:5格式
* 对于8BPP: color为调色板中的索引值,
* 其颜色取决于调色板中的数值
*/
void PutPixel(unsigned int x, unsigned int y, unsigned int color)
{
unsigned char red,green,blue; switch (bpp){
case :
{
unsigned short *addr = (unsigned short *)fb_base_addr + (y * xsize + x);
red = (color >> ) & 0x1f;
green = (color >> ) & 0x3f;
blue = (color >> ) & 0x1f;
color = (red << ) | (green << ) | blue; // 格式5:6:5
*addr = (unsigned short) color;
break;
} default:
break;
}
} /*
* 绘制同心圆
*/
void Mire(void)
{
unsigned int x,y;
unsigned int color;
unsigned char red,green,blue,alpha; for (y = ; y < ysize; y++)
for (x = ; x < xsize; x++){
color = ((x-xsize/)*(x-xsize/) + (y-ysize/)*(y-ysize/))/;
red = (color/) % ;
green = (color/) % ;
blue = (color/) % ;
alpha = (color*) % ; color |= ((unsigned int)alpha << );
color |= ((unsigned int)red << );
color |= ((unsigned int)green << );
color |= ((unsigned int)blue ); PutPixel(x,y,color);
}
} /*
* 将屏幕清成单色
* 输入参数:
* color: 颜色值
* 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
* 需要转换为5:6:5格式
* 对于8BPP: color为调色板中的索引值,
* 其颜色取决于调色板中的数值
*/
void ClearScr(unsigned int color)
{
unsigned int x,y; for (y = ; y < ysize; y++)
for (x = ; x < xsize; x++)
PutPixel(x, y, color);
}
lcddrv.c:
/*
* FILE: lcddrv.c
* 提供操作LCD控制器、调色板等的底层函数
*/ #include "s3c24xx.h"
#include "lcddrv.h" #define GPB0_tout0 (2<<(0*2))
#define GPB0_out (1<<(0*2))
#define GPB1_out (1<<(1*2)) #define GPB0_MSK (3<<(0*2))
#define GPB1_MSK (3<<(1*2)) unsigned int fb_base_addr;
unsigned int bpp;
unsigned int xsize;
unsigned int ysize; /*
* 初始化用于LCD的引脚
*/
void Lcd_Port_Init(void)
{
GPCUP = 0xffffffff; // 禁止内部上拉
GPCCON = 0xaaaaaaaa; // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
GPDUP = 0xffffffff; // 禁止内部上拉
GPDCON = 0xaaaaaaaa; // GPIO管脚用于VD[23:8]
GPBCON &= ~(GPB0_MSK); // Power enable pin
GPBCON |= GPB0_out;
GPBDAT &= ~(<<); // Power off } /*
* 初始化LCD控制器
* 输入参数:
* type: 显示模式
* MODE_TFT_8BIT_240320 : 240*320 8bpp的TFT LCD
* MODE_TFT_16BIT_240320 : 240*320 16bpp的TFT LCD
* MODE_TFT_8BIT_640480 : 640*480 8bpp的TFT LCD
* MODE_TFT_16BIT_640480 : 640*480 16bpp的TFT LCD
*/
void Tft_Lcd_Init()
{ /*
* 设置LCD控制器的控制寄存器LCDCON1~5
* 1. LCDCON1:
* 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
* 选择LCD类型: TFT LCD
* 设置显示模式: 16BPP
* 先禁止LCD信号输出
* 2. LCDCON2/3/4:
* 设置控制信号的时间参数
* 设置分辨率,即行数及列数
* 现在,可以根据公式计算出显示器的频率:
* 当HCLK=100MHz时,
* Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
* {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
* {2x(CLKVAL+1)/(HCLK)}]
* = 60Hz
* 3. LCDCON5:
* 设置显示模式为16BPP时的数据格式: 5:6:5
* 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
* 半字(2字节)交换使能
*/
LCDCON1 = (<<) | (LCDTYPE_TFT<<) | \
(BPPMODE_16BPP<<) | (ENVID_DISABLE<<);
LCDCON2 = (<<) | (<<) | \
(<<) | ();
LCDCON3 = (<<) | (<<) | ();
LCDCON4 = ;
LCDCON5 = (FORMAT8BPP_565<<) | (HSYNC_INV<<) | (VSYNC_INV<<) | \
(HWSWP<<); /*
* 设置LCD控制器的地址寄存器LCDSADDR1~3
* 帧内存与视口(view point)完全吻合,
* 图像数据格式如下:
* |----PAGEWIDTH----|
* y/x 0 1 2 239
* 0 rgb rgb rgb ... rgb
* 1 rgb rgb rgb ... rgb
* 1. LCDSADDR1:
* 设置LCDBANK、LCDBASEU
* 2. LCDSADDR2:
* 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
* 3. LCDSADDR3:
* OFFSIZE等于0,PAGEWIDTH等于(240*2/2)
*/
LCDSADDR1 = ((LCDFRAMEBUFFER>>)<<) | LOWER21BITS(LCDFRAMEBUFFER>>);
LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
()*()*)>>);
LCDSADDR3 = (<<) | (*/); /* 禁止临时调色板寄存器 */
TPAL = ; fb_base_addr = LCDFRAMEBUFFER;
bpp = ;
xsize = ;
ysize = ; } /*
* 设置是否输出LCD电源开关信号LCD_PWREN
* 输入参数:
* invpwren: 0 - LCD_PWREN有效时为正常极性
* 1 - LCD_PWREN有效时为反转极性
* pwren: 0 - LCD_PWREN输出有效
* 1 - LCD_PWREN输出无效
*/
void Lcd_PowerEnable(int invpwren, int pwren)
{
GPGCON = (GPGCON & (~(<<))) | (<<); // GPG4用作LCD_PWREN
GPGUP = (GPGUP & (~(<<))) | (<<); // 禁止内部上拉 LCDCON5 = (LCDCON5 & (~(<<))) | (invpwren<<); // 设置LCD_PWREN的极性: 正常/反转
LCDCON5 = (LCDCON5 & (~(<<))) | (pwren<<); // 设置是否输出LCD_PWREN
} /*
* 设置LCD控制器是否输出信号
* 输入参数:
* onoff:
* 0 : 关闭
* 1 : 打开
*/
void Lcd_EnvidOnOff(int onoff)
{
if (onoff == )
{
LCDCON1 |= ; // ENVID ON
GPBDAT |= (<<); // Power on
}
else
{
LCDCON1 &= 0x3fffe; // ENVID Off
GPBDAT &= ~(<<); // Power off
}
}
现在贴出重要的头文件做为理解用:
lcddrv.h:
/*
* FILE: lcddrv.h
* 操作LCD控制器、调色板等的底层函数接口
*/ #ifndef __LCDDRV_H__
#define __LCDDRV_H__ #define LOWER21BITS(n) ((n) & 0x1fffff) #define BPPMODE_16BPP 0xC #define LCDTYPE_TFT 0x3 #define ENVID_DISABLE 0
#define ENVID_ENABLE 1 #define FORMAT8BPP_5551 0
#define FORMAT8BPP_565 1 #define HSYNC_NORM 0
#define HSYNC_INV 1 #define VSYNC_NORM 0
#define VSYNC_INV 1 #define VDEN_NORM 0
#define VDEN_INV 1 #define BSWP 1
#define HWSWP 1 #define LCDFRAMEBUFFER 0x30400000 /*
* 初始化用于LCD的引脚
*/
void Lcd_Port_Init(void); /*
* 初始化LCD控制器
* 输入参数:
* type: 显示模式
* MODE_TFT_8BIT_640480 : 640*640 8bpp的TFT LCD
* MODE_TFT_16BIT_640480 : 640*640 16bpp的TFT LCD
*/
void Tft_Lcd_Init(); void Lcd_EnvidOnOff(int onoff); /*
* 设置是否输出LCD电源开关信号LCD_PWREN
* 输入参数:
* invpwren: 0 - LCD_PWREN有效时为正常极性
* 1 - LCD_PWREN有效时为反转极性
* pwren: 0 - LCD_PWREN输出有效
* 1 - LCD_PWREN输出无效
*/
void Lcd_PowerEnable(int invpwren, int pwren); #endif /*__LCDDRV_H__*/
自然不难看出,仍然有不少冗余项,这里先不做深究。
上面代码经过烧写验证,没有问题。
代码删减了串口,中断,以及print函数的硬件重定向等内容,以便更直观理解lcd驱动。
关于代码中重要函数,有时间补上。
实验九--裸机LCD的更多相关文章
- Linux基础入门(新版)(实验九-实验十二)
实验九 简单文本入门 一.常用的文本处理命令 二.文本处理命令 1.tr 命令 tr 命令可以用来删除一段文本信息中的某些文字.或者将其进行转换. 使用方式: tr [option]...SET1 [ ...
- 2017-2018-2 20155228 《网络对抗技术》 实验九:Web安全基础
2017-2018-2 20155228 <网络对抗技术> 实验九:Web安全基础 1. 实践内容 1.1 标理解常用网络攻击技术的基本原理 1.2 在Webgoat实验环境下实践相关实验 ...
- 实验九 ZStack 广播通信实验
实验九 ZStack 广播通信实验[实验目的]1. 了解 ZigBee 广播通信的原理2. 掌握在 ZigBee 网络中进行广播通信的方法[实验设备]1. 装有 IAR 开发工具的 PC 机一台2. ...
- 2017-2018-2 20155225《网络对抗技术》实验九 Web安全基础
2017-2018-2 20155225<网络对抗技术>实验九 Web安全基础 WebGoat 1.String SQL Injection 题目是想办法得到数据库所有人的信用卡号,用Sm ...
- 20155201 网络攻防技术 实验九 Web安全基础
20155201 网络攻防技术 实验九 Web安全基础 一.实践内容 本实践的目标理解常用网络攻击技术的基本原理.Webgoat实践下相关实验. 二.报告内容: 1. 基础问题回答 1)SQL注入攻击 ...
- 20155222卢梓杰 实验九 Web安全基础
实验九 Web安全基础 今天不多bb,打开webgoat就是干好吧 1.简单字符串sql注入 可以看到这个实验说明是 "下表允许用户查看其信用卡号码.尝试插入一个SQL字符串,以显示所有信用 ...
- # 2017-2018-2 20155231《网络对抗技术》实验九: Web安全基础实践
2017-2018-2 20155231<网络对抗技术>实验九: Web安全基础实践 实验要求: 本实践的目标理解常用网络攻击技术的基本原理.Webgoat实践下相关实验. 实验内容: ( ...
- 20155235 《网络攻防》 实验九 Web安全基础
20155235 <网络攻防> 实验九 Web安全基础 实验内容 SQL注入攻击 XSS攻击 CSRF攻击 WebGoat WebGoat是OWASP组织研制出的用于进行web漏洞实验的应 ...
- 20155313 杨瀚 《网络对抗技术》实验九 Web安全基础
20155313 杨瀚 <网络对抗技术>实验九 Web安全基础 一.实验目的 本实践的目标理解常用网络攻击技术的基本原理.Webgoat实践下相关实验. 二.基础问题回答 1.SQL注入攻 ...
随机推荐
- C#属性(Attribute)用法实例解析
属性(Attribute)是C#程序设计中非常重要的一个技术,应用范围广泛,用法灵活多变.本文就以实例形式分析了C#中属性的应用.具体入戏: 一.运用范围 程序集,模块,类型(类,结构,枚举,接口,委 ...
- Django之牛逼的Models
Django里的模型是对数据库对表的一次封装,是应用业务与数据之间的桥梁 要想使用Django的models 首先得配置settings Django默认使用的是sqlite,我使用的Mysql,配置 ...
- linux 打包/解包
zip: 压缩(递归) zip -r x.zip x 解压(覆盖所有) unzip -o x.zip tar: 打包 tar -czvf x.tar x 解包 tar -xzvf x.tar
- HDU 2845 Beans (DP)
Beans Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- 网络流sap算法模版
递归版sap: #include<cstdio> #include<iostream> #include<cstring> #include<algorith ...
- SVN管理规范
命名规范 tags 正式版 REL-X.X.X branches 发版前 RB-X.X.X 新功能 TRY-XXX 修BUG BUG-XXXX trunk 开发 使用注意事项 负责而谨慎地提交自己的代 ...
- 日历控件table布局
作为初学者,一开始就接触div+css ,所以说实话,我并不怎么喜欢table布局,一般逃避. 先上这次的效果图: 看到这个图,第一次用table布局没实现,原因是给tr加下边框失效.当时没找到原因, ...
- Table of Contents - Spring
The IoC container Spring 容器 属性注入 & 构造注入 Bean 实例的创建方式 p-namespace & c-namespace 集合属性的注入 作用域 延 ...
- 如何提高手机APP的用户体验?
详细内容请点击 随着移动互联网如日中天,如火如荼的时候,手机APP开发日益高涨了起来,关于手机APP的用户体验,也是一个老话长谈的话题.从事这行业也很久了,以下是我个人在工作中的一些关于APP的用户体 ...
- Log4.net使用配置
开发中经常使用到日志记录功能,Log4.net可以将日志记录到文件中,也可以记录到数据库中,使用非常方便,之前也一直在用,最近也参照了一下网上的资料,想简单总结一下 本文重在通过通用日志类来使用Log ...