用8G1K08做的红外感应开关,感应距离30厘米,下面的程序和电路看看合适
本帖最后由 DebugLab 于 2024-11-4 14:24 编辑#include"stc8.h"
#include"intrins.h"//使用nop()函数需引用此文件
typedef unsigned char uint8_t;
typedef unsigned int uint16_t;
typedef unsigned long uint32_t;
//280us @11.0592MHz
TH1 = 0xF3; \
ET1 = 1; \
TR1 = 1
void Timer1_Init(void) //280微秒@11.0592MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xE7; //设置定时初始值
TH1 = 0xF3; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
}
//引脚定义
sbit LED=P5^4; //指示灯
sbit IR_IO=P5^5; //红外发射
sbit KEY=P3^0; //按键
sbit JS_OUT=P3^1; //红外接收
sbit OUT1=P3^2; //数据输出1
sbit OUT2=P3^3; //数据输出2
//数据定义
bit IR_Flag=0; //红外数据接收完成标志位
u8 IR_time=0; //下降沿之间的时间计数值
u8 IR_data; //引导码+8个位数据各自占用的时间
bit IR_TimeFlag; //红外发射延时到标志
unsigned char count; //280us
static u8 IR_bit; //变量IR_bit用于指示红外数据的位数
//函数声明
void delay(u16 count); //延时函数声明
void Time0_init(void); //定时计数器0初始化函数
void Time1_init(void); //定时计数器1初始化函数
void Int0_init(void); //外部中断0初始化函数
u8 IR_decode(void); //红外解码函数
void Delay13us(void) //@11.0592MHz//13us延时,38KHZ载波频率,占空比50% 1/38K=26.3us
{
unsigned char data i;
i = 46;
while (--i);
}
void send_Ir(unsigned int i)//发送高电平//38Khz载波发射,发射i个周期
{
while(i--)
{
IR_EN=1;//1个载波信号 1个周期50%的38KHZ时间26.3us
Delay13us();
IR_EN=0;
Delay13us();}
}
void no_send_Ir(unsigned int i)//发送低电平 ,不发射载波
{
while(i--)
{
IR_EN=0;
Delay13us();
Delay13us();
}
}
void send_rc5_0(void)
{
send_Ir(14);
no_send_Ir(14);
}
void send_rc5_1(void)
{
send_Ir(15);
no_send_Ir(15);
}
--------------主函数----------------------------
void main(void)
{
u8 num=0;
//STC8G系列单片机除P3.0和P3.1外,所有I/O上电均为高阻输入状态,需先配置再使用
P3M0 &= ~0x0f;
P3M1 &= ~0x0f; //P3.0-3.3引脚为准双向口模式
P5M0 |=0x30; //P5.4引脚为推挽输出模式
P5M1 &= ~0x30; //P5.5引脚为推挽输出模式
Time0_init(); //定时计数器0初始化函数
Time1_init(); //定时计数器1初始化函数
Int0_init(); //外部中断0初始化函数
EA = 1; //开中断
delay(100); //等待配置稳定
IR_IO = 1; //红外发射置高
while(1)
{
Send_IR(IR_SENDDATA); //红外发送数据
delay(20000);
if(IR_Flag=JS OUT) //红外数据接收完成
{
IR_Flag=0;
if(IR_decode() == IR_SENDDATA) LED = ~LED;//红外接收正确改变指示灯状态
}
OUT1=1;
OUT2=2;
}
}
//-------------------------延时函数----------------------------
void delay(u16 count)
{
while(count--)
{
_nop_();
}
}
//-------------------------定时器0初始化----------------------------
void Time0_init(void) //139微秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式,工作方式2
TMOD &= 0xF0;
TMOD |= 0x02;
TL0 = 0x80;
TH0 = 0x80;
TF0 = 0; //清除标志
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
//-------------------------定时器1初始化---------------------------
void Time1_init(void) //278微秒@11.0592MHz
{
AUXR |= 0x40;//模式2 1T
TMOD &= 0x0F;
}
//-------------------------外部中断0初始化-------------------------
void Int0_init(void)
{
IT0 = 1; //触发方式为下降沿触发
EX0 = 1; //使能INT0中断
}
//-------------------------红外接收解码-------------------------
u8 IR_decode(void)
{
u8 j,k;
u8 IR_Value = 0;
k=1; //先让变量k等于1,因为k为0时取出的将会是“引导码的时间间隔”
for(j=0;j<=7;j++) //内层循环8次为了拼合8个数据位为1个字节
{
if(IR_data>5) //若“时间间隔”比5大那肯定是“1码”反之为“0码”
IR_Value|=0x80; //通过按位或运算高位填1
if(j<7) //若数据没有拼合完8次
IR_Value>>=1; //通过右移运算“腾出”位置准备下一位判定
k++; //下标变量自增
}
return IR_Value; //返回红外接收的数据
}
//-------------------------外部中断0服务函数-------------------------
void INT0_ISR() interrupt 0
{
if(IR_time>8) //判断引导码(0.56ms+1.12ms)
IR_bit=0; //清除位数变量,确保当前IR_bit为0,表示引导码
IR_data=IR_time; //存储相应位时间宽度
IR_time=0; //清零时间宽度计数值
IR_bit++; //位数变量自增
if(IR_bit==9) //如果达到了9位(引导码+8个数据位)
{
IR_Flag=1; //红外数据接收完成标志位置1
IR_bit=0; //位数变量清零
}
}
//-------------------------定时器0中断服务函数-------------------------
void TIMER0_ISR() interrupt 1
{
IR_time++;
}
//-------------------------定时器1中断服务函数-------------------------
void TIMER1_ISR() interrupt 3
{
count--;
if(count == 0)
{
IR_TimeFlag = 1;
ET1 = 1;//
}
}
接收电路不完整吧 红外反射到不了30cm,也就10~15cm 就是时间太长了 soma 发表于 2024-11-4 14:17
接收电路不完整吧
keil5老是有点问题,能帮忙看一下吗 接收输出只要一个高电平和低电平 用红外遥控接收头来做检测,太过灵敏,收发发射管都要套长套管增加指向性,并且使用编码验证抑制干扰 客户要求的 是有一个隔离导管
页:
[1]