单片机
返回首页

EM78P468 NTC lcd测温设计C语言源代码

2018-01-27 来源:eefocus

/********************************************************
 *  Description: 468N RC temperature                    *
 *  Company:     HANTA (suzhou) LTD.                  *
 *  Author:      Sunli                     *
 *  Date:        03/09/2007
 *  最后更新日期:13/09/2007                            *
 * Version:     v1.0                                   *
 *******************************************************/

#i nclude 'em78x468xx.h'
#i nclude 'table.h'

#define DISI() _asm{disi}
#define ENI() _asm{eni}
#define SLEP() _asm{slep}
#define NOP() _asm{nop}
#define WDTC() _asm{wdtc}

#define uchar unsigned char
#define ushort unsigned short
#define ulong unsigned long
#define Rp R55
#define Rc R61
#define Rm R60
#define SCL R63
#define SDA R62
#define LOW R65
#define MID R66
#define HI  R67
#define COOL R85
#define HOT  R86
#define COL_RST R87
#define LED R54
#define COOL_IF_L R57==0 //如果COOL关
#define COOL_IF_H R57==1 //如果COOL开
#define HEAT_IF_L R56==0 //如果HEAT关
#define HEAT_IF_H R56==1 //如果HEAT开 
#define SCL_L R63=0 //I2总线时钟线
#define SCL_H R63=1
#define SDA_L R62=0 //I2总线数据线
#define SDA_H R62=1
#define Rp_TO_IN P5CR|=0x20;NOP()
#define Rp_TO_OUT P5CR&=0xdf;NOP()
#define SDA_TO_IN P6CR|=0x04; NOP() //设数据线位输入
#define SDA_TO_OUT P6CR&=0xfb; NOP() //设数据线位输出
#define SDA_IF_L R62==0  //如果sda为低
#define SDA_IF_H R62==1   //如果sda为高
#define DELAY_us NOP();NOP();NOP();NOP()
#define PAGE_SIZE 8
#define SIZE 0x00ff
#define ON_OFF    0x1e
#define MODE      0x1d
#define FAN       0x1b
#define INCREASE  0x17
#define DECREASE  0x0f
#define W_ADD_COM 0xa0 //写字节命令及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 0
#define R_ADD_COM 0xa1 //读命令字节及器件地址(根据地址实际情况改变), 1010 A2 A1 A0 1
#define LCD_init(init_v) _asm{mov a,@init_v}\
       _asm{mov %LCDCR,a}


uchar lcd_ram[10]=
{ // 0  , 1  ,  2 , 3 ,  4  ,  5 , 6,   7  , 8 ,  9
 0xdf,0x0e,0xeb,0xaf,0x3e,0xbd,0xfd,0x0f,0xff,0xbf
};

ushort dly; 
ushort test_temp[6];
ushort Rm_t,Rc_t;

uchar RC_num,Rmin_p,Rmax_p;
ushort Rmin_t,Rmax_t;
ulong Ttmp;

uchar key_state = 0;//按键值
uchar new_key = 0;
uchar key_tCC = 0;
uchar key_temp= 0;
uchar timer_cnt=0;
uchar r_buf[2];
uchar w_buf[2];
uchar set_temper =0;
uchar fan_st   = 0;
uchar mode_on_off=0;
uchar timer1,times;
//ushort timer;
bit key_flag=0;
bit timer_2ms_ok=0;
bit COL_RST_FLAG=0;
/******************函数声明********************/
void main(void);
void sys_init(void);
void tms(uchar i);
void i2cstart(void);
uchar i2cwt(uchar a);
uchar i2crd(void);
void i2cstop(void);
uchar wt24c(uchar *p, uchar ad, uchar n);
void rd24c(uchar *p_dst, uchar ad_rsc, uchar num);
uchar KeySCAN(void);
void KeyDo(uchar key);
//void   key_find(void);
void display(uchar v,uchar tamp_v,uchar set_tmp);
unsigned char test_temperature(void);
unsigned char Bin1toBcd(unsigned char Xbin1);
/*********************end*********************/

