温控风扇的代码(开源) 新手写代码

  最近为了练习51单片机,便做了一个温控风扇的项目。

  先说一下温控风扇的功能吧,对于我来说,已经接触51单片机已经有一年的时间了,可是真正的开始做东西,却没有多长时间。我之前只是用51做过一个光立方。而光立方的代码却十分的简单(只是简单的光立方,,没有涉及更加复杂的原理,,,像神马傅里叶变换,,神马高大上的东西,,,我还是先学好高数吧),只是用了个74HC573进行锁存进而位控制。。。。。从这说起来,光立方基本都是队友焊接的,,我只是一个编程者(苦逼的程序员),而光立方也没有做的多么完美,但是已经尽力了,当时只接触51一个月便做完了光立方。

  最近因为一个比赛而接触了温控风扇,当时,,比赛没做出来(我实在是还太水),于是把未完成品带回去继续做,把上面的基本要求加拓展要求基本都做了出来,,唉 ,硬件调试的例程可真是艰辛啊,,代码更不用提  唉  ,说多了鼻子一把泪一把的。。好了,不扯太多东西,进入正题。

  此温控风扇的功能:大体来说,分为以下几类:1,电机驱动(不用多说)2,LCD1602(咦,这是做神马的?不用急,下面会提到)3,DS18B20(哎呀,温控啊温控,说实话,这个时序图到现在还没记住,哎呀,只能靠现查了,再copy一下别人的例程修改一下啦),,,,,,有点懒,,但是都看懂啦,也会修改啦。4,红外遥控器加发射器。。。唉,这个红外遥控从一开始到明白可是耗费了我一年的时间啊。5,蜂鸣器,,额外功能,没打算加了。

好了,开始贴贴代码啦啦啦~~~~~~~~~~~~~~~~~~~~~~~~~~·

#include
#include "18B20.h"
#define e P0 //LCD1602的D0~D7    
/***************************************************************************** 
* TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256;         * 
* TH0=(65536-C)/256,其中C为所要计数的次数即多长时间产生一次中断;TMOD是计数器* 
* 工作模式选择,0X01表示选用模式1,它有16位计数器,最大计数脉冲为65536,最长时 * 
* 间为1ms*65536=65.536ms                                                     * 
******************************************************************************/ 
#define V_TH0  0x0FC                  
#define V_TL0   0x18                  
#define V_TMOD 0X01 
#define T25 250
#define T30 300
#define T35 350
#define T40 400
sbit lcden=P1^4;//使能端
sbit lcdrs=P1^2;//读写选择端
sbit lcdrw=P1^5;//读写选择端
uchar num;
int result;
bit IrOK;
unsigned char IrValue[6];
unsigned char Time;
void IrInit();
void hongwai();
void deal(uint);
unsigned char ZKB1,ZKB2,ZKB3; 
sbit K1=P2^3;
sbit K2=P2^7;
sbit K3=P2^6;  
sbit K4=P2^5;    
void init_sys(void);            /*系统初始化函数*/ 
void delay(uint z);
sbit IRIN = P3^2;
//--定义全局变量--//
void jiema();
//--声明全局函数--//
extern void DelayMs(unsigned int );
sbit dianji=P1^1; 
/*******************************************************************************
* 函数名         : main
* 函数功能   : 主函数
* 输入           : 无
* 输出         : 无
*******************************************************************************/
/*******************************************************************************
* 函数名         : LCD延时
* 函数功能   : 延时
* 输入           : z
* 输出         : 无
*******************************************************************************/
void delay_lcd(uchar z)
{
uint x,y;
for(x=z;x>0;x--)
 {
  for(y=110;y>0;y--);
 }
}
void write_com(uint com)//写命令
{  
    lcden=0;  
lcdrw=0;
lcdrs=0;

e=com;
delay_lcd(5);
lcden=1;
delay_lcd(5);
lcden=0;
}
void init()//进行初始化
{
lcden=0;
write_com(0x3c);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
void write_data(uint date)//写数据
{
    lcden=0;
    lcdrw=0;
 lcdrs=1;
 e=date;
 delay_lcd(15);
 lcden=1;
 delay_lcd(15);
 lcden=0;
}
/*******************************************************************************
*函数名         :红外遥控
*函数功能       :红外遥控
*输入           ;无
*输出           ; 无                                                              
**********************************************************************************/


void hongwai()
{
   dianji=0;
// unsigned char i;
IrInit();
}  
/*******************************************************************************
* 函数名         : DelayMs()
* 函数功能   : 延时
* 输入           : x
* 输出         : 无
*******************************************************************************/


void DelayMs(unsigned int x)   //0.14ms误差 0us
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++)
{}
}
}
/*******************************************************************************
* 函数名         : IrInit()
* 函数功能   : 初始化红外线接收
* 输入           : 无
* 输出         : 无
*******************************************************************************/


