waqich 发表于 2024-9-28 07:45:17

8G1K08-36I-SOP16 做NTC温控器

   Ntc温控器程序, 温控器采用8G1K08-36I-SOP16做主芯片,TM1650驱动四位数码管显示NTC温度值。温度测量范围在-40到150度,程序参考STC32G 9.62实验箱配套程序,增加了继电器输出控制。把温度控制在上下限温度之间,四个按键Mode设置制冷或制热模式,Set键短按切换设置参数长按2秒可保存参数到EEPROM中,停电不会丢失设置的参数。Up键设置参数增加,Down键设置参数减少,停电不会丢失设置的参数。温度校准参数可设置温差在正负10度 。


原理图
主程序如下:
#include "COMM/stc.h"                //调用头文件



#include "test.h"
#include "intrins.h"               
#include "ntc.h"
#include "tim0.h"
#include "adc.h"
#include "COMM/EEPROM.h"
#include<math.h>
/***********初始化***********/
sbit scl = P1^7;   //TM1650时钟通讯IO
sbit sda = P1^6;   //TM1650数据通讯IO
sbit Relay = P5^4;   //继电器控制IO
bit Run_Flag =0;                //0制冷模式 1制热模式
u8Set_Mode =0;                //0-8 模式几 0:没有模式
bitTIM_Flag;                //定时标志位
//#define ADCTIM ( *(unsigned char volatile xdata *)0xfea8)
bit busy;
int ydsx,ydxx,ydjz;    //ydsx温度上限 ydsx温度下限 ydjz温度校准
int ydsxx,ydxxx,ydjzx;   //ydsx温度上限显示 ydsx温度下限显示 ydjz温度校准显示
int SEG0,SEG1,SEG2,SEG3; //四位数码管段码
uint8_t code Num_Buff={ //数码管共阴真值表0-F
      0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x76,0x38,0x37,0x3e,0x73,0x5c,0X40,0x00
};    //0, 1 ,2 ,3, 4 . 5.6, 7 ,8 ,9 ,A , b,C ,d ,E ,F ,H, L , N,U ,P, o, - , 隐
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
inte,      Temp;            //TempADC转换数值
intTempVal,TempValb;         //TempVal大于0的温度, TempValb小于0的温度
void delay_ms(u16 ms);      //unsigned int
void tm1650_start();    //TM1650通讯的开始信号
void tm1650_end();      //TM1650通讯的结束信号
void tm1650_ack();      //TM1650通讯的应答信号
void write_1();         //TM1650数据通讯 写1
void write_0();         //TM1650数据通讯 写0
void write_byte(unsigned char tem);//写一个字节
void sys_init();                //系统初始化
void DspTemp();         //数码管显示
void delay(unsigned int time)//延时
{
while(time--);
}
void main()                                        //程序开始运行的入口
{
      u8 LED_Data = 0XFE;      
      u8 num=0;
      u8 LED_DataTab = { 0XFE,0XFD, 0XFB,0XF7,0XEF,0XDF,0XBF,0X7F};      
      //int TEMP_VAL;
      //ADC_Init();      
      sys_init();               //IO口初始化
    P1M0 = 0x00;       //设置P1.0为ADC口
    P1M1 = 0x01;
    ydsx=-250;
      ydxx=150;
      ydjz=0;
    P_SW2|=0x80;
    ADCTIM=0x3f;//设置 ADC内部程序
    P_SW2&=0x7f;
    ADCCFG=0x2f;//设置 ADC时钟为系统时钟/2/16
    ADC_CONTR=0x80;//使能ADC选P10为ADC通道
    //EEPROM读操作,读取第0扇区,10 12 14字节-------------------
      ydsx=IapRead(SECTOR0 + 10); //从EEPROM第0扇区10字节取温度上限值
    ydxx=IapRead(SECTOR0 + 12); //从EEPROM第0扇区12字节取温度下限值
      ydjz=IapRead(SECTOR0 + 14); //从EEPROM第0扇区14字节取温度校准值
      BEEP = 0;                   //上电蜂鸣响一声
      delay_ms(10);         //延时10ms
      BEEP = 1;                   //关闭蜂鸣响
    tm1650_start();
    write_byte(0x48);//数码显示模式
    tm1650_ack();
    write_byte(0x31);//3级亮度,开显示。这里的指令数据 详情参阅TM1650的datasheet
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x68);
    tm1650_ack();
    write_byte(Num_Buff);//数码管千位上电显示1
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6a);
    tm1650_ack();
    write_byte(Num_Buff);//数码管百位上电显示8
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6c);
    tm1650_ack();
    write_byte(Num_Buff);//数码管十位上电显示8
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6e);
    tm1650_ack();
    write_byte(Num_Buff);//数码管个位上电显示8
    tm1650_ack();
    tm1650_end();
    //Timer0_Init();                        //定时器0初始化
      while(1)                        //无限循环
      {
                Test();          //按键查询处理
      delay_ms(1000);         //延时300ms
                ADC_CONTR|=0x40; //启动AD
      _nop_();
      _nop_();
      while(!(ADC_CONTR&0x20)) ;   //查询ADC完成标志
      ADC_CONTR &= ~0x20;         //清完成标志
      //ADCCFG = 0x00;                  //设置结果左对齐(会出问题原因不详)
                ADCCFG = 0x20;                  //设置结果右对齐
      Temp=(ADC_RES << 8) | ADC_RESL;   //读取ADC结果
         // Temp= Temp>>6 ;
            // TempVal= Temp*5/1024*1000;
            // Temp= TempVal;
            TempVal = Temp_Cal(Temp)+ydjz;      //ADC结果计算成温度值并加上校准值
                //TempVal = Temp;      //ADC结果计算成温度值并加上校准值
            if(Run_Flag==0)   //如果是制冷模式
            {      
                  if(TempVal<= ydxx)//实际温度低于温度下限
                  {
                        Relay=1;       //关闭继电器(关闭制冷)
                   }
                if(TempVal>= ydsx) //实际温度高于温度上限
                  {
                        Relay=0;      //打开继电器(启动制冷)
                   }
             }
      else                     //否则是制热模式
         {
               if(TempVal<= ydxx)    //实际温度低于温度下限
                   {
                        Relay=0;         //打开继电器(启动加热)
                   }
                if(TempVal>= ydsx)    //实际温度高于温度上限
                  {   
                         Relay=1;      //关闭继电器(关闭加热)
                  }      
            }
       if(TempVal>= 0) //温度在0度以上
         {
                SEG0 = TempVal/1000%10;   //温度千位
                        if (SEG0==0)
                        SEG0=23;            //千位为0时 ,消隐不显      
                SEG1 = TempVal/100%10;      //温度百位
                SEG2 = TempVal/10%10;       //温度十位
                SEG3 = TempVal/1%10;      //温度个位
                DspTemp();               //显示温度   
          }
       else            //温度在0度以下
          {      
               TempValb=abs(TempVal); //取温度绝对值
               SEG0 = 22;                   //千位显示“-”
               SEG1 = TempValb/100%10;          //温度百位
               SEG2 = TempValb/10%10;       //温度十位
               SEG3 = TempValb/1%10;      //温度个位
               DspTemp();      
          }
   }
}

