上电后第一次识别是正常的,第二次识别有一部分按键就会识别错误! 请高手指点下!
单片机源程序如下:
- #include "stc15f2k60s2.h"
- #include <intrins.h>
- #include "delay.h"
- #include "hongwaifashe.h"
- #define uchar unsigned char
- #define UINT unsigned int
- uchar setdata[3];//发送红外用的 用户码 用户码 数据码
- uchar IRtime; //储存检测红外高低电平持续时间
- uchar IRcord[4]; //储存解码后的4个字节数据
- uchar IRdata[33]; //包含起始码在内的33位数据
- bit IRpro_ok; //解码后4个字节数据接收完成标志位
- bit IRok; //33位数据接收完成标志
- uchar RX_Data[]=0; //用于串口1接收数据数组保存变量定义
- uchar TX_Data[]=0;
- //======================================================================
- /* Variable definition */
- //======================================================================
- /* 串口1相关变量定义 */
- #define FOSC 22118400L //系统晶振频率(单位:HZ)
- #define BAUD 9600 //串口1波特率
- #define NONE_PARITY 0 //无校验
- #define ODD_PARITY 1 //奇校验
- #define EVEN_PARITY 2 //偶校验
- #define MARK_PARITY 3 //标记校验
- #define SPACE_PARITY 4 //空白校验
- #define PARITYBIT NONE_PARITY //定义校验位(无校验)
- #define S1_S0 0x40 //P_SW1.6
- #define S1_S1 0x80 //P_SW1.7
- UINT CNT_RX; //用于串口1接收数据计数保存变量定义
- UINT DAT_RX; //用于串口1接收数据保存变量定义
- UINT JDE_RX; //用于串口1接收数据判断保存变量定义
- UINT DAT_Check; //用于串口1发送的HDT数据的校验和计算保存变量定义
- /* 串口中断变量定义 */
- uchar K,H; //用于循环计数变量定义
- //======================================================================
- /* Function declaration */
- //======================================================================
- void INIT_UART(void); //串口初始化子函数定义(定时器中断2)
- void SEND_UART(uchar DAT); //串口发送数据子函数定义
- /***********************************************************************/
- //======================================================================
- // MAIN FUNCTION
- //======================================================================
- /***********************************************************************/
- void time0() interrupt 1
- {
- IRtime++;//255us
-
- if(IRtime==100) {CNT_RX=0; JDE_RX=1; }
-
- }
- //外部中断0 存入33次脉宽
- void int0() interrupt 0
- {
- static uchar i;//静态变量用于存入33次数据计数
- static bit startflag;//开始储存脉宽标志位
- if(startflag)
- {
- /*判断引导码,如果是引导码则从起始码开始存*/
- if((IRtime < 63) && (IRtime >= 33)) i = 0; //
- IRdata[i] = IRtime;//以TO溢出的次数来计算脉宽把这个时间存放在数组中
- IRtime = 0;//计数清零
- i++;//计数脉宽存入次数自加
- if(i == 33) //i等于33那么就表示已经存入了33次脉宽
- {
- IRok = 1; //脉宽检查完成
- i = 0; //把脉宽计数清零准备下次存入
- }
- }
- else
- {
- IRtime = 0; //定时器0计数清零
- startflag = 1;//开始处理标志位置1
- }
-
-
-
- }
- //把提取的33次脉宽进行解码 NEC协议
- void IRcordpro()
- {
- uchar i;//i是用于计数处理4个字节
- uchar j;//j用于计数处理1个字节的8位数据
- uchar k;//k用于计数处理33次脉宽
- k = 1;//从第一位脉宽开始处理,丢掉起始码
- for(i = 0; i < 4; i++)
- {
- for(j = 0; j < 8; j++)
- {
- //如果脉宽大于数据0标准的1125us那么就判定为数据1
- if(IRdata[k] > 5
-
- ) IRcord[i] |= 0x80;//写1
- //只能右移7次,如果右移8次则会把第一位数据移出去
- if(j < 7) IRcord[i] >>= 1;
- k++; //处理下一次脉宽
- }
- }
- IRpro_ok = 1;//解码完成
- }
- void main(void)
- {
- /*===========================================================
- ===========================================================*/
- //上电,IO口初始化
- P3M1=0x00; P3M0=0x00; //准双向IO口
- P5M1=0x00; P5M0=0xff; //推挽
- P3=P5=0xFF;
- //上电,定时器中断0初始化
- AUXR|=0x80; //定时器时钟为1T模式
- TMOD&=0xF0; //定时计数器0, 工作方式1
- TL0 = 0xF8; //设置定时初值
- TH0 = 0xE9; //设置定时初值 //设置定时初值 255us
- ET0=1; //允许定时/计数器0 中断
- TR0=1; //启动定时/计数器0 中断
-
-
- //上电,允许外部中断0
- IT0 = 1;//设置外部中断0跳变沿触发方式
- EX0 = 1;//开外部中断0中断
-
-
- //上电,串口中断初始化
- INIT_UART(); //串口中断初始化
-
- EA=1; //打开总中断
-
- /*===========================================================
- ===========================================================*/
- while(1)
- {
- uchar i; //计数串口发送字节数
-
- if(IRok)//判断33次脉宽是否提取完成
- {
- IRcordpro();//根据脉宽解码出4个字节的数据
- IRok = 0;//清零脉宽检查完成标志位等待下一次脉宽检查
- if(IRpro_ok)//判断解码是否完成
- {
-
-
-
-
- // if( IRcord[2]==~IRcord[3] )
- //
- // {
-
-
- for(i = 0; i < 4; i++) //串口发送4个字节数据
- SEND_UART(IRcord[i]) ;
- // }
- //
- IRpro_ok = 0;//清零解码标志位
-
-
- for(i = 0; i < 4; i++){
- IRdata[i]=0;}
-
- }
- }
-
-
-
-
- if(JDE_RX==2) // 接收到指令
- {
-
- if(RX_Data[1]==0xf1)
-
-
- {
-
- setdata[0]= RX_Data[2] ;
- setdata[1]= RX_Data[3] ;
- setdata[2]= RX_Data[4] ;
-
- hongwaifashe( );
- JDE_RX=1; // 允许接收
- CNT_RX=0; // 接收数量清零
-
- }
- }
-
-
-
- }//while
-
- }//main
- /***********************************************************************/
- //======================================================================
- // UART interrupt service routine
- // 数据格式:0xFF,0x0A,0x05,0x06,0x00,0x00
- //======================================================================
- /***********************************************************************/
- void Uart_Isr() interrupt 4 using 1
- {
- if(RI)
- {
- RI=0; //清除RI位
- DAT_RX=SBUF; //读取串口1数据
-
- /* 串口1接收数据和判断数据结束 */
- if(JDE_RX==1) //接收数据保存判断
- {
- IRtime=0; //计时器清零
-
- if((DAT_RX==0xFA)&(CNT_RX==0)) //避免少发数据出错情况 每次接到FA 就会清空
- {
-
- for(K=0;K<8;K++){RX_Data[K]=0;} //串口接收的数据清0
- }
-
- RX_Data[CNT_RX]=DAT_RX;
-
- CNT_RX++; //接收数量+1
-
- if(CNT_RX==5) //接收5个字节
- {
-
- JDE_RX=2; //串口接收数据判断变量置2 接收完毕
- }
-
-
-
- }
-
- }
- //if(TI){ TI=0; } //清除TI位
- }
- /***********************************************************************/
- //======================================================================
- // 子函数定义
- //======================================================================
- /***********************************************************************/
- //串口初始化子函数定义(定时器中断2)
- void INIT_UART(void)
- {
- ACC = P_SW1;
- ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
- P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
-
- if(PARITYBIT==NONE_PARITY){ SCON = 0x50; } //8位可变波特率
- if((PARITYBIT==ODD_PARITY)|(PARITYBIT==EVEN_PARITY)|(PARITYBIT==MARK_PARITY)){ SCON = 0xda; } //9位可变波特率,校验位初始为1
- if(PARITYBIT==SPACE_PARITY){ SCON = 0xd2; } //9位可变波特率,校验位初始为0
-
- PCON = 0x80; //波特率不倍增
- T2L = (65536-(FOSC/4/BAUD)); //设置波特率重装值
- T2H = (65536-(FOSC/4/BAUD))>>8;
- AUXR |= 0x14; //T2为1T模式, 并启动定时器2
- AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
- ES = 1; //使能串口1中断
- }
- //串口发送数据子函数定义
- void SEND_UART(UCHAR DAT)
- {
- SBUF=DAT;
- while(!TI); //等特数据传送
- TI=0; //清除数据传送标志
- }
复制代码
|