找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3698|回复: 3
收起左侧

51单片机风扇和测温程序,舵机实现电机的来回摆动,利用红外来控制舵机和电机

[复制链接]
ID:627541 发表于 2020-2-11 10:04 | 显示全部楼层 |阅读模式
   使用的模块有:直流电机,舵机,蜂鸣器,红外,温度传感器,lcd1602, ,
  舵机,这种舵机它的频率是50HZ,一个周期为20ms,是通过一个周期中高低电平的占比来控制角度的角度的,本程序舵机是来回摆动,不是停在五个角度(0,45,90,135,180)的某个角度,可通过红外遥控来实现停在某个角度,电扇的开关,也由红外来控制。
  为了方便起见,将过温自动报警,和使用舵机的功能,分成两种模式,可通过红外遥控来切换,因为我之前遇到过,使用了舵机后(需要用到定时器),温度就不能正常显示,
通过DS18b20来测温度,在lcd1602上显示温度和时间,当温度超过26度时(可在代码中修改),直流电机打开,蜂鸣器报警,低于26关闭。也可遥控打开或关闭电机,没有使用舵机,此时直流电机不能改变方向。
  当遥控器按下时,lcd1602显示turn off,无法显示温度,定时器1初始化,舵机可以使用,利用舵机对直流电机来控制方向,ds18b20和舵机分开使用的原因,ds18b20对时序的要求很高,如果用舵机的话就会使温度无法正常显示。
   红外遥控的优先级始终大于超过温度。
   工程以压缩包的形式上传在附件中。

