📄 warter heater_v1.c
字号:
/*---------------------------------
文 件 名: water heater_v1.c
文件说明: 快热式热水器程序
作 者: cjy
时 间: 2008年5月14日 12:36
修改记录:
----------------------------------*/
#include<ht46r24.h>
#define MAX 0
#define MIN 1
#define INT _pd0 //外部中断输出,调试用
#define BELL _pa4 //蜂鸣器控制信号
#define RELAY _pc3 //继电器控制信号
//#define KEY0 _pa6 //要wake up 开下降沿唤醒
#define KEY1 _pa7 //要上拉 关进入睡眠
#define TRIAC _pc4 //光耦控制信号,0时导通
#define RELOAD0_L 0x00
#define RELOAD0_H 0x00
#define RELOAD1_L (65535-2000)%256 //定时2ms
#define RELOAD1_H (65535-2000)/256
//需经过实验测得,温度0点标定,满量程标定
#define N0 226 //温度为0时, 单片机采集的ad模拟量
#define N100 34 //温度为100时,单片机采集的ad模拟量
#define StartAdConversion()\
_start = 0;\
_start = 1;\
_start = 0
#define OpenHeater()\
_emi = 1;\
_eei = 1\
#define CloseHeater()\
_eei = 0;\
_et0i = 0;\
TRIAC = 1\
//函数说明
void SafeguardInit(void);
void ConfigureTimer0(void);
void ConfigureTimer1(void);
void ConfigureAd(void);
void InitPort(void);
unsigned char SampleAd(unsigned char, unsigned char);
unsigned char KeyScan (void);
unsigned char GetWaterTemperature(void);
void Display(unsigned char);
unsigned char WatchWaterTemperature(unsigned char);
void HeaterControl(unsigned char, unsigned char);
void DelayN50ms(unsigned long );
//数码管驱动码
const unsigned char table[] =
{
0x22, // 0
0xFA, // 1
0x16, // 2
0x52, // 3
0xCA, // 4
0x43, // 5
0x03, // 6
0xF2, // 7
0x02, // 8
0x42, // 9
0xFF, // N
0xDF, // -
0x8A, // H
0x07, // E
};
//温度表(单位:摄氏度)
const unsigned char ad_temperature_table[] =
{
0, 0 , 0 , 1 , 1, 1, 2, 2, 2, 3,
3, 4, 5, 5, 6, 6, 7, 8, 8, 9,
9, 10, 10, 11, 11, 12, 12, 13, 13, 14,
14, 15, 15, 16, 16, 17, 17, 18, 18, 19,
19, 20, 20, 20, 21, 21, 22, 22, 23, 23,
24, 24, 25, 25, 26, 26, 26, 26, 27, 27,
28, 28, 28, 29, 29, 30, 30, 30, 31, 31,
32, 32, 32, 33, 33, 34, 34, 34, 35, 35,
36, 36, 36, 37, 37, 38, 38, 38, 39, 39,
39, 40, 40, 41, 41, 41, 42, 42, 43, 43,
43, 44, 44, 45, 45, 45, 46, 46, 47, 47,
47, 48, 48, 49, 49, 49, 50, 50, 51, 51,
52, 52, 52, 53, 53, 54, 54, 55, 55, 55,
56, 56, 57, 57, 58, 58, 59, 59, 60, 60,
61, 61, 62, 62, 62, 63, 63, 64, 64, 65,
66, 66, 67, 67, 68, 68, 69, 69, 70, 70,
71, 72, 72, 73, 73, 74, 75, 75, 76, 77,
77, 78, 79, 79, 80, 81, 81, 82, 83, 84,
84, 85, 86, 87, 88, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100,102,103,
104,105,107
};
//功率控制表
const unsigned char power_table[] =
{
0xdc,0xd7, // 延时9ms触发->1/10 p
0xe0,0xbf, // 延时8ms触发->2/10 p
0xe4,0xa7, // 延时7ms触发->3/10 p
0xe8,0x8f, // 延时6ms触发->4/10 p
0xec,0x77, // 延时5ms触发->5/10 p
0xf0,0x5f, // 延时4ms触发->6/10 p
0xf4,0x47, // 延时3ms触发->7/10 p
0xf8,0x2f, // 延时2ms触发->8/10 p
0xfc,0x17 // 延时1ms触发->9/10 p,延时越短,功率越大
};
//功率档显示灯表,这个需要改 /*PA0-PA2=>3个LED灯
const unsigned char led_table[] =
{
//全灭 全亮
0b11111111,0b11111110,0b11111100,0b11111000
};
const unsigned char sbit[] = {0b111111101,0b11111110};//数码管位选码
//全局变量说明
unsigned char g_power_scale; //功率挡位
unsigned char g_temp[2]; //温度暂存
unsigned char g_count; //计数
void main()
{
unsigned char scale_new = 0; //用户调节的档位
unsigned char scale_old = 0;
unsigned char scale_new_temp= 0;
unsigned char t = 15; //水温初值
unsigned char temov = 0; //超温度标志
bit flag = 1;
//全局变量初始化
g_power_scale = 5; //系统功率初始化值
g_count = 0;
g_temp[0] = 11;
g_temp[1] = 11;
if(_to == 1)
{
_pa3 = 0;//点亮
_pc &= 0b11111100;
_delay(5000);
}
SafeguardInit();
InitPort();
ConfigureTimer0();
ConfigureTimer1();
ConfigureAd();
while(1)
{
if( flag == 1 || KEY1 == 0 || _to == 1)
{
if(KEY1 == 0)
{
BELL = 0;
DelayN50ms(3);
BELL = 1;
}
_pb = 0xff;
_pa0 = 1;//熄灭
_pc &= 0b11111100;
//进入睡眠前所有I/O口处理
_emi = 0;
_halt();
_halt();
BELL = 0;
DelayN50ms(3);
BELL = 1;
}
flag = 0;
_emi = 1;
_t1on = 1;
scale_new_temp = KeyScan();
scale_new = KeyScan();
if(scale_new == scale_new_temp)
{
if(scale_new != scale_old)
{
scale_old = scale_new;
g_temp[0] = scale_old/10;
if(g_temp[0] == 0)g_temp[0] = 14;
g_temp[1] = scale_old % 10;
DelayN50ms(20);
}
HeaterControl(scale_old,temov);
}
t = GetWaterTemperature();//这个所要经过的时间,知道所用时间
g_temp[0] =t/10;
g_temp[1] =t%10;
temov = WatchWaterTemperature(t);
_clrwdt();
}
}
//中断向量
#pragma vector IntExternal @ 0x04
#pragma vector IntTimer0 @ 0x08
#pragma vector IntTimer1 @ 0x0c
#pragma vector IntAd @ 0x10
//外部中断服务程序
void IntExternal()
{
INT = !INT;
_tmr0l = power_table[2*g_power_scale-1]; //可控硅导通延时角
_tmr0h = power_table[2*g_power_scale-2];
_et0i = 1;//中断允许
_t0on = 1;//启动定时器*/
}
//定时器0中断服务程序
void IntTimer0()
{
TRIAC = 0;
_t0on = 0;//停止计数
_et0i = 0;//关定时器中断
_delay(50);
TRIAC = 1;
}
void IntTimer1()
{
_t1on = 0;
_pc |= 0b00000011;//熄灭
_pb = table[g_temp[g_count]];
_pa3 = ( table[g_temp[g_count]] & 0b00000001 == 0x01?1:0 );
_pc &= sbit[g_count];//打开
g_count++;
if(g_count == 2)g_count = 0;
_tmr1l = RELOAD1_L;
_tmr1h = RELOAD1_H;
_t1on = 1;
}
//安全初始化寄存器
void SafeguardInit(void)
{
_intc0 = 0;
_tmr0c = 0;
_tmr0l = 0;
_tmr0h = 0;
_tmr1c = 0;
_tmr1h = 0;
_tmr1l = 0;
_pac = 0xff;
_pbc = 0xff;
_pcc = 0xff;
_pdc = 0xff;
}
//端口初始化程序
void InitPort(void)
{
_pac = 0b00110000;
_pbc = 0b11100000;
_pcc = 0b00000000; //I/O输出
_pa5 = 1; //外部中断口,不能加上拉
//
}
//配置定时器0
void ConfigureTimer0(void)
{
_t0m1 = 1;//定时模式,内部时钟
_t0m0 = 0;
_t0psc2 = 0;// FInt = FSys/4 1Mhz,1us计一个数
_t0psc1 = 1;
_t0psc0 = 0;
_tmr0l = RELOAD0_L;//先写L,在写H
_tmr0h = RELOAD0_H;//
_et0i = 1;//定时器0中断允许
//_t0on = 0;//开启定时器0
}
//配置定时器1
void ConfigureTimer1(void)
{
_t1m1 = 1;//定时模式,内部时钟
_t1m0 = 0;
//时钟源FSys/4Mhz,固定
_et1i = 1;
//_t1on = 0;
}
//配置AD
void ConfigureAd(void)
{
_pcr2 = 0; //PB0-AN0,PB1-AN1,PB0其他IO口
_pcr1 = 1;
_pcr0 = 0;
_adcs1 = 0;//ad转化时钟源为FSys/2
_adcs0 = 0;
//_eadi = 0;
}
//采集通第channel通道ad值n次
unsigned char SampleAd(unsigned char channel, unsigned char n)//n只能在0-20之间, 输入的channel只能在0-7
{
unsigned char i;
unsigned char ad_buffer[20];
unsigned long int total = 0;//除数类型要求,要有初值
ad_buffer[MAX] = 0;
ad_buffer[MIN] = 255;
_adcr &= 0b11111000;//通道选择
_adcr |= channel;
for(i = 0; i < n; i++)
{
//StartAdConversion();
_start = 0;
_start = 1;
_start = 0;
while(_eocb);
total += _adrh;
if(_adrh > ad_buffer[MAX])
{
ad_buffer[i] = ad_buffer[MAX];
ad_buffer[MAX] = _adrh;
}
else if(_adrh < ad_buffer[MIN])
{
ad_buffer[i] = ad_buffer[MIN];
ad_buffer[MIN] = _adrh;
}
else
{
ad_buffer[i] = _adrh;
}
}
total = total - ad_buffer[MAX] - ad_buffer[MIN] ;
return ( total / (n - 2) );
}
//旋钮等级扫描函数
unsigned char KeyScan(void)
{
unsigned char data, power_scale_temp=0;
data = SampleAd(1, 18);//采集通道1
if( data >= 0x00 && data < 0x19)//分界值需要修改
{
power_scale_temp = 0;// 0/10P
}
else if(data <= 0x33)
{
power_scale_temp = 1 ;// 1/10 P
}
else if(data <= 0x4c)
{
power_scale_temp = 2;
}
else if(data <= 0x66)
{
power_scale_temp = 3;
}
else if(data <= 0x80)
{
power_scale_temp = 4;
}
else if(data <= 0x99)
{
power_scale_temp = 5;
}
else if(data <= 0xb3)
{
power_scale_temp = 6;
}
else if(data <= 0xcc)
{
power_scale_temp = 7;
}
else if(data <= 0xe6)
{
power_scale_temp = 8;
}
else if(data <= 0xff)
{
power_scale_temp = 9;
}
return (power_scale_temp);//返回用户调节的加热功率档位
}
//加热控制程序
void HeaterControl(unsigned char power_scale_temp, unsigned char temov)
{
if(power_scale_temp == 0 || temov == 1 )//档位为0或温度超出,关闭,熄灭
{
CloseHeater();
// _p = led_table[0];//熄灭档位, 需要修改
}
else
{
g_power_scale = power_scale_temp;//设置加热档位
OpenHeater();
//_pc = led_table[power_scale_temp];//显示档位,需要修改
}
}
//动态扫描函数
//测量水温函数
unsigned char GetWaterTemperature(void)
{
unsigned char data, t;
data = SampleAd(0, 10);
t = ad_temperature_table[N0 -data];
return t;
}
//监控水温函数
unsigned char WatchWaterTemperature(unsigned char t)
{
unsigned char temov;
if(t > 65)
{
CloseHeater();
BELL = 0;
temov = 1;//置超温标志
}
else if( t < 45)
{
BELL = 1;
temov = 0;
}
return temov;
}
void DelayN50ms(unsigned long n )
{
unsigned long i;
for(i = 0; i < n; i++)
{
_delay(50000);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -