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

📄 lcd1602.c

📁 此程序实现
💻 C
字号:
/*
***************************************************************************
*
*					(C) Copyright 2007,单片机初学者园地
*                          All Rights reserved.
*
*项目名称:    51单片机学习开发系统
*                
*本文件名称:LCD1602.c 
*       
* 完成作者 : 单片机初学者 http://blog.ednchina.com/ahai0306/  qq:464976346   
* 当前版本 : V1.0        
* 完成日期 : 2007年4月20日
* 描    述 :  
*                此程序实现,完成液晶部分,数码管显示,中断切换界面
*            同时还进行发光管指示,和蜂鸣器的响声,是一个比较综合的 
*            程序,在以后的项目设计中,此程序是一个比较不错的范例!  
****************************************************************************
*/


#include <reg52.h>		 //调用头文件(单片机内部的寄存器定义)
#include<intrins.h>

#define uchar unsigned char
#define uint  unsigned int

/******本段为硬件I/O口定义********/
sbit 	LED0   = P0 ^ 0;	 //KEY和发光管复用,请将4个跳线插到KEY端
sbit 	LED1   = P0 ^ 1;
sbit 	LED2   = P0 ^ 2;
sbit 	LED3   = P0 ^ 3;
sbit 	DIG0   = P0 ^ 4;	 //数码管位0
sbit 	DIG1   = P0 ^ 5;	 //数码管位1

sbit 	BUZZ   = P3 ^ 3;	 //蜂鸣器
sbit LCD_RS = P3^7 ;             
sbit LCD_RW = P3^6 ;
sbit LCD_EN = P3^4 ;

#define  LED_SEG    P1		//数码管
#define  LCD_DATA   P2	 	//LCD
//#define  LCD_BUSY   0x80 	// 用于检测LCD的BUSY标识
sbit DQ = P3^5 ;  //定义DS18B20端口DQ  

bit presence  ;

 //数码管显示0~9,定义到代码段,和程序数据烧在FLASH中
code unsigned  char DispBuf[10]= {0x3f,0x06,0x5b,0x4f,0x66,
								  0x6d,0x7d,0x07,0x7f,0x6f};

//函数声明
void  disp_selec(unsigned  char bit_selec,unsigned  char  seg);


uchar code  cdis1[ ] = {"   DS18B20 OK   "} ;
uchar code  cdis2[ ] = {"  TEMP:    .  C "} ;
uchar code  cdis3[ ] = {"    welcom!     "} ;
uchar code  cdis4[ ] = {" MCU-STUDY-BOARD"} ;

unsigned char data  temp_data[2] = {0x00,0x00} ;
unsigned char data  display[5] =   {0x00,0x00,0x00,0x00,0x00} ;
unsigned char code  ditab[16] =    {0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
                                    0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09} ;
void beep(); 
unsigned char code  mytab[8] = {0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00} ;

#define delayNOP(); {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;

/**************************************************
** 函数名称: dellay
** 入口参数:h(unsigned int型)
** 出口参数:无
** 功能描述: 短暂延时,使用11.0592晶体,约0.01MS
****************************************************/
void dellay(unsigned int  h)
{
  while(h--);	   //0.01MS
}

/*******************************************************************/
void delay1(int ms)
{
 unsigned char y ;
  while(ms--)
 {
  for(y = 0 ; y<250 ; y++)
  {
   _nop_() ;
   _nop_() ;
   _nop_() ;
   _nop_() ;
  }
 }
}

/******************************************************************/
/*检查LCD忙状态                                                   */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。   */
/******************************************************************/ 
bit lcd_busy()
 {                          
    bit result ;
    LCD_RS = 0 ;
    LCD_RW = 1 ;
    LCD_EN = 1 ;
    delayNOP() ;
    result = (bit)(LCD_DATA&0x80) ;
    LCD_EN = 0 ;
    return(result) ; 
 }

/*写指令数据到LCD                                                  */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。          */
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{                          
   while(lcd_busy()) ;
    LCD_RS = 0 ;
    LCD_RW = 0 ;
    LCD_EN = 0 ;
    _nop_() ;
    _nop_() ; 
    LCD_DATA = cmd ;
    delayNOP() ;
    LCD_EN = 1 ;
    delayNOP() ;
    LCD_EN = 0 ;  
}

