亚洲春色中文字幕久久久-三上亚,91精品国产亚一区二区三区,久久久九色综合亚洲成色777,涩涩视频下载,国产午夜亚洲精品午夜鲁丝片,国产精品A一区二区三区腾讯导航,影音先锋色情AV在线看片,蜜臀国产在线视频,极品少妇高潮啪啪无码吴梦梦 ,精品人妻无码一区二区三区手机版

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1194|回復: 5
打印 上一主題 下一主題
收起左側

做紅外感應開關,要如何避開紅外干擾呢?

[復制鏈接]
跳轉到指定樓層
樓主
ID:1144894 發表于 2025-9-9 19:02 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
用STC8G1K08A做的紅外感應開關,用手機劉海的紅外感應頭對著單片機的紅外感應頭時,燈會一直在閃爍要如何避開,有沒有大佬解答一下要如何處理呢,


#include "reg51.h"
#include "intrins.h"

/*************        本地常量聲明        **************/
#define ADC_START        (1<<6)        /* 自動清0 */
#define ADC_FLAG        (1<<5)        /* 軟件清0 */

#define        ADC_SPEED        1                /* 0~15, ADC時鐘 = SYSclk/2/(n+1) */
#define        RES_FMT                (1<<5)        /* ADC結果格式 0: 左對齊, ADC_RES: D9 D8 D7 D6 D5 D4 D3 D2, ADC_RESL: D1 D0 0  0  0  0  0  0 */
                                                        /*             1: 右對齊, ADC_RES: 0  0  0  0  0  0  D9 D8, ADC_RESL: D7 D6 D5 D4 D3 D2 D1 D0 */

#define CSSETUP                (1<<7)        /* 0~1,  ADC通道選擇時間      0: 1個ADC時鐘, 1: 2個ADC時鐘,  默認0(默認1個ADC時鐘) */
#define CSHOLD                (2<<5)        /* 0~3,  ADC通道選擇保持時間  (n+1)個ADC時鐘, 默認1(默認2個ADC時鐘)                */
#define SMPDUTY                20                /* 10~31, ADC模擬信號采樣時間  (n+1)個ADC時鐘, 默認10(默認11個ADC時鐘)                                */
                                                        /* ADC轉換時間: 10位ADC固定為10個ADC時鐘, 12位ADC固定為12個ADC時鐘.                                 */
                                                      
#define MAIN_Fosc                22118400L        //定義主時鐘

sfr     ADC_CONTR   =   0xbc;
sfr     ADC_RES     =   0xbd;
sfr     ADC_RESL    =   0xbe;
sfr     ADCCFG      =   0xde;

sfr     P_SW2   =   0xba;
#define ADCTIM  (*(unsigned char volatile xdata *)0xfea8)

sfr AUXR = 0x8E;
sfr INT_CLKO = 0x8F;
sfr P_SW1 = 0xa2;

sfr     CCON    =   0xd8;
sbit    CF      =   CCON^7;
sbit    CR      =   CCON^6;
sbit    CCF2    =   CCON^2;
sbit    CCF1    =   CCON^1;
sbit    CCF0    =   CCON^0;

sfr     CMOD    =   0xd9;
sfr     CL      =   0xe9;
sfr     CH      =   0xf9;
sfr     CCAPM0  =   0xda;
sfr     CCAP0L  =   0xea;
sfr     CCAP0H  =   0xfa;
sfr     PCA_PWM0 =  0xf2;
sfr     CCAPM1  =   0xdb;
sfr     CCAP1L  =   0xeb;
sfr     CCAP1H  =   0xfb;
sfr     PCA_PWM1 =  0xf3;
sfr     CCAPM2  =   0xdc;
sfr     CCAP2L  =   0xec;
sfr     CCAP2H  =   0xfc;
sfr     PCA_PWM2 =  0xf4;

sfr     P0M1    =   0x93;
sfr     P0M0    =   0x94;
sfr     P1M1    =   0x91;
sfr     P1M0    =   0x92;
sfr     P2M1    =   0x95;
sfr     P2M0    =   0x96;
sfr     P3M1    =   0xb1;
sfr     P3M0    =   0xb2;
sfr     P4M1    =   0xb3;
sfr     P4M0    =   0xb4;
sfr     P5M1    =   0xc9;
sfr     P5M0    =   0xca;

sfr P4   = 0xC0;
sfr P5   = 0xC8;
sfr P6   = 0xE8;
sfr P7   = 0xF8;

sbit    IR_OUT    =   P5^4;
sbit    IR_IN           =   P5^5;

typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

#define         PCA0                        0
#define         PCA1                        1
#define         PCA2                        2

unsigned int ambient_light = 0;   // 環境光基準值
unsigned int ir_received        = 0;

