kl800.com省心范文网

红外线发射接收对管的简单应用基础


红外线发射接收对管的简单应用基础
作者:羊村村长(qq:332416820) 关键词:红外线、单片机、1T、AD 模数转换、红外对管、1602 元件清单:STC12C5A60S2、12MHz 晶振、30p 电容(2 个) 、103 可调电阻、1602 液晶、红外对管、电阻(220,47k 各 一个) 电路图:

说明:1、红外发射管工作电流一般为 100ma 左右,使用中长时间超过额定电流工作会造成期间损坏,此电路中限流电 阻为 220 欧,则工作电流 5/220 为 22ma 左右; 2、此电路实际测试中,感应距离 15cm 左右(从液晶上能看到电压变化) ,此距离为单程距离,从照片中可以看 到; 3、如果要增加感应距离,方法有三个:一个是加大发射电流(减小限流电阻) ,二是用单片机定时进行脉冲发 射,改变占空比,三是接收电流加三极管放大,提高接收电路灵敏度; 4、此电路所用 STC12C5A60S2 为 1Tcpu,具有 P1 口内部 adc 功能,传统 51 需改时延,并自己增加 ADC 模块。 5、特别提醒,红外接收管正极应该接地。 实验场景:

下面图一红圈标示的就是红外对管连接

图一 万能板实验图

图二

上面用东西遮挡引起电压变化

源程序清单: /*---------------------------------------------------------------------------------------------------------------*/ /* 12Mhz 晶振测试,100%通过 /*---------------------------------------------------------------------------------------------------------------*/ #include<reg51.h> #include "intrins.h" #define uchar unsigned char #define uint unsigned int uchar Vo; //A/D 转换后换算的电压值 /*Declare SFR associated with the ADC */ sfr ADC_CONTR = 0xBC; //ADC control register sfr ADC_RES = 0xBD; //ADC high 8-bit result register sfr ADC_RESL = 0xBE; //sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register sfr P1ASF = 0x9D; //P1 secondary function control register /*Define ADC operation const for ADC_CONTR*/ #define ADC_POWER 0x80 //ADC power control bit #define ADC_FLAG 0x10 //ADC complete flag 模数转换结束标志位 #define ADC_START 0x08 //ADC start control bit 模数转换启动控制位 //转换速度控制位 SPEED0 和 SPEED1,共四种状态,对应四种转换速度 #define ADC_SPEEDLL 0x00 //540 clocks #define ADC_SPEEDL 0x20 //360 clocks #define ADC_SPEEDH 0x40 //180 clocks #define ADC_SPEEDHH 0x60 //90 clocks uchar tCount; sbit RS = P2^0; sbit RW = P2^1; sbit EN = P2^2; void DelayMS(uint ms) { uint i; while(ms--) { */

for(i=0;i<120;i++); } } /*---------------------------Software delay function ----------------------------*/ void Delay(uint n) { uint x; while (n--) { x = 5000; while (x--); } } /*---------------------------------------------------------------------------------------------------------------*/ /* ADC 相关部分 /*---------------------------------------------------------------------------------------------------------------*/

*/

/*---------------------------Initial ADC sfr ----------------------------*/ void InitADC() { P1ASF = 0x01; //选择 P1.0 作为 A/D 输入通道 ADC_RES = 0; //清 0 ADC_CONTR = ADC_POWER | ADC_SPEEDLL; //0x10|0x00=0x10:开电源和设置 A/D 转换速度 Delay(2); //ADC power-on and delay } /*---------------------------Get ADC result ----------------------------*/ uchar GetADCResult(uchar ch) { ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;//0x00|0x00|ch|0x08:选择 A/D 输入通道,开始 A/D 转 换 _nop_(); //Must wait before inquiry , _nop_(); //设置 ADC_CONTR 寄存器后需加 4 个 CPU 时钟周期的延时,才能保证值被写入 ADC_CONTR 寄存器 _nop_(); _nop_(); while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag ADC_CONTR &= ~ADC_FLAG; //Close ADC Vo=ADC_RES*5*10/256; return Vo; //Return ADC result(为显示整数,这里将电压值扩大了十倍)

} /*---------------------------------------------------------------------------------------------------------------*/ /* 1602 显示相关部分 /*---------------------------------------------------------------------------------------------------------------*/ uchar Read_LCD_State() */

{ uchar state; RS=0; RW=1; EN=1; DelayMS(1); state=P0; EN = 0; DelayMS(1); return state; } void LCD_Busy_Wait() { while((Read_LCD_State()&0x80)==0x80); DelayMS(5); } void Write_LCD_Data(uchar dat) //写数据到 1602 { LCD_Busy_Wait(); RS=1; RW=0; EN=0; P0=dat; EN=1; DelayMS(1); EN=0; } void Write_LCD_Command(uchar cmd) //写命令 { LCD_Busy_Wait(); RS=0; RW=0; EN=0; P0=cmd; EN=1; DelayMS(1); EN=0; } void Init_LCD() //1602 初始化 { Write_LCD_Command(0x38); DelayMS(1); Write_LCD_Command(0x01); //清屏 DelayMS(1); Write_LCD_Command(0x06); // DelayMS(1); Write_LCD_Command(0x0c); DelayMS(1); } void Set_LCD_POS(uchar p)

{ Write_LCD_Command(p|0x80); } void Display_LCD_String(uchar p,uchar *s) //1602 显示 { uchar i; Set_LCD_POS(p); for(i=0;i<16;i++) { Write_LCD_Data(s[i]); DelayMS(1); } } void Format_DateTime(uchar d,uchar *a) { a[0]=d/10+'0'; a[1]=d%10+'0'; } //写入液晶第二行 void display(uchar add,uchar date) { uchar shi,ge; shi=date/10+'0'; ge=date%10+'0'; Write_LCD_Command(0x80+0x40+add); Write_LCD_Data(shi); Write_LCD_Data(ge); } //写入液晶第一行 void display1(uchar add,uchar date) { uchar shi,ge; shi=date/10; ge=date%10; Write_LCD_Command(0x80+add); Write_LCD_Data(0x30+shi); //0x30 即 48(十进制)对应的 ASCAII 码为字符‘0’ Write_LCD_Data(0x30+ge); } /*------------------------------------------------------------------------------------------- --------------------*/ /* 主程序 /*---------------------------------------------------------------------------------------------------------------*/ */

void main() { /* a,b,counter; a=0; b=0;*/ uint counter=9; Init_LCD();

InitADC(); Display_LCD_String(0,"Voltage:"); Display_LCD_String(10,"V "); Display_LCD_String(64,"counter:");//后面出现乱码,也请高手指出问题所在,qq:332416820 while (1) { GetADCResult(0); display1(8,Vo); display1(72,counter); counter++; DelayMS(1000); } }


赞助商链接