- 打卡等级:以坛为家I
- 打卡总天数:302
- 最近打卡:2025-05-02 05:18:21
已绑定手机
高级会员
- 积分
- 972
|
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制热模式
u8 Set_Mode =0; //0-8 模式几 0:没有模式
bit TIM_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[24]={ //数码管共阴真值表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#";
int e, Temp; //Temp ADC转换数值
int TempVal,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[8] = { 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]);//数码管千位上电显示1
tm1650_ack();
tm1650_end();
tm1650_start();
write_byte(0x6a);
tm1650_ack();
write_byte(Num_Buff[8]);//数码管百位上电显示8
tm1650_ack();
tm1650_end();
tm1650_start();
write_byte(0x6c);
tm1650_ack();
write_byte(Num_Buff[8]); //数码管十位上电显示8
tm1650_ack();
tm1650_end();
tm1650_start();
write_byte(0x6e);
tm1650_ack();
write_byte(Num_Buff[8]); //数码管个位上电显示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) //选择设置参数
{
case 1: //温度上限设置
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;
case 2: //温度下限设置
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;
case 3: //温度校准设置
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) //选择设置参数
{
case 1: //温度上限设置
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;
case 2: //温度下限设置
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;
case 3: //温度校准设置
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
{
Ntc测温.7z
(236.16 KB, 下载次数: 133)
i = MAIN_Fosc/6000;
while(--i);
}while(--ms);
}
|
|