按键控制舵机,红外遥控电机,两段代码分开都可以运行,但组合在一起时,按键控制不了舵机,但舵机输出口有脉冲信号。可以指点一下么
#include
typedef unsigned char uchar;
typedef unsigned int uint;
sbit IN1=P2^1; //为1 电机反转
sbit IN2=P2^0; //为1 电机正转
sbit EN1=P2^2; //为1 电机使能
sbit sg90_con = P1^0; //舵机输出
int angle;
int cnt = 0;
sbit P1_6=P1^6; //传感器输入
sbit P1_7=P1^7; //舵机自动复位接gnd
sbit IR = P3^2; //红外输入
//--------------------//
//----------- 功能定义 -----------//
#define left_motor_en EN1=1 //左电机使能
#define left_motor_stops EN1=0 //左电机停止
#define left_motor_go IN1=1,IN2=0 //电机正转
#define left_motor_back IN1=0,IN2=1 //电机反转
//----------- 功能定义 -----------//
//函数定义
void forward();//前进
void backward();//后退
void stop();//停止
uchar IRtime; //检测红外高电平持续时间(脉宽)
uchar IRcord[4]; //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节)
uchar IRdata[33]; //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16)
bit IRpro_ok, IRok; //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕
void init();
void IRcordpro();
void Delay2000ms() //@12.000MHz
{
unsigned char i, j, k;
i = 92;
j = 50;
k = 238;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay300ms() //@12.000MHz
{
unsigned char i, j, k;
i = 14;
j = 174;
k = 224;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer1Init(void) //500微秒@12.000MHz
{
//AUXR &= 0xBF; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL1 = 0x0C; //设置定时初值
TH1 = 0xFE; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //打开定时器0中断
EA = 1; //打开总中断EA
}
void motor2() //舵机
{
if ((P1_6==0)&&(P1_7==0))
{
angle = 1; //0度 按下不动保持
cnt = 0;
Delay2000ms();
if ((P1_7==0)&&(P1_6==1))
{
angle = 3; //90度 1.5ms高电平
cnt = 0;
Delay2000ms();}}
}
void IRcordpro() //进行数据解码
{
uchar i, j, k, cord, value;
k = 1;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 8; j++)
{
cord = IRdata[k];
if(cord > 5)
value = value | 0x80;
if(j < 7)
{
value = value >> 1;
}
k++;
}
IRcord[i] = value;
value = 0;
}
IRpro_ok = 1;
}
/*******************主函数**************************/
void main()
{
init(); //执行初始化定时器0和外部中断0
EN1 = 0;//一开始时不使能电
Delay300ms();//让硬件稳定一下
Timer1Init(); //初始化定时器
angle = 3; //初始角度是90度,0.5ms,溢出1就是0.5,高电平
cnt = 0;
sg90_con = 1;//一开始从高电平开始
while(1)
{ motor2();
if(IRok) //判断脉宽是否检测完毕
{
IRcordpro();//根据脉宽解码出4个字节的数据
IRok = 0; //重新等待脉宽检测
if(IRpro_ok) //判断是否解码完毕
{
switch(IRcord[2])
{
case 0x0c: forward();break; //前进数字1
case 0x5e: backward();break; //后退数字3
case 0x18: stop();break;//停止数字2
default: break;
}
IRpro_ok = 0;
}
}
}
}
/*前进*/
void forward()
{
left_motor_en;
left_motor_go;//电机正转
}
/*后退*/
void backward()
{
left_motor_en;
left_motor_back;
}
/*停止*/
void stop()
{
left_motor_stops;//电机停止
}
void init() //初始化定时器0 和外部中断0
{
TMOD = 0x02; //定时器0工作方式2,8位自动重装
TH0 = 0x00; //高8位装入0那么定时器溢出一次的时间是256个机器周期
TL0 = 0x00;
TR0 = 1; //启动定时器0
IT0 = 1; //设置外部中断0为跳沿触发方式,来一个下降沿触发一次
EA = 1; //总中断
ET0 = 1; //定时器0中断
EX0 = 1; //启动外部中断0
}
void time0() interrupt 1 //定义定时器0
{
IRtime++; //检测脉宽,1次为278us
}
void int0() interrupt 0 //定义外部中断0
{
static uchar i;
static bit startflag;
if(startflag)
{
if( (IRtime < 53) && (IRtime >= 32) )
i = 0;
IRdata[i] = IRtime;
IRtime = 0;
i++;
if(i == 33)
{
IRok = 1;
i = 0;
}
}
else
{
IRtime = 0; //引导码开始进入把脉宽计数清零开始计数
startflag = 1; //开始处理标志位置1
}
}
void Time1Handler() interrupt 3
{
cnt++; //统计溢出的次数
//重新给初值
TL1 = 0x0c;
TH1 = 0xFE;
//控制PWM波
if(cnt < angle){
sg90_con = 1;
}else{
sg90_con = 0;
}
if(cnt == 40){ //当溢出40次,经过了20ms
cnt = 0;
sg90_con = 1;
}
}