標題:
51單片機紅外遙控小車,實現(xiàn)松手檢測程序
[打印本頁]
作者:
幸福來陪伴
時間:
2023-9-13 11:58
標題:
51單片機紅外遙控小車,實現(xiàn)松手檢測程序
需要在外部中斷0,增加一個定時器,在確定是紅外引導碼之后,開啟定時器,只要是定時器的時間超過130ms,那么就退出紅外模式,因為紅外有個重復碼發(fā)送是108ms所以定時器的時間要大于108ms,這樣可以實現(xiàn)紅外遙控松手檢測,長按也可以執(zhí)行,松手就不執(zhí)行 ,代碼如下:
/*-----------------------------------------------
名稱:紅外遙控
------------------------------------------------*/
#include "IR.h"
#include "delay.h"
#include "1602.h"
unsigned int num=0; //超時計數(shù)器
unsigned int ir_flag=0;//紅外標志位
//用于存放地址碼、地址反碼、控制碼、控制反碼
unsigned char Ired_Data[4],Ired_Data1[4];
//紅外遙控管腳位定義
sbit IRED=P3^2;
sbit IN1 = P1^2; // 高電平1 后退(反轉(zhuǎn))
sbit IN2 = P1^3; // 高電平1 前進(正轉(zhuǎn))
sbit IN3 = P1^4; // 高電平1 前進(正轉(zhuǎn))
sbit IN4 = P1^5; // 高電平1 后退(反轉(zhuǎn))
sbit EN1 = P3^0; // 高電平使能
sbit EN2 = P3^1; // 高電平使能
extern unsigned char S1,cunt;
void hongwai(void)
{
stoprun();//關(guān)閉電機,防止上電電機轉(zhuǎn)動
if(ir_flag) //判斷是否接收到紅外遙控器數(shù)據(jù)
{
switch(Ired_Data[2])
{
case 0x00:stoprun();break;
case 0x45:S1++;if(S1>=4)S1=1;LCD_Clear(); break;
case 0x46:LCD_Write_Char(15,1,'b'); break;
case 0x47:LCD_Write_Char(15,1,'c'); break;
case 0x44:LCD_Write_Char(15,1,'d'); break;
case 0x40:LCD_Write_Char(15,1,'e'); break;
case 0x43:LCD_Write_Char(15,1,'f'); break;
case 0x07:cunt--;if(cunt<=0)cunt=99;LCD_Write_Char(15,1,'g'); break;
case 0x15:cunt++;if(cunt>=100)cunt=0;LCD_Write_Char(15,1,'h'); break;
case 0x09:LCD_Write_Char(15,1,'i'); break;
case 0x16:LCD_Write_Char(15,1,'0'); break;
case 0x19:LCD_Write_Char(15,1,'j'); break;
case 0x0d:LCD_Write_Char(15,1,'k'); break;
case 0x0c:LCD_Write_Char(15,1,'1'); break;
case 0x18:LCD_Write_Char(15,1,'2');run(); break;
case 0x5e:LCD_Write_Char(15,1,'3'); break;
case 0x08:LCD_Write_Char(15,1,'4');leftrun(); break;
case 0x1c:LCD_Write_Char(15,1,'5');stoprun(); break;
case 0x5a:LCD_Write_Char(15,1,'6');rightrun();break;
case 0x42:LCD_Write_Char(15,1,'7'); break;
case 0x52:LCD_Write_Char(15,1,'8');backrun(); break;
case 0x4a:LCD_Write_Char(15,1,'9'); break;
default:break;
}
}
else //未接收到紅外遙控器數(shù)據(jù)時,電機停止
{
stoprun();
}
}
//小車前進函數(shù)
void run(void)
{
IN1=0; //左電機
IN2=1;
IN3=1; //右電機
IN4=0;
EN1=1;
EN2=1;
}
//小車后退函數(shù)
void backrun(void)
{
IN1=1; //左電機
IN2=0;
IN3=0; //右電機
IN4=1;
EN1=1;
EN2=1;
}
//小車左轉(zhuǎn)函數(shù)
void leftrun(void)
{
IN1=0; //左電機
IN2=0;
IN3=1; //右電機
IN4=0;
EN1=1;
EN2=1;
}
//小車右轉(zhuǎn)函數(shù)
void rightrun(void)
{
IN1=0; //左電機
IN2=1;
IN3=0; //右電機
IN4=0;
EN1=1;
EN2=1;
}
//小車停止函數(shù)
void stoprun(void)
{
IN1=0; //左電機
IN2=0;
IN3=0; //右電機
IN4=0;
EN1=1;
EN2=1;
}
/*------------------------------------------------
中斷初始化
------------------------------------------------*/
void Ired_Init()
{
TMOD|=0x01; //定時器0工作在模式1(16位定時器模式)
TH0=(65536-9173)/256; //設(shè)置定時器初值,需根據(jù)實際情況調(diào)整參數(shù) 定時10ms
TL0=(65536-9173)%256; //設(shè)置定時器初值,需根據(jù)實際情況調(diào)整參數(shù)
EA=1; //打開總中斷
TR0=1; //啟動定時器0
IT0=1; //下降沿觸發(fā)
EX0=1; //打開中斷 0 允許
IRED=1; //初始化端口
}
void Ired() interrupt 0 //外部中斷 0 服務函數(shù)
{
unsigned char Ired_Hight_Time=0;
unsigned char i,j;
unsigned int Time=0;
if(IRED==0)
{
Time=1000;
while((IRED==0)&&(Time!=0)) //等待引導信號 9ms 低電平結(jié)束,若超過 10ms 強制退出
{
delay1(1); //延時約 10us
Time--;
if(Time==0)
return ;
}
if(IRED==1) //引導信號 9ms 低電平已過,進入高電平,2.25ms的為重復碼,4.5ms的為數(shù)據(jù)碼
{
ir_flag=1; //紅外遙控器數(shù)據(jù)接收標志位開啟
ET0=1;//開啟定時器
num=0;//計時清0
delay1(250); //延時2.5ms判斷紅外口是不是低電平,如果是低電平則為重復碼,如果是在2.5ms沒有低電平則判斷是不是到了4.5ms的數(shù)據(jù)碼
if(IRED==0)
{
Ired_Data[2]=Ired_Data1[2];//把上一次的值賦值到重復碼這里
return ;//必須要加退出,不然進入中斷會錯誤
}
Time=250;//再計算2.5ms判斷是否有低電平產(chǎn)生,如果超時就退出,如果在2.5ms內(nèi)有低電平則為數(shù)據(jù)碼,因為之前已經(jīng)延時了2.5ms,所以再加2.5ms判斷
while((IRED==1)&&(Time>=0)) //等待引導信號 4.5ms 高電平結(jié)束,如超過 5ms 強制退出
{
delay1(1);
Time--;
if(Time==0)
return ;
}
//地址碼,反地址碼,控制碼,反控制碼的收集
for(i=0;i<4;i++) //循環(huán) 4 次,讀取 4 個字節(jié)數(shù)據(jù)
{
for(j=0;j<8;j++) //循環(huán) 8 次讀取每位數(shù)據(jù)即一個字節(jié)
{
Time=600;
while((IRED==0)&&(Time!=0)) //等待數(shù)據(jù) 1 或 0 前面的 0.56ms 結(jié)束,若超過 6ms 強制退出
{
delay1(1);
Time--;
if(Time==0)
return;
}
Time=20;
while(IRED) //等待數(shù)據(jù) 1 或 0 后面的高電平結(jié)束,若超過 2ms 強制退出
{
delay1(10); //約 0.1ms
Ired_Hight_Time++;
if(Ired_Hight_Time>20)
return ;
}
Ired_Data[i]>>=1; //先讀取的為低位,然后是高位
if(Ired_Hight_Time>=8) //如果高電平時間大于 0.8ms,數(shù)據(jù)則為 1,否則為 0.
Ired_Data[i]|=0x80; //用或運算不影響其他位的數(shù)字
Ired_Hight_Time=0; //重新清零,等待下一次計算時間
}
}
Ired_Data1[2]=Ired_Data[2];//把采集的數(shù)據(jù)同時保存到另外一個數(shù)組,為下一次的重復碼賦值使用
}
if(Ired_Data[2]!=~Ired_Data[3]) //校驗控制碼與反控制碼,錯誤則返回
{
for(i=0;i<4;i++)
Ired_Data[i]=0;
return ;
}
}
}
void INT_Timer0() interrupt 1 //定時器0中斷函數(shù)
{
TH0=(65536-9173)/256; //重新設(shè)定定時器初值10ms
TL0=(65536-9173)%256; //重新設(shè)定定時器初值
num++;
if(num>=13)//130ms到了,沒有紅外按鍵按下,標志位清零,為什么要130ms,因為紅外重復碼是間隔108ms重發(fā)發(fā)送一次,所以要大于108ms,判斷沒有紅外按下
{
ir_flag=0; //清除紅外遙控器數(shù)據(jù)接收標志位
num=0;//計時清0
ET0=0;//關(guān)閉定時器0中斷
}
}
作者:
幸福來陪伴
時間:
2023-9-13 14:24
對于紅外遙控的小車做松手檢測很好的程序,程序驗證是通過的,網(wǎng)上資源很少,這是自己原創(chuàng)的,歡迎大家相互學習
作者:
愛電子998
時間:
2023-9-13 14:40
提個小小的建議,如果發(fā)就發(fā)全
作者:
幸福來陪伴
時間:
2023-9-13 16:03
愛電子998 發(fā)表于 2023-9-13 14:40
提個小小的建議,如果發(fā)就發(fā)全
第一次發(fā)帖,經(jīng)驗不足,下次改進,如果哪里不清楚,可以提一下
作者:
bobo電子愛好者
時間:
2023-10-20 13:38
程序沒發(fā)全呀
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1