#define EMIT_DURATION 20    // 發射持續時間(ms)
#define STOP_DURATION 10    // 停止持續時間(ms)
unsigned int emit_phase_samples = 0;  // 發射階段采樣值
unsigned int stop_phase_samples = 0;  // 停止階段采樣值
unsigned int net_ir_signal = 0;       // 凈反射信號強度
bit emission_state = 0;               // 發射狀態: 0=停止, 1=發射
unsigned int timer0_count = 0;        // 定時器0計數

void UpdatePcaPwm(u8 PCA_id, u16 pwm_value)
{
        if(PCA_id == PCA0)
        {
                PCA_PWM0 = (PCA_PWM0 & ~0x32) | (u8)((pwm_value & 0x0300) >> 4) | (u8)((pwm_value & 0x0400) >> 9);
                CCAP0H = (u8)pwm_value;
        }
        else if(PCA_id == PCA1)
        {
                PCA_PWM1 = (PCA_PWM1 & ~0x32) | (u8)((pwm_value & 0x0300) >> 4) | (u8)((pwm_value & 0x0400) >> 9);
                CCAP1H = (u8)pwm_value;
        }
        else if(PCA_id == PCA2)
        {
                PCA_PWM2 = (PCA_PWM2 & ~0x32) | (u8)((pwm_value & 0x0300) >> 4) | (u8)((pwm_value & 0x0400) >> 9);
                CCAP2H = (u8)pwm_value;
        }
}

void Timer0_Init(void)                //1毫秒@22.1184MHz
{
        //定時器0
        TMOD = 0x00;                                //模式0
        TL0  = 0xcd;                                 //[TH0,TL0]=65536-22.1184M*1000/12*1(1MS)
        TH0  = 0xf8;
        TR0  = 1;                                    //啟動定時器
        ET0  = 1;                                    //使能定時器中斷
        EA  = 1;
}

void TM0_Isr() interrupt 1        //1ms
{
        timer0_count++;
      
        // 控制發射時序: 發射20ms, 停止10ms
        if(emission_state)
        {
                if(timer0_count >= EMIT_DURATION)
                {
                        emission_state = 0;
                        timer0_count = 0;
                        IR_OUT = 0; // 停止發射
                }
        }
        else
        {
                if(timer0_count >= STOP_DURATION)
                {
                        emission_state = 1;
                        timer0_count = 0;
                        IR_OUT = 1; // 開始發射
                }
        }
}

void Timer1_Init(void)
{
        AUXR &= 0xBF;                        //定時器時鐘12T模式
        TMOD &= 0x0F;                        //設置定時器模式
        TL1 = 0xE8;                                //設置定時初始值
        TH1 = 0xFF;                                //設置定時初始值
        TF1 = 0;                                //清除TF1標志
        TR1 = 1;                                //定時器1開始計時
        ET1 = 1;                                //使能定時器1中斷
}

void Timer1_Isr(void) interrupt 3
{
        // 不再使用Timer1控制發射,改為由Timer0控制
}

// 初始化ADC
void ADC_Init(void)
{
    P5M0 &= ~0x20; P5M1 |= 0x20; // P5.5設為高阻輸入

    ADC_CONTR = 0x80 + 0;        //ADC on + channel
        ADCCFG = RES_FMT + ADC_SPEED;
        P_SW2 |=  0x80;        //訪問XSFR
        ADCTIM = CSSETUP + CSHOLD + SMPDUTY;
}

u16        Get_ADC10bitResult(u8 channel)
{
        ADC_RES = 0;
        ADC_RESL = 0;
        ADC_CONTR = 0x80 | ADC_START | channel;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        while((ADC_CONTR & ADC_FLAG) == 0)        ;        //等待ADC結束
        ADC_CONTR &= ~ADC_FLAG;
        #if ((RES_FMT & (1<<5)) != 0)
                return        ((u16)ADC_RES * 256 + (u16)ADC_RESL);        //右對齊
        #else
                return        ((u16)ADC_RES * 4 + (u16)(ADC_RESL >> 6));        //左對齊
        #endif
}

#define                SUM_LENGTH        16        /* 平均值采樣次數 最大值16 */

/***********************************
查詢方式做一次ADC, chn為通道號, chn=0~3通道對應P3.0~P3.3, 4通道-->P5.4, 5通道-->P5.5, 15通道為內部1.19V基準電壓做輸入的ADC值.
***********************************/
unsigned int        ADC_convert(u8 chn)
{
        u16        j;
        u8        k;                //平均值濾波時使用

        Get_ADC10bitResult(chn);                //參數i=0~11,15,查詢方式做一次ADC, 切換通道后第一次轉換結果丟棄. 避免采樣電容的殘存電壓影響.
        Get_ADC10bitResult(chn);                //參數i=0~11,15,查詢方式做一次ADC, 切換通道后第二次轉換結果丟棄. 避免采樣電容的殘存電壓影響.
        for(k=0, j=0; k<SUM_LENGTH; k++)      
                j += Get_ADC10bitResult(chn);        // 采樣累加和   參數0~15,查詢方式做一次ADC, 返回值就是結果
        j = j / SUM_LENGTH;                // 求平均
      
        return j;
}

