本帖最后由 a939561900 于 2015-6-23 13:52 编辑
//###########################################################################
// LCD12864液晶显示程序
//###########################################################################
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
// Prototype statements for functions found within this file.
void delay_loop(Uint32);
void Gpio_select(void);
void write_byte(Uint16 x); //写8位数据
void lcd_write_cmd(Uint16); //lcd 命令写
void lcd_write_data(Uint16); //lcd 数据写
Uint16 lcd_read_data(void); //lcd 数据读
void lcd_set_dot(unsigned char x, unsigned char y);
#define BASIC_SET 0x30 //基本指令集 00110000
#define EXTEND_SET 0x34 //扩展指令集 00110100
#define DRAW_ON 0x36 //绘图显示开 00110110
#define DRAW_OFF 0x34 //绘图显示关 00110100
#define execute_72us delay_loop(400) //执行时间
#define SCLK_quarter delay_loop(40) //四分之一SCLK时钟 SCLK是LCD串行通信时钟
#define SCLK_half delay_loop(80) //二分之一SCLK时钟 SCLK是LCD串行通信时钟
#define CS_1 GpioDataRegs.GPADAT.bit.GPIO5=1 //GPIO5作为CS
#define CS_0 GpioDataRegs.GPADAT.bit.GPIO5=0 //GPIO5作为CS
#define SCLK_1 GpioDataRegs.GPADAT.bit.GPIO4=1 //GPIO4作为SCLK
#define SCLK_0 GpioDataRegs.GPADAT.bit.GPIO4=0 //GPIO4作为SCLK
#define SDATA_OUT GpioCtrlRegs.GPADIR.bit.GPIO2=1 //GPIO2作为SDATA
#define SDATA_IN GpioCtrlRegs.GPADIR.bit.GPIO2=0 //GPIO2作为SDATA
#define SDATA GpioDataRegs.GPADAT.bit.GPIO2
#define RST_1 GpioDataRegs.GPADAT.bit.GPIO3=1 //GPIO3做RST
#define RST_0 GpioDataRegs.GPADAT.bit.GPIO3=0 //GPIO3做RST
#define uchar unsigned char
#define uint Uint16
uchar AC_TABLE[]={
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, //第一行汉字位置
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97, //第二行汉字位置
0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, //第三行汉字位置
0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, //第四行汉字位置
};
Uint16 sign[]={
0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,
0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,
0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,
};
uchar str2[]="合肥零零电子科技";
uchar str1[]="黄河远上白云间,一片孤城万仞山。羌笛何须怨杨柳,春风不度玉门关。";
Uint16 bmp1[];
Uint16 Key = 1;
/******************************************************************************************
* 函数名称 :Delay
******************************************************************************************/
void Delay(uint MS)
{
uchar us,usn;
while(MS!=0) //for 12M
{
usn = 2;
while(usn!=0)
{
us = 0xf5;
while (us!=0)
{
us--;
};
usn--;
}
MS--;
}
}
/******************************************************************************************
* 函数名称 :DelayKey
******************************************************************************************/
void DelayKey(uint Second , uint MS100)
{ //输入精确到0.1S,是用","
uint i;
for(i=0;i<Second*100+MS100*10;i++)
{
if(Key==0)
{
Delay(20);
while(Key==0)
{
Delay(20);
}
break;
}
else Delay(10);
}
}
/******************************************************************************************
* 函数名称 :LcmInit
******************************************************************************************/
void LcmInit( void )
{
lcd_write_cmd(0x30); //8BitMCU,基本指令集合
lcd_write_cmd(0x03); //AC归0,不改变DDRAM内容
lcd_write_cmd(0x0C); //显示ON,游标OFF,游标位反白OFF
lcd_write_cmd(0x01); //清屏,AC归0
lcd_write_cmd(0x06); //写入时,游标右移动
}
/******************************************************************************************
* 函数名称 :LcmClearTXT
* 功能描述 :文本区清RAM函数
******************************************************************************************/
void LcmClearTXT( void )
{
uchar i;
lcd_write_cmd(0x30); //8BitMCU,基本指令集合
lcd_write_cmd(0x80); //AC归起始位
for(i=0;i<64;i++)
lcd_write_data(0x20);
}
/******************************************************************************************
* 函数名称 :LcmClearBMP
* 功能描述 :图形区清RAM函数
******************************************************************************************/
void LcmClearBMP( void )
{
uchar i,j;
lcd_write_cmd(0x34); //8Bit扩充指令集,即使是36H也要写两次
lcd_write_cmd(0x36); //绘图ON,基本指令集里面36H不能开绘图
for(i=0;i<32;i++) //12864实际为256x32
{
lcd_write_cmd(0x80|i); //行位置
lcd_write_cmd(0x80); //列位置
for(j=0;j<32;j++) //256/8=32 byte
lcd_write_data(0);
}
}
/******************************************************************************************
* 函数名称 :PutStr
******************************************************************************************/
void PutStr(uchar row,uchar col,uchar *puts)
{
lcd_write_cmd(0x30); //8BitMCU,基本指令集合
lcd_write_cmd(AC_TABLE[8*row+col]); //起始位置
while(*puts != '\0') //判断字符串是否显示完毕
{
if(col==8) //判断换行
{ //若不判断,则自动从第一行到第三行
col=0;
row++;
}
if(row==4) row=0; //一屏显示完,回到屏左上角
lcd_write_cmd(AC_TABLE[8*row+col]);
lcd_write_data(*puts); //一个汉字要写两次
puts++;
lcd_write_data(*puts);
puts++;
col++;
}
}
/******************************************************************************************
* 函数名称 :PutSign
******************************************************************************************/
void PutSign(uchar row,uchar col,Uint16 *sign)
{
Uint16 i=0;
lcd_write_cmd(0x30); //8BitMCU,基本指令集合
lcd_write_cmd(AC_TABLE[8*row+col]); //起始位置 sign_TABLE[8*row+col]
for(i=0;i<32;i++) //判断字符串是否显示完毕
{
if(col==8) //判断换行 半宽符号,所以一行16个
{ //若不判断,则自动从第一行到第三行
col=0;
row++;
}
if(row==4) row=0; //一屏显示完,回到屏左上角
lcd_write_cmd(AC_TABLE[8*row+col]);
lcd_write_data(*sign); //一个汉字要写两次
sign++;
col++;
}
}
/******************************************************************************************
* 函数名称 :PutBMP
******************************************************************************************/
void PutBMP(Uint16 *puts)
{
uint x=0;
uchar i,j;
lcd_write_cmd(0x34); //8Bit扩充指令集,即使是36H也要写两次
lcd_write_cmd(0x36); //绘图ON,基本指令集里面36H不能开绘图
for(i=0;i<32;i++) //12864实际为256x32
{
lcd_write_cmd(0x80|i); //行位置
lcd_write_cmd(0x80); //列位置
for(j=0;j<16;j++) //256/8=32 byte
{ //列位置每行自动增加
lcd_write_data(((puts[x]&0xFF00)>>8));
lcd_write_data((puts[x]&0x00FF));
x++;
}
}
}
/******************************************************************************************
* 函数名称 :DisplayDots
******************************************************************************************/
void DisplayDots(uchar DotByte)
{
uchar i,j;
lcd_write_cmd(0x34); //8Bit扩充指令集,即使是36H也要写两次
lcd_write_cmd(0x36); //绘图ON,基本指令集里面36H不能开绘图
for(i=0;i<32;i++) //12864实际为256x32
{
lcd_write_cmd(0x80|i); //行位置
lcd_write_cmd(0x80); //列位置
for(j=0;j<32;j++) //256/8=32 byte
{ //列位置每行自动增加
lcd_write_data(DotByte);
}
DotByte=~DotByte;
}
}
/******************************************************************************************/
void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
InitSysCtrl();
// Step 2. Initalize GPIO:
Gpio_select();
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.
InitPieVectTable();
RST_0;
Delay(30);
RST_1;
LcmInit();
LcmClearTXT();
LcmClearBMP();
for(;;)
{
// lcd_set_dot(2,2);
//显示图像
LcmClearTXT();
PutBMP(bmp1);
DelayKey(20,5);
/*
//全屏间隔显示点
DisplayDots(0x55);
DelayKey(1,5);
//全屏间隔显示点
LcmClearTXT();
DisplayDots(0xaa);
DelayKey(1,5);
*/
//全屏显示文字
LcmClearBMP();
DelayKey(15,5);
PutStr(0,0,str1);
DelayKey(30,5);
// PutSign(0,0,sign);
/*
LcmClearTXT();
DelayKey(15,5);
PutStr(0,0,str2);
DelayKey(30,5);
//全屏间隔显示半型符号
LcmClearTXT();
PutSign(0,0,sign);
DelayKey(30,5);
// while(1); */
}
}
/******************************************************************************************
* 函数名称 :delay_loop
******************************************************************************************/
void delay_loop(Uint32 x)
{
Uint32 i;
for (i = 0; i < x; i++) {}
}
/******************************************************************************************
* 函数名称 :Gpio_select
******************************************************************************************/
void Gpio_select(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO2 = 0;
GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0;
GpioCtrlRegs.GPAPUD.bit.GPIO4 = 0;
GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0;
GpioCtrlRegs.GPAMUX1.bit.GPIO2=0;
GpioCtrlRegs.GPAMUX1.bit.GPIO4=0;
GpioCtrlRegs.GPAMUX1.bit.GPIO3 =0;
GpioCtrlRegs.GPAMUX1.bit.GPIO5 =0;
GpioCtrlRegs.GPADIR.bit.GPIO2=1;
GpioCtrlRegs.GPADIR.bit.GPIO4=1;
GpioCtrlRegs.GPADIR.bit.GPIO3=1;
GpioCtrlRegs.GPADIR.bit.GPIO5=1;
EDIS;
}
/******************************************************************************************
* 函数名称 :write_byte
******************************************************************************************/
void write_byte(Uint16 x)
{
Uint16 i = 0;
SDATA_OUT;
SCLK_quarter;
for(i=0;i<=7;i++)
{
SCLK_0;
SCLK_quarter;
SDATA=(0x1&((x)>>(7-i))); //先把高位移出然后发送
SDATA=(0x1&((x)>>(7-i)));
SCLK_quarter;
SCLK_1; //把时间改成上升沿锁存的
SCLK_half;
SCLK_0;
SCLK_quarter;
}
SDATA=0;
}
/*void write_byte(Uint16 x)
{
Uint16 i = 0;
SDATA_OUT;
for(i=0;i<=7;i++)
{
SCLK_0;
SCLK_quarter;
if((0x1&((x)>>(7-i)))==1)
{
GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all|0x04000000; //GPIO26输出1
}
else
{
GpioDataRegs.GPADAT.all = GpioDataRegs.GPADAT.all&0xFBFFFFFF; //GPIO26 输出0
}
SCLK_quarter;
SCLK_1; //把时间改成上升沿锁存的
SCLK_half;
SCLK_0;
SCLK_quarter;
}
SDATA=0;
}
*/
/******************************************************************************************
* 函数名称 :read_byte
******************************************************************************************/
Uint16 read_byte(void)
{
Uint16 i = 0;
Uint16 data = 0;
SDATA_IN;
data=0;
for(i=0;i<=7;i++)
{
SCLK_0;
SCLK_quarter;
SCLK_1;
SCLK_quarter;
if(SDATA)
{
data= (data|(0x01<<(7-i))); //注意!
}
SCLK_quarter;
SCLK_0;
SCLK_quarter;
}
return data;
}
/******************************************************************************************
* 函数名称 :lcd_write_cmd
******************************************************************************************/
void lcd_write_cmd(Uint16 data) //lcd 命令写
{
Uint16 tmp1,tmp2;
CS_1;
delay_loop(40);
tmp1= (data&0xF0); //高四位
tmp2= ((data&0x0F)<<4); //低四位左移
write_byte(0xF8); //0xF8 ==11111000 b 这个代表从MCU到LCD 并且是指令
write_byte(tmp1);
write_byte(tmp2);
delay_loop(40);
CS_0;
execute_72us;
}
/******************************************************************************************
* 函数名称 :lcd_write_data
******************************************************************************************/
void lcd_write_data(Uint16 data)
{
Uint16 tmp1,tmp2;
CS_1;
delay_loop(40);
tmp1= (data&0xF0); //高四位
tmp2= ((data&0x0F)<<4); //低四位左移
write_byte(0xFA); //0xFA ==11111010 b 这个代表从MCU到LCD 并且是数据
write_byte(tmp1);
write_byte(tmp2);
delay_loop(40);
CS_0;
execute_72us;
}
/******************************************************************************************
* 函数名称 :lcd_read_data
******************************************************************************************/
Uint16 lcd_read_data(void)
{
Uint16 tmp1,tmp2,data;
CS_1;
write_byte(0xFE); //0xFA ==11111110 b 这个代表从MCU到LCD 并且是数据
tmp1=read_byte();
tmp2=read_byte();
CS_0;
execute_72us;
data= (tmp1&0xF0); //高四位
data= (data|((tmp2&0xF0)>>4)); //低四位
return data;
}
/******************************************************************************************
* 函数名称 :lcd_set_dot
******************************************************************************************/
void lcd_set_dot(unsigned char x, unsigned char y)
{
unsigned char x_byte, x_bit; //在横坐标的哪一个字节,哪一个位
unsigned char y_byte, y_bit;
// unsigned char tmph, tmpl; //定义两个临时变量,用于存放读出来的数据
x &= 0x7F;
y &= 0x3F;
x_byte = x / 16; //算出它在哪一个字节(地址)
//注意一个地址是16位的
x_bit = x&0x0F; //算出它在哪一个位
y_byte = y /32; //y是没在哪个字节这个说法
//这里只是确定它在上半屏还是下半屏
//0:上半屏 1:下半屏
y_bit = y&0x3F; //y_bit确定它是在第几行
lcd_write_cmd(EXTEND_SET); //扩展指令集
lcd_write_cmd(DRAW_ON); //绘图显示打开
lcd_write_cmd(0x80 + y_bit); //先写垂直地址(最高位必须为1)
//具体参照数据手册
lcd_write_cmd(0x80 + x_byte + 8 * y_byte); //水平坐标
//下半屏的水平坐标起始地址为0x88
//(+8*y_byte)就是用来确定
//在上半屏还是下半屏
if (x_bit < 8) //绻鹸_bit位∮?
{
lcd_write_data(0x01 << (7 - x_bit)); //写高字节。因为坐标是从左向右的
//而GDRAM高位在左,底位在右
lcd_write_data(0x00); //低字节全部填0
}
else
{
lcd_write_data(0x00); //高字节全部填0
lcd_write_data(0x01 << (15 - x_bit));
}
return ;
}
//===========================================================================
// No more.
//===========================================================================
|
|