void IrInit()
{
IT0=1;//下降沿触发
EX0=1;//打开中断0允许
EA=1; //打开总中断
IRIN=1;//初始化端口
}
/*******************************************************************************
* 函数名         : ReadIr()
* 函数功能   : 读取红外数值的中断函数
* 输入           : 无
* 输出         : 无
*******************************************************************************/


void ReadIr() interrupt 0
{
unsigned char j,k;
unsigned int err;
uchar code LCD_hongwai[]="B 0123456789";//hongwai
Time=0;  
DelayMs(70);


if(IRIN==0) //确认是否真的接收到正确的信号
{  

err=1000; //1000*10us=10ms,超过说明接收到错误的信号
/*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
侯,程序死在这里*/
while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去  
{
DelayMs(1);
err--;

if(IRIN==1) //如果正确等到9ms低电平
{
err=500;
while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
{
DelayMs(1);
err--;
}
for(k=0;k<4;k++) //共有4组数据
{
for(j=0;j<8;j++) //接收一组数据
{


err=60;
while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
{
DelayMs(1);
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
DelayMs(1);//0.14ms
Time++;
err--;
if(Time>30)
{
EX0=1;
return;
}
}
IrValue[k]>>=1; //k表示第几组数据
if(Time>=8) //如果高电平出现大于565us,那么是1
{
IrValue[k]|=0x80;
}
Time=0; //用完时间要重新赋值
}

}
}
if(IrValue[2]!=~IrValue[3])
{
IrOK=0;
return;
}
else
{
 IrOK=1; 
 if (IrValue[2]==0x08)
        {
 write_com(0x80);
 write_data(LCD_hongwai[0]);
     delay(5); 
 write_data(LCD_hongwai[1]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_bai]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_shi]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_ge]);
     delay(5); 
 result=ZKB1;
}
  else if(IrValue[2]==0x18)
   {
 write_com(0x80);
 write_data(LCD_hongwai[0]);
     delay(5); 
 write_data(LCD_hongwai[1]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_bai]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_shi]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_ge]);
     delay(5); 
 result=ZKB2;
}
  else if(IrValue[2]==0x0C)
  {
     write_com(0x80);
 write_data(LCD_hongwai[0]);
     delay(5); 
 write_data(LCD_hongwai[1]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_bai]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_shi]);
     delay(5); 
 write_data(LCD_hongwai[2+temp_ge]);
     delay(5); 
result=ZKB3;
   }
 else 
   {
 
 dianji=0;
}

}  
IrOK=0;
  
}

}
void main (void) 

     uchar code LCD[]="0123456789";
uchar code LCD_anjian1[]="A1 0123456789";//ZKB1
uchar code LCD_anjian2[]="A2 0123456789";//ZKB2
uchar code LCD_anjian3[]="A3 0123456789";//ZKB3
uchar code LCD_anjian4[]="A4 0123456789";//稳控
     uchar code LCD_hongwai[]="B 0123456789";//hongwai
     init();
     hongwai();
Init_DS18B20();
ReadOneChar();
WriteOneChar(dat);
ReadTemperature();
     ZKB1=30;            /*占空比初始值设定*/ 
     ZKB2=0;
     ZKB3=90;   
init_sys();
temp_broken();
while(1)
{  
if(K1==0)
  delay(20);
  if(K1==0)
     {
result=ZKB1;
write_com(0x80);
write_data(LCD_anjian1[0]);
   delay(5); 
write_data(LCD_anjian1[1]);
   delay(5); 
write_data(LCD_anjian1[2]);
   delay(5); 
write_data(LCD_anjian1[3+temp_bai]);
   delay(5); 
write_data(LCD_anjian1[3+temp_shi]);
   delay(5); 
write_data(LCD_anjian1[3+temp_ge]);
   delay(5); 


}
     if(K2==0)
  delay(20);
  if(K2==0)
     {
  result=ZKB2;
   write_com(0x80);
  write_data(LCD_anjian2[0]);
   delay(5); 
write_data(LCD_anjian2[1]);
   delay(5); 
write_data(LCD_anjian2[2]);
   delay(5); 
write_data(LCD_anjian2[3+temp_bai]);
   delay(5); 
write_data(LCD_anjian2[3+temp_shi]);
   delay(5); 
write_data(LCD_anjian2[3+temp_ge]);
   delay(5); 
}
    if(K3==0)
 delay(20);
 if(K3==0)
    {
  result=ZKB3;
   write_com(0x80);
  write_data(LCD_anjian3[0]);
   delay(5); 
write_data(LCD_anjian3[1]);
   delay(5); 
write_data(LCD_anjian3[2]);
   delay(5); 
write_data(LCD_anjian3[3+temp_bai]);
   delay(5); 
write_data(LCD_anjian3[3+temp_shi]);
   delay(5); 
write_data(LCD_anjian3[3+temp_ge]);
   delay(5); 
}
delay(20);
    if(K4==0)
 delay(20);
if(K4==0)
{
   deal(temp);
   write_com(0x80);
   write_data(LCD_anjian4[0]);
   delay(5); 
write_data(LCD_anjian4[1]);
   delay(5); 
write_data(LCD_anjian4[2]);
   delay(5); 
write_data(LCD_anjian4[3+temp_bai]);
   delay(5); 
write_data(LCD_anjian4[3+temp_shi]);
   delay(5); 
write_data(LCD_anjian4[3+temp_ge]);
   delay(5); 
}  
     }
             /*占空比初始值设定*/ 