void sys_init()                //系统初始化
{
    P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
    P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
    P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
    P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
    P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
    P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
    P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
    P3M0 = 0x00;
    P3M1 = 0x00;
    P3M0 &= ~0x03;
    P3M1 |= 0x03;
}

void Timer0_Isr(void) interrupt 1//定时器0中断处理
{
      static timcount = 0;      
      TR0=0;
      timcount++;                              //1ms+1
      if( timcount>=300 )                //如果这个变量大于等于300ms
          {
                timcount = 0;
                TIM_Flag = 1;      //定时时间到了
      }
      TR0=1;
}

void DspTemp()
{
      write_byte(0x48);//数码显示模式
    tm1650_ack();
    write_byte(0x11);//1级亮度,开显示。这里的指令数据 详情参阅TM1650的datasheet
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x68);
    tm1650_ack();
    write_byte(Num_Buff[ SEG0]);//显示千位
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6a);
    tm1650_ack();
    write_byte(Num_Buff[ SEG1]);//显示百位
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6c);
    tm1650_ack();
    write_byte(Num_Buff[ SEG2]+0x80);//显示十位加小数点
    tm1650_ack();
    tm1650_end();
    tm1650_start();
    write_byte(0x6e);
    tm1650_ack();
    write_byte(Num_Buff[ SEG3]);//显示个位
    tm1650_ack();
    tm1650_end();         
}