单片机源程序如下:
  1. #include "reg52.h"                         
  2. #include"temp.h"
  3. #include"1302.h"       
  4. sbit  IRIN=P3^2;  //红外
  5. sbit  duoji=P3^5;

  6. uchar IrValue[6];//温度数组
  7. uchar zxc,count=0,flag1=1,flag2,k,m;
  8. uchar Disp[16]="trun off        ";
  9. uchar push_val_left=14,pwm_val_left;
  10. uint timer=0,flex;

  11. uchar DisplayData[14]={'t'-0x30,'e'-0x30,'m'-0x30,'p'-0x30,':'-0x30,' '-0x30};
  12. uchar code smgduan[10]={0,1,2,3,4,5,6,7,8,9};
  13. void pwm_Servomoto_angle(unsigned int angle,unsigned int Servo_time)
  14. {
  15.                   push_val_left=5+angle*20/180;          //舵机向左转90度
  16.                  // timer=0;
  17.                   while(timer<=Servo_time); //延时400MS让舵机转到其位置                 4000
  18.                   delay(flex);
  19. }
  20. void pwm_Servomoto(void)
  21. {  

  22.     if(pwm_val_left<=push_val_left)
  23.                duoji=1;
  24.         else
  25.                duoji=0;
  26.         if(pwm_val_left>=200)
  27.         pwm_val_left=0;

  28. }

  29. void datapros(int temp)          
  30. {
  31.            float tp; uint h=4000;
  32.         if(temp< 0)                                //当温度值为负数
  33.           {
  34.                 DisplayData[0] = 0x40;           //   -
  35.                 //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
  36.                 temp=temp-1;
  37.                 temp=~temp;
  38.                 tp=temp;
  39.                 temp=tp*0.0625*100+0.5;       
  40.                

  41.           }
  42.         else
  43.           {                       
  44.                 DisplayData[6] = 0x00;
  45.                 tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  46.                 //如果温度是正的那么,那么正数的原码就是补码它本身
  47.                 temp=tp*0.0625*100+0.5;       
  48.                
  49.         }
  50.         if(flag2==0)
  51.         if(temp>2600)
  52.            {dj=1;
  53.            while(h)
  54.            {beep=~beep;
  55.            delay(10);
  56.                   h--;
  57.                 }
  58.            }
  59.         else
  60.            dj=0;
  61.         DisplayData[7] = smgduan[temp / 10000];
  62.         DisplayData[8] = smgduan[temp % 10000 / 1000];
  63.         DisplayData[9] = smgduan[temp % 1000 / 100] ;
  64.         DisplayData[10] = -2;
  65.         DisplayData[11] = smgduan[temp % 100 / 10];
  66.         DisplayData[12] = smgduan[temp % 10];
  67.         DisplayData[13] =51;
  68.        
  69. }
  70. void test_servo(void)
  71. {
  72. int pos;
  73.         for(pos=0;pos<180;pos+=3)
  74.         {
  75.                

  76.        
  77.                 pwm_Servomoto_angle(pos,100) ;
  78.                 delay(300);
  79.         }
  80.         for(pos = 180; pos>=0; pos-=3)     // goes from 180 degrees to 0 degrees
  81.         {
  82.        
  83.           pwm_Servomoto_angle(pos,100) ;
  84.           delay(300);
  85.         }
  86. }
  87.                                                                   
  88. void LcdDisplay()
  89. {
  90.         lcdwrc(0x80+0X40);
  91.         lcdwrd('t');
  92.         lcdwrd('i');
  93.         lcdwrd('m');
  94.         lcdwrd('e');
  95.         lcdwrd(':');
  96.         lcdwrd(' ');
  97.         lcdwrd('0'+hsp[2]/16);                                //时
  98.         lcdwrd('0'+(hsp[2]&0x0f));                                 
  99.         lcdwrd('-');
  100.         lcdwrd('0'+hsp[1]/16);                                //分
  101.         lcdwrd('0'+(hsp[1]&0x0f));       
  102.         lcdwrd('-');
  103.     lcdwrd('0'+hsp[0]/16);                                //秒
  104.         lcdwrd('0'+(hsp[0]&0x0f));
  105. }                                                                                          

  106.                                                                 //外部中断0初始化
  107. void IrInit()          
  108. {
  109.         IT0=1;//下降沿触发
  110.         EX0=1;//打开中断0允许
  111.         EA=1;        //打开总中断

  112.         IRIN=1;//初始化端口
  113. }
  114.                                 //定时器1初始化
  115. void timeinit()
  116. {TMOD=0X10;
  117.         TH1=(65536-100)/256;          //100US定时
  118.         TL1=(65536-100)%256;
  119.         TR1= 1;
  120.         ET1= 1;
  121.         EA = 1;
  122. }               

  123.                                 //main函数
  124. void main()
  125. {uchar i,n=0;
  126. IrInit(); //红外初始化
  127. lcdinit();
  128. Ds1302Init();

  129.   dj=0;
  130. while(1)
  131.   {
  132.     if(flag1==1)         //关闭定时器,实现功能为超过设定温度打开电机
  133.        {  
  134.              Ds1302ReadTime();
  135.              datapros(Ds18b20ReadTemp());         //数据处理函数
  136.          for(i=0;i<14;i++)
  137.               {               
  138.                lcdwrd(DisplayData[i]+0x30);
  139.               }
  140.                LcdDisplay();
  141.               lcdwrc(0x80);
  142.            }
  143.     else        //打开定时器,(电机舵机)关闭温度传感器,和lcd1602
  144.             {  if(m==0)
  145.                     { timeinit();
  146.                       m=1;
  147.                           dj=0;
  148.                     }
  149.                         test_servo();
  150.                  for(n=0;n<16;n++)
  151.                {
  152.                     lcdwrd(Disp[n]);       
  153.                 }
  154.                    lcdwrc(0x80+0x40);
  155.                   for(n=0;n<16;n++)
  156.                     { lcdwrd(' ');
  157.                         }
  158.                   
  159.               lcdwrc(0x80);
  160.                 }
  161.                
  162.   }
  163. }
  164. void ReadIr() interrupt 0
  165. {
  166.         uchar j,k;
  167.         uchar err;
  168.     zxc=0;                                         
  169.         delay(700);        //7ms
  170.         if(IRIN==0)                //确认是否真的接收到正确的信号
  171.         {         
  172.                
  173.                 err=1000;                                //1000*10us=10ms,超过说明接收到错误的信号
  174.                        
  175.                 while((IRIN==0)&&(err>0))        //等待前面9ms的低电平过去                 
  176.                 {                       
  177.                         delay(1);
  178.                         err--;
  179.                 }
  180.                 if(IRIN==1)                        //如果正确等到9ms低电平
  181.                 {
  182.                         err=500;
  183.                         while((IRIN==1)&&(err>0))                 //等待4.5ms的起始高电平过去
  184.                         {
  185.                                 delay(1);
  186.                                 err--;
  187.                         }
  188.                         for(k=0;k<4;k++)                //共有4组数据
  189.                         {                               
  190.                                 for(j=0;j<8;j++)        //接收一组数据
  191.                                 {

  192.                                         err=60;               
  193.                                         while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
  194.                                         {
  195.                                                 delay(1);
  196.                                                 err--;
  197.                                         }
  198.                                         err=500;
  199.                                         while((IRIN==1)&&(err>0))         //计算高电平的时间长度。
  200.                                         {
  201.                                                 delay(10);         //0.1ms
  202.                                                 zxc++;
  203.                                                 err--;
  204.                                                 if(zxc>30)
  205.                                                 {
  206.                                                         return;
  207.                                                 }
  208.                                         }
  209.                                         IrValue[k]>>=1;         //k表示第几组数据
  210.                                         if(zxc>=8)                        //如果高电平出现大于565us,那么是1
  211.                                         {
  212.                                                 IrValue[k]|=0x80;
  213.                                         }
  214.                                         zxc=0;                //用完时间要重新赋值                                                       
  215.                                 }
  216.                         }
  217.                 }
  218.                 if(IrValue[2]!=~IrValue[3])
  219.                 {
  220.                         return;
  221.                 }
  222.         }
  223.         if(IrValue[2]==0x45)   //电源键          模式一 过温
  224.            {flag1=1;
  225.         TR1=0;
  226.            }
  227.           
  228.           
  229.         if(IrValue[2]==0x46)   //mode         模式二 调整舵机
  230.            {flag1=0;
  231.             m=0;
  232.            }
  233.         if(IrValue[2]==0x47)
  234.            {dj=1;                                //                打开电机  注意flag2的作用为设置为了控制优先级大于if(temp>25)
  235.             flag2=1;
  236.                 }
  237.         if(IrValue[2]==0x44)         //      关闭电机
  238.            {dj=0;
  239.             flag2=0;
  240.            }
  241.         if(IrValue[2]==0x16)   //按键0 舵机0度
  242.           flex=550;
  243.         if(IrValue[2]==0x0c)  //按键1 舵机45度
  244.           flex=1100;
  245.         if(IrValue[2]==0x18)  //按键2 舵机90度
  246.           ;
  247.         if(IrValue[2]==0x5e)  //按键3 舵机135度
  248.           ;
  249.         if(IrValue[2]==0x08) //按键4 舵机180度
  250.           ;       
  251. }
  252. void time1()interrupt 3   
  253. {       
  254.      TH1=(65536-100)/256;          //100US定时
  255.          TL1=(65536-100)%256;
  256.          timer++;                                  //定时器100US为准。在这个基础上延时
  257.          pwm_val_left++;
  258.          
  259.          pwm_Servomoto();
  260.          
  261.          
  262. }       
复制代码

所有资料51hei提供下载:
副本.7z (2.52 MB, 下载次数: 52)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:328014 发表于 2020-2-15 19:53 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:839162 发表于 2020-11-7 15:18 | 显示全部楼层
你好 有仿真图吗
回复

使用道具 举报

ID:840238 发表于 2020-11-9 09:45 来自手机 | 显示全部楼层
有protues仿真图嘛?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表