標(biāo)題:
STM32紅外舵機(jī)自動(dòng)壁障小車(chē)源程序
[打印本頁(yè)]
作者:
zxcvbnm..
時(shí)間:
2018-4-8 17:37
標(biāo)題:
STM32紅外舵機(jī)自動(dòng)壁障小車(chē)源程序
基于STM32的紅外舵機(jī)自動(dòng)壁障小車(chē)
單片機(jī)源程序如下:
#include "stm32f10x_it.h"
#include "stm32f10x_lib.h"
#include "stm32f10x_type.h"
#include "stm32f10x_usart.h"
#include "defines.h"
#include "stm32f10x_flash.h"
#include "cpu.h"
#include <stdio.h>
#define FLASH_ADDRESS (0x08000000 + 1024 * 32 - 4096) /* 存儲(chǔ)數(shù)據(jù)Flash頁(yè)首地址 */
#define DUTY_WIDTH 25 //占空比最大級(jí)數(shù)
#define CAR_QIAN_JIN 0 //小車(chē)前進(jìn)
#define CAR_HOU_TUI 1 //小車(chē)后退
u8 debug_switch = 0;//調(diào)試開(kāi)關(guān)
u32 IR_ref_value_L = 0;//紅外感應(yīng)參考值,開(kāi)機(jī)前將小車(chē)置于空曠位置,系統(tǒng)便于識(shí)別環(huán)境光強(qiáng)度
u32 IR_ref_value_R = 0;//紅外感應(yīng)參考值,開(kāi)機(jī)前將小車(chē)置于空曠位置,系統(tǒng)便于識(shí)別環(huán)境光強(qiáng)度
u8 moto_run = 0;//電機(jī)運(yùn)行標(biāo)志
u8 moto_R_speed = 0;//電機(jī)速度
u8 moto_R_dir = CAR_QIAN_JIN;//電機(jī)方向
u8 moto_L_speed = 0;//電機(jī)速度
u8 moto_L_dir = CAR_QIAN_JIN;//電機(jī)方向
u8 moto_speed = 0;//電機(jī)前進(jìn)的速度
s8 moto_speed_adj = 1;//左右電機(jī)速度校正,-3~+3,已左邊輪子速度為基準(zhǔn),在右邊輪子速度加校正值
//u32 TIME_L_R = (TIMER_FREQ / 3);//轉(zhuǎn)彎時(shí)間,完成后自動(dòng)歸正
u8 moto_L_switch = 0;//左轉(zhuǎn)有效
u8 moto_R_switch = 0;//右轉(zhuǎn)有效
u32 left_turn_cnt = 0; //轉(zhuǎn)彎時(shí)間定時(shí)器
u32 right_turn_cnt = 0; //轉(zhuǎn)彎時(shí)間定時(shí)器
u32 b_led_cnt = 0;//剎車(chē)燈時(shí)間定時(shí)器
u32 beep_cnt = 0;//喇叭時(shí)間定時(shí)器,ms
u8 lamp_front_bright = 0; //大燈亮度
u8 lamp_f = 0; //大燈開(kāi)關(guān)切換
void Lamp_front(u8 de);
/***********************************************************************
函數(shù)功能: 寫(xiě)flash,數(shù)據(jù)長(zhǎng)度不超過(guò)1扇區(qū)
入口參數(shù):
出口參數(shù):
***********************************************************************/
void WriteFlash(u32 byte_addr , u16 len , u8 *dat)
{
u16 i = 0;
len = len / 2 * 2 + (len % 2) * 2;
FLASH_Unlock();
FLASH_ErasePage(byte_addr); /* 擦除頁(yè) */
//FLASH_ProgramWord(FLASH_ADR,0 << 1 | 0); /* 寫(xiě)16位半字 */
for(i = 0 ; i < len ; i += 2)
{
FLASH_ProgramHalfWord(byte_addr + i , *(u16*)&dat[i]); /* 寫(xiě)16位半字 */
}
FLASH_Lock();
}
/***********************************************************************
函數(shù)功能:延時(shí)_dlytime毫秒
入口參數(shù):
出口參數(shù):
***********************************************************************/
void Delay_ms(u32 _dlytime)
{
u32 i;
u32 j;
for (i = 0; i < _dlytime * 10; i++)
for (j = 0; j < 0xff; j++);
}
/***********************************************************************
函數(shù)功能:延時(shí)
入口參數(shù):
出口參數(shù):
***********************************************************************/
void Delay(u32 _dlytime)
{
u32 i;
u32 j;
for (i = 0; i < _dlytime * 1; i++)
for (j = 0; j < 0x13; j++);
}
/***********************************************************************
函數(shù)功能:獲取AD值
入口參數(shù):
出口參數(shù):
***********************************************************************/
u16 GetADCVal(u8 ADC_Channel)
{
ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_239Cycles5);
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
return ADC_GetConversionValue(ADC1);
}
/***********************************************************************
函數(shù)功能:判斷左側(cè)是否有障礙物
入口參數(shù):
出口參數(shù): 1:有障礙,
***********************************************************************/
u8 CheckHinder_Left()
{
u16 adc = 0 , avg = 0;
static u32 adc_temp = 0 , times = 0;
adc = GetADCVal(ADC_Channel_5);
adc_temp += adc;
times ++;
if(adc > IR_ref_value_L + 350)
return 1;
avg = (adc_temp / times); //獲取平均值
if(adc > avg + 60)//如果當(dāng)前值大于平均值較多,也認(rèn)為是有障礙
return 2;
return 0;
}
/***********************************************************************
函數(shù)功能:判斷右側(cè)是否有障礙物
入口參數(shù):
出口參數(shù): 1:有障礙,
***********************************************************************/
u8 CheckHinder_Right()
{
u16 adc = 0 , avg = 0;
static u32 adc_temp = 0 , times = 0;
adc = GetADCVal(ADC_Channel_4);
adc_temp += adc;
times ++;
if(adc > IR_ref_value_R + 150)
return 1;
avg = (adc_temp / times); //獲取平均值
if(adc > avg + 50)//如果當(dāng)前值大于平均值較多,也認(rèn)為是有障礙
return 2;
return 0;
}
/***********************************************************************
函數(shù)功能:向串口發(fā)數(shù)據(jù)
入口參數(shù):
出口參數(shù):
***********************************************************************/
void SendDataToUart(u8 dat)
{
UART1_SendByte(dat);
}
/***********************************************************************
函數(shù)功能:發(fā)送數(shù)據(jù)
入口參數(shù):
出口參數(shù):
***********************************************************************/
void SendStrToUart(char*str)
{
while(*str)
{
SendDataToUart(*str ++);
}
}
/***********************************************************************
函數(shù)功能:
入口參數(shù):
出口參數(shù):
***********************************************************************/
void Timer2ISR(void)
{
static u32 cnt = 0 , st = 0 , cnt_t = 0 , beep_freq_cnt = 0 , beep_freq = 1000 ;
static u8 b = 0 , l_r_led = 0;
static u32 l_r_led_cnt = 0;//轉(zhuǎn)彎燈時(shí)間定時(shí)器
u32 audio_adc_val = 0;
//
if(cnt < DUTY_WIDTH)//占空比計(jì)數(shù)
{
cnt ++;
}
else
{
cnt = 0;
}
GPIO_WriteBit(GPIOC , GPIO_Pin_13 , l_r_led); //cpu狀態(tài)指示燈
GPIO_WriteBit(GPIOB, GPIO_Pin_2 , l_r_led);
//剎車(chē)燈控制
if(b_led_cnt < TIMER_FREQ / 2)
{
b_led_cnt ++;
GPIO_WriteBit(GPIOB, GPIO_Pin_2 , 1);
}
else
{
//GPIO_WriteBit(GPIOB, GPIO_Pin_2 , 0);
}
if(l_r_led_cnt < TIMER_FREQ / 5)
{
l_r_led_cnt ++ ;
}
else
{
l_r_led_cnt = 0;
l_r_led = !l_r_led;
}
//轉(zhuǎn)彎控制
if(moto_L_switch) //左轉(zhuǎn)
{
if(left_turn_cnt > 0)
{
left_turn_cnt --;
GPIO_WriteBit(GPIOA, GPIO_Pin_1 , l_r_led);
GPIO_WriteBit(GPIOA, GPIO_Pin_12 , 0);
}
else
{
moto_L_speed = moto_speed;//轉(zhuǎn)彎結(jié)束,自動(dòng)歸正
moto_R_speed = moto_speed;//轉(zhuǎn)彎結(jié)束,自動(dòng)歸正
moto_L_switch = 0;
moto_L_dir = CAR_QIAN_JIN;
moto_R_dir = CAR_QIAN_JIN;
GPIO_WriteBit(GPIOA, GPIO_Pin_1 , 0);
}
}
else
if(moto_R_switch) //右轉(zhuǎn)
{
if(right_turn_cnt > 0)
{
right_turn_cnt --;
GPIO_WriteBit(GPIOA, GPIO_Pin_12 , l_r_led);
GPIO_WriteBit(GPIOA, GPIO_Pin_1 , 0);
}
else
{
moto_L_speed = moto_speed;//轉(zhuǎn)彎結(jié)束,自動(dòng)歸正
moto_R_speed = moto_speed;//轉(zhuǎn)彎結(jié)束,自動(dòng)歸正
moto_R_switch = 0;
moto_R_dir = CAR_QIAN_JIN;
moto_L_dir = CAR_QIAN_JIN;
GPIO_WriteBit(GPIOA, GPIO_Pin_12 , 0);
}
}
//右電機(jī)控制,定時(shí)器模擬PWM控制
GPIO_WriteBit(GPIOB, GPIO_Pin_3 , moto_R_speed > 0 ? (cnt <= moto_R_speed + moto_speed_adj ? (moto_R_dir == CAR_QIAN_JIN ? moto_run & 1 : 0) : 0) : 0);
GPIO_WriteBit(GPIOA, GPIO_Pin_15 , moto_R_speed > 0 ? (cnt <= moto_R_speed + moto_speed_adj ? (moto_R_dir == moto_run & 1 ? moto_run & 1 : 0) : 0) : 0);
//左電機(jī)控制,定時(shí)器模擬PWM控制
GPIO_WriteBit(GPIOA, GPIO_Pin_2 , moto_L_speed > 0 ? (cnt <= moto_L_speed ? (moto_L_dir == moto_run & 1 ? moto_run & 1 : 0) : 0) : 0);
GPIO_WriteBit(GPIOA, GPIO_Pin_3 , moto_L_speed > 0 ? (cnt <= moto_L_speed ? (moto_L_dir == CAR_QIAN_JIN ? moto_run & 1 : 0) : 0) : 0);
GPIO_WriteBit(GPIOA, GPIO_Pin_11 , cnt < lamp_front_bright);// 大燈
if(beep_freq_cnt < TIMER_FREQ / beep_freq / 2)//喇叭頻率計(jì)數(shù)器
{
beep_freq_cnt ++;
}
else
{
beep_freq_cnt = 0;
b = !b;
}
if(beep_cnt > 0)//喇叭響持續(xù)時(shí)間
{
beep_cnt --;
GPIO_WriteBit(GPIOB, GPIO_Pin_0 , b);
}
else
{
GPIO_WriteBit(GPIOB, GPIO_Pin_0 , 0);
}
}
/***********************************************************************
函數(shù)功能:串口接收數(shù)據(jù)中斷程序,處理命令
入口參數(shù):
出口參數(shù):
***********************************************************************/
void Uart1RevISR(u8 dat)
{
char txt[33];
switch(dat)
{
case '0': //開(kāi)關(guān)大燈
lamp_f = !lamp_f;
break;
case 'a': //查詢(xún)連接
SendStrToUart("b");
break;
case 'd': //調(diào)試開(kāi)關(guān)
debug_switch = !debug_switch;
sprintf(txt , "調(diào)試開(kāi)關(guān):%d\r\n" , debug_switch);
SendStrToUart(txt);
break;
case '5': //開(kāi)關(guān)喇叭
beep_cnt = (TIMER_FREQ / 1000) * 300;
sprintf(txt , "beep:%d\r\n" , beep_cnt);
SendStrToUart(txt);
break;
case ' ': //開(kāi)關(guān)喇叭
beep_cnt = (TIMER_FREQ / 1000) * 300;
sprintf(txt , "beep:%d\r\n" , beep_cnt);
SendStrToUart(txt);
break;
case '8': //加速
moto_run = 1;
if(CAR_QIAN_JIN == moto_L_dir && CAR_QIAN_JIN == moto_R_dir) //
{
if(moto_speed < DUTY_WIDTH - 4)
moto_speed += 1;
}
else
if(CAR_HOU_TUI == moto_L_dir && CAR_HOU_TUI == moto_R_dir) //
{
if(moto_speed > 0)
moto_speed -= 1;
else
{
moto_speed = 0;
moto_L_dir = CAR_QIAN_JIN; //減速到0時(shí)開(kāi)始后退
moto_R_dir = CAR_QIAN_JIN; //減速到0時(shí)開(kāi)始后退
}
}
moto_L_speed = moto_speed;
moto_R_speed = moto_speed;
sprintf(txt , "L:%d , R:%d\r\n" , moto_L_speed , moto_R_speed);
SendStrToUart(txt);
break;
case '2': //減速
if(CAR_QIAN_JIN == moto_L_dir && CAR_QIAN_JIN == moto_R_dir) //
{
if(moto_speed > 0)
moto_speed -= 1;
else
{
moto_speed = 0;
moto_L_dir = CAR_HOU_TUI; //減速到0時(shí)開(kāi)始后退
moto_R_dir = CAR_HOU_TUI; //減速到0時(shí)開(kāi)始后退
}
}
else
if(CAR_HOU_TUI == moto_L_dir && CAR_HOU_TUI == moto_R_dir) //
{
if(moto_speed < DUTY_WIDTH / 2)
moto_speed += 1;
}
b_led_cnt = 0;
moto_L_speed = moto_speed;
moto_R_speed = moto_speed;
sprintf(txt , "L:%d , R:%d\r\n" , moto_L_speed , moto_R_speed);
SendStrToUart(txt);
break;
case '7': //左轉(zhuǎn)校正
if(moto_speed_adj < 3)
moto_speed_adj ++;
break;
case '9': //右轉(zhuǎn)校正
if(moto_speed_adj > -3)
moto_speed_adj --;
break;
case '4': //左轉(zhuǎn)
moto_L_switch = 1;
moto_R_switch = 0;
moto_L_dir = CAR_QIAN_JIN;
moto_R_dir = CAR_QIAN_JIN;
left_turn_cnt = (TIMER_FREQ / 5);//轉(zhuǎn)彎時(shí)間定時(shí)器
moto_L_speed = moto_speed / 3;
moto_R_speed = moto_speed;
sprintf(txt , "L:%d , R:%d\r\n" , moto_L_switch , moto_R_switch);
SendStrToUart(txt);
break;
case '6': //右轉(zhuǎn)
moto_R_switch = 1;
moto_L_switch = 0;
moto_R_dir = CAR_QIAN_JIN;
moto_L_dir = CAR_QIAN_JIN;
right_turn_cnt = (TIMER_FREQ / 5);//轉(zhuǎn)彎時(shí)間定時(shí)器
moto_R_speed = moto_speed / 3;
moto_L_speed = moto_speed;
sprintf(txt , "L:%d , R:%d\r\n" , moto_L_switch , moto_R_switch);
SendStrToUart(txt);
break;
case 'l': //左轉(zhuǎn)大彎,并稍微后退,避障用
moto_L_switch = 1;
moto_R_switch = 0;
moto_L_dir = CAR_HOU_TUI;
moto_R_dir = CAR_HOU_TUI;
left_turn_cnt = (TIMER_FREQ / (moto_speed / 20 + 1) );//轉(zhuǎn)彎時(shí)間定時(shí)器, 轉(zhuǎn)彎時(shí)間與速度相關(guān)
moto_L_speed = moto_speed;
moto_R_speed = moto_speed / 4;
//sprintf(txt , "L:%d , R:%d\r\n" , moto_L_switch , moto_R_switch);
//SendStrToUart(txt);
break;
case 'r': //右轉(zhuǎn)大彎,并稍微后退,避障用
moto_R_switch = 1;
moto_L_switch = 0;
moto_R_dir = CAR_HOU_TUI;
moto_L_dir = CAR_HOU_TUI;
right_turn_cnt = (TIMER_FREQ / (moto_speed / 20 + 1) );//轉(zhuǎn)彎時(shí)間定時(shí)器, 轉(zhuǎn)彎時(shí)間與速度相關(guān)
moto_R_speed = moto_speed;
moto_L_speed = moto_speed / 4;
//sprintf(txt , "L:%d , R:%d\r\n" , moto_L_switch , moto_R_switch);
//SendStrToUart(txt);
break;
}
}
/***********************************************************************
函數(shù)功能:串口接收數(shù)據(jù)中斷程序,處理命令
入口參數(shù):
出口參數(shù):
***********************************************************************/
void Uart2RevISR(u8 dat)
{
u8 n = 0 , i = 0 , len = 0 , ch = 0;
float val = 0.0;
static float current_adj = 1.0;
}
/***********************************************************************
函數(shù)功能:大燈控制
入口參數(shù):
出口參數(shù):
***********************************************************************/
void Lamp_front(u8 de)
{
u8 i = 0;
if(de == 1)//燈漸亮
{
if(lamp_front_bright == 0)
{
for(i = 0 ; i < DUTY_WIDTH ; i ++)
{
lamp_front_bright = i;
Delay_ms(20);
}
}
}
else //燈漸暗
{
if(lamp_front_bright == DUTY_WIDTH - 1)
{
for(i = 0 ; i < DUTY_WIDTH ; i ++)
{
lamp_front_bright = DUTY_WIDTH - i - 1;
Delay_ms(20);
}
}
}
}
/***********************************************************************
函數(shù)功能:
入口參數(shù):
出口參數(shù):
***********************************************************************/
int main(void)
{
char txt[44];
int i = 0 , ls = 0 , rs = 0 , t = 0;
s32 ad = 0;
STM32_Board_Init();
//SendStrToUart("AT+BAUD8");//設(shè)置波特率為115200
moto_speed = 18; //
moto_run = 1;
moto_R_speed = moto_speed;
moto_R_dir = CAR_QIAN_JIN;//電機(jī)方向
moto_L_speed = moto_speed;
moto_L_dir = CAR_QIAN_JIN ;//電機(jī)方向
Delay_ms(200);
//自動(dòng)識(shí)別環(huán)境光強(qiáng)度
for(i = 0 ; i < 20 ; i ++)
{
t += GetADCVal(ADC_Channel_5);
}
t /= 20;
IR_ref_value_L = t;
t = 0;
for(i = 0 ; i < 20 ; i ++)
{
t += GetADCVal(ADC_Channel_4);
}
t /= 20;
IR_ref_value_R = t;
//FlashData=*(vu32*)(FLASH_ADR); /* 讀取地址中的16位數(shù)據(jù) */
//SendDataToUart('A');
lamp_front_bright = 0; //大燈亮度
beep_cnt = (TIMER_FREQ / 1000) * 100;//喇叭叫
while(1)
{
if(debug_switch == 0)
{
if(lamp_front_bright == 0)
{
if(lamp_f == 1)
{
Lamp_front(lamp_f);
}
}
else
{
if(lamp_f == 0)
{
Lamp_front(lamp_f);
}
}
rs = CheckHinder_Right();
if( rs ) //判斷右側(cè)是否有障礙物 , 如有則左轉(zhuǎn)
{
if(moto_L_switch == 0)
{
Uart1RevISR('l'); //發(fā)送左轉(zhuǎn)指令
if(lamp_f == 0) //如果大燈沒(méi)開(kāi),這里打開(kāi)大燈
lamp_front_bright = (rs - 0 ) * 10 + 0;
if(beep_cnt == 0)
beep_cnt = (TIMER_FREQ / 1000) * 50; //喇叭叫一聲
//SendStrToUart("<<<\r\n");
}
}
else
{
ls = CheckHinder_Left();
//判斷左側(cè)是否有障礙物 , 如有則右轉(zhuǎn)
if(ls)
{
if(moto_R_switch == 0)
{
Uart1RevISR('r'); //發(fā)送右轉(zhuǎn)指令
if(lamp_f == 0) //如果大燈沒(méi)開(kāi),這里打開(kāi)大燈
lamp_front_bright = (ls - 0 ) * 10 + 0;
if(beep_cnt == 0)
beep_cnt = (TIMER_FREQ / 1000) * 10; //喇叭叫一聲
//SendStrToUart(">>>\r\n");
}
}
else
{
if(lamp_f == 0 && lamp_front_bright > 0)
lamp_front_bright = 0;
}
}
Delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_9) == 0) //key1按下 ,開(kāi)車(chē)和停車(chē)切換
{
moto_run = !moto_run;
while(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_9) == 0);
Delay_ms(20);
}
#if 0
if(lamp_f == 0) //如果大燈沒(méi)開(kāi),這里打開(kāi)大燈
{
ad = GetADCVal(ADC_Channel_6);
ad -= 2000;
if(ad > 0)
ad = 0;
ad = 0 - ad;
ad /= 200;
lamp_front_bright = ad;
}
#endif
}
//GPIO_WriteBit(GPIOC , GPIO_Pin_13 , 0);//led
//Delay_ms(200);
//GPIO_WriteBit(GPIOC , GPIO_Pin_13 , 1);//led
if(debug_switch)
{
Delay_ms(50);
sprintf(txt , "右側(cè)紅外感應(yīng)AD4:%4d,左側(cè)紅外感應(yīng)AD5:%4d,音頻:%4d\r\n" , GetADCVal(ADC_Channel_4) , GetADCVal(ADC_Channel_5) , GetADCVal(ADC_Channel_6) );
SendStrToUart(txt);
}
}
return 0;
}
復(fù)制代碼
所有資料51hei提供下載:
stm32 Car V1.0.zip
(603.16 KB, 下載次數(shù): 23)
2018-4-8 17:36 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
作者:
灰泰郎
時(shí)間:
2019-4-7 19:22
下載學(xué)習(xí)一下。
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1