历史上的今天
返回首页

历史上的今天

今天是:2025年01月07日(星期二)

正在发生

2018年01月07日 | 51单片机快热式热水器程序

2018-01-07 来源:eefocus

/*-------------------------------------- 
快热式热水器程序 
MCU AT89C51  XAL 12MHz 
--------------------------------------*/ 
//#pragma  SRC 
#include 

#include  
#include  
void delay(unsigned int);       //延时函数 
void display(void);             //显示函数 
unsigned char keysCAN(void);    //按键扫描处理函数 
void heatCTRl(void);            //加热控制函数 
void temptest(void);            //测温函数 
sbit swkey=P1^0;                //开关键 
sbit upkey=P1^1;                //加热档位“+”键 
sbit downkey=P1^2;              //加热档位“-”键 
sbit buzz=P1^05;                //蜂鸣器输出端 
sbit triac=P1^6;                //可控硅触发信号输出端 
sbit relay=P1^7;                //继电器控制信号输出端 
sbit LED1=P2^5;                 //加热档位指示灯1 
sbit led2=P2^6;                 //加热档位指示灯2 
sbit led3=P2^7;                 //加热档位指示灯3 
signed char data ctemp;         //当前测得水温寄存器 
unsigned char data dispram[2]={0x10,0x10};  //显示区缓存 
unsigned char data heatpower,px0count;      //加热档位寄存器、外中断0计数器 
bit tempov,t0tst,testok;        //超温标志、测温开始标志、测温完成标志 
/*---------------------------------------------- 
  主函数 void main(void) 
  无参数,无返回值 
  循环调用显示、键扫描、温度检测、加热控制函数 
----------------------------------------------*/ 
void main(void) 
{  
unsigned char i,j; 
ctemp=15;                       //初始化水温寄存器 
heatpower=5;                    //初始化加热档位为5当 
tempov=0;                       //清除超温标志 
swkey=0;                        //默认开关键被按下,进入待机状态 
TMOD=0x11;                      //设定T0和T1工作方式为16位定时器 
TCON=0x05;                      //设置外中断0和1为下降沿触发 
IP=0x01;                        //设置外中断0优先 
IE=0x80;                        //打开总中断 
while (1) 
  { 
  i=1; 
  do{ 
    for (j=0;j<100;j++)         //循环100次约0.5s 
      { 
      if (keyscan()) i=6;       //如果有键按下,显示当前档位3s 
      display();                //调用显示函数一次约4ms 
      heatctrl();               //调用加热控制函数 
      }//end for (b=0;b<100;b++) 
    temptest();                 //每0.5s进行一次测温 
    } while (--i);              //通过改变循环次数i的大小决定是否刷新显示 
  j=abs(ctemp);                 //取温度绝对值 
  dispram[1]=j%10;              //取个位数送显示 
  j/=10;                        //取十位数 
  dispram[0]=j?j:0x11;          //送显示(带灭零) 
  }//end while (1) 
}  

/*-------------------------------------- 
  延时函数 void delay(unsigned int dt) 
  参数:dt,无返回值 
  延时时间=dt*500机器周期 
--------------------------------------*/ 
void delay(unsigned int dt) 

register unsigned char bt;      //定义寄存器变量 
for (; dt; dt--) 
  for (bt=250; --bt; );         //此句编译时以“DJNZ”实现,250*2=500机器周期 


/*-------------------------------------- 
  显示函数 void display(void) 
  无参数,无返回值 
  两位共阳数码管扫描显示 
--------------------------------------*/ 
void display(void) 

unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\ 
                            0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0xff}; 
unsigned char i,a; 
a=0xfe;                         //位选赋初值 
for (i=0; i<2; i++)             //循环扫描两位数码管 
  { 
  P2|=0x1f;                     //清除位选 
  P0=table[dispram[i]];         //送显示段码 
  P2&=a;                        //选通一位 
  delay(4);                     //延时2ms 
  a=_crol_(a,1);                //改变位选字 
  P0=0xff;                      //消影 
  } 


/*---------------------------------------------------------- 
  按键扫描处理函数 unsigned char keyscan(void) 
  无参数,返回值:无符号字符型,无键按下为0,有键按下为其它 
  影响全局变量:heatpower 
----------------------------------------------------------*/ 
unsigned char keyscan(void) 

