当前位置:文档之家› 光电技术实验三蔡成灼

光电技术实验三蔡成灼

哈尔滨理工大学实验报告课程名称:光电技术学院:自动化学院专业班级:电技12-3班学生姓名:蔡成灼学号:1212020301 指导教师:王宏民实验三一、实验目的本实验采用以STC实验箱4在完成红外遥控信号的NEC编码接收的基础上,完成红外遥控信息NEC编码的发射。

1、进一步熟悉和掌握STC单片机硬件环境下的红外遥控信息发射与接收;2、完成采用NEC编码的信息发射程序设计,并通过程序设定来改变用户码的设定;3、完成程序设计和调试任务。

二、实验内容1、熟悉KEILuVison4环境下的软件设计;2、熟悉STC实验箱,完成系统配置和程序下载运行;3、学习并熟悉NEC编码4、设计完成红红外发射程序。

5、完成用户码的修改设置,将用户码修改为20156、完成程序验证,给出验证结果。

三、实验步骤指导1、建立工程,编辑源程序;2、添加STC15FXXXX.H 文件3、运行、调试程序。

注意各个窗口的观察方法;4、下载程序到单片机的程序存储器中5、运行测试:(1)接收NEC遥控器编码数据(2)通过实验箱键盘发送数据/接收数据记录实验过程,并截图四、实验结果创建工程并导入源文件编译成功后,将生成的HEX文件导入STC-ISP软件中并通过USB 线下载至实验箱。

此次实验需要两台实验箱,故在程序的相应位置修改用户名为自己的用户码,格式为“年级-学号”,此处我的为1217。

修改用户码:高四位赋值年级,第四位赋值学号下载成功截图:下载成功后运行截图:发送接收A实验者用户码:(1217 18)发送接收B实验者用户码:(1117 13)注意事项:涉及下载硬件的实验,都必须注意ISP软件上晶振频率和程序中初始化代码里写的一致,否则无法下载。

还有就是软硬件型号的匹配。

本实验的源文件保存格式为C,我在一开始时以asm保存结果无法创建工程。

