注册会员
- 积分
- 81
- 威望
- 50
- 贡献
- 27
- 兑换币
- 27
- 注册时间
- 2013-10-19
- 在线时间
- 2 小时
|
#include <pic.h> //调用PIC16F87XA单片机的头文件
__CONFIG(XT&WDTDIS&LVPDIS);
#define uchar unsigned char
#define uint unsigned int
//const uchar dx[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-f段选显示码
//uchar sz[]={0x01,0X02,0X04,0X08,0X10,0X20,0X40,0X80};
uchar i;
void delay_ms(uint xms)
{
int i,j;
for(i=0;i<xms;i++)
{for(j=0;j<71;j++);}
}
//---------------------------------------
//红外解码寄存器设置
unsigned char tmr_times;
unsigned char code_data;
unsigned char code;
unsigned char int_times;
unsigned char buf1;
bit head_ok;
bit code_ok;
//---------------------------------------
//名称:解码错误处理函数
//---------------------------------------
void wrong(void) //如果有错误,将相应寄存器清零,准备下一次接收
{
int_times=0;
tmr_times=0;
head_ok=0;
code_data=0;
code_ok=0;
code=0;
}
//---------------------------------------
void init()
{
ADCON1=0X06;
TRISA=0;
TRISB=0;
TRISC=0X04;
TRISE=0;
PORTA=0;
PORTB=0;
PORTE=0;
RA1=1;
RBIE=0;
}
void TMR0init()
{
OPTION=0X80;
TMR0IF=0;
TMR0IE=1;
TMR0=131;
GIE=1;
PEIE=1;
}
void ccp1init()
{
CCP1CON=0x04; //每个脉冲上降沿捕捉
T1CON=0x01;
TRISC2=1; //RC2设置为输入状态
CCP1IF=0;
CCP1IE=1; //该捕捉允许中断
}
//名称:0或1判断函数
unsigned char one_zero(void)
{
//参看遥控器芯片HT6221的说明书,0编码的脉冲周期为1.12ms
//本例中,时间中断为0.25ms,所以我们判定取大于0.75ms小于1.5ms的脉冲均为0编码
if((tmr_times>2)&(tmr_times<7))
{
return 0;
}
//参看遥控器芯片HT6221的说明书,1编码的脉冲周期为2.24ms
//本例中,时间中断为0.25ms,所以我们判定取大于1.75ms小于2.75ms的脉冲均为1编码
else if((tmr_times>7)&(tmr_times<13))
{
return 1;
}
else
{
return 2;
}
//如果脉冲周期不在0.75-1.5ms或者1.75-2.75ms区间的,我们认为是错码,返回2
}
//---------------------------------------
//名称:中断服务程序
//---------------------------------------
void interrupt ISR(void) //PIC单片机的所有中断都是这一个入口
{
if(T0IF==1) //需要进一步判断是否是T0中断
{
T0IF=0; //清中断标志位,以备下次中断
TMR0=131; //定时器中断后,要重置初值,以备下次中断
//***此处用户自行添加定时器T0中断处理程序***
tmr_times++; //每250us计数一次
//******************************************
}
if(CCP1IF==1) //需要进一步判断是否是CCP1中断
{
CCP1IF=0; //清中断标志位,以备下次中断
GIE=0; //全局中断关掉,以避免解码过程进入其他中断
int_times++; //捕捉中断计次
if(head_ok==0) //如果还没接收到头码,那么先判断脉冲编码是否为头码
{
//参看遥控器芯片HT6221的说明书,发射代码的头码由一个9ms的起始码和一个4.5ms的结果码组成
//本例中,时间中断为0.25ms,所以我们判定大于12.5ms小于14.5ms的脉冲均为13.5ms的头码编码
if(tmr_times>0x31&tmr_times<0x37)
{
head_ok=1; //有效头码标志位置一,以示头码接收完成
int_times=0; //外部中断计次寄存器清零,以准备接收后面的4组共32个脉冲
tmr_times=0; //定时器中断计次寄存器清零,准备开始对后面的脉冲计时
TMR0=131;
}
else
{
wrong(); //如果不是有效的头码,转入错误处理程序
}
}
else //如果已经接收到头码,那么开始对后面的32个脉冲进行解码
{ TMR0=131;
code_data=code_data>>1; //将接收缓冲区右移一位,以准备接收下一位
buf1=one_zero(); //判断编码是0或1,或者是错码
tmr_times=0; //时间中断计次寄存器清零
if(buf1==1) //如果是编码1
{
code_data|=0x80; //将1移入code_data的最高位
}
else if(buf1==0) //如果是编码0
{
code_data&=0x7f; //将0移入code_data的最高位
}
else //编码非0非1,即为错码,
{
wrong(); //调用错误处理程序
return;
}
if(int_times==8) //如果收到了8个编码脉冲,意味着低8位地址码已经接收完
{
//本遥控器的低8位地址码为0X00,这个是遥控器厂家决定的,如果要订做,可以随便改
if(code_data!=0x00) //如果不是0x00 ,说明不是我们提供的遥控器,我们不予识别
{
wrong(); //调用错误处理程序
return;
}
}
else if(int_times==16) //如果收到了16个编码脉冲,意味着高8位地址码已经接收完
{
//本遥控器的低高8位地址码为0XFF
if(code_data!=0xFF) //如果不是0xff ,说明不是我们提供的遥控器,我们不予识别
{
wrong(); //调用错误处理程序
return;
}
}
else if(int_times==24) //收到的第三组8位字节即为8位数据码
{
code=code_data; //将这个8位数据码暂存至code_data1
}
else if(int_times==32) //收到的第四组8位字节即为8位数据码的反码
{
int_times=0; //清零中断次数寄存器,以便下次从头开始
head_ok=0; //将头码标志位清零,以便下次再接收时,从头码开始
if((code+code_data)==0xff) //判断第三组数据和第四组数据是否互为反码
{
code_ok=1; //如果互为反码,说明接收来的编码为正确,置位标志位,以通知液晶显示
}
}
}
}
GIE=1; //开放全局中断
}
//电机状态函数
void zheng_a() //电机A正转
{
RB2=1; //电机A控制口ENA
RB3=1; //电机A输入口IN1
RB4=0; //电机A输入口IN2
}
void fan_a() //电机A反转
{
RB2=1; //电机A控制口ENA
RB3=0; //电机A输入口IN1
RB4=1; //电机A输入口IN2
}
void ting_a() //电机A停
{
RB2=1; //电机A控制口ENA
RB3=0; //电机A输入口IN1
RB4=0; //电机A输入口IN2
}
void zheng_b() //电机B正转
{
RB5=1;//电机B控制口ENB
RB6=1; //电机B输入口IN3
RB7=0; //电机B输入口IN4
}
void fan_b() //电机B反转
{
RB5=1;//电机B控制口ENB
RB6=0; //电机B输入口IN3
RB7=1; //电机B输入口IN4
}
void ting_b() //电机B停
{
RB5=1;//电机B控制口ENB
RB6=0; //电机输入口IN3
RB7=0; //电机B输入口IN4
}
//---------------------------------------
//名称: 主函数
//---------------------------------------
void main(void) //主函数,单片机开机后就是从这个函数开始运行
{
init();
TMR0init();
ccp1init();
while(1) //死循环,单片机初始化后,将一直运行这个死循环
{
if(code_ok==1) //如果接收到了有效地的遥控器按键码
{
code_ok=0; //清掉该标志位
if(code==0x18) //按键2全速前进
{
zheng_a();
zheng_b();
//wrong();
delay_ms(300);
if(code==0x18)
{
zheng_a();
zheng_b();
}
else
{
ting_a();
ting_b();
}
}
if(code==0x52) //按键8全速后退
{
fan_a();
fan_b();
//wrong();
delay_ms(300);
if(code==0x52)
{
fan_a();
fan_b();
}
else
{
ting_a();
ting_b();
}
}
}
}
}
|
|