void tm1650_start()
{
   sda = 1;
   scl = 1;
   delay(10);
   sda = 0;
   delay(5);
}
void tm1650_end()
{
   sda = 0;
   scl = 1;
   delay(6);
   sda = 1;
   delay(2);
}
void tm1650_ack()
{
while(sda);
delay(5);
scl = 1;
delay(5);
scl = 0;
delay(5);
}
void write_1()
{
   sda = 1;
   scl = 0;
   delay(5);
   scl = 1;
   delay(10);
   scl = 0;
   delay(5);
   sda = 0;
}
void write_0()
{
   sda = 0;
   scl = 0;
   delay(5);
   scl = 1;
   delay(10);
   scl = 0;
}
void write_byte(unsigned char tem)
{
   unsigned char i;
   for(i=8;i>0;i--)
    {
      if(tem&0x80)
      write_1();
      else
      write_0();
      tem<<=1;
    }
}
按键处理程序如下:


#include "test.h"
//#include "Tm1650.h"
//#include "IIC.h"
#include<math.h>
#include "COMM/EEPROM.h"
extern void DspTemp();
int   de=0;
void Test(void)                        //按键处理
{
      if( Mode == 0)                //模式键
      {      
         if( Run_Flag==0 )                        //Run_Flag==0制冷
               {
                  SEG0 = 20;            //千位显示P
                     SEG1 = 22;            //百位显示-
                  SEG2 = 22;            //十位显示-
            SEG3 = 12;            //个位显示C      
                  DspTemp();                      //显示模式
             }
         else
          {
               SEG0 = 20;            //显示P
               SEG1 = 22;            //显示-
               SEG2 = 22;            //显示-
             SEG3 = 16;            //显示H      
               DspTemp();                      //显示模式         
          }
         delay_ms(10);                        //延时10ms               
          while(Mode == 0 );                //按钮按下,并等待按钮松开                                          
                        if( Run_Flag==0 )                        //Run_Flag==0制冷
                        { //-------默认是制冷模式---------------------               
                              Run_Flag = 1;                        //Run_Flag==1制热
                              SEG0 = 20;            //千位显示P
                            SEG1 = 22;            //显示-
                        SEG2 = 22;            //显示-
                  SEG3 = 16;            //显示H
                            DspTemp();                  //显示模式                                       
                              BEEP = 0;                              //打开蜂鸣
                              delay_ms(20);                        //延时10ms
                              BEEP = 1;                              //关闭蜂鸣
                        }
         else   //-如果已是制热模式则转换到制冷模式---------------------      
                        {
                              Run_Flag = 0;         //Run_Flag==0制冷
                              SEG0 = 20;            //显示P
                            SEG1 = 22;            //显示-
                        SEG2 = 22;            //显示-
                  SEG3 = 12;            //显示C
                              DspTemp();                  //显示模式      
                              BEEP = 0;                         //打开蜂鸣
                              delay_ms(20);               //延时10ms
                              BEEP = 1;                        //关闭蜂鸣               
                        }               
      }
      if( Set == 0 )                //设置键
      {
                delay_ms( 10 );
                if( Set == 0 )
                {
                  BEEP = 0;                              //打开蜂鸣
                        delay_ms(10);                        //延时10ms
                        BEEP = 1;                              //关闭蜂鸣                        
                        Set_Mode ++;      
                        SEG0 = 20;            //显示P
                        SEG1 = 22;         //显示模式
                  SEG2 = 22;            //显示-
                SEG3 = Set_Mode;      //显示-
                  DspTemp();                      //显示模式                                       
                        delay_ms(1000);         
                        //模式选择
                        if( Set_Mode>3 )                //如果模式>8
                              Set_Mode = 0;                //回到模式1               
                         de=0;
                        while( Set == 0)                //等待松开执行了
                        {
                                 de++;
                                 SEG0 = 13;   //显示d
                                 SEG3 = de/10;   
                                 DspTemp();                  //显示模式               
            //BEEP = 0;                   //打开蜂鸣
                            delay_ms(100);                        //延时10ms
                        //    BEEP = 1;                              //关闭蜂鸣                        
                              if(de>=100)                              //按住Set键2秒以上保存参数                        
                            {                        
                  EA=0;
                        //P6 =      0XFE;   P6<<1+1
                              IapErase(SECTOR0);                                        // 擦除第0扇区                                       
                  IapProgram(SECTOR0+10,ydsx);      // 保存温度上限
                IapProgram(SECTOR0+12,ydxx);      // 保存温度下限
                IapProgram(SECTOR0+14,ydjz);      // 保存温度校准
                        // 在第0扇区,第10字节,写入ydsx      
                BEEP = 0;                              //打开蜂鸣
                            delay_ms(10);                        //延时10ms
                            BEEP = 1;                              //关闭蜂鸣                        
               delay_ms(10);      
                BEEP = 0;                              //打开蜂鸣
                            delay_ms(10);                        //延时10ms
                        BEEP = 1;                              //关闭蜂鸣                        
                        EA=1;      
                  delay_ms(10);                        //延时10ms      
                        de=0;               
                        }                              
                                 delay_ms(10);
                        //de=0;
                        }      
                        de=0;               
                }
      }
   if( Up == 0)                //增加键处理
      {
                SEG0 = 20;            //显示P
                SEG1 = 22;            //显示-
            SEG2 = 22;            //显示-
            SEG3 = Set_Mode;      //显示模式
            DspTemp();                  //显示模式               
                BEEP = 0;                              //打开蜂鸣
                delay_ms(50);                        //延时10ms
            BEEP = 1;                              //关闭蜂鸣      
                delay_ms(50);                        //延时10ms
                while(Up == 0 )
                {                              
                        switch(Set_Mode)            //选择设置参数                              
                        {
                      case1:                      //温度上限设置                                                      
                            ydsx++;                      //温度上限加1
                              if( ydsx >= 1200) //温度上限大于120度
                              {
                                    ydsx=-450;      //温度上限设置为-45度
                               }
                           
                        if      (ydsx<=0)            //温度上限小于0时   
                                  {
                              SEG0 = 22;             //数码管千位显示“-”   
                                    ydsxx=abs(ydsx);         //取温度上限绝对值
                                    SEG1 =ydsxx/100%10;      //百位 计算
                        SEG2 = ydsxx/10%10;   //十位 计算
                        SEG3 = ydsxx/1%10;      //个位 计算
                            DspTemp();      
                              }                              
                else
                           {      
                           ydsxx=ydsx;      
                               SEG0 = ydsxx/1000%10;   //千位计算
                                 if (SEG0==0)
                                           SEG0=23;            //千位为0时 ,消隐不显      
                     SEG1 =ydsxx/100%10;       //百位 计算
                     SEG2 = ydsxx/10%10;       //十位 计算
                     SEG3 = ydsx/1%10;         //个位 计算
                           DspTemp();      
                           }
                                  delay_ms(30);         
                              break;
                        case2:                           //温度下限设置                                             
                            ydxx++;                     //温度下限加1
                              if( ydxx >= 1200)      
                              {
                                     ydxx=-450;
                               }
                        
                            if      (ydxx<=0)       //温度下限小于0时   
                                  {
                              SEG0 = 22;      //数码管第一位显示“-”
                                    ydxxx=abs(ydxx);         //取温度下限绝对值
                        SEG1 =ydxxx/100%10;       //百位 计算
                        SEG2 = ydxxx/10%10;    //十位 计算
                        SEG3 = ydxxx/1%10;       //个位 计算
                            DspTemp();      
                              }                              
                else
                           {      
                           ydxxx=ydxx;      
                               SEG0 = ydxxx/1000%10;   //千位计算
                                          if (SEG0==0)
                                           SEG0=23;            //千位为0时 ,消隐不显                                                
                     SEG1 =ydxxx/100%10;       //百位 计算
                     SEG2 = ydxxx/10%10;       //十位 计算
                     SEG3 = ydxxx/1%10;      //个位 计算
                           DspTemp();      
                           }
                                  delay_ms(30);         
                              break;
                  case3:                           //温度校准设置                                                      
                            ydjz++;                     //温度校准加1
                              if( ydjz>= 100)      
                              {
                                    ydjz=-100;
                              }
                           
                            if (ydjz<=0)            //温度校准小于0时         
                                 {
                               SEG0 = 22;               //为负时数码管千位显示“-”               
                                 ydjzx=abs(ydjz);         //取温度校准绝对值
                                 SEG1 =ydjzx/100%10;       //百位 计算
                     SEG2 = ydjzx/10%10;      //十位 计算
                     SEG3 = ydjzx/1%10;    //个位 计算
                           DspTemp();      
                           }                              
                else
                           {      
                            ydjzx=ydjz;      
                              SEG0 = ydjzx/1000%10;   //千位计算
                                        if (SEG0==0)
                                           SEG0=23;            //千位为0时 ,消隐不显      
                        SEG1 =ydjzx/100%10;      //百位 计算
                        SEG2 = ydjzx/10%10;   //十位 计算
                        SEG3 = ydjzx/1%10;    //个位 计算
                            DspTemp();      
                              }
                                  delay_ms(30);         
                              break;                                    
                        default:
                  Set_Mode=0;               
                        }                              
                  delay_ms(50);      
               }                        
                }
if(Down == 0)                        //减少键处理
      {
                SEG0 = 20;            //显示P
                SEG1 = 22;            //显示-
                SEG2 = 22;            //显示-
            SEG3 = Set_Mode;      //显示模式
                DspTemp();                      //显示模式               
            BEEP = 0;                              //打开蜂鸣
                delay_ms(50);                        //延时50ms
            BEEP = 1;                              //关闭蜂鸣      
                delay_ms(50);                        //延时50ms
                while(Down == 0 )
                {
                  switch(Set_Mode)               //选择设置参数               
                        {
                        case1:                     //温度上限设置            
                           ydsx--;                   //温度上限减1
                                 if( ydsx <= -450)      
                               {
                                     ydsx=1200;
                              }
                           delay_ms(10);         
                            if      (ydsx<=0)      //温度上限小于0时   
                                  {
                              SEG0 = 22;      //数码管第一位显示“-”   
                                    ydsxx=abs(ydsx);         //取温度上限绝对值
                                    SEG1 =ydsxx/100%10;      //百位 计算
                        SEG2 = ydsxx/10%10;   //十位 计算
                        SEG3 = ydsxx/1%10;       //个位 计算
                            DspTemp();      
                              }                              
                else
                           {      
                           ydsxx=ydsx;      
                               SEG0 = ydsxx/1000%10;   //千位计算
                                        if (SEG0==0)
                                           SEG0=23;            //千位为0时 ,消隐不显      
                     SEG1 =ydsxx/100%10;      //百位 计算
                     SEG2 = ydsxx/10%10;   //十位 计算
                     SEG3 = ydsx/1%10;       //个位 计算
                           DspTemp();      
                           }
                              break;
                        case2:                           //温度下限设置
                     ydxx--;               //温度下限减1
                              if( ydxx <= -450 )      
                           {
                                 ydxx=1200;
                              }
                            delay_ms(10);         
                            if      (ydxx<=0)       //温度下限小于0时   
                                 {
                               SEG0 = 22;      //数码管第一位显示“-”
                                 ydxxx=abs(ydxx);         //取温度下限绝对值
                     SEG1 =ydxxx/100%10;      //百位 计算
                     SEG2 = ydxxx/10%10;   //十位 计算
                     SEG3 = ydxxx/1%10;       //个位 计算
                           DspTemp();      
                           }                              
                else
                              {      
                           ydxxx=ydxx;      
                               SEG0 = ydxxx/1000%10;   //千位计算
                                        if (SEG0==0)
                                           SEG0=23;            //千位为0时 ,消隐不显         
                     SEG1 =ydxxx/100%10;      //百位 计算
                     SEG2 = ydxxx/10%10;   //十位 计算
                     SEG3 = ydxxx/1%10;       //个位 计算
                           DspTemp();      
                              }
                              break;
                  case3:                           //温度校准设置                                                      
                            ydjz--;               //温度校准减1
                              if( ydjz<= -100)      
                              {
                                     ydjz=100;
                               }
                            delay_ms(10);         
                            if (ydjz<=0)         //温度校准小于0时         
                                  {
                                 SEG0 = 22;
                                     ydjzx=abs(ydjz);         //取温度校准绝对值
                                     SEG1 =ydjzx/100%10;      //百位 计算
                         SEG2 = ydjzx/10%10;   //十位 计算
                         SEG3 = ydjzx/1%10;       //个位 计算
                           DspTemp();      
                              }                              
                else
                           {      
                           ydjzx=ydjz;      
                               SEG0 = ydjzx/1000%10;   //千位计算
                                        if (SEG0==0)
                                           SEG0=23;            //千位为0时 ,消隐不显      
                     SEG1 =ydjzx/100%10;   //百位 计算
                     SEG2 = ydjzx/10%10;   //十位 计算
                     SEG3 = ydjzx/1%10;      //个位 计算
                           DspTemp();      
                           }
                              break;                                    
                        default:
                  Set_Mode=0;
                }
                  delay_ms(50);      
                }      
      }
}
void delay_ms(u16 ms)      //unsigned int
{
      u16 i;
      do
      {
                i = MAIN_Fosc/6000;
                while(--i);
      }while(--ms);
}