附录:实验程序/************* 本程序功能说明**************红外接收程序。

适用于NEC编码。

应用层查询B_IR_Press标志为,则已接收到一个键码放在IR_code中, 处理完键码后,用户程序清除B_IR_Press标志.数码管左起4位显示用户码, 最右边两位显示数据, 均为十六进制.用户可以在宏定义中指定用户码.用户底层程序按固定的时间间隔(60~125us)调用"IR_RX_NEC()"函数.按下IO行列键(不支持ADC键盘),显示发送、接收到的键值。

******************************************/#define MAIN_Fosc 22118400L //定义主时钟#include "STC15Fxxxx.H"sbit P_IR_TX = P3^7; //定义红外发送脚/****************************** 用户定义宏***********************************/#define SysTick 14225 // 次/秒, 系统滴答频率, 在4000~16000之间/***********************************************************/#define DIS_DOT 0x20#define DIS_BLACK 0x10#define DIS_ 0x11/****************************** 自动定义宏***********************************/#define Timer0_Reload (65536UL - ((MAIN_Fosc + SysTick/2) / SysTick)) //Timer 0 中断频率, 在config.h中指定系统滴答频率, 例程为14225./*****************************************************************************//************* 本地常量声明**************/u8 code t_display[]={ //标准字库// 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71, //black - H J K L N o P U t G Q r M y 0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1 u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码/************* I O口定义**************/sbit P_HC595_SER = P4^0; //pin 14 SER data inputsbit P_HC595_RCLK = P5^4; //pin 12 RCLk store (latch) clocksbit P_HC595_SRCLK = P4^3; //pin 11 SRCLK Shift data clock/************* 本地变量声明**************/u8 LED8[8]; //显示缓冲u8 display_index; //显示位索引bit B_1ms; //1ms标志u8 cnt_1ms; //1ms基本计时u8 IO_KeyState, IO_KeyState1, IO_KeyHoldCnt; //行列键盘变量u8 KeyHoldCnt; //键按下计时u8 KeyCode; //给用户使用的键码, 1~16有效u8 cnt_27ms;u16 PCA_Timer0;/************* 红外发送程序变量声明**************/u8 IR_TxIndex; //发送步骤索引, 用户把数据准备好, 用IR_TxIndex = 1; 来启动,之后程序自动发送完成u8 IR_TxData[5]; //发送数据, IR_TxData[0] -- 用户码低字节, IR_TxData[1] -- 用户码高字节,//IR_TxData[2] -- 用户数据字节, IR_TxData[3] -- 数据字节反码, IR_TxData[4]留空.u8 IR_Tx_Tick; //(系统使用,用户不可操作) 发送时隙, 做0.5625ms延时计数u8 IR_TxPulseTime; //(系统使用,用户不可操作) 发送38KHZ时间u8 IR_TxSpaceTime; //(系统使用,用户不可操作) 发送空格时间u8 IR_TxTmp; //(系统使用,用户不可操作) 发送缓冲u8 IR_TxBitCnt; //(系统使用,用户不可操作) 发送bit计数u8 IR_TxFrameTime; //(系统使用,用户不可操作) 帧时间, 108msbit B_StopCR; //(系统使用,用户不可操作) 停止PCAbit B_Space; //发送空闲(延时)标志u16 tx_cnt; //发送或空闲的脉冲计数(等于38KHZ的脉冲数,对应时间), 红外频率为38KHZ, 周期26.3us/************* 红外接收程序变量声明**************/sbit P_IR_RX = P3^6; //定义红外接收输入IO口u8 IR_SampleCnt; //采样计数u8 IR_BitCnt; //编码位数u8 IR_UserH; //用户码(地址)高字节u8 IR_UserL; //用户码(地址)低字节u8 IR_data; //数据原码u8 IR_DataShit; //数据移位bit P_IR_RX_temp; //Last samplebit B_IR_Sync; //已收到同步标志bit B_IR_Press; //安键动作发生u8 IR_code; //红外键码u16 UserCode; //用户码/*********************************//************* 本地函数声明**************/void IO_KeyScan(void);void PCA_config(void);/********************** 主函数************************/void main(void){u8 i;P0M1 = 0; P0M0 = 0; //设置为准双向口P1M1 = 0; P1M0 = 0; //设置为准双向口P2M1 = 0; P2M0 = 0; //设置为准双向口P3M1 = 0; P3M0 = 0; //设置为准双向口P4M1 = 0; P4M0 = 0; //设置为准双向口P5M1 = 0; P5M0 = 0; //设置为准双向口P6M1 = 0; P6M0 = 0; //设置为准双向口P7M1 = 0; P7M0 = 0; //设置为准双向口display_index = 0;AUXR = 0x80; //Timer0 set as 1T, 16 bits timer auto-reload,TH0 = (u8)(Timer0_Reload / 256);TL0 = (u8)(Timer0_Reload % 256);ET0 = 1; //Timer0 interrupt enableTR0 = 1; //Tiner0 runEA = 1; //打开总中断B_StopCR = 0;PCA_config();for(i=0; i<8; i++) LED8[i] = DIS_; //上电显示-LED8[4] = DIS_BLACK;LED8[5] = DIS_BLACK;while(1){if(B_1ms) //1ms到{B_1ms = 0;if(++cnt_27ms >= 27){cnt_27ms = 0;IO_KeyScan();if(KeyCode > 0) //检测到收到红外键码{IR_TxData[0] = 0x00; //IR_TxData[0] -- 用户码低字节IR_TxData[1] = 0x00; //IR_TxData[1] -- 用户码高字节IR_TxData[2] = KeyCode; //IR_TxData[2] -- 用户数据字节IR_TxData[3] = ~KeyCode; //IR_TxData[3] -- 数据字节反码IR_TxIndex = 1; //启动,之后程序自动发送完成KeyCode = 0;}}if(B_IR_Press) //检测到收到红外键码{B_IR_Press = 0;LED8[0] = (u8)((UserCode >> 12) & 0x0f); //用户码高字节的高半字节LED8[1] = (u8)((UserCode >> 8) & 0x0f); //用户码高字节的低半字节LED8[2] = (u8)((UserCode >> 4) & 0x0f); //用户码低字节的高半字节LED8[3] = (u8)(UserCode & 0x0f); //用户码低字节的低半字节LED8[6] = IR_code >> 4;LED8[7] = IR_code & 0x0f;}}}}/**********************************************//*****************************************************行列键扫描程序使用XY查找4x4键的方法,只能单键,速度快Y P04 P05 P06 P07| | | |X | | | |P00 ---- K00 ---- K01 ---- K02 ---- K03 ----| | | |P01 ---- K04 ---- K05 ---- K06 ---- K07 ----| | | |P02 ---- K08 ---- K09 ---- K10 ---- K11 ----| | | |P03 ---- K12 ---- K13 ---- K14 ---- K15 ----| | | |******************************************************/ u8 code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};void IO_KeyDelay(void){u8 i;i = 60;while(--i) ;}void IO_KeyScan(void) //50ms call{u8 j;j = IO_KeyState1; //保存上一次状态P0 = 0xf0; //X低,读YIO_KeyDelay();IO_KeyState1 = P0 & 0xf0;P0 = 0x0f; //Y低,读XIO_KeyDelay();IO_KeyState1 |= (P0 & 0x0f);IO_KeyState1 ^= 0xff; //取反if(j == IO_KeyState1) //连续两次读相等{j = IO_KeyState;IO_KeyState = IO_KeyState1;if(IO_KeyState != 0) //有键按下{F0 = 0;if(j == 0) F0 = 1; //第一次按下else if(j == IO_KeyState){if(++IO_KeyHoldCnt >= 37) //1秒后重键{IO_KeyHoldCnt = 33; //108ms repeatF0 = 1;}}if(F0){j = T_KeyTable[IO_KeyState >> 4];if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0))KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16; //计算键码,17~32}}else IO_KeyHoldCnt = 0;}P0 = 0xff;}/**************** 向HC595发送一个字节函数******************/void Send_595(u8 dat){u8 i;for(i=0; i<8; i++){dat <<= 1;P_HC595_SER = CY;P_HC595_SRCLK = 1;P_HC595_SRCLK = 0;}}/********************** 显示扫描函数************************/void DisplayScan(void){Send_595(~T_COM[display_index]); //输出位码Send_595(t_display[LED8[display_index]]); //输出段码P_HC595_RCLK = 1;P_HC595_RCLK = 0; //锁存输出数据if(++display_index >= 8) display_index = 0; //8位结束回0}/******************** 红外采样时间宏定义, 用户不要随意修改*******************/#define IR_SAMPLE_TIME (1000000UL/SysTick) //查询时间间隔, us, 红外接收要求在60us~250us之间#if ((IR_SAMPLE_TIME <= 250) && (IR_SAMPLE_TIME >= 60))#define D_IR_sample IR_SAMPLE_TIME //定义采样时间,在60us~250us 之间#endif#define D_IR_SYNC_MAX (15000/D_IR_sample) //SYNC max time#define D_IR_SYNC_MIN (9700 /D_IR_sample) //SYNC min time#define D_IR_SYNC_DIVIDE (12375/D_IR_sample) //decide data 0 or 1#define D_IR_DATA_MAX (3000 /D_IR_sample) //data max time#define D_IR_DATA_MIN (600 /D_IR_sample) //data min time#define D_IR_DATA_DIVIDE (1687 /D_IR_sample) //decide data 0 or 1#define D_IR_BIT_NUMBER 32 //bit number//************************************************************************************** *****//**************************** IR RECEIVE MODULE ********************************************void IR_RX_NEC(void){u8 SampleTime;IR_SampleCnt++; //Sample + 1F0 = P_IR_RX_temp; //Save Last sample statusP_IR_RX_temp = P_IR_RX; //Read current statusif(F0 && !P_IR_RX_temp) //Pre-sample is high,and current sample is low, so is fall edge{SampleTime = IR_SampleCnt; //get the sample timeIR_SampleCnt = 0; //Clear the sample counterif(SampleTime > D_IR_SYNC_MAX) B_IR_Sync = 0; //large the Maxim SYNC time, then errorelse if(SampleTime >= D_IR_SYNC_MIN) //SYNC{if(SampleTime >= D_IR_SYNC_DIVIDE){B_IR_Sync = 1; //has received SYNCIR_BitCnt = D_IR_BIT_NUMBER; //Load bit number}}else if(B_IR_Sync) //has received SYNC{if(SampleTime > D_IR_DATA_MAX) B_IR_Sync=0; //data samlpe time too largeelse{IR_DataShit >>= 1; //data shift right 1 bitif(SampleTime >= D_IR_DATA_DIVIDE) IR_DataShit |= 0x80; //devide data 0 or 1if(--IR_BitCnt == 0) //bit number is over?{B_IR_Sync = 0; //Clear SYNCif(~IR_DataShit == IR_data) //判断数据正反码{UserCode = ((u16)IR_UserH << 8) + IR_UserL;IR_code = IR_data;B_IR_Press = 1; //数据有效}}else if((IR_BitCnt & 7)== 0) //one byte receive{IR_UserL = IR_UserH; //Save the User code high byteIR_UserH = IR_data; //Save the User code low byteIR_data = IR_DataShit; //Save the IR data byte}}}}}/********************** Timer0 1ms中断函数************************/void timer0 (void) interrupt TIMER0_VECTOR{IR_RX_NEC();if(IR_TxIndex > 0) //有发送任务, 用户把数据准备好, 用IR_TxIndex = 1; 来启动,之后程序自动发送完成{if(++IR_Tx_Tick >= 8) //8*70.3=562.4us, 接近标准的256 / 0.455 = 562.6us, 一般遥控器使用455K晶体(0.455MHZ){IR_Tx_Tick = 0;if(IR_TxPulseTime > 0) //发送时间未完{if(--IR_TxPulseTime == 0) B_StopCR = 1; //脉冲时间发完, 停止发送脉冲}else if(IR_TxSpaceTime > 0) IR_TxSpaceTime--; //空格时间未完if((IR_TxPulseTime | IR_TxSpaceTime) == 0) //一个脉冲发完了{if(IR_TxIndex == 1) //刚开始, 发送数据同步头, IR_TxPulseTime = 9ms, IR_TxSpaceTime = 4.5ms{CL = 0;CH = 0;PCA_Timer0 = 10;CCAP0L = 10; //将影射寄存器写入捕获寄存器,先写CCAP0LCCAP0H = 0; //后写CCAP0HCR = 1;IR_TxPulseTime = 16; //16*0.5625 = 9msIR_TxSpaceTime = 8; // 8*0.5625 = 4.5msIR_TxIndex = 2;IR_TxTmp = IR_TxData[0]; //取第一个数据IR_TxBitCnt = 0;}else if(IR_TxIndex == 2){ CL = 0;CH = 0;PCA_Timer0 = 10;CCAP0L = 10; //将影射寄存器写入捕获寄存器,先写CCAP0LCCAP0H = 0; //后写CCAP0HCR = 1;IR_TxPulseTime = 1;if(IR_TxTmp & 1) I R_TxSpaceTime = 3; //数据1对应1.6875 + 0.5625 mselse IR_TxSpaceTime = 1; //数据0对应0.5625 + 0.5625 msIR_TxTmp >>= 1;if(++IR_TxBitCnt >= 33) //4个字节发送完成{IR_TxIndex = 3; //下一步就结束了}else if((IR_TxBitCnt & 7) == 0) IR_TxTmp = IR_TxData[IR_TxBitCnt >> 3];//发完一个字节, 取一个数}else if(IR_TxIndex == 3) IR_TxIndex = 0; //发送完成了}}}if(--cnt_1ms == 0){cnt_1ms = SysTick / 1000;B_1ms = 1; //1ms标志DisplayScan(); //1ms扫描显示一位}}//========================================================================// 函数: void PCA_config(void)// 描述: PCA配置函数.// 参数: None// 返回: none.//========================================================================void PCA_config(void){// PCA0初始化CCAPM0 = 0x48 + 1; //工作模式+ 中断允许0x00: PCA_Mode_Capture, 0x42: PCA_Mode_PWM, 0x48: PCA_Mode_SoftTimerPCA_Timer0 = 100; //随便给一个小的初值CCAP0L = (u8)PCA_Timer0; //将影射寄存器写入捕获寄存器,先写CCAP0LCCAP0H = (u8)(PCA_Timer0 >> 8); //后写CCAP0HPPCA = 1; //高优先级中断CMOD = (CMOD & ~0xe0) | 0x08; //选择时钟源, 0x00: 12T, 0x02: 2T, 0x04: Timer0溢出, 0x06: ECI, 0x08: 1T, 0x0A: 4T, 0x0C: 6T, 0x0E: 8TCH = 0;CL = 0;CR = 0;P_IR_TX = 1; //停止发射}//========================================================================// 函数: void PCA_Handler (void) interrupt PCA_VECTOR// 描述: PCA中断处理程序.// 参数: None// 返回: none.//========================================================================#define D_38K_DUTY ((MAIN_Fosc * 26) / 1000000UL + MAIN_Fosc / 3000000UL) /* 38KHZ周期时间26.3us */#define D_38K_OFF ((MAIN_Fosc * 17) / 1000000UL + MAIN_Fosc / 3000000UL) /* 发射管关闭时间 17.3us */#define D_38K_ON ((MAIN_Fosc * 9) / 1000000UL) /* 发射管导通时间 9us */void PCA_Handler (void) interrupt PCA_VECTOR{CCON = 0x40; //清除所有中断标志,但不关CRP_IR_TX = ~P_IR_TX;if(P_IR_TX) PCA_Timer0 += D_38K_OFF;//装载高电平时间17.3uselse PCA_Timer0 += D_38K_ON; //装载低电平时间9usCCAP0L = (u8)PCA_Timer0; //将影射寄存器写入捕获寄存器,先写CCAP0LCCAP0H = (u8)(PCA_Timer0 >> 8); //后写CCAP0Hif(B_StopCR){CR = 0;B_StopCR = 0;P_IR_TX = 1;}}成绩评定:指导教师:年月日。

相关主题