/*******************************************************************/
/*写显示数据到LCD                            */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。       */
/*******************************************************************/
void lcd_wdat(uchar dat)
{                          
   while(lcd_busy()) ;
    LCD_RS = 1 ;
    LCD_RW = 0 ;
    LCD_EN = 0 ;
    LCD_DATA = dat ;
    delayNOP() ;
    LCD_EN = 1 ;
    delayNOP() ;
    LCD_EN = 0 ; 
}


/*  LCD初始化设定                                                  */
/*******************************************************************/
void lcd_init()
{ 
    delay1(15) ;   
    lcd_wcmd(0x01) ;      //清除LCD的显示内容            
    lcd_wcmd(0x38) ;      //16*2显示,5*7点阵,8位数据
    delay1(5) ;
    lcd_wcmd(0x38) ;         
    delay1(5) ;
    lcd_wcmd(0x38) ;         
    delay1(5) ;

    lcd_wcmd(0x0c) ;      //显示开,关光标
    delay1(5) ;
    lcd_wcmd(0x06) ;      //移动光标
    delay1(5) ;
    lcd_wcmd(0x01) ;      //清除LCD的显示内容
    delay1(5) ;
}

/*  设定显示位置                                    */
/*******************************************************************/
void lcd_pos(uchar pos)
{                          
  lcd_wcmd(pos | 0x80) ;  //数据指针=80+地址变量
}

/*自定义字符写入CGRAM                                   */
/*******************************************************************/
void  writetab()  
{  
    unsigned char i ;
    lcd_wcmd(0x40) ;            //写CGRAM
    for (i = 0 ; i< 8 ; i++)       
    lcd_wdat(mytab[ i ]) ;        
}

/*us级延时函数                                        */
/*******************************************************************/

void Delay(unsigned int num)
{
  while( --num ) ;
}

/*初始化ds1820                                      */
/*******************************************************************/
Init_DS18B20(void)
{  
     DQ = 1 ;      //DQ复位
     Delay(8) ;    //稍做延时

     DQ = 0 ;      //单片机将DQ拉低
     Delay(90) ;   //精确延时 大于 480us

     DQ = 1 ;       //拉高总线
     Delay(8) ;

     presence = DQ ;    //如果=0则初始化成功 =1则初始化失败
     Delay(100) ;
     DQ = 1 ; 
     
     return(presence) ; //返回信号,0=presence,1= no presence
}


/* 读一个字节                     */
/*******************************************************************/
 ReadOneChar(void)
{
unsigned char i = 0 ;
unsigned char dat = 0 ;

for (i = 8 ; i > 0 ; i--)
  {
    DQ = 0 ; // 给脉冲信号
    dat >>= 1 ;
    DQ = 1 ; // 给脉冲信号

    if(DQ)
     dat |= 0x80 ;
    Delay(4) ;
  }

    return (dat) ;
}

/* 写一个字节                                         */
/*******************************************************************/
 WriteOneChar(unsigned char dat)
{
  unsigned char i = 0 ;
  for (i = 8 ; i > 0 ; i--)
  {
    DQ = 0 ;
    DQ = dat&0x01 ;
    Delay(5) ;

    DQ = 1 ;
    dat>>=1 ;
  }
}

/* 读取温度                            */
/*******************************************************************/
 Read_Temperature(void)
{
     Init_DS18B20() ;
  
     WriteOneChar(0xCC) ;  // 跳过读序号列号的操作
     WriteOneChar(0x44) ;  // 启动温度转换

     Init_DS18B20() ;
     WriteOneChar(0xCC) ;  //跳过读序号列号的操作
     WriteOneChar(0xBE) ;  //读取温度寄存器

     temp_data[0] = ReadOneChar() ;   //温度低8位
     temp_data[1] = ReadOneChar() ;   //温度高8位 
}

/* 数据转换与温度显示                                              */
/*******************************************************************/
 Disp_Temperature()
{
  display[4]=temp_data[0]&0x0f ;
  display[0]=ditab[display[4]]+0x30 ;     //查表得小数位的值
  
  display[4]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4) ;
  display[3]=display[4]/100+0x30 ;
  display[1]=display[4]%100 ;
  display[2]=display[1]/10+0x30 ;
  display[1]=display[1]%10+0x30 ;

    if(display[3]==0x30)        //高位为0,不显示
   { 
     display[3]=0x20 ;              
     if(display[2]==0x30)      //次高位为0,不显示
     display[2]=0x20 ;
   }

     lcd_pos(0x48) ;             
     lcd_wdat(display[3]) ;        //百位数显示 
     lcd_pos(0x49) ;             
     lcd_wdat(display[2]) ;        //十位数显示 
  lcd_pos(0x4a) ;             
     lcd_wdat(display[1]) ;        //个位数显示 
  lcd_pos(0x4c) ;             
     lcd_wdat(display[0]) ;        //小数位数显示 
}  

