标题:
求助!单片机红外接收异常 上电后第一次正常
[打印本页]
作者:
kaixin8318
时间:
2020-2-4 09:52
标题:
求助!单片机红外接收异常 上电后第一次正常
上电后第一次识别是正常的,第二次识别有一部分按键就会识别错误! 请高手指点下!
单片机源程序如下:
#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; //清除数据传送标志
}
复制代码
作者:
12abcfef
时间:
2020-2-4 13:55
各连接处固定后上电 接触松动 造成局部电压不稳
作者:
仰空
时间:
2020-2-4 15:41
我以前在学单片机,看着你的代码感觉我自己要加油呀
作者:
kaixin8318
时间:
2020-2-4 18:10
电路没有虚连的情况,只要上电第一次解码 肯定是正常的,第2次开始 有一部分按键的数据或者数据反码 就会出现一位的错误
就是说解码部分运行一次就不正常了!~
作者:
kaixin8318
时间:
2020-2-4 18:12
而且我试过解码成功发送完毕后,我从新执行一次上电初始化的内容也不管用
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1