之前做的時候茍了一周編出來的程序
QX-A51小車跟隨前方障礙物運動
s2控制小車前進后退左轉右轉
s3跟蹤
s4光敏
功能蠻全的,跟蹤不是特別靈敏,跟小車硬件有關,可以再調整。
單片機源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- #include <C:\Users\Administrator\Desktop\QXA51.h>
- unsigned char pwm_left_val =180;//左電機占空比值 取值范圍0-170,0最快
- unsigned char pwm_right_val = 175;//右電機占空比值取值范圍0-170 ,0最快
- unsigned char pwm_t;//周期
- #define MAIN_Fosc 11059200UL //宏定義主時鐘HZ
- #define PCF8591_ADDR 0x90 //PCF8591地址
- #define DACOUT_EN 0x40 //DAC輸出使能
- typedef unsigned char INT8U;
- typedef unsigned char uchar;
- typedef unsigned int INT16U;
- typedef unsigned int uint;
- sbit SDA = P2^0; //I2C串行數據
- sbit SCL = P2^1; //I2C串行時鐘
- sbit we = P2^7; //位定義數碼管位選鎖存器接口
- sbit du = P2^6; //位定義數碼管位選鎖存器接口
- sbit LED0 = P1^0;
- sbit LED1 = P1^1;
- sbit LED2 = P1^2;
- sbit LED3 = P1^3;
- sbit LED4 = P1^4;
- sbit LED5 = P1^5;
- sbit LED6 = P1^6;
- sbit LED7 = P1^7;//led流水燈
- uchar code leddata[]={
- 0x3F, //"0"
- 0x06, //"1"
- 0x5B, //"2"
- 0x4F, //"3"
- 0x66, //"4"
- 0x6D, //"5"
- 0x7D, //"6"
- 0x07, //"7"
- 0x7F, //"8"
- 0x6F, //"9"
- 0x00, //熄滅
- 0x00 //自定義
- }; //數碼管段選表
- uchar AD_Value; //存儲AD轉換回的數字量
- uint i=0,a=0,b=0,c=0;
- void Delay_Ms(INT16U ms)
- {
- INT16U i;
- do{
- i = MAIN_Fosc / 96000;
- while(--i); //96T per loop
- }while(--ms);
- }
- void Delay5us()
- {
- #if MAIN_Fosc == 11059200
- _nop_();
- #elif MAIN_Fosc == 12000000
- _nop_();
- #elif MAIN_Fosc == 22118400
- _nop_(); _nop_(); _nop_();
- #endif
- }
- /*====================================
- 函數:I2C_init()
- 描述:I2C總線初始化
- ====================================*/
- void I2C_init()
- {
- SDA = 1; //數據總線高
- _nop_();
- SCL = 1; //時鐘總線高
- _nop_();
- }
- /*====================================
- 函數:I2C_Start()
- 描述:I2C起始信號
- ====================================*/
- void I2C_Start()
- {
- SCL = 1;
- _nop_();
- SDA = 1;
- Delay5us();
- SDA = 0;
- Delay5us();
- }
- /*====================================
- 函數:I2C_Stop()
- 描述:I2C停止信號
- ====================================*/
- void I2C_Stop()
- {
- SDA = 0;
- _nop_();
- SCL = 1;
- Delay5us();
- SDA = 1;
- Delay5us();
- }
- /*====================================
- 函數:Master_ACK(bit i)
- 參數:i 為0時發送非應答 為1時發送應答
- 描述:I2C主機發送應答
- ====================================*/
- void Master_ACK(bit i)
- {
- SCL = 0; // 拉低時鐘總線允許SDA數據總線上的數據變化
- _nop_(); // 讓總線穩定
- if (i) //如果i = 1 那么拉低數據總線 表示主機應答
- {
- SDA = 0;
- }
- else
- {
- SDA = 1; //發送非應答
- }
- _nop_();//讓總線穩定
- SCL = 1;//拉高時鐘總線 讓從機從SDA線上讀走 主機的應答信號
- _nop_();
- SCL = 0;//拉低時鐘總線, 占用總線繼續通信
- _nop_();
- SDA = 1;//釋放SDA數據總線。
- _nop_();
- }
- /*====================================
- 函數:Test_ACK()
- 返回:0為非應答 1為應答
- 描述:I2C檢測從機應答
- ====================================*/
- bit Test_ACK() // 檢測從機應答
- {
- SCL = 1;//時鐘總線為高電平期間可以讀取從機應答信號
- Delay5us();
- if (SDA)
- {
- SCL = 0;
- I2C_Stop();
- return(0);
- }
- else
- {
- SCL = 0;
- return(1);
- }
- }
- /*====================================
- 函數:I2C_send_byte(uchar byte)
- 參數:byte 要發送的字節
- 描述:I2C發送一個字節
- ====================================*/
- void I2C_send_byte(uchar byte)
- {
- uchar i;
- for(i = 0 ; i < 8 ; i++)
- {
- SCL = 0;
- _nop_();
- if (byte & 0x80) //
- {
- SDA = 1;
- _nop_();
- }
- else
- {
- SDA = 0;
- _nop_();
- }
- SCL = 1;
- _nop_();
- byte <<= 1;
- }
- SCL = 0;
- _nop_();
- SDA = 1;
- _nop_();
- }
- /*====================================
- 函數:I2C_read_byte()
- 返回:讀取的字節
- 描述:I2C讀一個字節
- ====================================*/
- uchar I2C_read_byte()
- {
- uchar i, dat;
- SCL = 0 ;
- _nop_();
- SDA = 1;
- _nop_();
- for(i = 0 ; i < 8 ; i++)
- {
- SCL = 1;
- _nop_();
- dat <<= 1;
- if (SDA)
- {
- dat |= 0x01;
- }
- _nop_();
- SCL = 0;
- _nop_();
- }
- return(dat);
- }
- /*DAC輸出*/
- bit DAC_OUT(uchar DAT)
- {
- I2C_Start();
- I2C_send_byte(PCF8591_ADDR+0);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_send_byte(DACOUT_EN); //DA輸出使能
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_send_byte(DAT);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_Stop();
- return(1);
- }
- /*讀AD數據*/
- bit ADC_Read(uchar CON)
- {
- I2C_Start();
- I2C_send_byte(PCF8591_ADDR+0);
- if (!Test_ACK())
- {
- return(0);
- }
- I2C_send_byte(CON);
- Master_ACK(0);
- I2C_Start();
- I2C_send_byte(PCF8591_ADDR+1);
- if (!Test_ACK())
- {
- return(0);
- }
- AD_Value = I2C_read_byte();
- Master_ACK(0);
- I2C_Stop();
- return(1);
- }
- /*小車前進*/
- void forward()
- {
- left_motor_en; //左電機使能
- right_motor_en;//右電機使能
- left_motor_go; //左電機前進
- right_motor_go; //右電機前進
- }
- /*小車后退*/
- void backward()
- {
- left_motor_en; //左電機使能
- right_motor_en;//右電機使能
- left_motor_back; //左電機后退
- right_motor_back; //右電機后退
- }
- /*小車左轉*/
- void left()
- {
- left_motor_stops; //左電機停止
- right_motor_en;//右電機使能
- right_motor_go; //右電機前進
- }
- /*小車右轉*/
- void right()
- {
- right_motor_stops;//右電機停止
- left_motor_en; //左電機使能
- left_motor_go; //左電機前進
- }
- /*小車停止*/
- void stop()
- {
- right_motor_stops;//右電機停止
- left_motor_stops; //左電機停止
- }
- void timer0() interrupt 1
- {
- pwm_t++;//周期計時加
- if(pwm_t == 255)
- pwm_t = EN1 = EN2 = 0;
- if(pwm_left_val == pwm_t)//左電機占空比
- EN1 = 1;
- if(pwm_right_val == pwm_t)//右電機占空比
- EN2 = 1;
- }
- void main()
- {
- unsigned char j;
- for(;;)
- {
- while(1)
- {
- if(key_s2 == 0)//判斷S2是否按下
- {
- Delay_Ms(5);//軟件消抖
- if(key_s2 == 0)
- {
- while(!key_s2);//松手檢測
- beep = 0;
- Delay_Ms(1000);
- beep = 1;
-
- TMOD |= 0x02;//8位自動重裝模塊
- TH0 = 220;
- TL0 = 220;//11.0592M晶振下占空比最大比值是256,輸出100HZ
- TR0 = 1;//啟動定時器0
- ET0 = 1;//允許定時器0中斷
- EA = 1;
-
- forward();//小車前進
- Delay_Ms(1000);//毫秒級延時
-
- stop();//小車停止
- Delay_Ms(1000);//毫秒級延時
-
- backward();//小車后退
- beep = 0;//蜂鳴器鳴叫
- Delay_Ms(1000);//毫秒級延時
-
- stop();//小車停止
- beep = 1;//蜂鳴器停止鳴叫
- Delay_Ms(1000);//毫秒級延時
-
- left(); // 小車左轉
- beep = 0;//蜂鳴器鳴叫
- Delay_Ms(1000);//毫秒級延時
-
- stop();//小車停止
- beep = 1;//蜂鳴器停止鳴叫
- Delay_Ms(1000);//毫秒級延時
-
- right();// 小車右轉延時
- beep = 0;//蜂鳴器鳴叫
- Delay_Ms(1000);//毫秒級延時
-
- stop();//小車停止
- beep=1;//蜂鳴器停止鳴叫
- Delay_Ms(1000);//毫秒級延時
- }
- }
- if(key_s3 == 0)//判斷S3是否按下
- {
- Delay_Ms(5);//軟件消抖
- if(key_s3 == 0)
- {
- while(!key_s3);//松手檢測
- beep = 0;//蜂鳴器鳴叫
- Delay_Ms(1000);//毫秒級延時
- beep = 1;//蜂鳴器停止鳴叫
- TMOD |= 0x02;//8位自動重裝模塊
- TH0 = 220;
- TL0 = 220;//11.0592M晶振下占空比最大比值是256,輸出100HZ
- TR0 = 1;//啟動定時器0
- ET0 = 1;//允許定時器0中斷
- EA = 1;
- I2C_init();
- while(1)
- {
- if (ADC_Read(0x00))
- if (DAC_OUT(AD_Value))
- if (AD_Value > 150) {stop(); }
- else {forward(); }
- Delay_Ms(5);
- }
- }
- }
- if(key_s4 == 0)// 實時檢測S3按鍵是否被按下
- {
- Delay_Ms(5);//軟件消抖
- if(key_s4 == 0)//再檢測S3是否被按下
- {
- while(!key_s4);//松手檢測
- beep = 0; //使能有源蜂鳴器
- Delay_Ms(1000);//200毫秒延時
- beep = 1; //關閉有源蜂鳴器
- TMOD |= 0x02;//8位自動重裝模塊
- TH0 = 220;
- TL0 = 220;//11.0592M晶振下占空比最大比值是256,輸出100HZ
- TR0 = 1;//啟動定時器0
- ET0 = 1;//允許定時器0中斷
- EA = 1;//總中斷允許
-
- while(1)
- {
- we = 1;//打開位選
- P0 = 0xfe;//,注意數碼管的排序,P0.0對應連接的是左邊第一位數碼管
- we = 0; //關閉位選
- du = 1; //打開段選
- P0 = leddata[b];
- du = 0; //關閉段選
- Delay_Ms(1);
-
- we = 1;//打開位選
- P0 = 0xfd;//,注意數碼管的排序,P0.0對應連接的是左邊第一位數碼管
- we = 0; //關閉位選
- du = 1; //打開段選
- P0 = leddata[i];
- du = 0; //關閉段選
- Delay_Ms(1);
-
- if(left_led2 == 1 && right_led2 == 1)//為0 識別障礙物 為1沒有識別到障礙物
- { stop();
- }
-
- if(left_led2 == 0 && right_led2 == 0)//左右識別到障礙物,前進跟隨
- {
- forward();
- for(c=0;c<=27000;c++)
- {
- if(c==27000)
- { j++;
- a++;}
- }
- }
- if(left_led2 == 1 && right_led2 == 0)//小車右側識別到障礙物,右轉跟隨
- {
- right();
- for(c=0;c<=27000;c++)
- {
- if(c==27000)
- { j++;
- a++;}
- }
- }
-
- if(left_led2 == 0 && right_led2 == 1)//小車左側識別到障礙物,左轉跟隨
- {
- left();
- for(c=0;c<=27000;c++)
- {
- if(c==27000)
- { j++;
- a++;}
- }
- }
-
- if(j==10) //當數值為10時,清零
- {
- j=0;
- b++;
- }
- if(b==9)
- { b=0;}
- if(a==90)
- {
- a=0;
- j=0;
- b=0;
- }
- }
- }
- }
- }
- break;
- }
- }
復制代碼
所有資料51hei提供下載:
程序.rar
(35.83 KB, 下載次數: 16)
2019-3-24 09:58 上傳
點擊文件名下載附件
|