如題,用的是stc89c52單片機,本人新手,想做一個超聲波測距小車,已實現測距,但連接小車時,小車不動,數碼管閃爍。
希望實現功能:小車可以邊運動邊測距,距離墻50mm時可以左轉,當左轉四次后停止。
標紅出為中斷地址重疊出,希望各位大佬可以給出解決代碼,謝謝大家
代碼如下
- #include"reg52.h"
- #include <intrins.h>
- sbit IN1=P1^0;
- sbit IN2=P1^1;
- sbit IN3=P1^2;
- sbit IN4=P1^3;
- sbit L_PWM=P1^4;
- sbit R_PWM=P1^5;
- sbit RX=P1^7;
- sbit TX=P1^6;
- unsigned int time=0;
unsigned int timer=0;
unsigned char posit=0;
unsigned long S=0;
bit flag =0;
//--定義使用的IO--//
#define GPIO_DIG P0
#define L_go IN1=0;IN2=1
#define L_back IN1=1;IN2=0
#define L_stop IN1=0;IN2=0
#define R_go IN3=0;IN4=1
#define R_back IN3=1;IN4=0
#define R_stop IN3=0;IN4=0 - #define car_go L_go;R_go;
#define car_back L_back;R_back
#define car_left R_go;L_stop
#define car_right L_go;R_stop
#define car_stop L_stop;R_stop
#define car_left_360 R_go;L_back
#define car_right_360 L_go;R_back - //定義數碼管位選控制信號
sbit LSA=P2^0;
sbit LSB=P2^1;
sbit LSC=P2^2;
sbit LSD=P2^3; - //--定義全局變量--//
unsigned char code DIG_CODE[17]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的顯示碼
unsigned char disbuff[4] ={ 0,0,0,0,};
//數據定義
unsigned char l_tt=0; //定時器計數用 - unsigned char l_Lpwm=0; //左輪PWM占空比值,我們設計10個格,0-9,0為停止,9為全速
unsigned char l_Rpwm=0; //右輪PWM占空比值,我們設計10個格,0-9,0為停止,9為全速
/*******************************************************************************
* 函 數 名 : DigDisplay
* 函數功能 : 使用數碼管顯示
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
void DigDisplay()
{
unsigned char i;
unsigned int j;
for(i=0;i<4;i++)
{
switch(i) //位選,選擇點亮的數碼管
{
case(0):
LSA=0;LSB=1;LSC=1;LSD=1; break;//顯示第1位
case(1):
LSA=1;LSB=0;LSC=1;LSD=1; break;//顯示第2位
case(2):
LSA=1;LSB=1;LSC=0;LSD=1; break;//顯示第3位
case(3):
LSA=1;LSB=1;LSC=1;LSD=0; break;//顯示第4位
}
GPIO_DIG=disbuff[ i];//發送段碼
j=10; //掃描間隔時間設定
while(j--);
GPIO_DIG=0xFF;//消隱
}
}
/********************************************************/
void Conut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S= (long)(time*0.17); //算出來是MM
if((S>=4000)||flag==1) //超出測量范圍顯示“ERR0”
{
flag=0;
disbuff[3]=0xc0; //“-”
disbuff[2]=~0x50; //“-”
disbuff[1]=~0x50; //“-”
disbuff[0]=0x86; //“-”
}
else
{
disbuff[0]=DIG_CODE[S%10000/1000];
disbuff[1]=DIG_CODE[S%1000/100];
disbuff[2]=DIG_CODE[S%100/10];
disbuff[3]=DIG_CODE[S%10/1];
}
}
/********************************************************/
void zd0() interrupt 1 //T0中斷用來計數器溢出,超過測距范圍
{
flag=1; //中斷溢出標志
}
/********************************************************/
void zd3() interrupt 3 //T1中斷用來掃描數碼管和計800MS啟動模塊
{
TH1=0xf8;
TL1=0x30;
DigDisplay();
timer++;
if(timer>=100)
{
timer=0;
TX=1; //800MS 啟動一次模塊
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TX=0;
}
}
/*********************************************************/
//TIMER0中斷服務子函數產生PWM信號
void timer0()interrupt 1 using 2
{
TH0=0XFC; //定時1毫秒,10格調速,為100HZ頻率,此頻率下效果比較好,過大有噪聲,過小振動大
TL0=0X17;
l_tt++;
if(l_tt>9)l_tt=0; //比較用,10格調速
if(l_tt<=l_Lpwm){//左調速,占空比數值越大,輸出高電平時間越寬,電機轉速越高,我們設計10個格,0-9,0為停止,9為全速
L_PWM=1;
}
else{
L_PWM=0;
}
if(l_tt<=l_Rpwm){//右調速,同上
R_PWM=1;
}
else{
R_PWM=0;
}
}- [ i]/*********************************************************/
- [ i] void main( void )
- [ i] { int i=0;
TMOD=0x11; //設T0為方式1,GATE=1;
TH0=0;
TL0=0;
TH1=0xf8; //2MS定時
TL1=0x30;
ET0=1; //允許T0中斷
ET1=1; //允許T1中斷
TR1=1; //開啟定時器
EA=1; //開啟總中斷
car_go; //前進
while(1)
{
while(!RX); //當RX為零時等待
TR0=1; //開啟計數
while(RX); //當RX為1計數并等待
TR0=0; //關閉計數
Conut(); //計算
if(S<=500)
{L_go;
i++;}
else
{car_go;}
if(i==3)
break; //左轉四次后跳出循環
}
car_stop;
} - [ i]謝謝大家
|