/*对占空比值限定范围*/ 
}
/****************************************************** 
*函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/ 
void init_sys(void)            /*系统初始化函数*/ 

  /*定时器初始化*/ 
    TMOD=V_TMOD; 
    TH0=V_TH0; 
    TL0=V_TL0; 
    TR0=1;//开启定时器计数 
    ET0=1;// 开启定时器中断
    EA=1;//开启总中断 



/*中断函数*/ 
void timer0(void) interrupt 1 using 2 

    uchar click=0;                  /*中断次数计数器变量*/ 
    TH0=V_TH0;                                    /*恢复定时器初始值*/ 
    TL0=V_TL0; 
    ++click; 
    if (click>=100)
    click=0; 


    if (click       dianji=1; 
    if(click>=result)
       dianji=0; 
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void deal(uint t)
{

if((t>T25)&&(t{
result=ZKB1;
}
if((t>T30)&&(t{
result=ZKB3;
}
if((t>T35)&&(t{
result=ZKB3;
}
else
dianji=0;

}

也许你会说,,,,咦,,,,18B20.H呢???????????哎呀  别急  继续贴啦啦~~~~~~~~

#ifndef _18B20_H_
#define _18B20_H_
#define uchar unsigned char 
#define uint unsigned int 
int readdata[2];
uint temp_shi,temp_ge,temp_bai;
uint temp,dat;
float f_temp;
sbit DQ=P3^4; 
void delay_18B20(uint i)
{
  while(i--);

/**********ds18b20初始化函数**********************/
void Init_DS18B20(void)
{  
  unsigned char x=0;  
DQ = 1;          //DQ复位 
  delay_18B20(2); //稍做延时 
DQ = 0;          //单片机将DQ拉低 
delay_18B20(60); //精确延时 大于 480us 
DQ = 1;          //拉高总线
delay_18B20(2); 
x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 
delay_18B20(15); 
}
/***********ds18b20读一个字节**************/ 
unsigned char ReadOneChar(void)
{  
unsigned char i=0; 
unsigned char dat = 0; 
for (i=8;i>0;i--) 
{
DQ = 0; // 给脉冲信号     
dat>>=1;   
DQ = 1; // 给脉冲信号  
if(DQ)    
dat |=0x80;  
delay_18B20(4); 
}   
  return(dat); 
}
/*************ds18b20写一个字节****************/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;   
for (i=8; i>0; i--)  
  {   
    DQ = 0;   
  DQ = dat&0x01; 
  delay_18B20(2);  
  DQ = 1;     
  dat>>=1;  
  }
}
ReadTemperature(void)
{  
delay_18B20(40);       // this message is very important 
Init_DS18B20(); 
delay_18B20(1);
WriteOneChar(0xCC);    // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换  
delay_18B20(40);       // this message is very important
Init_DS18B20();  
WriteOneChar(0xCC); //跳过读序号列号的操作  
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度  
delay_18B20(40);       
readdata[0]=ReadOneChar();    //读取温度值低位 
readdata[1]=ReadOneChar();      //读取温度值高位
  temp=readdata[1];
  temp<<=8;
  temp=temp|readdata[0];
  f_temp=temp*0.0625;
  temp=f_temp*10+0.5;
  f_temp=f_temp+0.05;
  return temp;
}
void temp_broken() //将temp分成个位和十位还有百位
{
  temp_bai=temp/100;  
  temp_shi=temp%100/10;
  temp_ge=temp%100%10;
}


#endif

这些程序中存在有一些问题,就是代码的效率问题,代码的效率不够高,数据结构没怎么学,没怎么分配好内存,不知道如何提速,如何更快的完成一个程序,导致了两个问题:一:导致了LCD1602的显示不是瞬间就显示,而是缓慢的显示出来。二:红外遥控不够灵敏,导致红外遥控有时要按好多下才可以。

温控风扇基本搞定,但是却存在有一些不足之处,还有需要改进的地方,比如说PID模糊控制没有添加进去,直到现在还在认真学习PID模糊控制。

然后接下来,我要做的就是两个项目:一个是基于51单片机的GPRS模块的一个项目。第二个便是最近挺火热的ARDUINO的项目,也是用GPRS来做

做完这两个项目,还有一个,打算开学再做的用ARDUINO做的四轴飞行器。

期间还要学习模电的知识,确实任务量很大,任务量很是艰巨,但是,我要做到这一些,加油!!!!!!!

你可能感兴趣的:(温控风扇的代码(开源) 新手写代码)