本帖最后由 yxy112 于 2012-6-16 15:58 编辑
#include <pic.h> //调用头文件,可以去PICC软件下去查找PIC16F87XA单片机的头文件
//__CONFIG(XT&WDTDIS&LVPDIS); //定义配置字,晶振类型:XT,关闭开门狗,禁止低电压编程
#define RSPIN RB5 //Data or Instrument Select
#define RWPIN RB4 //Write or Read
#define EPIN RB3 //6800 mode Enable single
#define key RC1//读端口
unsigned char tmrh_times;
unsigned char tmrl_times;
unsigned char code_data1;
unsigned char code_data2;
unsigned char code_data3;
//unsigned char code;
unsigned char int_times;
unsigned char buf1;
bit head_ok;
bit code_ok;
bit clrbit;
void init_timer0(void)
{
T0CS=0; //TMR0工作于
PSA=1; //TMR0不分频器
TMR0IF=0; //T0中断标志位清零
TMR0IE=1; //T0中断允许
TMR0=0x87; //赋初值,以使T0120US中断
GIE=1; //开总中断
}
void wrong(void) //如果有错误,将相应寄存器清零,准备下一次接收
{
int_times=0;
tmrl_times=0;
tmrh_times=0;
head_ok=0;
code_data1=0;
code_data2=0;
code_data3=0;
code_ok=0;
}
void scanhead(void)
{
while(key==0)
{
}
init_timer0();
while(key==1)
{
}
init_timer0();
while(key==0)
{
}
if(((tmrh_times>3)&(tmrh_times<5))&&((tmrl_times>110)&(tmrl_times<138)))
{
init_timer0();
tmrl_times=0;
tmrh_times=0;
headok=1;
}
else
{
init_timer0();
tmrl_times=0;
tmrh_times=0;
headok=0;
}
}
void redata(void)
{
if(headok==1)
{
int_times++; //如果已经接收到头码,那么开始对后面的24个脉冲进行解码
buf1=one_zero(); //判断编码是0或1,或者是错码
tmrl_times=0; //时间中断计次寄存器清零
tmrh_times=0;
if(buf1==1) //如果是编码1
{
if(int_times<9)
{
code_data1|=0x80; //将1移入code_data的最高位
code_data1=code_data1>>1;//将接收缓冲区右移一位,以准备接收下一位 }
}
if(int_times<17)
{
code_data2|=0x80; //将1移入code_data的最高位
code_data2=code_data2>>1;//将接收缓冲区右移一位,以准备接收下一位 }
}
if(int_times<25)
{
code_data3|=0x80; //将1移入code_data的最高位
code_data3=code_data3>>1;//将接收缓冲区右移一位,以准备接收下一位 }
}
}
else if(buf1==0) //如果是编码0
{
if(int_times<9)
{
code_data1&=0x7f; //将0移入code_data的最高位
code_data1=code_data1>>1;
}
if(int_times<17)
{
code_data2&=0x7f; //将0移入code_data的最高位
code_data2=code_data2>>1;
}
if(int_times<25)
{
code_data3&=0x7f; //将0移入code_data的最高位
code_data3=code_data3>>1;
}
}
else //编码非0非1,即为错码,
{
wrong(); //调用错误处理程序
return;
}
if(int_times==24) //收到的第三组8位字节即为24代码
{
int_times=0;
tmrl_times=0;
tmrh_times=0;
head_ok=0;
code_ok=1;
}
}
}
unsigned char one_zero(void)
{
//参看遥控器芯片ev1517的说明书,0编码的脉冲周期为高4clk低12clk
//本例中,时间中断为0.12ms,4clk为480us
if(((tmrh_times>3)&(tmrh_times<5))&&((tmrl_times>10)&(tmrl_times<14)))
{
return 0;
}
//参看遥控器芯片ev1517的说明书,1编码的脉冲周期为高12clk低4clk
//本例中,时间中断为0.12ms
else if(((tmrl_times>3)&(tmrl_times<5))&&((tmrh_times>10)&(tmrh_times<14)))
{
return 1;
}
//如果脉冲周期不在0.75-1.5ms或者1.75-2.75ms区间的,我们认为是错码,返回2
return 2;
}
//名称: CCP2初始化函数
//void ccp2_int(void)
//{
// CCP2CON=0x04; //捕捉模式,捕捉每个下降沿
// T1CON=0x00; //CCP要使用捕捉特性,T1必须运行在定时工作或者同步计数器模式下
// TRISC1=1; //RC1设置为输入状态,该引脚接到了红外接收头的数据引脚上
// CCP2IF=0; //捕捉中断标志位清零
// CCP2IE=1; //该捕捉允许中断
// TMR1ON=1; //T1启动
//}
//名称: 中断处理函数
void interrupt ISR(void) //中断处理函数
{
if(TMR0IF==1) //如果是T0中断标志位为1,即120US时间到并引发中断
{
TMR0=0x87; //给TO赋初值,以便下一个循环开始
TMR0IF=0; //清除TO中断标志位
// tmr_times++; //记录中断的次数,依据此来判断接收编码的状态
if(key==1)
tmrh_times++;
if(key==0)
tmrl_times++;
}
}
//---------------------------------------
//名称: 延时函数
//-----------------------------------------
void delay(unsigned int t)
{
unsigned int i,j;
for(i=0;i<t;i++)
{
for(j=0;j<10;j++);
}
}
//---------------------------------------
//名称: 1602忙检测函数
//-----------------------------------------
void lcd_wait_busy(void)
{
TRISD7=1; //为读状态做准备,把RD7设为输入
RSPIN=0; //选择指令寄存器
RWPIN=1; //选择读
EPIN=1; //使能线电平变化
while(RD7==1); //读忙状态,不忙时退出
EPIN=0; //恢复使能线电平
TRISD7=0; //把RD7设置为输出
}
//---------------------------------------
//名称: 1602写命令函数
//-----------------------------------------
void lcd_write_com(unsigned char combuf)
{
RSPIN=0; //选择指令寄存器
RWPIN=0; //选择写
PORTD=combuf; //把命令字送入RD
EPIN=1; //使能线电平变化,命令送入1602的8位数据口
asm("NOP"); //来一个空操作,以延时片刻
EPIN=0; //恢复使能线电平
}
//---------------------------------------
//名称: 1602写命令函数(带忙检测)
//-----------------------------------------
void lcd_write_com_busy(unsigned char combuf)
{
lcd_wait_busy(); //调用忙检测函数
lcd_write_com(combuf); //调用写命令函数
}
//---------------------------------------
//名称: 1602写数据函数(带忙检测)
//-----------------------------------------
void lcd_write_data(unsigned char databuf)
{
lcd_wait_busy(); //调用忙检测函数
RSPIN=1; //选择数据寄存器
RWPIN=0; //选择写
PORTD=databuf; //把数据字送入RD口
EPIN=1; //使能线电平变化,命令送入1602的8位数据口
asm("NOP");
EPIN=0; //恢复使能线电平
}
//---------------------------------------
//名称: 1602显示地址写函数
//-----------------------------------------
void lcd_write_address(unsigned char x,unsigned char y)
{
x&=0x0f; //列地址限制在0-15
y&=0x01; //行地址限制在0-1
if(y==0x00)
lcd_write_com_busy(x|0x80); //第一行的列地址写入
else
lcd_write_com_busy((x+0x40)|0x80); //第二行的列地址写入
}
//---------------------------------------
//名称: 1602初始化函数
//-----------------------------------------
void lcdreset(void)
{
delay(150);
lcd_write_com(0x38);
delay(50);
lcd_write_com(0x38);
delay(50);
lcd_write_com(0x38);
lcd_write_com_busy(0x38); //8位数据,双列,5*7字形
lcd_write_com_busy(0x08); //显示功能关,无光标
lcd_write_com_busy(0x01); //清屏指令
lcd_write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动
lcd_write_com_busy(0x0c); //显示功能开,无光标,
}
//---------------------------------------
//名称: 指定地址写入函数
//-----------------------------------------
void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf)
{
lcd_write_address(x,y); //写入地址
lcd_write_data(buf); //写入显示数据
}
//---------------------------------------
//名称: 主函数
//-----------------------------------------
main(void)
{
unsigned char buf;
TRISB=0B11000111; //RB3-5设置为输出
TRISC=0B11111111; //RD设置为输出
TRISD=0B00000000; //RD设置为输出
//ccp2_int(); //CCP2初始化函数
lcdreset(); //复位1602
lcd_write_char(0,0,'P'); //P
lcd_write_char(1,0,'r'); //r
lcd_write_char(2,0,'e'); //e
lcd_write_char(3,0,'s'); //s
lcd_write_char(4,0,'s'); //s
lcd_write_char(6,0,'R'); //R
lcd_write_char(7,0,'e'); //e
lcd_write_char(8,0,'m'); //m
lcd_write_char(9,0,'o'); //o
lcd_write_char(10,0,'t'); //t
lcd_write_char(11,0,'e'); //e
lcd_write_char(13,0,'c'); //c
lcd_write_char(14,0,'o'); //o
lcd_write_char(15,0,'n'); //n
lcd_write_char(0,1,'t'); //t
lcd_write_char(1,1,'r'); //r
lcd_write_char(2,1,'o'); //o
lcd_write_char(3,1,'l'); //l
clrbit=1; //置位清屏标志位,以便在第一次显示按键编码时,将上述的提示字符清掉。
TRISC1=1;
while(1)
{
redata();
if(code_ok==1) //如果接收到了有效地的遥控器按键码
{
code_ok=0; //清掉该标志位
if(clrbit) //如果为第一次显示遥控器按键编码
{
clrbit=0;
lcdreset(); //清一次屏幕
}
lcd_write_char(0,0,'C'); //C
lcd_write_char(1,0,'O'); //O
lcd_write_char(2,0,'D'); //D
lcd_write_char(3,0,'E'); //E
lcd_write_char(4,0,':'); //:
lcd_write_char(6,0,'0'); //0
lcd_write_char(7,0,'X'); //X
buf=code>>4; //显示按键编码高4位
if(buf<10) //如果小于10
{
buf+=0x30; //直接加0x30,1602即可显示出该码
}
else //如果大约或等于10,
{
buf+=0x37; //直接加0x37,1602即可显示出该码
}
lcd_write_char(8,0,buf); //显示数据码高4位
buf=code&0x0f;
if(buf<10) //如果小于10
{
buf+=0x30; //直接加0x30,1602即可显示出该码
}
else //如果大约或等于10,
{
buf+=0x37; //直接加0x37,1602即可显示出该码
}
lcd_write_char(9,0,buf); //显示数据码低4位
}
}
}
程序 |