登录
|
立即注册
|
使用QQ帐号登录
论坛
>
51单片机
发帖
|
基于51单片机的红外遥控和按键调速风扇程序
看3501
|
回2
|
收藏
楼主
ID:974010
只看他
2022-3-28 20:47
代码:
/*************************************************************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/***********端口定义*****************/
sbit IR_R=P3^3; //红外线数据接收口
sbit dianji1=P1^0;
sbit dianji2=P1^1;
/************************************/
/***********寄存器定义***************/
//以下为红外接收解码用到的寄存器
uchar IR_receive_time; //红外接收脉冲时间计数
bit IR_receive_flag; //红外接收检测启动标志位
uchar IR_receive_data[33]; //红外数据接收缓存接收计数脉冲个数 引导码+8位地址码+8位地址码+8位数据码+8位数据反码
uchar IR_receive_bit; //红外接收数据位标志
bit IR_receive_OK; //红外数据接收完毕标志
uchar IR_receive_code[4]; //红外解码数据缓存
bit IR_receive_end; //红外解码结束标志位
//键值相关定义
bit ON_flag; //开标志
//PWM相关寄存器定义
#define PWM_DUTY_MAX 10 // 0~255 PWM周期, 最大255
#define PWM_ON 0 // 定义占空比的电平, 1 或 0
#define PWM_OFF (!PWM_ON)
uchar pwm_cnt; //周期计数值
uchar PWM_val;
uchar PWM_val_buf;
/*******1ms基准延时程序*******************/
void Delay1ms(uint t) //1ms延时程序
{
uchar j;
while(t--)
{
for(j=0;j<125;j++)
{ ; }
}
}
/****************************************/
/************************************************************************
//定时器1中断服务子函数产生PWM信号
void timer1() interrupt 3 //定时器1设置为8位自动重装
{
if(++pwm_cnt==PWM_DUTY_MAX) //PWM周期结束,重新开始新的周期
{
pwm_cnt=0;
P1=PWM_ON;
}
if(pwm_cnt==PWM_val) P1=PWM_OFF; //判断PWM占空比是否结束 高电平结束
}
/***************************************************/
/********************红外解码初始化设置程序***********************/
void IR_receive_init(void) //定时器0设置函数
{
IR_receive_time=0;
IR_receive_flag=0;
IR_receive_bit=0;
IR_receive_OK=0;
IR_receive_end=0;
TMOD=0x22; //设置定时器0为8位自动重装计数
TH0=0x00;
TL0=0x00; //设置定时时间为256us
ET0=1; //定时器0中断打开
EA=1; //总中断打开
TR0=1; //启动定时器0
}
/*************************************************************/
/*******************红外接收口外部中断0设置函数*********************/
void int0init(void)
{
IT0=1; //外部中断0触发方式设置为下降沿触发
EX0=1; //外部中断0中断打开
EA=1; //总中断打开
}
/*******************************************************************/
/***********************红外接收产生256us定时计数程序***************/
void time0(void) interrupt 1 //定时器0中断处理函数
{
IR_receive_time++; //红外接收定时脉冲计数器
}
/*******************************************************************/
/***********************红外33位数据(含一位引导码)接收程序************************/
void int0() interrupt 0 //外部中断0处理程序
{
if(IR_receive_flag) //红外数据接收检测标志位
{
if(IR_receive_time>32&&IR_receive_time<63) //检测接收时间是否在8-16ms范围,若在,说明接收到红外引导码
{
IR_receive_bit=0; //红外接收数据位标志 清0
}
IR_receive_data[IR_receive_bit]=IR_receive_time; //接收数据(每位数据的脉冲时间)
IR_receive_time=0; //红外接收定时脉冲计数器 清0 准备等待接收下一位数的脉冲时间
IR_receive_bit++; //红外接收数据位标志 接收下一位数据
if(IR_receive_bit==33) //判断包括一位引导码和32位数据是否接收完成
{
IR_receive_bit=0; //接收完毕,则接收数据位标志清0
IR_receive_OK=1; //红外接收完毕标志位置1,表示数据已接收完
}
}
else
{
IR_receive_flag=1; //红外接收启动标志
IR_receive_time=0; //红外接收脉冲计数器清0 准备计数
}
}
/*********************************************************************/
/*****************************红外数据解码程序************************/
void IR_code(void)
{
uchar k,i,j,value;
k=1; //k=1意思是跳过引导码数据,不处理接收引导码
for(j=0;j<4;j++) //有4组数据,即8位地址码+8位地址码+8位数据码+8位数据码反码
{
for(i=0;i<8;i++) //每组数据有8位二进制数
{
value=value>>1; //寄存器数据位右移一位 接收数据是从每组数据的低位到高位接收的
if(IR_receive_data[k]>6) //通过判断计数脉冲时长确定个位数是0还是1 通过计算我们得知数据0的时长为4.4ms,数据1的时长为8.8ms,我们取中间值6,则大于6说明为数量1
{
value=value|0x80; //确定一组8位数据的一位(bit)数值
}
k++;
}
IR_receive_code[j]=value; //确定一组8位数据的值
}
IR_receive_end=1; //红外数据解码完成标志
}
/*********************************************************************/
/*********定时器1初始化程序*********************/
void timer1_init(void)
{
TMOD = 0x22; //设置定时器为模式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周期结束,重新开始新的周期
{
pwm_cnt=0;
// P1=PWM_ON;
dianji1=0;
// zhishi=0;
}
if(pwm_cnt>=PWM_val) // P1=PWM_OFF; //判断PWM占空比是否结束 高电平结束
{
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(); //红外初始化设置程序
int0init(); //外部中断0设置
//P2=0x00;
dianji2=1;
while(1)
{
if(IR_receive_OK)
{
// IR_receive_OK=0;
IR_code(); //红外数据解码
}
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(); //再次启动红外解码设置程序,等待下一次解码
int0init(); //外部中断0设置
}
}
}
/************************************************************/
可以通过红外遥控控制电机挡位。
沙发
ID:1032802
只看他
2022-6-7 09:26
请问有没有仿真电路图
板凳
ID:974010
只看他
2022-7-15 21:03
引用:
@无名 发表于 2022-6-7 09:26
请问有没有仿真电路图
不好意思,没有啊。就是跟普中开发板一样的电路图
51黑电子论坛
Powered by
Discuz!
X3.1
首页
|
标准版
|
触屏版
|
电脑版