📄 340_lcd.c
字号:
/******************************************************************************
由于LV595芯片片选引脚与以太网控制芯片CP2200中断引脚复用因些在此例程中加入了将
CP2200芯片中断关闭的代码。还要在建立工程文件时将CP220X_REG.C文件包含到工程中.
******************************************************************************/
#include "C8051F340.h"
#include "INTRINS.H"
#include "cp220x_reg.h"
#define uchar unsigned char
#define uint unsigned int
#define BASE_ADDRESS 0x10
#define EMIF_TIMING 0x9E
sbit LcdCs=P0^3;
sbit led=P2^4;
bit SPI_BUSY;
//***************DS1302*******************************
//**************************************************
#define NOP _nop_()
#define uchar unsigned char
sbit IO=P3^1;
sbit SCLK=P3^2;
sbit RSTB=P3^3;
uchar xdata virt_port;
uchar xdata discode;//开关显示、光标、闪烁的命令字暂存单元
uint Count1ms;
//signed char xdata tab1[16]={0x20,0x20,0x42,0x54,0x20,0x46,0x33,0x34,0x30,0x20,0x56,0x31,0x2e,0x30,0x20,0x20};
unsigned char xdata Netdata[16]={0x77,0x77,0x77,0x2e,0x78,0x68,0x6c,0x2e,0x63,0x6f,0x6d,0x2e,0x63,0x6e,0x20,0x20};
//void delay(uint timer);
void writelcd(uchar spi_data);
void writecode(uchar ins);
void writedata(uchar d);
void lcdinit();
void lcdchar (void);
void lcdaddr(uchar DDRAM);
void cursoropen(uchar position);//开光标,关闪烁
void displayopen(void); //开显示,光标、闪烁不变
void ether_reset_low();
void ether_reset_high (void);
void Delay1ms(uint T);
void EMIF_Init (void);
uint da;
void delay1us(void)
{
uchar xdata i;
for(i=10;i>0;i--);
}
void delay(uchar i)
{
while (--i);
}
//*****************************RESET FUNCTION///////////////
void reset()
{
RSTB=0;
SCLK=0;
delay(100);
RSTB=1;
delay(100);
}
//***************************BYTE WRITE************//
void wbyte(uchar w_byte)
{
uchar i;
for(i=0;i<8;++i)
{
IO=0;
if(w_byte&0x01) IO=1; //w_byte最低位是否为1,若为1,IO=1,否则不改变IO值
SCLK=0; // 产生上升沿脉冲
delay(20);
SCLK=1;
delay(20);
w_byte>>=1;
}
}
//*********************** BYTE READ******************//
uchar rbyte()
{
uchar i;
uchar R_BYTE;
uchar TMPBYTE;
R_BYTE=0X00;
IO=1;
for(i=0;i<8;++i)
{
SCLK=1;
delay(20);
SCLK=0;
TMPBYTE=(uchar)IO;
TMPBYTE<<=7;
R_BYTE>>=1;
R_BYTE|=TMPBYTE;
delay(20);
}
return(R_BYTE);
}
uchar time_data[8]={0,0,1,1,1,1,1,1};//sec,min,hrs,dte,mon,day,yr
uchar time_diplay[14]={0x31,0x35,0x38,0x32,0x39,0x33,0x34,0x33,0x32,0x37,0x31};
//*********************时间初始校准与初始化**************************************//
void time_int_DS1302() //24小时模式
{
uchar time[8]={0,0,0x12,1,1,1,0,0};//sec,min,hrs,dte,mon,day,yr
// uchar i;
reset();
wbyte(0x8e);//写保护控制寄存器
wbyte(0);//允许写入
reset();
wbyte(0x90); //涓流充电控制寄存器
wbyte(0); //禁止充电
reset();
wbyte(0x80); //秒 //2000年1月1日12点0分13秒 星期一
wbyte(0x13);
reset();
wbyte(0x82); //分
wbyte(0x00);
reset();
wbyte(0x84); //HR
wbyte(0x12);
reset();
wbyte(0x86); //DATA
wbyte(0x00);
reset();
wbyte(0x88); //MOUTH
wbyte(0x00);
reset();
wbyte(0x8A); //DAY
wbyte(0x00);
reset();
wbyte(0x8C); //YEAR
wbyte(0x20);
reset();
// for(i=0;i<8;i++)
// wbyte(time[i]);
// reset();
}
//****************************************************************************
//****************DS1302显示数据 ASCII码数字转化 ***********************/
//******************************************************************************
/*void display_xlat()
{
uchar i,j=0,num1,num2;
for(i=0;i<7;i++)
{
num1=time_data[i]&0x0F;
num2=time_data[i];
num2>>=4;
time_diplay[j]=num1+0x30;
time_diplay[j+1]=num2+0x30;
j+=2;
}
}
*/uchar time_sec=0; 定义秒 //定义秒,且初始化为0
//**********************时间显示***************************************
void time_display_DS1302()
{
reset();
wbyte(0x81);
time_sec=rbyte();
reset();
time_data[0]=(time_sec>>4)+0x30; //将秒的个位与十位分离,且转化为acsII码在,LCD1602上显示
time_data[1]=(time_sec&0x0f)+0x30;
}
void SPI_Init() //1602采用SPI方式传送数据,对SPI方式初始化
{
SPI0CFG = 0x70;
SPI0CN = 0x01;
SPI0CKR = 0x3B;
}
void writelcd(uchar spi_data) //向LV595写数据以SPI方式
{
uint xdata i,j;
for(i=0;i<3;i++)
LcdCs=0;
SPI_BUSY=1;
delay1us();
SPI0DAT=spi_data;
for(j=0;j<500;j++)
{
if(!SPI_BUSY)break;
}
delay1us();
LcdCs=1;
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
delay1us();
// for(j=0;j<5000;j++);
}
void writecode(uchar ins) //向液晶控制模块写命令
{
uchar xdata t;
uint xdata j;
for(j=0;j<500;j++);
virt_port|=ins&0xf0; //取高字节向1602写数据
writelcd(virt_port); //先写高4位后再写低4位 这是在选择四个数据线的时候
virt_port|=0x08;
writelcd(virt_port); //使能E脚为高电平
virt_port&=~0x08;
writelcd(virt_port); //使能E脚为低电平
t=ins<<4;
virt_port|=t&0xf0; //取低字节向1602写数据
writelcd(virt_port);
virt_port|=0x08; //使能E脚为高电平
writelcd(virt_port);
virt_port&=~0x08; //使能E脚为低电平
writelcd(virt_port);
virt_port=0;
writelcd(virt_port);
}
void writedata(uchar d) //写数据到1602
{
uchar xdata i,t;
uint xdata j;
for(j=0;j<500;j++);
virt_port|=0x02; //光标返回指令
writelcd(virt_port);
virt_port|=d&0xf0; //取高字节数据给数据寄存器
writelcd(virt_port);
virt_port|=0x08; //使能E脚为高电平
writelcd(virt_port);
virt_port&=0xf7; //使能E脚为低电平
writelcd(virt_port);
virt_port&=0x07; //设置光标右移,文字也右移
writelcd(virt_port);
t=d&0x0f;
virt_port|=t<<4; //取低字节数据给数据寄存器
writelcd(virt_port);
virt_port|=0x08; //使能E脚为高电平
writelcd(virt_port);
for(i=3;i>0;i--);
virt_port&=0xf7; //使能E脚为低电平
writelcd(virt_port);
virt_port=0; //数据清零
writelcd(virt_port);
}
void lcdchar (void)
{
uint xdata i,j,k;
for(j=0;j<5000;j++); //数据读、写操作,画面不动
for(k=0;k<5000;k++);
for(i=0;i<2;i++)
{
writedata(time_data[i]);
for(j=0;j<5000;j++); //数据读、写操作,画面不动
for(k=0;k<5000;k++);
}
}
void lcdinit()
{
uint xdata i;
virt_port=0x00;
writelcd(virt_port); //RS脚为零写指令寄存器 RW为低电平
virt_port|=0x08; //使能脚E=1
writelcd(virt_port);
virt_port&=0xf7; //使E=0使能脚发生跳变高--低
writelcd(virt_port);
for(i=1000;i>0;i--); //3次延时,重要!
for(i=8000;i>0;i--); //用延时代替查询
virt_port=0; //写入20码,设置为4位总线方式,非常重要!!!!!
writelcd(virt_port);
virt_port|=0x20; //只写高字节
writelcd(virt_port);
virt_port|=0x08; //E=1
writelcd(virt_port);
for(i=20;i>0;i--); //使命令执行
virt_port&=0xf7; //E=0
writelcd(virt_port);
for(i=10;i>0;i--);
virt_port=0;
writelcd(virt_port);
writecode(0x38); //设两行显示,4线方式5*10字符显示
for(i=50;i>0;i--);
writecode(0x06); //光标右移
for(i=50;i>0;i--);
writecode(0x0c); //开显示指令
for(i=50;i>0;i--);
writecode(0x02); //光标返回指令
for(i=50;i>0;i--);
writecode(0x01); //清屏指令
for(i=50;i>0;i--);
}
void port_init()
{
P0MDOUT=0xff;
XBR0 = 0x02;
XBR1 = 0x40;
P1MDOUT|= 0xDf; // /WR and /RD are push-pull
P2MDOUT|= 0xFF;
P3MDOUT =0xFD;
P4MDOUT |= 0xFF;
}
void main(void)
{
uint j;
PCA0MD &= ~0x40; //关闭看门狗定时器
OSCICN |= 0x03; //内部高频振荡器12M晶振做为系统时钟
port_init(); //端口初始化
EMIF_Init ();
ether_reset_low();
for(j=0;j<5000;j++);
ether_reset_high ();
INT0EN = 0x00;
INT1EN = 0x00;
SPI_Init();
time_int_DS1302();
IE = 0x40;
EA=1;
lcdinit();
//while(1) {
//液晶初始化
while(1)
{ //
EA=0;
time_display_DS1302();
EA=1;
lcdchar();
delay(60000);
delay(60000);
delay(60000);
delay(60000);
delay(60000);
//time_display_DS1302();
}
}
//}
void spi_isr(void) interrupt 6
{
if(SPIF)
{
SPIF=0;
SPI_BUSY=0;
}
if(WCOL)
{
WCOL=0;
}
}
void ether_reset_low()
{
P1 &= ~0x01; // Pull reset low
}
void ether_reset_high (void)
{
P1 |= 0x01; // Allow /RST to rise
while(!(P1 & 0x01)); // Wait for /RST to go high
}
void EMIF_Init (void)
{
EMI0CF = 0x1B; // non-muxed mode; split mode
// with bank select
EMI0TC = EMIF_TIMING; // This constant may be modified
// according to SYSCLK to meet the
// timing requirements for the CP2200
EMI0CN = BASE_ADDRESS; // Page of XRAM accessed by EMIF
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -