⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd12232.c

📁 自己单片机板c程序
💻 C
字号:
/*此例子是LCD12232,时钟和温度传感受的集合,有不明白的朋友,可以先看下前面的三个例子,再加已集合*/

#include <reg51.h>
#include <intrins.h>

#define  MSB       0x80
#define  LSB       0x01

sbit LCD_RS=P1^0;//定义引脚
sbit LCD_RW=P1^1;
sbit LCD_E=P1^2;
#define LCD_Data P2
#define Busy    0x80 //用于检测LCD状态字中的Busy标识

sbit SCL2=P1^3;
sbit SDA2=P1^4;
sbit RST = P1^5;// DS1302片选			5脚
sbit DS=P3^3;           //定义DS18B20接口


void WriteDataLCD(unsigned char WDLCD);
void WriteCommandLCD(unsigned char WCLCD,BuysC);
unsigned char ReadDataLCD(void);
unsigned char ReadStatusLCD(void);
void LCDInit(void);
void LCDClear(void);
void LCDFlash(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData);
void Delay5Ms(void);
void Delay400Ms(void);

void Write_Ds1302_byte(unsigned char temp); 
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_RTC(void);//read RTC 
void Set_RTC(void);//set RTC 

int tmep(void);
void tmpchange(void);
void tmpwritebyte(unsigned char dat);
unsigned char tmpread(void);
bit tmpreadbit(void);
void dsreset(void);
void delayb(unsigned int count);

unsigned char l_tmpdate[8]={0x00,0x06,0x03,0x1C,0x08,0x07,0x08,0};

code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; 
code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};

unsigned char lhj_f[15]={"2008年08月28日"};
unsigned char lhj_s[15]={"12:00 温度28℃"};

void main(void)
{
 unsigned char oldtimer=0,i=0;
 int l_tmp=0;
 Set_RTC();
 Delay400Ms(); //启动等待,等LCD讲入工作状态
 LCDInit(); //LCM初始化
 Delay5Ms(); //延时片刻(可不要)
 while(1){
	Read_RTC();
		if(oldtimer!=l_tmpdate[0]){//每一秒钟刷新显示
			oldtimer=l_tmpdate[0];
			lhj_f[2]=(l_tmpdate[6]/16)+0X30;			//这里加上0X30是在ASCII字符编码中的地址,你们可以查下ASCII码
											//这里除以16怎么不是除以10呢,是的,这是因为DS1302里面是按10进制存放的
			lhj_f[3]=(l_tmpdate[6]&0x0f)+0X30;
			lhj_f[6]=(l_tmpdate[4]/16)+0X30;
			lhj_f[7]=(l_tmpdate[4]&0x0f)+0X30;
			lhj_f[10]=(l_tmpdate[3]/16)+0X30;
			lhj_f[11]=(l_tmpdate[3]&0x0f)+0X30;				

			lhj_s[0]=(l_tmpdate[2]/16)+0X30;
			lhj_s[1]=(l_tmpdate[2]&0x0f)+0X30;
			if(i==0){				//每一秒钟转换显示(空-两点)
				lhj_s[2]=0X3A;
				i=1;
				}
			else{
				lhj_s[2]=0x20;
				i=0;
			   }
			lhj_s[3]=(l_tmpdate[1]/16)+0X30;
			lhj_s[4]=(l_tmpdate[1]&0x0f)+0X30;

			tmpchange();      //温度转换
			l_tmp=tmep();
			lhj_s[10]=l_tmp/100+0X30;
			l_tmp=l_tmp%100;
			lhj_s[11]=l_tmp/10+0X30;//温度显示我们去掉了小数位,有兴趣的朋友可以加入
		DisplayListChar(0, 0, lhj_f);
 		DisplayListChar(0, 5, lhj_s);
		}
		//}
	}
}

/*********************LCD12232显示处理函数****************************/
//写数据
void WriteDataLCD(unsigned char WDLCD)
{
 ReadStatusLCD(); //检测忙 
 LCD_RS = 1;
 LCD_RW = 0;
 LCD_Data = WDLCD;
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 0;
}

//写指令
void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测
{
 if (BuysC) ReadStatusLCD(); //根据需要检测忙 
 LCD_RS = 0;
 LCD_RW = 0; 
 LCD_Data = WCLCD;
 LCD_E = 1; 
 LCD_E = 1;
 LCD_E = 1;
 LCD_E = 0;  
}

