为什么运行舵机就会导致单片机复位?
时间:10-02
整理:3721RD
点击:
我在做基于舵机调整方向的超声波避障的蓝牙遥控智能小车,用的是stc12c5a60s2单片机,超声波用外部中断和定时器1来测距,舵机用定时器0调整方向,小车的轮子转动是用单片机的内置两路PWM输出的,单独运行超声波时不会影响到PWM的输出,而运行舵机的时候就会导致单片机复位,求大神帮我看看原因啊!
#include<at89x51.h>
#include<STC12C5A60S2_PWM.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/***自定义一些数据*/
#define leftdata 0x11
#define rightdata 0x22
#define forwarddata 0x33
#define backdata 0x44
#define stopdata 0x55
/*****接线定义******/
sbit IN1=P1^5;
sbit IN2=P1^6;
sbit IN3=P1^1;
sbit IN4=P1^2;
sbit EN1=P1^3;
sbit EN2=P1^4;
/*****独立波特率发生器专用寄存器*******/
sfr AUXR=0x8e;//AUXR的SFR地址在0x8e
sfr BRT=0x9c;//BRT的SFR地址在0x9C
//*********************************************************************************************************
sbit trig = P3^2;
sbit echo = P3^3;
bit flagg; //中断进入标志
#define ControlPort P1_0
unsigned char push_val_left = 11;
unsigned char TimeOutCounter=0;
float dis=0;
unsigned char posit=0;
unsigned long S=0;
unsigned char const discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff};
unsigned char const positon[3]={ 0xbf,0xdf,0xef};
unsigned char disbuff[4] ={ 0,0,0,0,};
void Display(void) //扫描数码管
{
if(posit==0)
{P0=(discode[disbuff[posit]])&0x7f;}
else
{P0=discode[disbuff[posit]];}
P2=positon[posit];
if(++posit>=3)
posit=0;
}
void delay_20us()
{
uchar bt ;
for(bt = 0;bt<10;bt++);
}
//*************************************************************************************************
void Forward(unsigned char Speed_Right,unsigned char Speed_Left); //申明一个“前进函数”
void Stop(void);//申明一个“停止”函数
unsigned char SBUF_DATA,flag;
//void SendString(unsigned char *pt);
void Send_Char(unsigned char DATA);
//L 左
//R 右
void Forward(unsigned char Speed_Right,unsigned char Speed_Left)//Speed_Right,Speed_Left为左右电机对应的速度参数0-255之间,255最快,0最慢。
{
IN1=0;
IN2=1;
IN3=0;
IN4=1;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Back(unsigned char Speed_Right,unsigned char Speed_Left)//Speed_Right,Speed_Left为左右电机对应的速度参数0-255之间,255最快,0最慢。
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Turn_Left(unsigned char Speed_Right,unsigned char Speed_Left)
{
IN1=1;
IN2=0;
IN3=0;
IN4=1;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Turn_Right(unsigned char Speed_Right,unsigned char Speed_Left)
{
IN1=0;
IN2=1;
IN3=1;
IN4=0;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Stop(void) //刹车
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
PWM_Set(0,0);
}
void delayuus(unsigned char dela)
{
while(dela--);
}
void delayms(unsigned char nn)
{
while(nn--)
{
delayuus(245);
delayuus(245);
}
}
void test(void)
{
TH1 = 0x00;
TL1 = 0x00;
trig = 1;
delay_20us();
trig = 0;
while(!echo);
TR1 = 1;
EX1 = 1;
delayms(30);
if(flagg==1)
{ flagg=0;
dis = (TH1 * 256 + TL1);
S=(dis*1.7)/100; //算出来是CM
if(S>=700) //超出测量范围显示“-”
{
disbuff[0]=10; //“-”
disbuff[1]=10; //“-”
disbuff[2]=10; //“-”
}
else
{
disbuff[0]=S%1000/100;
disbuff[1]=S%1000%100/10;
disbuff[2]=S%1000%10 %10;
}
}
TH1=0;
TL1=0;
TR1=0;
EX1=0;
}
void ISR_INT1(void) interrupt 2
{
TR1=0;
EX1=0;
flagg=1;
}
void serial() interrupt 4 //中断法
{
flag=1; //如果产生了中断,说明单片机串口接收到数据,串口中断标志置1
SBUF_DATA=SBUF;//将接收到的数据存放到a中
RI=0;//中断标志
}
void time1()interrupt 1 //舵机PWM输出
{
TH0=(65536-125)/256;
TL0=(65536-125)%256;
TimeOutCounter ++;
switch(push_val_left)
{
case 6 :
{
if( TimeOutCounter <= 7) //右:7
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 7 : //
{
if( TimeOutCounter <= 16) //左
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 8 : //
{
if( TimeOutCounter <= 12) //中 12:中
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
default : break;
}
if( TimeOutCounter == 160 ) //周期20ms(理论值)
{
TimeOutCounter = 0;
}
}
void main(void)
{
unsigned char sudu=130;
PWM_ini();
//*****************************************************************************************************
TMOD=0x11;
TH1=0x00; //
TL1=0x00;
TH0=(65536-125)/256;
TL0=(65536-125)%256;
//TR0=1;
ET0=1;
//*********************************************************************************************************
SCON=0x50;// 0 1 0 1 0 0 0 0
//SM0 SM1 SM2 REN TB8 RB8 TI RI
//从上面化成二进制之后可以看到SCON的各位设置
//①SMO SM0=01 ,说明串口工作在方式1
//②REN=1,允许串口接收数据
BRT=0xfd;//9600波特率的初值
AUXR=0x11;//12T,BRTR=1启动独立波特率发生器
//S1BRS=1,串口1选着独立波特率发生器作为波特率发生器
PS=1; //中断太多,置串口为高优先级中断
ES=1;//允许串行中断
EA=1;//开总中断
IT1=1; //IT1=1表示边沿触发
TR0=1;
push_val_left=8;
delayms(240);
delayms(240);
TR0=0;
while(1)
{
if(SBUF_DATA==0x15)
{
TR0=0;
test(); //超声波测距
Display(); //数码管显示
if(S<=10)
{
TR0=1;
push_val_left=6;
delayms(240);
delayms(240);
delayms(240);
delayms(240);
push_val_left=7;
delayms(240);
delayms(240);
delayms(240);
delayms(240);
delayms(240);
delayms(240);
TR0=0;
}
else
{
TR0=0;
test();
Display();
}
}
if(flag==1)//如果产生过中断,证明串口接收到了数据
{ EX1=1;
flag=0;
switch(SBUF_DATA) //小车行驶方向控制 pwm
{
case leftdata: Turn_Left(sudu,sudu); break;
case rightdata: Turn_Right(sudu,sudu); break;
case forwarddata: Forward(sudu,sudu); break;
case backdata: Back(sudu,sudu); break;
case stopdata: Stop(); break;
default: break;
}
}
}
}
#include<at89x51.h>
#include<STC12C5A60S2_PWM.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/***自定义一些数据*/
#define leftdata 0x11
#define rightdata 0x22
#define forwarddata 0x33
#define backdata 0x44
#define stopdata 0x55
/*****接线定义******/
sbit IN1=P1^5;
sbit IN2=P1^6;
sbit IN3=P1^1;
sbit IN4=P1^2;
sbit EN1=P1^3;
sbit EN2=P1^4;
/*****独立波特率发生器专用寄存器*******/
sfr AUXR=0x8e;//AUXR的SFR地址在0x8e
sfr BRT=0x9c;//BRT的SFR地址在0x9C
//*********************************************************************************************************
sbit trig = P3^2;
sbit echo = P3^3;
bit flagg; //中断进入标志
#define ControlPort P1_0
unsigned char push_val_left = 11;
unsigned char TimeOutCounter=0;
float dis=0;
unsigned char posit=0;
unsigned long S=0;
unsigned char const discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff};
unsigned char const positon[3]={ 0xbf,0xdf,0xef};
unsigned char disbuff[4] ={ 0,0,0,0,};
void Display(void) //扫描数码管
{
if(posit==0)
{P0=(discode[disbuff[posit]])&0x7f;}
else
{P0=discode[disbuff[posit]];}
P2=positon[posit];
if(++posit>=3)
posit=0;
}
void delay_20us()
{
uchar bt ;
for(bt = 0;bt<10;bt++);
}
//*************************************************************************************************
void Forward(unsigned char Speed_Right,unsigned char Speed_Left); //申明一个“前进函数”
void Stop(void);//申明一个“停止”函数
unsigned char SBUF_DATA,flag;
//void SendString(unsigned char *pt);
void Send_Char(unsigned char DATA);
//L 左
//R 右
void Forward(unsigned char Speed_Right,unsigned char Speed_Left)//Speed_Right,Speed_Left为左右电机对应的速度参数0-255之间,255最快,0最慢。
{
IN1=0;
IN2=1;
IN3=0;
IN4=1;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Back(unsigned char Speed_Right,unsigned char Speed_Left)//Speed_Right,Speed_Left为左右电机对应的速度参数0-255之间,255最快,0最慢。
{
IN1=1;
IN2=0;
IN3=1;
IN4=0;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Turn_Left(unsigned char Speed_Right,unsigned char Speed_Left)
{
IN1=1;
IN2=0;
IN3=0;
IN4=1;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Turn_Right(unsigned char Speed_Right,unsigned char Speed_Left)
{
IN1=0;
IN2=1;
IN3=1;
IN4=0;
PWM_Set(255-Speed_Right,255-Speed_Left);
}
void Stop(void) //刹车
{
IN1=0;
IN2=0;
IN3=0;
IN4=0;
PWM_Set(0,0);
}
void delayuus(unsigned char dela)
{
while(dela--);
}
void delayms(unsigned char nn)
{
while(nn--)
{
delayuus(245);
delayuus(245);
}
}
void test(void)
{
TH1 = 0x00;
TL1 = 0x00;
trig = 1;
delay_20us();
trig = 0;
while(!echo);
TR1 = 1;
EX1 = 1;
delayms(30);
if(flagg==1)
{ flagg=0;
dis = (TH1 * 256 + TL1);
S=(dis*1.7)/100; //算出来是CM
if(S>=700) //超出测量范围显示“-”
{
disbuff[0]=10; //“-”
disbuff[1]=10; //“-”
disbuff[2]=10; //“-”
}
else
{
disbuff[0]=S%1000/100;
disbuff[1]=S%1000%100/10;
disbuff[2]=S%1000%10 %10;
}
}
TH1=0;
TL1=0;
TR1=0;
EX1=0;
}
void ISR_INT1(void) interrupt 2
{
TR1=0;
EX1=0;
flagg=1;
}
void serial() interrupt 4 //中断法
{
flag=1; //如果产生了中断,说明单片机串口接收到数据,串口中断标志置1
SBUF_DATA=SBUF;//将接收到的数据存放到a中
RI=0;//中断标志
}
void time1()interrupt 1 //舵机PWM输出
{
TH0=(65536-125)/256;
TL0=(65536-125)%256;
TimeOutCounter ++;
switch(push_val_left)
{
case 6 :
{
if( TimeOutCounter <= 7) //右:7
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 7 : //
{
if( TimeOutCounter <= 16) //左
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
case 8 : //
{
if( TimeOutCounter <= 12) //中 12:中
{
ControlPort = 1;
}
else
{
ControlPort = 0;
}
break;
}
default : break;
}
if( TimeOutCounter == 160 ) //周期20ms(理论值)
{
TimeOutCounter = 0;
}
}
void main(void)
{
unsigned char sudu=130;
PWM_ini();
//*****************************************************************************************************
TMOD=0x11;
TH1=0x00; //
TL1=0x00;
TH0=(65536-125)/256;
TL0=(65536-125)%256;
//TR0=1;
ET0=1;
//*********************************************************************************************************
SCON=0x50;// 0 1 0 1 0 0 0 0
//SM0 SM1 SM2 REN TB8 RB8 TI RI
//从上面化成二进制之后可以看到SCON的各位设置
//①SMO SM0=01 ,说明串口工作在方式1
//②REN=1,允许串口接收数据
BRT=0xfd;//9600波特率的初值
AUXR=0x11;//12T,BRTR=1启动独立波特率发生器
//S1BRS=1,串口1选着独立波特率发生器作为波特率发生器
PS=1; //中断太多,置串口为高优先级中断
ES=1;//允许串行中断
EA=1;//开总中断
IT1=1; //IT1=1表示边沿触发
TR0=1;
push_val_left=8;
delayms(240);
delayms(240);
TR0=0;
while(1)
{
if(SBUF_DATA==0x15)
{
TR0=0;
test(); //超声波测距
Display(); //数码管显示
if(S<=10)
{
TR0=1;
push_val_left=6;
delayms(240);
delayms(240);
delayms(240);
delayms(240);
push_val_left=7;
delayms(240);
delayms(240);
delayms(240);
delayms(240);
delayms(240);
delayms(240);
TR0=0;
}
else
{
TR0=0;
test();
Display();
}
}
if(flag==1)//如果产生过中断,证明串口接收到了数据
{ EX1=1;
flag=0;
switch(SBUF_DATA) //小车行驶方向控制 pwm
{
case leftdata: Turn_Left(sudu,sudu); break;
case rightdata: Turn_Right(sudu,sudu); break;
case forwarddata: Forward(sudu,sudu); break;
case backdata: Back(sudu,sudu); break;
case stopdata: Stop(); break;
default: break;
}
}
}
}
人工置顶啦。
舵机和单片机要单独供电
太复杂
看不懂
单片机实现不了,但是PLC我能实现了
电源电压波动,干扰单片机