// 在全局變量中定義濾波系數和濾波后的值
#define ALPHA 0.2f  // 濾波系數 (0 < ALPHA < 1)。值越小越平滑,但響應也越慢。
unsigned int filtered_ir_value = 0;

void main()
{
        P0M0 = 0x00;
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0xe0;
        P3M1 = 0x00;
        P4M0 = 0x00;
        P4M1 = 0x00;
        P5M0 = 0x00;
        P5M1 = 0x00;
      
    P3M0 |= 0x08; P3M1 &= ~0x08; //P3.3推挽模式
        P3M0 |= 0x04; P3M1 &= ~0x04; //P3.2推挽模式

    P_SW1 = 0x00; //ECI/P1.2, CCP0/P1.1, CCP1/P1.0, CCP2/P3.7
      
        CCON = 0x00;
        CMOD = 0x08; //PCA 時鐘為系統時鐘
        CL = 0x00;
        CH = 0x00;

        //-- 10 位 PWM--      
        CCAPM0 = 0x02;          //PCA 模塊 0 為 PWM 工作模式
        PCA_PWM0 = 0xc0; //PCA 模塊 0 輸出 10 位 PWM
        CCAP0L = 0;
        CCAP0H = 0;
      
        CCAPM1 = 0x02;          //PCA 模塊 1 為 PWM 工作模式
        PCA_PWM1 = 0xc0; //PCA 模塊 1 輸出 10 位 PWM
        CCAP1L = 0;
        CCAP1H = 0;
        CR = 1; //啟動 PCA 計時器
      
        //定時器
        Timer0_Init();
        Timer1_Init();

        UpdatePcaPwm(PCA1,1023);
        UpdatePcaPwm(PCA0,1023);
      
        ADC_Init();
      
        ambient_light = ADC_convert(5);
      
    while (1)
        {
                // 同步采樣策略
                if(emission_state && timer0_count > EMIT_DURATION/2)
                {
                        // 在發射階段后期采樣 (包含自身發射的反射信號 + 環境光)
                        emit_phase_samples = ADC_convert(5);
                }
                else if(!emission_state && timer0_count > STOP_DURATION/2)
                {
                        // 在停止發射階段采樣 (主要是環境光)
                        stop_phase_samples = ADC_convert(5);
                       
                        // 計算凈反射信號強度
                        if(emit_phase_samples > stop_phase_samples)
                        {
                                net_ir_signal = emit_phase_samples - stop_phase_samples;
                        }
                        else
                        {
                                net_ir_signal = 0;
                        }
                       
                        // 使用凈反射信號進行濾波
                        filtered_ir_value = (unsigned int)((1 - ALPHA) * filtered_ir_value + ALPHA * net_ir_signal);
                       
                        // 環境光補償:使用停止階段的采樣值作為環境光基準
                        ambient_light = stop_phase_samples;
                       
                        // 手勢檢測:基于凈反射信號
                        if(net_ir_signal > 83) // 閾值可能需要調整
                        {
                                UpdatePcaPwm(PCA1,0);
                                UpdatePcaPwm(PCA0,0);
                        }
                        else
                        {
                                UpdatePcaPwm(PCA1,1023);
                                UpdatePcaPwm(PCA0,1023);
                        }
                }
        }      
}
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:879348 發表于 2025-9-10 07:53 | 只看該作者
加入簡易自主協議,比如在發射信號加入50%方波,因為其他干擾不可能出現這種簡單的波形
回復

使用道具 舉報

板凳
ID:648281 發表于 2025-9-10 22:14 | 只看該作者
在收發加入一個通訊協議,協議對的上感應才有效
回復

使用道具 舉報

地板
ID:1034262 發表于 2025-9-11 12:11 | 只看該作者
使用類似紅外遙控的數據編碼
回復

使用道具 舉報

5#
ID:879809 發表于 2025-9-11 17:33 | 只看該作者
用通訊協議會降低響應速度,一般調制成38k方波就可以了,外來干擾是38k的概率基本是零。
回復

使用道具 舉報

6#
ID:1160416 發表于 2025-9-15 17:06 | 只看該作者
手機紅外傳感器的工作頻率通常是固定的(如 38kHz 或特定載波頻率),而你的紅外接收頭可能對所有紅外信號都敏感。解決思路是讓單片機只響應特定頻率編碼的紅外信號,過濾掉手機的干擾信號。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表