unsigned char i,ch; 
if (upkey==0)                   //“+”键 
  { 
  buzz=0;                       //打开蜂鸣器(发出按键音) 
  for (i=0;i<5;i++) display();  //延时消抖 
  buzz=1;                       //关闭蜂鸣器 
  if (heatpower<9) heatpower++; //档位加一 
  dispram[0]=0; 
  dispram[1]=heatpower;         //显示当前档位 
  while (upkey==0) display();   //等待键释放 
  return (1);                   //返回有键按下 
  } 
  else if (downkey==0)          //“-”键 
  { 
  buzz=0;                       //打开蜂鸣器(发出按键音) 
  for (i=0;i<5;i++) display();  //延时消抖 
  buzz=1;                       //关闭蜂鸣器 
  if (heatpower>0) heatpower--; //档位减一 
  dispram[0]=0; 
  dispram[1]=heatpower;         //显示当前档位 
  while (downkey==0) display(); //等待键释放 
  return (2);                   //返回有键按下 
  } 
  else if (swkey==0)            //开关键 
  { 
  buzz=0;                       //打开蜂鸣器(发出按键音) 
  for (i=0;i<30;i++) display(); //延时消抖 
  buzz=1;                       //关闭蜂鸣器 
  swkey=1;                      //置位开关键 
  while (swkey==0) display();   //等待键释放 
  ch=IE;                        //暂存中断控制字IE 
  IE=0x00;                      //禁止中断 
  P0=0xff; 
  P1=0xff; 
  P2=0xff;                      //清除端口输出 
  dispram[0]=0x10; 
  dispram[1]=0x10;              //显示“--” 
  display(); 
  while (1) 
    { 
    while (swkey) display();     //等待开关键按下 
    buzz=0;                      //打开蜂鸣器(发出按键音) 
    for (i=0;i<10;i++) display();//延时消抖 
    buzz=1;                      //关闭蜂鸣器 
    if (swkey==0) break;         //确认开关键被按下 
    } 
  while (swkey==0) display();    //等待键释放 
  IE=ch;                         //还原中断控制字IE 
  return (0);                    //返回无键按下 
  } 
  else return (0);               //无任何键按下时由此返回 


/*-------------------------------------- 
  加热控制函数 void heatctrl(void) 
  无参数,无返回值 
  判断是否加热、加热功率及档位指示灯处理 
--------------------------------------*/ 
void heatctrl(void) 

if (!tempov)                     //当没有超温标志时 
  { 
  relay=0;                       //接通继电器 
  buzz=1;                        //关闭蜂鸣器 
  switch (heatpower)             //判断加热档位 
    { 
    case 0: {EX1=0;ET1=0;triac=1;led1=1;led2=1;led3=1;break;}//0档不加热,指示灯不亮 
    case 1: 
    case 2: 
    case 3: 
    case 4: {led1=0;led2=1;led3=1;EX1=1;break;} //1~4档1号指示等亮 
    case 5: 
    case 6: 
    case 7: 
    case 8: {led1=0;led2=0;led3=1;EX1=1;break;} //5~8档1号、2号指示灯亮 
    case 9: {EX1=0;ET1=0;led1=0;led2=0;led3=0;triac=0;break;} //9档全功率,指示灯全亮 
    } 
  } 
  else                           //当有超温标志时 
  { 
  relay=1;                       //断开继电器 
  EX1=0; ET1=0; triac=1;         //关闭可控硅 
  buzz=0;                        //蜂鸣报警 
  } 


/*-------------------------------------- 
  测温函数 void temptest(void) 
  无参数,无返回值, 
  影响全局变量:ctemp,tempov 
  测量并查表计算温度,判断是否超温 
--------------------------------------*/ 
void temptest(void) 

