|
|
用STC8G1K08A做的紅外感應(yīng)開關(guān),用手機(jī)劉海的紅外感應(yīng)頭對著單片機(jī)的紅外感應(yīng)頭時(shí),燈會一直在閃爍要如何避開,有沒有大佬解答一下要如何處理呢,
#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時(shí)鐘 = SYSclk/2/(n+1) */
#define RES_FMT (1<<5) /* ADC結(jié)果格式 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通道選擇時(shí)間 0: 1個(gè)ADC時(shí)鐘, 1: 2個(gè)ADC時(shí)鐘, 默認(rèn)0(默認(rèn)1個(gè)ADC時(shí)鐘) */
#define CSHOLD (2<<5) /* 0~3, ADC通道選擇保持時(shí)間 (n+1)個(gè)ADC時(shí)鐘, 默認(rèn)1(默認(rèn)2個(gè)ADC時(shí)鐘) */
#define SMPDUTY 20 /* 10~31, ADC模擬信號采樣時(shí)間 (n+1)個(gè)ADC時(shí)鐘, 默認(rèn)10(默認(rèn)11個(gè)ADC時(shí)鐘) */
/* ADC轉(zhuǎn)換時(shí)間: 10位ADC固定為10個(gè)ADC時(shí)鐘, 12位ADC固定為12個(gè)ADC時(shí)鐘. */
#define MAIN_Fosc 22118400L //定義主時(shí)鐘
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; // 環(huán)境光基準(zhǔn)值
unsigned int ir_received = 0;
#define EMIT_DURATION 20 // 發(fā)射持續(xù)時(shí)間(ms)
#define STOP_DURATION 10 // 停止持續(xù)時(shí)間(ms)
unsigned int emit_phase_samples = 0; // 發(fā)射階段采樣值
unsigned int stop_phase_samples = 0; // 停止階段采樣值
unsigned int net_ir_signal = 0; // 凈反射信號強(qiáng)度
bit emission_state = 0; // 發(fā)射狀態(tài): 0=停止, 1=發(fā)射
unsigned int timer0_count = 0; // 定時(shí)器0計(jì)數(shù)
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
{
//定時(shí)器0
TMOD = 0x00; //模式0
TL0 = 0xcd; //[TH0,TL0]=65536-22.1184M*1000/12*1(1MS)
TH0 = 0xf8;
TR0 = 1; //啟動定時(shí)器
ET0 = 1; //使能定時(shí)器中斷
EA = 1;
}
void TM0_Isr() interrupt 1 //1ms
{
timer0_count++;
// 控制發(fā)射時(shí)序: 發(fā)射20ms, 停止10ms
if(emission_state)
{
if(timer0_count >= EMIT_DURATION)
{
emission_state = 0;
timer0_count = 0;
IR_OUT = 0; // 停止發(fā)射
}
}
else
{
if(timer0_count >= STOP_DURATION)
{
emission_state = 1;
timer0_count = 0;
IR_OUT = 1; // 開始發(fā)射
}
}
}
void Timer1_Init(void)
{
AUXR &= 0xBF; //定時(shí)器時(shí)鐘12T模式
TMOD &= 0x0F; //設(shè)置定時(shí)器模式
TL1 = 0xE8; //設(shè)置定時(shí)初始值
TH1 = 0xFF; //設(shè)置定時(shí)初始值
TF1 = 0; //清除TF1標(biāo)志
TR1 = 1; //定時(shí)器1開始計(jì)時(shí)
ET1 = 1; //使能定時(shí)器1中斷
}
void Timer1_Isr(void) interrupt 3
{
// 不再使用Timer1控制發(fā)射,改為由Timer0控制
}
// 初始化ADC
void ADC_Init(void)
{
P5M0 &= ~0x20; P5M1 |= 0x20; // P5.5設(shè)為高阻輸入
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結(jié)束
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 /* 平均值采樣次數(shù) 最大值16 */
/***********************************
查詢方式做一次ADC, chn為通道號, chn=0~3通道對應(yīng)P3.0~P3.3, 4通道-->P5.4, 5通道-->P5.5, 15通道為內(nèi)部1.19V基準(zhǔn)電壓做輸入的ADC值.
***********************************/
unsigned int ADC_convert(u8 chn)
{
u16 j;
u8 k; //平均值濾波時(shí)使用
Get_ADC10bitResult(chn); //參數(shù)i=0~11,15,查詢方式做一次ADC, 切換通道后第一次轉(zhuǎn)換結(jié)果丟棄. 避免采樣電容的殘存電壓影響.
Get_ADC10bitResult(chn); //參數(shù)i=0~11,15,查詢方式做一次ADC, 切換通道后第二次轉(zhuǎn)換結(jié)果丟棄. 避免采樣電容的殘存電壓影響.
for(k=0, j=0; k<SUM_LENGTH; k++)
j += Get_ADC10bitResult(chn); // 采樣累加和 參數(shù)0~15,查詢方式做一次ADC, 返回值就是結(jié)果
j = j / SUM_LENGTH; // 求平均
return j;
}
// 在全局變量中定義濾波系數(shù)和濾波后的值
#define ALPHA 0.2f // 濾波系數(shù) (0 < ALPHA < 1)。值越小越平滑,但響應(yīng)也越慢。
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 時(shí)鐘為系統(tǒng)時(shí)鐘
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 計(jì)時(shí)器
//定時(shí)器
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)
{
// 在發(fā)射階段后期采樣 (包含自身發(fā)射的反射信號 + 環(huán)境光)
emit_phase_samples = ADC_convert(5);
}
else if(!emission_state && timer0_count > STOP_DURATION/2)
{
// 在停止發(fā)射階段采樣 (主要是環(huán)境光)
stop_phase_samples = ADC_convert(5);
// 計(jì)算凈反射信號強(qiáng)度
if(emit_phase_samples > stop_phase_samples)
{
net_ir_signal = emit_phase_samples - stop_phase_samples;
}
else
{
net_ir_signal = 0;
}
// 使用凈反射信號進(jìn)行濾波
filtered_ir_value = (unsigned int)((1 - ALPHA) * filtered_ir_value + ALPHA * net_ir_signal);
// 環(huán)境光補(bǔ)償:使用停止階段的采樣值作為環(huán)境光基準(zhǔn)
ambient_light = stop_phase_samples;
// 手勢檢測:基于凈反射信號
if(net_ir_signal > 83) // 閾值可能需要調(diào)整
{
UpdatePcaPwm(PCA1,0);
UpdatePcaPwm(PCA0,0);
}
else
{
UpdatePcaPwm(PCA1,1023);
UpdatePcaPwm(PCA0,1023);
}
}
}
}
|
|