欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
Smart_car4紅外避障+超聲波跟隨設計源代碼
[打印本頁]
作者:
QXDBOY
時間:
2018-6-1 17:05
標題:
Smart_car4紅外避障+超聲波跟隨設計源代碼
這是我上個月做的單片機智能小車,目前可實現紅外避障和藍牙遙控。保證原創,請多多指教。
0.png
(9.36 KB, 下載次數: 31)
下載附件
2018-6-2 01:40 上傳
單片機源程序如下:
#include<reg52.h>
#include<C52_car.h>
#include <intrins.h>//包含_nop_指令的頭文件
#define MAIN_Fosc 11059200UL //宏定義主時鐘HZ
#define PCF8591_ADDR 0x90 //PCF8591地址
#define DACOUT_EN 0x40 //DAC輸出使能
typedef unsigned char uchar;
typedef unsigned int uint;
unsigned char pwm_left_val = 0;//左電機占空比值 取值范圍0-80,0最快
unsigned char pwm_right_val = 0;//右電機占空比值取值范圍0-80 ,0最快
unsigned char pwm_t = 0;//周期
unsigned char control=0X01;//車運動控制全局變量,默認開機為停車狀態
unsigned int time = 0;//傳輸時間
unsigned long S = 0;//距離
unsigned char count=0;
unsigned char SEH_count; //舵機朝向前面
#define LCD1602_DB P0 //LCD1602數據總線
uchar Control_mode = 0;
uchar AD_Value; //存儲AD轉換回的數字量
sbit LCD1602_RS = P3^5; //RS端
sbit LCD1602_RW = P3^6; //RW端
sbit LCD1602_EN = P3^4; //EN端
sbit DU = P2^6;//
sbit WE = P2^7;//數碼管位選段選用于關閉數碼管顯示
void delay(unsigned int z)//毫秒級延時
{
unsigned int x,y;
for(x = z; x > 0; x--)
for(y = 114; y > 0 ; y--);
}
void Delay10us(unsigned char i) //10us延時函數 啟動超聲波模塊時使用
{
unsigned char j;
do{
j = 10;
do{
_nop_();
}while(--j);
}while(--i);
}
/*====================================
函數:void Delay5us()
描述:12T 51單片機5微秒延時函數自適應時鐘(11.0592M,12M,22.1184M)
====================================*/
void Delay5us()
{
#if MAIN_Fosc == 11059200
_nop_();
#elif MAIN_Fosc == 12000000
_nop_();
#elif MAIN_Fosc == 22118400
_nop_(); _nop_(); _nop_();
#endif
}
/*小車前進*/
void forward()
{
left_motor_go; //左電機前進
right_motor_go; //右電機前進
}
/*小車左轉*/
void left_run()
{
left_motor_stops; //左電機停止
right_motor_go; //右電機前進
}
/*小車右轉*/
void right_run()
{
right_motor_stops;//右電機停止
left_motor_go; //左電機前進
}
/*PWM控制使能 小車后退*/
void backward()
{
left_motor_back; //左電機后退
right_motor_back; //右電機后退
}
void stop()
{
left_motor_stops; //左電機后退
right_motor_stops; //右電機后退
}
void Init(void)
{
EA = 1; //開總中斷
PT0 = 1;
IT0 = 0; //邊沿觸發方式
IT1 = 0; //邊沿觸發方式
SCON |= 0x50; // SCON: 模式1, 8-bit UART, 使能接收
T2CON |= 0x34; //設置定時器2為串口波特率發生器并啟動定時器2
TL2 = RCAP2L = (65536-(FOSC/32/BAUD)); //設置波特率
TH2 = RCAP2H = (65536-(FOSC/32/BAUD)) >> 8;
ES= 1; //打開串口中斷
TMOD |= 0x01; //定時器0,工作模式1,16位定時模式
TH0 = 0;
TL0 = 0; //T0,16位定時計數用于記錄ECHO高電平時間
TR0 = 1; //啟動定時器0
ET0 = 1; //允許定時器0中斷
TMOD |= 0x10; //定時器1,16位定時模式。
TH1 = 0xff; //配置定時器0初值,溢出時間為0.1ms
TL1 = 0xa3;
TR1 = 1; //啟動定時器1
ET1 = 1; //允許T1中斷
}
void StartModule() //啟動超聲波模塊
{
TX=1; //啟動一次模塊
Delay10us(2);
TX=0;
}
/*計算超聲波所測距離并顯示*/
void Conut()
{
time=TH0*256+TL0;
TH0 = 0;
TL0 = 0;
S=(float)(time*1.085)*0.17; //算出來是MM
if(S>=7000) //超出測量范圍
{
stop();
beep = 0;
delay(1000);
beep = 1;
}
}
/*====================================
函數:void SEH_count_0()
描述:舵機在左側時指令
====================================*/
void SEH_count_5()
{
StartModule(); //啟動模塊測距
while(!RX); //當RX(ECHO信號回響)為零時等待
TR0 = 1; //開啟計數
while(RX) ; //當RX為1計數并等待
TR0 = 0; //關閉計數
Conut(); //計算距離
if(S > 170 && S <850 )//設置隨動距離(單位毫米)
{
left_run();
}
}
/*====================================
函數:void SEH_count_10()
描述:舵機在中間時指令
====================================*/
void SEH_count_10()
{
StartModule(); //啟動模塊測距
while(!RX); //當RX(ECHO信號回響)為零時等待
TR0 = 1; //開啟計數
while(RX) ; //當RX為1計數并等待
TR0 = 0; //關閉計數
Conut(); //計算距離
if(S > 170 && S <850 )//設置隨動距離(單位毫米)
{
forward();
}
}
/*====================================
函數:void SEH_count_20()
描述:舵機在右側時指令
====================================*/
void SEH_count_15()
{
StartModule(); //啟動模塊測距
while(!RX); //當RX(ECHO信號回響)為零時等待
TR0 = 1; //開啟計數
while(RX) ; //當RX為1計數并等待
TR0 = 0; //關閉計數
Conut(); //計算距離
if(S > 150 && S <850 )//設置隨動距離(單位毫米)
{
right_run();
}
}
/*====================================
函數: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);
}
/*讀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);
}
/*=================================================
*函數名稱:Read_Busy
*函數功能:判斷1602液晶忙,并等待
=================================================*/
void Read_Busy()
{
uchar busy;
LCD1602_DB = 0xff;//復位數據總線
LCD1602_RS = 0; //拉低RS
LCD1602_RW = 1; //拉高RW讀
do
{
LCD1602_EN = 1;//使能EN
busy = LCD1602_DB;//讀回數據
LCD1602_EN = 0; //拉低使能以便于下一次產生上升沿
}while(busy & 0x80); //判斷狀態字BIT7位是否為1,為1則表示忙,程序等待
}
/*=================================================
*函數名稱:LCD1602_Write_Cmd
*函數功能:寫LCD1602命令
*調用:Read_Busy();
*輸入:cmd:要寫的命令
=================================================*/
void LCD1602_Write_Cmd(uchar cmd)
{
Read_Busy(); //判斷忙,忙則等待
LCD1602_RS = 0;
LCD1602_RW = 0; //拉低RS、RW操作時序情況1602課件下中文使用說明基本操作時序章節
LCD1602_DB = cmd;//寫入命令
LCD1602_EN = 1; //拉高使能端 數據被傳輸到LCD1602內
LCD1602_EN = 0; //拉低使能以便于下一次產生上升沿
}
/*=================================================
*函數名稱:LCD1602_Write_Dat
*函數功能:寫LCD1602數據
*調用:Read_Busy();
*輸入:dat:需要寫入的數據
=================================================*/
void LCD1602_Write_Dat(uchar dat)
{
Read_Busy();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_EN = 1;
LCD1602_EN = 0;
}
/*=================================================
*函數名稱:LCD1602_Dis_Str
*函數功能:在指定位置顯示字符串
*調用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();
*輸入:x:要顯示的橫坐標取值0-40,y:要顯示的行坐標取值0-1(0為第一行,1為第二行)
*str:需要顯示的字符串
=================================================*/
void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)
{
if(y) x |= 0x40;
x |= 0x80;
LCD1602_Write_Cmd(x);
while(*str != '\0')
{
LCD1602_Write_Dat(*str++);
}
}
/*=================================================
*函數名稱:Init_LCD1602
*函數功能:1602初始化
*調用: LCD1602_Write_Cmd();
=================================================*/
void Init_LCD1602()
{
LCD1602_Write_Cmd(0x38); // 設置16*2顯示,5*7點陣,8位數據接口
LCD1602_Write_Cmd(0x0c); //開顯示
LCD1602_Write_Cmd(0x06); //讀寫一字節后地址指針加1
LCD1602_Write_Cmd(0x01); //清除顯示
}
/*=================================================
*函數名稱:Dispaly_LCD1602
*函數功能:1602顯示字符
*調用: LCD1602_Write_Cmd();
=================================================*/
void Dispaly_LCD1602()
{
int LCD_CK=0;
uchar Str_1[] = {"Welcome to use"};
uchar Str_2[] = {"Pick a pattern"};
uchar Str_3[] = {"S2 -> automatic"};
uchar Str_4[] = {"S3 -> bluetooth"};
Init_LCD1602();//1602初始化
for(;;) //死循環
{
if(LCD_CK == 0)
{
LCD1602_Dis_Str(0, 0, &Str_1[0]); //顯示字符串
LCD1602_Dis_Str(0, 1, &Str_2[0]); //顯示字符串
delay(10);
}
if(LCD_CK == 20000)
{
LCD1602_Dis_Str(0, 0, &Str_3[0]); //顯示字符串
LCD1602_Dis_Str(0, 1, &Str_4[0]); //顯示字符串
delay(10);
}/**/
if(key_s2 == 0)// 實時檢測S2按鍵是否被按下
{
delay(5); //軟件消抖
if(key_s2 == 0)//再檢測S2是否被按下
{
while(!key_s2);//松手檢測
delay(50);//50毫秒延時
Control_mode = 0;
break; //退出FOR死循環
}
}
if(key_s3 == 0)// 實時檢測S3按鍵是否被按下
{
delay(5); //軟件消抖
if(key_s3 == 0)//再檢測S3是否被按下
{
while(!key_s3);//松手檢測
delay(50);//50毫秒延時
Control_mode = 1;
break; //退出FOR死循環
}
}
if(LCD_CK <= 40000) LCD_CK++;
if(LCD_CK >= 40000) LCD_CK = 0;
}
}
void main()
{
DU = 0;
WE = 0;
EN2 = EN1 =1;
SEH_count = 10;
Dispaly_LCD1602();
I2C_init();//I2C初始化
LCD1602_Write_Cmd(0x08); //關閉1602顯示
Init();//定時器、串口初始化Init();//定時器、串口初始化
beep = 0;
delay(200);//延時1秒
beep = 1;
while(1)
{
if(Control_mode == 1)
{
EX0 = 0; //關閉外部中斷1
EX1 = 0; //關閉外部中斷2
while(1)
{
if(control>0X07)//如果成立,則表示接收的命令不在運行命令內
{
stop(); // 停車
}
switch(control)
{
case 0X02: forward(); break;//前進
case 0X03: backward(); break;//后退
case 0X04: left_run(); break;//左轉
case 0X05: right_run(); break;//右轉
case 0X01: stop(); break;//停車
case 0X08: beep = 0; break;//鳴笛
case 0X09: beep = 1; break;//停止鳴笛
case 0X0B: SEH_count = 10; break;//SEH_COUNT: 10:0.5+1(0.1*10T)=1.5ms->90°舵機角度
case 0X0A: Control_mode = 0;break;
}
break;
}
}
if(Control_mode == 0)
{
EX0 = 1; //打開外部中斷1
EX1 = 1; //打開外部中斷2
for (;;)
{
SEH_count = 12;
delay(300);
ADC_Read(0x03);//體感模塊,當檢測到人體收輸出3.3高電平
if(AD_Value > 100) SEH_count_10();
SEH_count = 6;
delay(300);
ADC_Read(0x03);//體感模塊,當檢測到人體收輸出3.3高電平
if(AD_Value > 100) SEH_count_5();//大于3.1V表示感應到了人體,小車行進
SEH_count = 12;
delay(300);
ADC_Read(0x03);//體感模塊,當檢測到人體收輸出3.3高電平
if(AD_Value > 100) SEH_count_10();
SEH_count = 18;
delay(300);
ADC_Read(0x03);//體感模塊,當檢測到人體收輸出3.3高電平
if(AD_Value > 150) SEH_count_15();
if(control == 0X0C)
{
Control_mode = 1;
break;
}
}
}
}
}
void int0() interrupt 0
{
EX0 = 0;
delay(10);
if(left_led2 == 0)
{
backward();
delay(500);
key_s3 = 1;
right_run();
delay(700);
forward();
delay(500);
stop();
}
EX0 = 1;
}
//定時器0中斷
void timer0() interrupt 1
{
/* pwm_t++;//周期計時加
if(pwm_t == 120)
pwm_t = EN1 = EN2 = 0;
if(pwm_left_val == pwm_t)//左電機占空比
EN1 = 1;
if(pwm_right_val == pwm_t)//右電機占空比
EN2 = 1;
*/
}
void int1() interrupt 2
{
EX1 = 0;
delay(10);
if(right_led2 == 0)
{
backward();
delay(500);
key_s3 = 1;
left_run();
delay(700);
forward();
delay(500);
stop();
}
EX1 = 1;
}
//定時器1中斷
void timer1() interrupt 3 //T1中斷用來計數器溢出
{
TR1 = 0; //關閉定時器1
TH1 = 0xff; //重裝初值0.1ms
TL1 = 0xa3;
//舵機1
if(count <= SEH_count) //控制占空比左右
{
//如果count的計數小于(5-25)也就是0.5ms-2.5ms則這段小t周期持續高電平。產生方波
Servo = 1;
}
else
{
Servo = 0;
}
count++;
if (count >= 200) //T = 20ms則定時器計數變量清0
{
count = 0;
}
TR1 = 1; //開啟定時器1
}
/******************************************************************/
/* 串口中斷程序*/
/******************************************************************/
void UART_SER () interrupt 4
{
unsigned char n; //定義臨時變量
if(RI) //判斷是接收中斷產生
{
RI=0; //標志位清零
n=SBUF; //讀入緩沖區的值
control=n;
/* if((n >= 51) && (n <= 150))//左電機調速0~100個檔位 手機端軟件進行調節
pwm_left_val = 0.8-((n-50)*0.8);
if((n >= 151) && (n <= 250)) //右電機調速0~100個檔位 手機端軟件進行調節
pwm_right_val = 0.8-((n-150)*0.8);*/
if((n >= 51) && (n <= 150))//左電機調速0~100個檔位 手機端軟件進行調節
pwm_left_val = 1.7-((n-50)*1.7);
if((n >= 151) && (n <= 250)) //右電機調速0~100個檔位 手機端軟件進行調節
pwm_right_val = 1.7-((n-150)*1.7);
}
}
復制代碼
所有資料51hei提供下載:
Smart_car4 紅外避障&超聲波跟隨.rar
(56.44 KB, 下載次數: 25)
2018-6-1 17:04 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1