void sys_init(void)
{
 SBPCR=0x17; //rc 2.13mHz,sleep->Idle mode,sub-cLOCk run program
 IRCR=0;  //dISAble IR/PWM,port5 is general i/o
 ISR=0;  //clear count1 interrupt flag bit
 
 P5CR=0xc3;  //port7 is lcd segment,port8 is general i/o
 P6CR=0x00;
 P7CR=0;
 P8CR=0x1f;
 CNT12CR=0x06;
 CNT1PR=5;
 CNT1EN=1;
 HPWTPR=0;
 LPWTPR=0;
 IMR|=0x08;  //enable count1 interrupt
 
// WUCR=0x70; //enable p60~3 wake up
// TCCCR=0x0f; //disable main interrupt,TCC pre-scaler 1:256
 WDTCR=0xff; //0xf7; //disable WDT  
 HLPWTCR=0x77;
 P6PH=0xff;  //enable  port6 internal pull high
 P6OD=0;  //disable por6 open-drain
 P8PH=0xff;  //disable port8 internal pull high
 P6PL=0;  //disable port6 internal pull down

 PORT5=0x00;
 PORT6=0x00;
 PORT8=0x00;
 //变量清零
 COL_RST_FLAG=0;
 
}

void tms(uchar i)
{
 uchar j;
 for(;i>0;i--)
  {
   for(j=0;j<200;j++);
   WDTC();
   }
}


/**********************W/R EEPROM*******************************************/
//起始信号
void i2cstart(void)
{  
 SCL_L; DELAY_us;
    SDA_H; DELAY_us;
    SCL_H; DELAY_us;
    SDA_L; DELAY_us;
    SCL_L; DELAY_us;
}


