標(biāo)題:
基于51單片機(jī)的紅外遙控和按鍵調(diào)速風(fēng)扇程序
[打印本頁]
作者:
hjx12
時間:
2022-3-28 20:47
標(biāo)題:
基于51單片機(jī)的紅外遙控和按鍵調(diào)速風(fēng)扇程序
/*************************************************************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/***********端口定義*****************/
sbit IR_R=P3^3; //紅外線數(shù)據(jù)接收口
sbit dianji1=P1^0;
sbit dianji2=P1^1;
/************************************/
/***********寄存器定義***************/
//以下為紅外接收解碼用到的寄存器
uchar IR_receive_time; //紅外接收脈沖時間計數(shù)
bit IR_receive_flag; //紅外接收檢測啟動標(biāo)志位
uchar IR_receive_data[33]; //紅外數(shù)據(jù)接收緩存接收計數(shù)脈沖個數(shù) 引導(dǎo)碼+8位地址碼+8位地址碼+8位數(shù)據(jù)碼+8位數(shù)據(jù)反碼
uchar IR_receive_bit; //紅外接收數(shù)據(jù)位標(biāo)志
bit IR_receive_OK; //紅外數(shù)據(jù)接收完畢標(biāo)志
uchar IR_receive_code[4]; //紅外解碼數(shù)據(jù)緩存
bit IR_receive_end; //紅外解碼結(jié)束標(biāo)志位
//鍵值相關(guān)定義
bit ON_flag; //開標(biāo)志
//PWM相關(guān)寄存器定義
#define PWM_DUTY_MAX 10 // 0~255 PWM周期, 最大255
#define PWM_ON 0 // 定義占空比的電平, 1 或 0
#define PWM_OFF (!PWM_ON)
uchar pwm_cnt; //周期計數(shù)值
uchar PWM_val;
uchar PWM_val_buf;
/*******1ms基準(zhǔn)延時程序*******************/
void Delay1ms(uint t) //1ms延時程序
{
uchar j;
while(t--)
{
for(j=0;j<125;j++)
{ ; }
}
}
/****************************************/
/************************************************************************
//定時器1中斷服務(wù)子函數(shù)產(chǎn)生PWM信號
void timer1() interrupt 3 //定時器1設(shè)置為8位自動重裝
{
if(++pwm_cnt==PWM_DUTY_MAX) //PWM周期結(jié)束,重新開始新的周期
{
pwm_cnt=0;
P1=PWM_ON;
}
if(pwm_cnt==PWM_val) P1=PWM_OFF; //判斷PWM占空比是否結(jié)束 高電平結(jié)束
}
/***************************************************/
/********************紅外解碼初始化設(shè)置程序***********************/
void IR_receive_init(void) //定時器0設(shè)置函數(shù)
{
IR_receive_time=0;
IR_receive_flag=0;
IR_receive_bit=0;
IR_receive_OK=0;
IR_receive_end=0;
TMOD=0x22; //設(shè)置定時器0為8位自動重裝計數(shù)
TH0=0x00;
TL0=0x00; //設(shè)置定時時間為256us
ET0=1; //定時器0中斷打開
EA=1; //總中斷打開
TR0=1; //啟動定時器0
}
/*************************************************************/
/*******************紅外接收口外部中斷0設(shè)置函數(shù)*********************/
void int0init(void)
{
IT0=1; //外部中斷0觸發(fā)方式設(shè)置為下降沿觸發(fā)
EX0=1; //外部中斷0中斷打開
EA=1; //總中斷打開
}
/*******************************************************************/
/***********************紅外接收產(chǎn)生256us定時計數(shù)程序***************/
void time0(void) interrupt 1 //定時器0中斷處理函數(shù)
{
IR_receive_time++; //紅外接收定時脈沖計數(shù)器
}
/*******************************************************************/
/***********************紅外33位數(shù)據(jù)(含一位引導(dǎo)碼)接收程序************************/
void int0() interrupt 0 //外部中斷0處理程序
{
if(IR_receive_flag) //紅外數(shù)據(jù)接收檢測標(biāo)志位
{
if(IR_receive_time>32&&IR_receive_time<63) //檢測接收時間是否在8-16ms范圍,若在,說明接收到紅外引導(dǎo)碼
{
IR_receive_bit=0; //紅外接收數(shù)據(jù)位標(biāo)志 清0
}
IR_receive_data[IR_receive_bit]=IR_receive_time; //接收數(shù)據(jù)(每位數(shù)據(jù)的脈沖時間)
IR_receive_time=0; //紅外接收定時脈沖計數(shù)器 清0 準(zhǔn)備等待接收下一位數(shù)的脈沖時間
IR_receive_bit++; //紅外接收數(shù)據(jù)位標(biāo)志 接收下一位數(shù)據(jù)
if(IR_receive_bit==33) //判斷包括一位引導(dǎo)碼和32位數(shù)據(jù)是否接收完成
{
IR_receive_bit=0; //接收完畢,則接收數(shù)據(jù)位標(biāo)志清0
IR_receive_OK=1; //紅外接收完畢標(biāo)志位置1,表示數(shù)據(jù)已接收完
}
}
else
{
IR_receive_flag=1; //紅外接收啟動標(biāo)志
IR_receive_time=0; //紅外接收脈沖計數(shù)器清0 準(zhǔn)備計數(shù)
}
}
/*********************************************************************/
/*****************************紅外數(shù)據(jù)解碼程序************************/
void IR_code(void)
{
uchar k,i,j,value;
k=1; //k=1意思是跳過引導(dǎo)碼數(shù)據(jù),不處理接收引導(dǎo)碼
for(j=0;j<4;j++) //有4組數(shù)據(jù),即8位地址碼+8位地址碼+8位數(shù)據(jù)碼+8位數(shù)據(jù)碼反碼
{
for(i=0;i<8;i++) //每組數(shù)據(jù)有8位二進(jìn)制數(shù)
{
value=value>>1; //寄存器數(shù)據(jù)位右移一位 接收數(shù)據(jù)是從每組數(shù)據(jù)的低位到高位接收的
if(IR_receive_data[k]>6) //通過判斷計數(shù)脈沖時長確定個位數(shù)是0還是1 通過計算我們得知數(shù)據(jù)0的時長為4.4ms,數(shù)據(jù)1的時長為8.8ms,我們?nèi)≈虚g值6,則大于6說明為數(shù)量1
{
value=value|0x80; //確定一組8位數(shù)據(jù)的一位(bit)數(shù)值
}
k++;
}
IR_receive_code[j]=value; //確定一組8位數(shù)據(jù)的值
}
IR_receive_end=1; //紅外數(shù)據(jù)解碼完成標(biāo)志
}
/*********************************************************************/
/*********定時器1初始化程序*********************/
void timer1_init(void)
{
TMOD = 0x22; //設(shè)置定時器為模式2(8位自動重裝載)
TL1=0x9C; //初始化計時值 100us 9C 50us CE
TH1=0x9C;
TR1=1; //啟動定時器1
ET1=1; //開啟定時器1中斷
EA=1; //開總中斷
}
/***********************************************/
void timer1(void) interrupt 3
{
pwm_cnt++;
if(pwm_cnt>=PWM_DUTY_MAX) //PWM周期結(jié)束,重新開始新的周期
{
pwm_cnt=0;
// P1=PWM_ON;
dianji1=0;
// zhishi=0;
}
if(pwm_cnt>=PWM_val) // P1=PWM_OFF; //判斷PWM占空比是否結(jié)束 高電平結(jié)束
{
dianji1=1;
//zhishi=1;
}
}
/***********************************************/
/*****************紅外鍵值處理程序***************************/
void IR_check(uchar tmp)
{
switch(tmp){
case 0x45:
//按鍵1 開 LED燈
// if(ON_flag==0)
// {
// ON_flag=1;
PWM_val=PWM_val_buf;
//P2=0x00;
// }
timer1_init();//定時器1初始化
PWM_val=1;
break;
case 0x0C:
//P2=0xff;
// timer1_init();//定時器1初始化
PWM_val_buf=PWM_val;
PWM_val=0;
// }
break;
case 0x08: //亮度
// if(ON_flag==1)
// {
// timer1_init();//定時器1初始化
PWM_val=4;
// }
break;
case 0x18: //亮度
// timer1_init();//定時器1初始化
PWM_val=1;
break;
case 0x5E: //亮度
// timer1_init();//定時器1初始化
PWM_val=3;
break;
}
}
/************************************************************/
/**************主程序****************************************/
void main()
{
//PWM_val=5; //占空比
//PWM_val_buf=5;
IR_receive_init(); //紅外初始化設(shè)置程序
int0init(); //外部中斷0設(shè)置
//P2=0x00;
dianji2=1;
while(1)
{
if(IR_receive_OK)
{
// IR_receive_OK=0;
IR_code(); //紅外數(shù)據(jù)解碼
}
if(IR_receive_end)
{
IR_receive_end=0;
EX0=0;
if(IR_receive_code[0]==0x00&&IR_receive_code[1]==0xFF) //判斷用戶碼是否正確
{
if(IR_receive_code[2]==~IR_receive_code[3]) //判斷反碼是否正確
{
IR_check(IR_receive_code[2]); //紅外按鍵值處理程序
}
}
// IR_receive_init(); //再次啟動紅外解碼設(shè)置程序,等待下一次解碼
int0init(); //外部中斷0設(shè)置
}
}
}
/************************************************************/
復(fù)制代碼
可以通過紅外遙控控制電機(jī)擋位。
作者:
@無名
時間:
2022-6-7 09:26
請問有沒有仿真電路圖
作者:
hjx12
時間:
2022-7-15 21:03
@無名 發(fā)表于 2022-6-7 09:26
請問有沒有仿真電路圖
不好意思,沒有啊。就是跟普中開發(fā)板一樣的電路圖
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1