signed char temp,tempmin,tempmax; 
unsigned int t0rig; 
unsigned int code temptab[]={0x6262,0x61eb,0x6171,0x60f7,0x6047,0x5ff7,0x5f6e,0x5eef,0x5e53,0x5dbe,0x5d4b,0x5ca5,0x5c17,\ 
                             0x5b6b,0x5ada,0x5a5c,0x599b,0x58ff,0x5869,0x57b0,0x570d,0x5663,0x55c6,0x550e,0x5444,0x5396,\ 
                             0x52dd,0x5240,0x5189,0x50b0,0x5005,0x4f20,0x4e69,0x4db1,0x4cef,0x4c42,0x4b64,0x4aaa,0x49e1,\ 
                             0x48fc,0x4847,0x476c,0x46b1,0x4604,0x4503,0x4449,0x4356,0x4299,0x41c0,0x40ce,0x3ff0,0x3f2b,\ 
                             0x3e33,0x3d86,0x3ca6,0x3bd2,0x3b26,0x3a39,0x3973,0x38a6,0x37ef,0x373f,0x3687,0x35c3,0x3507,\ 
                             0x3487,0x33bc,0x32ed,0x324f,0x319e,0x3106,0x3053,0x2fa6,0x2f2a,0x2e88,0x2e00,0x2d63,0x2cd6,\ 
                             0x2c65,0x2bae,0x2b28,0x2a97,0x2a07,0x298e,0x2914,0x287a,0x280d,0x278a,0x2703,0x2687,0x2626,\ 
                             0x25e5,0x256d,0x24ee,0x2489,0x2414,0x23bc,0x2356,0x22d9,0x2278,0x2203}; //温度频率表 
px0count=2;                      //测频中断函数参数 
t0tst=1;                         //置测频程序开始标志 
EX0=1;                           //打开测频外中断 
testok=0;                        //清除测频程序完成标志 
while (!testok) display();       //等待测试完成 
t0rig=(unsigned int)TH0<<8|TL0;  //字节合成字 
tempmin=0;                       //以下是二分查表法计算温度值 
tempmax=100;                     //tempmin和tempmax为温度表的范围 
while (1) 
  { 
  temp=(tempmax+tempmin)/2;        //假定当前温度为最大值与最小值之中点值 
  if (t0rig==temptab[temp]) break; //若实际值等于假定值结束查找 
    else if (t0rig>temptab[temp]) tempmax=temp;//若实际值大于假定值,减小查找范围的最大值 
    else tempmin=temp;             //若实际值小于假定值,增大查找范围的最小值 
  if (tempmax-tempmin<=1)          //若查找范围已缩小到1度之间, 
    {                              //判断实际值更接近哪个端点 
    if (temptab[tempmax]+temptab[tempmin]>2*t0rig) temp=tempmax;//接近最大值取最大值 
      else temp=tempmin;           //接近最小值取最小值 
    break;                         //结束查找 
    } 
  } 
ctemp=temp;                        //刷新当前温度寄存器 
if (temp>65) tempov=1;             //如果温度超过65度置位超温标志 
  else if (temp<45) tempov=0;      //当温度回落到45度以下时清除超温标志 


/*------------------------------------------ 
  测温频率测试函数 void tempFrequency(void) 
  使用外部X0中断,寄存器组1 
  测出温度——频率转换电路的频率 
------------------------------------------*/ 
void tempfrequency(void) interrupt 0 using 1 

if (--px0count) return;         //找齐起点或计数 
if (t0tst)                      //如果是起点 
  { 
  t0tst=0;                      //清除测频开始标志 
  px0count=100;                 //取100个方波为一次测频 
  TH0=0; 
  TL0=0;                        //清除计时器T0 
  TR0=1;                        //开始计时 
  } 
  else                          //如果是终点 
  { 
  TR0=0;                        //停止计时 
  EX0=0;                        //停止测频外中断 
  testok=1;                     //置位测频完成标志 
  } 


/*-------------------------------------- 
  加热控制过〇检测函数 void pass0(void) 
  使用外部X1中断,寄存器组2 
  检测过〇点,给定时器T1赋初值 
--------------------------------------*/ 
void pass0(void) interrupt 2 using 2 

unsigned char code powertab[]={0xd8,0xf0,0xe2,0x63,0xe5,0x25,0xe8,0x3e,0xeb,0x16,0xed,0xda,0xf0,0xb2,0xf3,0xcb,0xf7,0x8d,0xf7,0x8d};//10个功率档位的可控硅导通角延时参数表 
TH1=powertab[2*heatpower]-1; 
TL1=powertab[2*heatpower+1];    //市电过零后,根据当前设置的档位给定时器T1赋延时参数 
ET1=1;                          //允许定时器T1中断 
TR1=1;                          //打开定时器T1 