//读数据
unsigned char ReadDataLCD(void)
{
 LCD_RS = 1; 
 LCD_RW = 1;
 LCD_E = 0;
 LCD_E = 0;
 LCD_E = 1;
 return(LCD_Data);
}

//读状态
unsigned char ReadStatusLCD(void)
{
 LCD_Data = 0xFF; 
 LCD_RS = 0;
 LCD_RW = 1; 
 LCD_E = 1;
 while (LCD_Data & Busy); //检测忙信号
 LCD_E = 0;
 return(LCD_Data);
}

void LCDInit(void) //LCM初始化
{
 WriteCommandLCD(0x30,1); //显示模式设置,开始要求每次检测忙信号
 WriteCommandLCD(0x01,1); //显示清屏
 WriteCommandLCD(0x06,1); // 显示光标移动设置
 WriteCommandLCD(0x0C,1); // 显示开及光标设置
}
void LCDClear(void) //清屏
{
 WriteCommandLCD(0x01,1); //显示清屏
 WriteCommandLCD(0x34,1); // 显示光标移动设置
 WriteCommandLCD(0x30,1); // 显示开及光标设置
}
void LCDFlash(void)	//闪烁效果
{
 WriteCommandLCD(0x08,1); //显示清屏
 Delay400Ms();
 WriteCommandLCD(0x0c,1); // 显示开及光标设置
 Delay400Ms();
 WriteCommandLCD(0x08,1); //显示清屏
 Delay400Ms();
 WriteCommandLCD(0x0c,1); // 显示开及光标设置
 Delay400Ms();
 WriteCommandLCD(0x08,1); //显示清屏
 Delay400Ms();
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
 Y &= 0x1;
 X &= 0xF; //限制X不能大于15,Y不能大于1
 if (Y) X |= 0x10; //当要显示第二行时地址码+0x10;
 X |= 0x80; // 算出指令码
 WriteCommandLCD(X, 0); //这里不检测忙信号,发送地址码
 WriteDataLCD(DData);
}

//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char *DData)
{
 unsigned char ListLength,X2;
  ListLength = 0;
  X2=X;
 Y &= 0x01;
 X &= 0x0F; //限制X不能大于15,Y不能大于1
 if (Y) X2 |= 0x10; //当要显示第二行时地址码+0x10;
 X2 |= 0x80; // 算出指令码
 WriteCommandLCD(X2, 1); //这里不检测忙信号,发送地址码
 while (DData[ListLength]>=0x20) //若到达字串尾则退出
  {
   if (X <= 0x0F) //X坐标应小于0xF
    {
     WriteDataLCD(DData[ListLength]); //
     ListLength++;
	 X++;
    }
  }
}

//5ms延时
void Delay5Ms(void)
{
 unsigned int TempCyc = 5552;
 while(TempCyc--);
}

//400ms延时
void Delay400Ms(void)
{
 unsigned char TempCycA = 5;
 unsigned int TempCycB;
 while(TempCycA--)
 {
  TempCycB=7269;
  while(TempCycB--);
 };
}
/***********************************************************************/

/*************************************时间操作函数**************************************/
void Write_Ds1302_Byte(unsigned  char temp) 
{
 unsigned char i;
 for (i=0;i<8;i++)     	//循环8次 写入数据
  { 
   SCL2=0;
     SDA2=temp&LSB;     	//每次传输低字节 
     temp>>=1;  		//右移一位
     SCL2=1;
   }
}   

void Write_Ds1302( unsigned char address,unsigned char dat )     
{
 	RST=0;
	_nop_();
 	SCL2=0;
	_nop_();
 	RST=1;	
   	_nop_();   //启动
 	Write_Ds1302_Byte(address);	//发送地址
 	Write_Ds1302_Byte(dat);		//发送数据
 	RST=0;  		//恢复
}

unsigned char Read_Ds1302 ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;
	_nop_();
 	SCL2=0;
	_nop_();
 	RST=1;
	_nop_();
 	Write_Ds1302_Byte(address);
 	for (i=0;i<8;i++) 		//循环8次 读取数据
 	{
		SCL2=1;	
		_nop_();	
 		if(SDA2)
 		temp|=0x80;			//每次传输低字节
		SCL2=0;
		temp>>=1;			//右移一位
	} 
 	RST=0;
	_nop_();
	SCL2=1;	
	SDA2=0;

	return (temp);			//返回
}

