使用的模塊有:直流電機,舵機,蜂鳴器,紅外,溫度傳感器,lcd1602, , 舵機,這種舵機它的頻率是50HZ,一個周期為20ms,是通過一個周期中高低電平的占比來控制角度的角度的,本程序舵機是來回擺動,不是停在五個角度(0,45,90,135,180)的某個角度,可通過紅外遙控來實現停在某個角度,電扇的開關,也由紅外來控制。 為了方便起見,將過溫自動報警,和使用舵機的功能,分成兩種模式,可通過紅外遙控來切換,因為我之前遇到過,使用了舵機后(需要用到定時器),溫度就不能正常顯示, 通過DS18b20來測溫度,在lcd1602上顯示溫度和時間,當溫度超過26度時(可在代碼中修改),直流電機打開,蜂鳴器報警,低于26關閉。也可遙控打開或關閉電機,沒有使用舵機,此時直流電機不能改變方向。 當遙控器按下時,lcd1602顯示turn off,無法顯示溫度,定時器1初始化,舵機可以使用,利用舵機對直流電機來控制方向,將ds18b20和舵機分開使用的原因,ds18b20對時序的要求很高,如果用舵機的話就會使溫度無法正常顯示。 紅外遙控的優先級始終大于超過溫度。 工程以壓縮包的形式上傳在附件中。
單片機源程序如下:
- #include "reg52.h"
- #include"temp.h"
- #include"1302.h"
- sbit IRIN=P3^2; //紅外
- sbit duoji=P3^5;
- uchar IrValue[6];//溫度數組
- uchar zxc,count=0,flag1=1,flag2,k,m;
- uchar Disp[16]="trun off ";
- uchar push_val_left=14,pwm_val_left;
- uint timer=0,flex;
- uchar DisplayData[14]={'t'-0x30,'e'-0x30,'m'-0x30,'p'-0x30,':'-0x30,' '-0x30};
- uchar code smgduan[10]={0,1,2,3,4,5,6,7,8,9};
- void pwm_Servomoto_angle(unsigned int angle,unsigned int Servo_time)
- {
- push_val_left=5+angle*20/180; //舵機向左轉90度
- // timer=0;
- while(timer<=Servo_time); //延時400MS讓舵機轉到其位置 4000
- delay(flex);
- }
- void pwm_Servomoto(void)
- {
-
- if(pwm_val_left<=push_val_left)
- duoji=1;
- else
- duoji=0;
- if(pwm_val_left>=200)
- pwm_val_left=0;
-
- }
- void datapros(int temp)
- {
- float tp; uint h=4000;
- if(temp< 0) //當溫度值為負數
- {
- DisplayData[0] = 0x40; // -
- //因為讀取的溫度是實際溫度的補碼,所以減1,再取反求出原碼
- temp=temp-1;
- temp=~temp;
- tp=temp;
- temp=tp*0.0625*100+0.5;
-
-
- }
- else
- {
- DisplayData[6] = 0x00;
- tp=temp;//因為數據處理有小數點所以將溫度賦給一個浮點型變量
- //如果溫度是正的那么,那么正數的原碼就是補碼它本身
- temp=tp*0.0625*100+0.5;
-
- }
- if(flag2==0)
- if(temp>2600)
- {dj=1;
- while(h)
- {beep=~beep;
- delay(10);
- h--;
- }
- }
- else
- dj=0;
- DisplayData[7] = smgduan[temp / 10000];
- DisplayData[8] = smgduan[temp % 10000 / 1000];
- DisplayData[9] = smgduan[temp % 1000 / 100] ;
- DisplayData[10] = -2;
- DisplayData[11] = smgduan[temp % 100 / 10];
- DisplayData[12] = smgduan[temp % 10];
- DisplayData[13] =51;
-
- }
- void test_servo(void)
- {
- int pos;
- for(pos=0;pos<180;pos+=3)
- {
-
-
- pwm_Servomoto_angle(pos,100) ;
- delay(300);
- }
- for(pos = 180; pos>=0; pos-=3) // goes from 180 degrees to 0 degrees
- {
-
- pwm_Servomoto_angle(pos,100) ;
- delay(300);
- }
- }
-
- void LcdDisplay()
- {
- lcdwrc(0x80+0X40);
- lcdwrd('t');
- lcdwrd('i');
- lcdwrd('m');
- lcdwrd('e');
- lcdwrd(':');
- lcdwrd(' ');
- lcdwrd('0'+hsp[2]/16); //時
- lcdwrd('0'+(hsp[2]&0x0f));
- lcdwrd('-');
- lcdwrd('0'+hsp[1]/16); //分
- lcdwrd('0'+(hsp[1]&0x0f));
- lcdwrd('-');
- lcdwrd('0'+hsp[0]/16); //秒
- lcdwrd('0'+(hsp[0]&0x0f));
- }
- //外部中斷0初始化
- void IrInit()
- {
- IT0=1;//下降沿觸發
- EX0=1;//打開中斷0允許
- EA=1; //打開總中斷
- IRIN=1;//初始化端口
- }
- //定時器1初始化
- void timeinit()
- {TMOD=0X10;
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- TR1= 1;
- ET1= 1;
- EA = 1;
- }
- //main函數
- void main()
- {uchar i,n=0;
- IrInit(); //紅外初始化
- lcdinit();
- Ds1302Init();
- dj=0;
- while(1)
- {
- if(flag1==1) //關閉定時器,實現功能為超過設定溫度打開電機
- {
- Ds1302ReadTime();
- datapros(Ds18b20ReadTemp()); //數據處理函數
- for(i=0;i<14;i++)
- {
- lcdwrd(DisplayData[i]+0x30);
- }
- LcdDisplay();
- lcdwrc(0x80);
- }
- else //打開定時器,(電機舵機)關閉溫度傳感器,和lcd1602
- { if(m==0)
- { timeinit();
- m=1;
- dj=0;
- }
- test_servo();
- for(n=0;n<16;n++)
- {
- lcdwrd(Disp[n]);
- }
- lcdwrc(0x80+0x40);
- for(n=0;n<16;n++)
- { lcdwrd(' ');
- }
-
- lcdwrc(0x80);
- }
-
- }
- }
- void ReadIr() interrupt 0
- {
- uchar j,k;
- uchar err;
- zxc=0;
- delay(700); //7ms
- if(IRIN==0) //確認是否真的接收到正確的信號
- {
-
- err=1000; //1000*10us=10ms,超過說明接收到錯誤的信號
-
- while((IRIN==0)&&(err>0)) //等待前面9ms的低電平過去
- {
- delay(1);
- err--;
- }
- if(IRIN==1) //如果正確等到9ms低電平
- {
- err=500;
- while((IRIN==1)&&(err>0)) //等待4.5ms的起始高電平過去
- {
- delay(1);
- err--;
- }
- for(k=0;k<4;k++) //共有4組數據
- {
- for(j=0;j<8;j++) //接收一組數據
- {
- err=60;
- while((IRIN==0)&&(err>0))//等待信號前面的560us低電平過去
- {
- delay(1);
- err--;
- }
- err=500;
- while((IRIN==1)&&(err>0)) //計算高電平的時間長度。
- {
- delay(10); //0.1ms
- zxc++;
- err--;
- if(zxc>30)
- {
- return;
- }
- }
- IrValue[k]>>=1; //k表示第幾組數據
- if(zxc>=8) //如果高電平出現大于565us,那么是1
- {
- IrValue[k]|=0x80;
- }
- zxc=0; //用完時間要重新賦值
- }
- }
- }
- if(IrValue[2]!=~IrValue[3])
- {
- return;
- }
- }
- if(IrValue[2]==0x45) //電源鍵 模式一 過溫
- {flag1=1;
- TR1=0;
- }
-
-
- if(IrValue[2]==0x46) //mode 模式二 調整舵機
- {flag1=0;
- m=0;
- }
- if(IrValue[2]==0x47)
- {dj=1; // 打開電機 注意flag2的作用為設置為了控制優先級大于if(temp>25)
- flag2=1;
- }
- if(IrValue[2]==0x44) // 關閉電機
- {dj=0;
- flag2=0;
- }
- if(IrValue[2]==0x16) //按鍵0 舵機0度
- flex=550;
- if(IrValue[2]==0x0c) //按鍵1 舵機45度
- flex=1100;
- if(IrValue[2]==0x18) //按鍵2 舵機90度
- ;
- if(IrValue[2]==0x5e) //按鍵3 舵機135度
- ;
- if(IrValue[2]==0x08) //按鍵4 舵機180度
- ;
- }
- void time1()interrupt 3
- {
- TH1=(65536-100)/256; //100US定時
- TL1=(65536-100)%256;
- timer++; //定時器100US為準。在這個基礎上延時
- pwm_val_left++;
-
- pwm_Servomoto();
-
-
- }
復制代碼
所有資料51hei提供下載:
副本.7z
(2.52 MB, 下載次數: 52)
2020-2-15 19:51 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|