/*******************************************************************/
/* 蜂鸣器响一声                 */
/******************************************************************
void beep()
  {
    unsigned char y ;
    for (y=0 ;y<100 ;y++)
    {
      Delay(60) ;
      BUZZ=!BUZZ ;                //BUZZ取反
    } 
    BUZZ=1 ;                      //关闭蜂鸣器
 Delay(40000) ;
  }

/* DS18B20 OK 显示菜单                                             */
/*******************************************************************/
void  Ok_Menu ()
{ 
    uchar  m ;
    lcd_init() ;                //初始化LCD 
            
    lcd_pos(0) ;                //设置显示位置为第一行的第1个字符
     m = 0 ;
    while(cdis1[m] != '\0')
     {                         //显示字符
       lcd_wdat(cdis1[m]) ;
       m++ ;
     }

    lcd_pos(0x40) ;             //设置显示位置为第二行第1个字符
     m = 0 ;
    while(cdis2[m] != '\0')
     {
       lcd_wdat(cdis2[m]) ;      //显示字符
       m++ ;
     }

     writetab() ;               //自定义字符写入CGRAM
     delay1(5) ;
     lcd_pos(0x4d) ;
     lcd_wdat(0x00) ;          //显示自定义字符
}


/* DS18B20 ERROR 显示菜单                             */
/*******************************************************************/
void  other_Menu ()
{
     uchar  m ;
     lcd_init() ;                //初始化LCD 
 
    lcd_pos(0) ;                //设置显示位置为第一行的第1个字符
     m = 0 ;
     while(cdis3[m] != '\0')
     {                         //显示字符
       lcd_wdat(cdis3[m]) ;
       m++ ;
     }

     lcd_pos(0x40) ;             //设置显示位置为第二行第1个字符
     m = 0 ;
     while(cdis4[m] != '\0')
     {
       lcd_wdat(cdis4[m]) ;      //显示字符
       m++ ;
     }
}


unsigned  char	  time_temp;		   //全局变量,定时器加1
unsigned  char	  time_num;		       //全局变量,按一次键加1


/************主程序**************/
main()
{ 	unsigned  char  i=0;		    //要显示的数
    unsigned  char  temp_a,temp_b;	//个位、十位数
	 P0=0;    //所有的发光管亮
     delay1(10) ;
     Ok_Menu () ;
	 Read_Temperature() ;
    Disp_Temperature() ; 

   while(1)	  		
  {unsigned  int temp;

   {
    temp_b=i/10;
	temp_a=i%10;
    for(temp=0;temp<100;temp++)
    { 
	   disp_selec(0,temp_a);		 //显示个位数
 	   dellay(100);
	   disp_selec(1,temp_b); 		 //显示十位数
	   dellay(100);
     }							 //显示数加1
      i++;
	Read_Temperature() ;
    Disp_Temperature() ; 
	  if(i%2)
	  { P0&=0Xf0; P0|=0X05;}
	   else
	   { P0&=0Xf0; P0|=0X0a;}
	   if(i%10==0)
		 { BUZZ=0;
		dellay(15000);	 //能被10整除时,蜂鸣器响170MS
		BUZZ=1;
		 }
	    BUZZ=0;
		dellay(200);	//蜂鸣器响20MS  
	  if(i>99)
	   {  i=0;
	   	dellay(50000);	//能被100整除时,蜂鸣器响670MS
	   }
	  	BUZZ=1;
	   P1=~P1;
	 } 
 
  }	    
} 



/**************************************************
** 函数名称: disp_selec
** 入口参数:bit_selec,seg
** 出口参数:无
** 功能描述: 选择相应数码管,进行显示
****************************************************/
void  disp_selec(unsigned  char bit_selec,unsigned  char  seg)
{
   if(bit_selec==0)	  //数码管位选0
	{
	  DIG0=0;
	  DIG1=1;
	 }
	if(bit_selec==1)   //数码管位选1
	 {
	   DIG0=1;
	   DIG1=0;
	 }
	  P1=DispBuf[seg];

}

⌨️ 快捷键说明

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