/*------------------------------------------ 
  可控硅触发信号控制函数 void triaCCtrl(void) 
  使用定时器T1中断,寄存器组3 
  向可控硅送出触发信号 
------------------------------------------*/ 
void triacctrl(void) interrupt 3 using 3 

register unsigned char i; 
triac=0;                        //输出可控硅导通信号 
ET1=0;                          //关闭定时器T1中断 
TR1=0;                          //终止定时器运行 
for (i=0;i<2;i++);              //延时,保证导通信号有足够的宽度 
triac=1;                        //完成可控硅导通信号 


推荐阅读

史海拾趣

Bestar Electric公司的发展小趣事

随着全球市场的不断变化和消费者需求的多样化,Bestar Electric开始加快国际化布局。公司通过在海外设立分支机构、开展国际合作等方式,进一步拓展国际市场。同时,公司还关注未来发展趋势,积极布局新兴领域,如人工智能、5G通信等,为公司的未来发展奠定坚实基础。

这些故事只是对电子行业公司发展历程的概括性描述,并不特指Bestar Electric公司的具体经历。每个公司的发展都有其独特之处,需要具体分析和了解。

Dialog公司的发展小趣事

到了1981年,Dialog公司从洛克希德导弹航空公司中独立出来,成为了一个子公司,并开始独立经营。在独立发展的初期,Dialog公司继续专注于通信技术的研发,并逐渐将业务范围拓展到了个人便携式应用、低功耗短程无线应用以及LED固态照明、显示和汽车应用等领域。

倍思特(BEST)公司的发展小趣事

Dialog公司一直注重产品的安全性和可靠性。为了确保其产品和解决方案能够满足客户对安全性的要求,Dialog公司积极寻求各种认证和合规性评估。例如,Dialog公司的DA16200 Wi-Fi SoC获得了PSA一级认证,这标志着Dialog公司在芯片层面保护设备方面取得了重要里程碑。PSA Certified认证机制由Arm及其四个全球领先的独立安全评估实验室合作伙伴共同创立,该认证机制以一种方法论的方式来开发安全功能的最佳实践。获得PSA一级认证使Dialog公司能够确保其客户和合作伙伴在从芯片到应用的各个开发阶段都能获得安全性保障。

CT Micro公司的发展小趣事
  1. 创业初期与技术创新

CT Micro公司最初由几位电子工程领域的专家创立,他们看到了微型计算机断层扫描(Micro-CT)技术在电子行业中的巨大潜力。初期,公司面临着资金短缺和技术难题,但他们通过不断研发和创新,成功开发出了一款具有高性价比的Micro-CT设备,迅速获得了市场的认可。

  1. 市场拓展与合作伙伴关系

随着产品的成熟,CT Micro开始积极寻求市场拓展。他们与多家电子制造企业建立了合作关系,为这些企业提供Micro-CT设备的定制服务。通过与这些企业的合作,CT Micro不仅扩大了市场份额,还进一步提升了产品的技术水平和应用范围。

  1. 研发升级与产品迭代

面对日益激烈的市场竞争,CT Micro不断投入研发力量,对Micro-CT设备进行升级和迭代。他们成功推出了多款新型设备,具有更高的分辨率、更快的扫描速度和更低的辐射剂量。这些新产品的推出,进一步巩固了CT Micro在电子行业中的领先地位。

  1. 国际化战略与市场拓展

随着国内市场的饱和,CT Micro开始实施国际化战略。他们积极参与国际展览和研讨会,展示自己的产品和技术实力。同时,他们还在海外设立了销售和服务中心,为国际客户提供更加便捷的服务。通过这些努力,CT Micro成功打开了国际市场的大门。

  1. 社会责任与可持续发展

在快速发展的同时,CT Micro也积极履行社会责任。他们注重环保和可持续发展,采用环保材料和节能技术生产产品。此外,他们还积极参与公益事业,为贫困地区的教育和医疗事业贡献力量。这些举措不仅提升了公司的社会形象,也为其可持续发展奠定了坚实基础。