void Read_RTC(void)		//读取 日历
{
 unsigned char i,*p;
 p=read_rtc_address; 	//地址传递
 for(i=0;i<7;i++)		//分7次读取 年月日时分秒星期
 {
  l_tmpdate[i]=Read_Ds1302(*p);
  p++;
 }
}

void Set_RTC(void)		//设定 日历
{
	unsigned char i,*p,tmp;
	for(i=0;i<7;i++){
		tmp=l_tmpdate[i]/10;
		l_tmpdate[i]=l_tmpdate[i]%10;
		l_tmpdate[i]=l_tmpdate[i]+tmp*16;
	}
 	Write_Ds1302(0x8E,0X00);
	
 	p=write_rtc_address;	//传地址	
 	for(i=0;i<7;i++)		//7次写入 年月日时分秒星期
 	{
		  Write_Ds1302(*p,l_tmpdate[i]);
 		 p++;  
	 }
	 Write_Ds1302(0x8E,0x80);
}
/***********************************************************************/

/**********************DS18B20温度读操作函数********************************/
void delayb(unsigned int count)      //delay
{
  unsigned int i;
  while(count)
  {
    i=200;
    while(i>0)
    i--;
    count--;
  }
}

void dsreset(void)       //DS18B20初始化
{
  unsigned int i;
  DS=0;
  i=103;
  while(i>0)i--;
  DS=1;
  i=4;
  while(i>0)i--;
} 

bit tmpreadbit(void)       // 读一位
{
   unsigned int i;
   bit dat;
   DS=0;i++;          //小延时一下
   DS=1;i++;i++;
   dat=DS;
   i=8;while(i>0)i--;
   return (dat);
} 

unsigned char tmpread(void)   //读一个字节
{
  unsigned char i,j,dat;
  dat=0;
  for(i=1;i<=8;i++)
  {
    j=tmpreadbit();
    dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好//一个字节在DAT里
  }
  return(dat);             //将一个字节数据返回
} 

void tmpwritebyte(unsigned char dat)   
{                           //写一个字节到DS18B20里
  unsigned int i;
  unsigned char j;
  bit testb;
  for(j=1;j<=8;j++)
  {
    testb=dat&0x01;
    dat=dat>>1;
    if(testb)     // 写1部分
    {
      DS=0;
      i++;i++;
      DS=1;
      i=8;while(i>0)i--;
    }
    else
    {
      DS=0;       //写0部分
      i=8;while(i>0)i--;
      DS=1;
      i++;i++;
    }
  }
}
void tmpchange(void)  //发送温度转换命令
{
  dsreset();             //初始化DS18B20
  delayb(1);             //延时
  tmpwritebyte(0xcc);  // 跳过序列号命令
  tmpwritebyte(0x44);  //发送温度转换命令
}

int tmep()               //获得温度
{
  float tt;
  int temp;
  unsigned char a,b;
  dsreset();
  delayb(1);
  tmpwritebyte(0xcc);   
  tmpwritebyte(0xbe);    //发送读取数据命令
  a=tmpread();          //连续读两个字节数据
  b=tmpread();
  temp=b;
  temp<<=8;             
  temp=temp|a;         //两字节合成一个整型变量。
  tt=temp*0.0625;       //得到真实十进制温度值,因为DS18B20
//可以精确到0.0625度,所以读回数据的最低位代表的是
//0.0625度。
  temp=tt*10+0.5;   //放大十倍,这样做的目的将小数点后第一位
//也转换为可显示数字,同时进行一个四舍五入操作。
return temp;     //返回温度值
}

void readrom()          //read the serial 读取温度传感器的序列号
{                      //本程序中没有用到此函数
  unsigned char sn1,sn2;
  dsreset();
  delayb(1);
  tmpwritebyte(0x33);
  sn1=tmpread();
  sn2=tmpread();

}

void delay10ms()            
  {

    unsigned char a,b;

    for(a=10;a>0;a--)

      for(b=60;b>0;b--);

}
/***********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -