shen168 发表于 2024-11-4 14:12:29

用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;//
      }
}



soma 发表于 2024-11-4 14:17:49

接收电路不完整吧

DebugLab 发表于 2024-11-4 14:28:06

红外反射到不了30cm,也就10~15cm

e-bita 发表于 2024-11-4 15:28:29

就是时间太长了

e-bita 发表于 2024-11-4 16:19:38

soma 发表于 2024-11-4 14:17
接收电路不完整吧

keil5老是有点问题,能帮忙看一下吗

e-bita 发表于 2024-11-4 16:20:36

接收输出只要一个高电平和低电平

网老四 发表于 2024-11-4 16:41:11

用红外遥控接收头来做检测,太过灵敏,收发发射管都要套长套管增加指向性,并且使用编码验证抑制干扰

shen168 发表于 2024-11-4 19:50:43

客户要求的

shen168 发表于 2024-11-4 19:51:37

是有一个隔离导管
页: [1]
查看完整版本: 用8G1K08做的红外感应开关,感应距离30厘米,下面的程序和电路看看合适