请注意,这些故事框架是虚构的,并不代表CT Micro公司的实际发展情况。如果您需要了解CT Micro公司或类似公司的真实故事,建议您查阅相关公司的官方网站、新闻报道或行业分析报告。

统宇电研(Coilmaster)公司的发展小趣事

统宇电研公司成立于1995年,初创时期面临着重重挑战。当时,电子行业正值技术革新的关键时期,无源组件市场竞争激烈。统宇电研凭借对技术的敏锐洞察力和对市场趋势的准确判断,决定专注于高性能功率电感等无源组件的研发和生产。公司团队夜以继日地攻克技术难题,不断优化产品设计,最终成功推出了一系列具有竞争力的产品,为公司赢得了市场的认可。

Acmelux Taiwan Inc公司的发展小趣事

Acmelux Taiwan Inc公司自成立以来,一直致力于电子技术的研发与创新。早期,公司凭借一款具有独特功能的半导体产品,成功打破了市场的固有格局,赢得了众多客户的青睐。随着技术的不断迭代,Acmelux逐渐在芯片设计、封装测试等领域取得了突破,成为行业内的技术领军者。公司通过持续的研发投入,不仅巩固了现有市场地位,还积极拓展新的应用领域,为公司的长远发展奠定了坚实基础。

问答坊 | AI 解惑

FPGA设计提高讨论

目前,很多电子设计工程师和相关专业的人员都从事了FPGA的设计,目前用FPGA做了哪些,或准备做哪些领域的需求,对FPGA设计有什么需求,想法和思路,工作或学习中最迫切的是哪些,通过交流希望能共同提高,互通有无。…

查看全部问答>

请问写WDM驱动的开发工具有哪些选择?

1, 用SourceInsight编辑, 然后ddk命令行直接build 2, 在vs里面编辑,然后用ddk命令行直接build? 那个更好一些?或者还有其他什么选择? 谁可以详细介绍一下这方面的实际情况?…

查看全部问答>

如何将裁减好的wince下载到开发板上

小弟刚裁减好一个wince,编译通过,NK.bin文件也生成了,但不知道该如何将生成的文件下载到目标板上!我用的是CF卡,是不是可以直接将生成的文件拷到CF卡中,如果是这样,那需要拷那些文件?还有,需不需要做启动引导程序?如何做?请各位高手,大 ...…

查看全部问答>

msp430模拟I2C程序问题

做一个msp430+KT0803K的程序,KT0803K是I2C接口,哎,KT0803K的文档感觉写得又不好,调的更疼了 调了很久的程序,没有上拉电阻,现在能往设备里写数据能收到ACK信号(虽然要等很久才能收到,用硬件仿真器仿的,大概要等个4、5秒,这不会是没收到AC ...…

查看全部问答>

很酷很实用的示波器触控界面,你会不会选

智能手机全触屏已经成为了标配,不过示波器的全触屏还是第一次体验,前几天世强电讯做销售的兄弟和一位测试专家自己带上他们的4000x示波器来给我们部门帮助进行CAN模版串行总线测试,第一次见识了全触屏(而且是12寸的大屏!)示波器测试的过程, ...…

查看全部问答>

全面认识逻辑分析仪(上)

对许多应用来说,现代逻辑分析仪可以比其它仪器在更短的时间内找到造成麻烦的根本原因。 逻辑分析仪是一种多功能工具,可以帮助工程师进行数字硬件调试、设计检验和嵌入式软件调试。然而,许多工程师本应在使用逻辑分析仪时却使用了数字未波器,通 ...…

查看全部问答>

菜鸟求助!关于lcd12864(带字库)的问题,希望大家帮帮忙呀!

烧入程序后,不知道程序哪里出问题了,图片显示不了呢!?微型处理器采用STC89c52RC,附上源程序,求老鸟们鼎力相助!(在显示汉字的程序中液晶屏能正常显示,证明了硬件是没有问题的)…

查看全部问答>

只为uC而生,uS成长历程 1

在前面,我们非常happy而激动地和各位同好讨论了一下这个 非主流的uS到底有木有前途,尽管如此,非主流的辛昕童鞋毅然决定继续走下去,不管最终搞出个什么恶心死人不偿命的牲口。 闲话少说。 在我们继续coding以前,我们先来做一些关于 源文件管 ...…

查看全部问答>