//把一个字节数据输入器件,并以收到应答信号为止
//写入成功返回1,失败返回0
uchar i2cwt(uchar a)
{   uchar i;
 
    for(i=0;i<8;i++)
    {   SCL_L; DELAY_us;
        if((a<     else SDA_L;
     DELAY_us;
        SCL_H; DELAY_us;
       
    }
    SCL_L; DELAY_us;
    SDA_H; DELAY_us;
    SCL_H; DELAY_us;
 
 SDA_TO_IN;   
 
    if(SDA_IF_L)  //测试有无应答
    { SDA_TO_OUT;
     return(1);  //有应答
    }
    else
    { SDA_TO_OUT;
     return(0);  //无应答
    }
}


//i2c读要调用的函数
//从器件读出一个字节
uchar i2crd(void)
{   uchar i,temp;
           
    for(i=0;i<8;i++)
    {   SCL_L; DELAY_us; 
        SDA_H; DELAY_us;    //置数据线接上内部上拉(数据输入方式),此为必须
        SCL_H; DELAY_us;
        temp<<=1;
       
        SDA_TO_IN;   
       
  if(SDA_IF_H) temp+=1;
        DELAY_us;
       
        SDA_TO_OUT;   
 }
    SCL_L; DELAY_us;  //主器件应答脉冲
    SDA_L; DELAY_us;
    SCL_H; DELAY_us;
    return(temp);
}
 

//停止信号
void i2cstop(void)
{   SCL_L; DELAY_us;
    SDA_L; DELAY_us;
    SCL_H; DELAY_us;
    SDA_H;
}


uchar wt24c(uchar *p, uchar ad, uchar n)
{ uchar t=0;
 
 i2cstart();     //发送起始信号
  
 if(i2cwt(W_ADD_COM))  //发送写字节命令及器件地址
 { 
  i2cwt(ad);    //ad_dst的低位到器件
   
  for(;n>0;n--)   //发送要写入的数据
  {   i2cwt(*p);
   p++;
  }
 }
// else syserr=I2C_ERR;  //写字节命令及器件地址错
 
 i2cstop();
    tms(6);      //延时6ms
 
 return(*p);
}

//从24cxx读出数据
//参数: *p_dst要读入数据的主机内存地址指针; ad_rsc要输出数据的i2c的地址(整形); num数据个数(整形)
//参数条件:  ad_dst+(num-1)不能大于器件的最高地址; num必须>0;
void rd24c(uchar *p_dst, uchar ad_rsc, uchar num)

    uchar t=0;
 i2cstart();     //发送起始信号
  
 if(i2cwt(W_ADD_COM))  //发送写字节命令及器件地址
 { 
  i2cwt(ad_rsc);   //ad_rsc的低位
    
  i2cstart();    //再发送起始信号
  i2cwt(R_ADD_COM);  //发送SLA_R, 读命令字节及器件地址
    
  for(;num>0;num--)
  {   *p_dst=i2crd();  //从器件读出一个字节
   p_dst++;
  }
 }
// else syserr=I2C_ERR;  //写字节命令及器件地址错或对方无应答
  
 i2cstop();

}

/***************************************************************************/
unsigned char Bin1toBcd(unsigned char Xbin1)
{
 unsigned short xBCD=0;
 do
 {
  //if(Xbin1>=100)
  //{
  // Xbin1-=100;
  // xBCD+=0x100;
  //}
  //else
  //{
   if(Xbin1>=10)
   {
    Xbin1-=10;
    xBCD+=0x10;
   }
   else
   {
    xBCD+=Xbin1;
    break;
   }
  //}
 }while(1);
 return xBCD;
}

unsigned char test_temperature(void)
{  
    uchar tamp=0;
    Ttmp=0;
 RC_num=0;
 do
 {
  P6CR&=0xfc;
  Rp_TO_OUT;
  Rm=0;
  Rc=0;
  Rp=0;
  for(dly=0xa00;dly;dly--)
  {
   WDTC();
  }
 
  Rm_t=0;
  P6CR|=0x02;
  Rp_TO_IN;
  Rm=1;      //用基准电阻充电
  while(1)
  {
   if(Rp)
   {
    break;
   }
   Rm_t++;
  }
  WDTC();
  test_temp[RC_num]=Rm_t;
  RC_num++;
 }while(RC_num<6);
 
 RC_num=0;  
 Rmin_p=0;
 Rmax_p=5;
 Rmin_t=test_temp[0];
 Rmax_t=test_temp[5];
 do
 {
  if(test_temp[RC_num+1]  {
   Rmin_t=test_temp[RC_num+1];
   Rmin_p=RC_num+1;
  }
  if(test_temp[4-RC_num]>Rmax_t)
  {
   Rmax_t=test_temp[4-RC_num];
   Rmax_p=4-RC_num;
  }
  RC_num++;
 }while(RC_num<5);
 
 RC_num=0;
 Rm_t=0;
 do
 {
  if(RC_num!=Rmin_p)
  {
   if(RC_num!=Rmax_p)
   {
    Rm_t+=test_temp[RC_num];
   }
  }
  RC_num++;
 }while(RC_num<6);//去max,min,取平均值
 Rm_t>>=2;

 RC_num=0;
 do
 {
  P6CR&=0xfc;
  Rp_TO_OUT;
  Rm=0;
  Rc=0;
  Rp=0;
  for(dly=0xa00;dly;dly--)
  {
   WDTC();
  }
 
  Rc_t=0;
  P6CR|=0x01;//用NTC充电
  Rp_TO_IN;
  Rc=1;
  while(1)
  {
   if(Rp)
   {
    break;
   }
   Rc_t++;
  }
  WDTC();
  test_temp[RC_num]=Rc_t;
  RC_num++;
 }while(RC_num<6);
 
 RC_num=0;  
 Rmin_p=0;
 Rmax_p=5;
 Rmin_t=test_temp[0];
 Rmax_t=test_temp[5];
 do
 {
  if(test_temp[RC_num+1]  {
   Rmin_t=test_temp[RC_num+1];
   Rmin_p=RC_num+1;
  }
  if(test_temp[4-RC_num]>Rmax_t)
  {
   Rmax_t=test_temp[4-RC_num];
   Rmax_p=4-RC_num;
  }
  RC_num++;
 }while(RC_num<5);
 
 RC_num=0;
 Rc_t=0;
 do
 {
  if(RC_num!=Rmin_p)
  {
   if(RC_num!=Rmax_p)
   {
    Rc_t+=test_temp[RC_num];
   }
  }
  RC_num++;
 }while(RC_num<6);//去max,min,取平均值
 Rc_t>>=2;
 
 Ttmp=(unsigned long)Rc_t*9950;
 Ttmp=Ttmp/Rm_t;//求ntc值
 
 if(Ttmp>=32960)
 {
  return 0;
 }
 if(Ttmp<=3588)
 {
  return 0x50;
 }
 
 RC_num=0;
 Rm_t=Ttmp;

 do
 {
  if(Rm_t>=table[RC_num+1])//查表微调
  {
   /*Rm_t-=table[RC_num+1];
   Rc_t=table[RC_num]-table[RC_num+1];
   Rm_t*=10;
   Rm_t=Rm_t/Rc_t;
//   RC_num++;*/
   break;
  }
  RC_num++;
 }while(RC_num<48);

 tamp=Bin1toBcd(RC_num);
 //Rc_t<<=4;
 //Rm_t|=Rc_t;
 P6CR&=0xfC;
 PORT6&=0xfC;

 return tamp;
}

void display(uchar v,uchar tamp_v,uchar set_tmp)
{      
        uchar real_dep,tmp1;
       
        LCD_ADDR=6;
        LCD_DB=0x08;
        //风速+冷热
        LCD_ADDR=0;
        LCD_DB=tamp_v;
        LCD_ADDR=23;
      _asm
  {
   swap %tamp_v
  }
     LCD_DB=tamp_v;
     //当时温度
     real_dep=v;
     v>>=4;
  
     real_dep&=0x0f; 
  LCD_ADDR=4;
  tmp1=lcd_ram[real_dep];
  tmp1&=0xf7;
  LCD_DB=tmp1;
  
  LCD_ADDR=3;
  _asm
  {
   swap %tmp1
  }
  LCD_DB=tmp1;  
  
  tmp1=v&0x0f; 
  LCD_ADDR=2;
  tmp1=lcd_ram[tmp1];
  LCD_DB=tmp1;
  LCD_ADDR=1;
  _asm
  {
   swap %tmp1
  }
  LCD_DB=tmp1;
  //设置温度
  real_dep=set_tmp;
     set_tmp>>=4;
  
     real_dep&=0x0f; 
  LCD_ADDR=10;
  tmp1=lcd_ram[real_dep];
  LCD_DB=tmp1;
  
  LCD_ADDR=9;
  _asm
  {
   swap %tmp1
  }
  LCD_DB=tmp1;  
  
  tmp1=set_tmp&0x0f; 
  LCD_ADDR=8;
  tmp1=lcd_ram[tmp1];
  LCD_DB=tmp1;
  LCD_ADDR=7;
  _asm
  {
   swap %tmp1
  }
  LCD_DB=tmp1;   
}

/*void lcd_on_off(void)
{  
    uchar i;
 for(i=0;i<32;i++)
 {
  LCD_ADDR=i;
  LCD_DB=0xff;
 }
 
 for(dly=0x00ff;dly;dly--)
 {
  WDTC();
 }
   
 for(i=32;i;i--)
 {
  LCD_ADDR=i;
  LCD_DB=0;
 }
 
 for(dly=0x1fff;dly;dly--)
 {
  WDTC(); 
 }
  
}*/

/******************************按键扫描************************/
/*****************************按键处理************************/
void KeyDo(uchar key)
{  
    uchar fan_temp;
    if (key == ON_OFF){
      if(mode_on_off==0)
        {
         key_flag=1;
         mode_on_off=1;
        }
      else
        {
         mode_on_off=0;
        }

    }
    else if (key == FAN)
    {
     timer1=0;
      key_flag=1;
        if(mode_on_off==1)
         {
         fan_temp=fan_st&0xe0;
         if(fan_temp==0x80)
          {
           fan_st|=0x40;
           fan_st&=0x7f;
          }
         else if(fan_temp==0x40)
          {
           fan_st|=0x20;
           fan_st&=0xbf;
          }
         else if(fan_temp==0x20)
          {
           fan_st|=0x80;
           fan_st&=0xdf;
          }
         }
    }
   else if (key == MODE)
   {
    timer1=0;
     key_flag=1;
     if(mode_on_off==1)
      {
        fan_temp=fan_st&0x03;
        if(fan_temp==0x01)
           fan_st++;
           else
           {
           fan_st|=0x01;
           fan_st&=0xfd;
           }     
      }
    }
    else if (key == DECREASE)
    {      
           timer1=0;
           key_flag=1;
            if (set_temper == 10)
            {
                set_temper = 10;
            }
            else
            {
                set_temper--;
            }
    }
    else if (key == INCREASE)
    {       timer1=0;
           key_flag=1;
            set_temper++;
            if (set_temper > 30)
            {
               set_temper = 30;
            }

    }

}
uchar KeyScan(void)
{
      uchar temp = 0;
      temp = PORT8;
      temp&=0x1f;
      if(temp!=0x1f)
      return temp;
    return 0x1f;
}

void _intcall counter1_l(void) @ 0x0C:low_int 3
{
 
}

void _intcall counter1(void) @ int 3
{
  //backup R4
  _asm
   {
     SWAPA 0x04
     MOV 0x1F,A
   }   
 
   //backup C system
  _asm
    {
    BS 0X4,6
    BS 0X4,7   
 MOV A,0X10 // USE 1 BYTE C TYPE,C SYSTEM BACKUP
 MOV 0X3C+1,A
 MOV A,0X14
 MOV 0X3B+1,A
 MOV A,0X18
 MOV 0X3A+1,A
 MOV A,0X1B
 MOV 0X39+1,A
 MOV A,0X1C
 MOV 0X38+1,A
    }
   
            ISR=0;
            timer_2ms_ok=1;
            if (key_state == 0)
           {
            new_key = KeyScan();
            if (new_key != 0x1f)
            {
                key_state++;
            }
           }
        else if (key_state < 5)
        {
            if (KeyScan() == new_key)
            {
                key_state++;
            }
            else
            {
                key_state = 0;
            }
        }
        else if (key_state == 5)
        {
            key_state++;
            KeyDo(new_key);
        }
        else if (key_state == 6)
        {
            key_temp = KeyScan();
            if (key_temp == 0x1f)
            {
                key_state ++;
            }
            else if (key_temp == DECREASE || key_temp == INCREASE)
            {
                if (key_tcc >= 10)
                {
                    key_tcc = 5;
                    KeyDo(key_temp);
                }
                else
                {
                    key_tcc++;
                }
            }
        }
        else if (key_state < 10)
        {
            if (KeyScan() == 0x1f)
            {
                key_state ++;
            }
            else
            {
                key_state = 6;
            }
        }
        else if (key_state == 10)
        {
            key_state = 0;
            key_tcc = 0;
       
        }
     if(mode_on_off)
     {
     times++;
     timer1++;
     //rst_tim++;
     }
 
  // Write your code (inline assembly or C) here
 
   //restore C system
  _asm
    { 
    BS 0X4,6
    BS 0X4,7
 MOV A,0X3C+1 // USE 1 BYTE C TYPE,C SYSTEM RESTORE
 MOV 0X10,A
 MOV A,0X3B+1
 MOV 0X14,A
 MOV A,0X3A+1
 MOV 0X18,A
 MOV A,0X39+1
 MOV 0X1B,A
 MOV A,0X38+1
 MOV 0X1C,A
    }


  //restore R4
  _asm
   {
     SWAPA 0x1F
     MOV 0X04,A
   }
  
}

void  main()
  {
  uchar temp1,temp2;
  uchar i,j;
  uchar *r;
     uchar b;
     uchar c;
     uchar stst;
     uchar *w;
     uchar x;
     uchar y;
       DISI(); 
    tms(10);
    sys_init();
    //lcd_init(0xf7);
       r_buf[0]=0;
       r_buf[1]=0;

     r=r_buf; //读参数
     b=0x00;
     c=2;

     w=w_buf; //写参数
     x=0x00;
     y=2;
    
     //w_buf[0]=0x81;
     //w_buf[1]=0x19;
     // wt24c(w,x,y); //出厂写EEPROM

     rd24c(r,b,c); //初始读EEPROM
     fan_st=r_buf[0];
     set_temper=r_buf[1];
     temp1=test_temperature();
  for(i=0;i<32;i++)// 清屏
 {
  LCD_ADDR=i;
  LCD_DB=0;
 }
  for(dly=0x1fff;dly;dly--)
 {
  WDTC(); 
 }
 //LED=1;
 ENI();
 while(1)
 {  
     //key_find();
   while(timer_2ms_ok)
   {
   timer_2ms_ok=0;
   if(mode_on_off==1)
    {
     lcd_init(0xf7);
     if(key_flag)
     {
     LED=1;
     if(timer1>=200)
      {
      timer1=0;
      LED=0;
      if((r_buf[0]!=fan_st)||(r_buf[1]!=set_temper))
      {
      r_buf[0]=fan_st;
      r_buf[1]=set_temper;
      w_buf[0]=fan_st;
      w_buf[1]=set_temper;
      wt24c(w,x,y); //写
      }
      key_flag=0;      
         }
      }
        if(times>=250)
         {
          temp1=test_temperature();
       times=0;
      }
       temp2=Bin1toBcd(set_temper);
    display(temp1,fan_st,temp2);
    PORT6=fan_st&0xe0;
    stst=fan_st&0x01;
    if(stst==0x01)
    { 
       COOL=1;
       HOT=0;
       tms(1);
       if((temp1>temp2)&&(COL_RST_FLAG==0))
         { 
            j=0;
          while((COOL_IF_L)&&(j<=3))
            {
             j++;
             COL_RST=1;
                   tms(10);
                   COL_RST=0;
             COL_RST_FLAG=1;                  
             }        
                   j=0;
          }
        else if((temp1         {  
            j=0;
        while((COOL_IF_H)&&(j<=3))
             {
             j++;  
             COL_RST=1;
                   tms(10);
                   COL_RST=0;
             COL_RST_FLAG=0;                  
             }        
                  j=0;
         }         
    }
        //stst=fan_st&0x02;
    else
     { 
        COOL=0;
         if((temp1         HOT=1;
         else
         HOT=0;
      }
       
    }
    else
    {
     LED=0;
     lcd_init(0x00);
     LOW=0;
     MID=0;
     HI=0;
     COOL=0;
     HOT=0;
     }

 WDTC(); 
   } 
 WDTC(); 
 }
  }


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

最新器件
精选电路图
  • 基于IC555的可变PWM振荡器电路

  • 优化电路板布局的简单方法

  • 如何使用LED驱动器LM3915制作振动计

  • 使用NE555和磁簧开关的橱柜照明电路

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章