小涵子爸爸 发表于 2024-9-28 08:56:43

感谢分享

hjx5548 发表于 2024-12-21 10:44:52

<p>8H1K08替换8G1K08为不能显示?</p>

waqich 发表于 2024-12-22 05:59:41

hjx5548 发表于 2024-12-21 10:44
8H1K08替换8G1K08为不能显示?

8H1K08要独立的ADC参考电压,请查阅8H1K08的数据手册。

xxkj2010 发表于 2024-12-22 09:07:35

<p>很好用的,谢谢分享!</p>

305444337 发表于 2024-12-22 13:17:23

<p>学习了<img alt="baoquan" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/baoquan.gif" title="baoquan" /></p>

hjx5548 发表于 2024-12-22 18:41:24

waqich 发表于 2024-12-22 05:59
8H1K08要独立的ADC参考电压,请查阅8H1K08的数据手册。

参考电压用电源不行吗?

waqich 发表于 2024-12-22 19:40:11

hjx5548 发表于 2024-12-22 18:41
参考电压用电源不行吗?
上电初始会显示1888吗?

waqich 发表于 2024-12-22 19:45:10

不显示则检查SCLSDA 引脚定义,或检查时钟频率

waqich 发表于 2024-12-23 15:37:29

hjx5548 发表于 2024-12-22 18:41
参考电压用电源不行吗?

C1C2不要装
页: [1] 2 3
查看完整版本: 8G1K08-36I-SOP16 做NTC温控器