标题:
STM32红外舵机自动壁障小车源程序
[打印本页]
作者:
zxcvbnm..
时间:
2018-4-8 17:37
标题:
STM32红外舵机自动壁障小车源程序
基于STM32的红外舵机自动壁障小车
单片机源程序如下:
#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) /* 存储数据Flash页首地址 */
#define DUTY_WIDTH 25 //占空比最大级数
#define CAR_QIAN_JIN 0 //小车前进
#define CAR_HOU_TUI 1 //小车后退
u8 debug_switch = 0;//调试开关
u32 IR_ref_value_L = 0;//红外感应参考值,开机前将小车置于空旷位置,系统便于识别环境光强度
u32 IR_ref_value_R = 0;//红外感应参考值,开机前将小车置于空旷位置,系统便于识别环境光强度
u8 moto_run = 0;//电机运行标志
u8 moto_R_speed = 0;//电机速度
u8 moto_R_dir = CAR_QIAN_JIN;//电机方向
u8 moto_L_speed = 0;//电机速度
u8 moto_L_dir = CAR_QIAN_JIN;//电机方向
u8 moto_speed = 0;//电机前进的速度
s8 moto_speed_adj = 1;//左右电机速度校正,-3~+3,已左边轮子速度为基准,在右边轮子速度加校正值
//u32 TIME_L_R = (TIMER_FREQ / 3);//转弯时间,完成后自动归正
u8 moto_L_switch = 0;//左转有效
u8 moto_R_switch = 0;//右转有效
u32 left_turn_cnt = 0; //转弯时间定时器
u32 right_turn_cnt = 0; //转弯时间定时器
u32 b_led_cnt = 0;//刹车灯时间定时器
u32 beep_cnt = 0;//喇叭时间定时器,ms
u8 lamp_front_bright = 0; //大灯亮度
u8 lamp_f = 0; //大灯开关切换
void Lamp_front(u8 de);
/***********************************************************************
函数功能: 写flash,数据长度不超过1扇区
入口参数:
出口参数:
***********************************************************************/
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); /* 擦除页 */
//FLASH_ProgramWord(FLASH_ADR,0 << 1 | 0); /* 写16位半字 */
for(i = 0 ; i < len ; i += 2)
{
FLASH_ProgramHalfWord(byte_addr + i , *(u16*)&dat[i]); /* 写16位半字 */
}
FLASH_Lock();
}
/***********************************************************************
函数功能:延时_dlytime毫秒
入口参数:
出口参数:
***********************************************************************/
void Delay_ms(u32 _dlytime)
{
u32 i;
u32 j;
for (i = 0; i < _dlytime * 10; i++)
for (j = 0; j < 0xff; j++);
}
/***********************************************************************
函数功能:延时
入口参数:
出口参数:
***********************************************************************/
void Delay(u32 _dlytime)
{
u32 i;
u32 j;
for (i = 0; i < _dlytime * 1; i++)
for (j = 0; j < 0x13; j++);
}
/***********************************************************************
函数功能:获取AD值
入口参数:
出口参数:
***********************************************************************/
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);
}
/***********************************************************************
函数功能:判断左侧是否有障碍物
入口参数:
出口参数: 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)//如果当前值大于平均值较多,也认为是有障碍
return 2;
return 0;
}
/***********************************************************************
函数功能:判断右侧是否有障碍物
入口参数:
出口参数: 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)//如果当前值大于平均值较多,也认为是有障碍
return 2;
return 0;
}
/***********************************************************************
函数功能:向串口发数据
入口参数:
出口参数:
***********************************************************************/
void SendDataToUart(u8 dat)
{
UART1_SendByte(dat);
}
/***********************************************************************
函数功能:发送数据
入口参数:
出口参数:
***********************************************************************/
void SendStrToUart(char*str)
{
while(*str)
{
SendDataToUart(*str ++);
}
}
/***********************************************************************
函数功能:
入口参数:
出口参数:
***********************************************************************/
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;//转弯灯时间定时器
u32 audio_adc_val = 0;
//
if(cnt < DUTY_WIDTH)//占空比计数
{
cnt ++;
}
else
{
cnt = 0;
}
GPIO_WriteBit(GPIOC , GPIO_Pin_13 , l_r_led); //cpu状态指示灯
GPIO_WriteBit(GPIOB, GPIO_Pin_2 , l_r_led);
//刹车灯控制
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;
}
//转弯控制
if(moto_L_switch) //左转
{
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;//转弯结束,自动归正
moto_R_speed = moto_speed;//转弯结束,自动归正
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) //右转
{
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;//转弯结束,自动归正
moto_R_speed = moto_speed;//转弯结束,自动归正
moto_R_switch = 0;
moto_R_dir = CAR_QIAN_JIN;
moto_L_dir = CAR_QIAN_JIN;
GPIO_WriteBit(GPIOA, GPIO_Pin_12 , 0);
}
}
//右电机控制,定时器模拟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);
//左电机控制,定时器模拟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)//喇叭频率计数器
{
beep_freq_cnt ++;
}
else
{
beep_freq_cnt = 0;
b = !b;
}
if(beep_cnt > 0)//喇叭响持续时间
{
beep_cnt --;
GPIO_WriteBit(GPIOB, GPIO_Pin_0 , b);
}
else
{
GPIO_WriteBit(GPIOB, GPIO_Pin_0 , 0);
}
}
/***********************************************************************
函数功能:串口接收数据中断程序,处理命令
入口参数:
出口参数:
***********************************************************************/
void Uart1RevISR(u8 dat)
{
char txt[33];
switch(dat)
{
case '0': //开关大灯
lamp_f = !lamp_f;
break;
case 'a': //查询连接
SendStrToUart("b");
break;
case 'd': //调试开关
debug_switch = !debug_switch;
sprintf(txt , "调试开关:%d\r\n" , debug_switch);
SendStrToUart(txt);
break;
case '5': //开关喇叭
beep_cnt = (TIMER_FREQ / 1000) * 300;
sprintf(txt , "beep:%d\r\n" , beep_cnt);
SendStrToUart(txt);
break;
case ' ': //开关喇叭
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时开始后退
moto_R_dir = CAR_QIAN_JIN; //减速到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 '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时开始后退
moto_R_dir = CAR_HOU_TUI; //减速到0时开始后退
}
}
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': //左转校正
if(moto_speed_adj < 3)
moto_speed_adj ++;
break;
case '9': //右转校正
if(moto_speed_adj > -3)
moto_speed_adj --;
break;
case '4': //左转
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);//转弯时间定时器
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': //右转
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);//转弯时间定时器
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': //左转大弯,并稍微后退,避障用
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) );//转弯时间定时器, 转弯时间与速度相关
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': //右转大弯,并稍微后退,避障用
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) );//转弯时间定时器, 转弯时间与速度相关
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;
}
}
/***********************************************************************
函数功能:串口接收数据中断程序,处理命令
入口参数:
出口参数:
***********************************************************************/
void Uart2RevISR(u8 dat)
{
u8 n = 0 , i = 0 , len = 0 , ch = 0;
float val = 0.0;
static float current_adj = 1.0;
}
/***********************************************************************
函数功能:大灯控制
入口参数:
出口参数:
***********************************************************************/
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);
}
}
}
}
/***********************************************************************
函数功能:
入口参数:
出口参数:
***********************************************************************/
int main(void)
{
char txt[44];
int i = 0 , ls = 0 , rs = 0 , t = 0;
s32 ad = 0;
STM32_Board_Init();
//SendStrToUart("AT+BAUD8");//设置波特率为115200
moto_speed = 18; //
moto_run = 1;
moto_R_speed = moto_speed;
moto_R_dir = CAR_QIAN_JIN;//电机方向
moto_L_speed = moto_speed;
moto_L_dir = CAR_QIAN_JIN ;//电机方向
Delay_ms(200);
//自动识别环境光强度
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位数据 */
//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 ) //判断右侧是否有障碍物 , 如有则左转
{
if(moto_L_switch == 0)
{
Uart1RevISR('l'); //发送左转指令
if(lamp_f == 0) //如果大灯没开,这里打开大灯
lamp_front_bright = (rs - 0 ) * 10 + 0;
if(beep_cnt == 0)
beep_cnt = (TIMER_FREQ / 1000) * 50; //喇叭叫一声
//SendStrToUart("<<<\r\n");
}
}
else
{
ls = CheckHinder_Left();
//判断左侧是否有障碍物 , 如有则右转
if(ls)
{
if(moto_R_switch == 0)
{
Uart1RevISR('r'); //发送右转指令
if(lamp_f == 0) //如果大灯没开,这里打开大灯
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按下 ,开车和停车切换
{
moto_run = !moto_run;
while(GPIO_ReadInputDataBit(GPIOB , GPIO_Pin_9) == 0);
Delay_ms(20);
}
#if 0
if(lamp_f == 0) //如果大灯没开,这里打开大灯
{
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 , "右侧红外感应AD4:%4d,左侧红外感应AD5:%4d,音频:%4d\r\n" , GetADCVal(ADC_Channel_4) , GetADCVal(ADC_Channel_5) , GetADCVal(ADC_Channel_6) );
SendStrToUart(txt);
}
}
return 0;
}
复制代码
所有资料51hei提供下载:
stm32 Car V1.0.zip
(603.16 KB, 下载次数: 23)
2018-4-8 17:36 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
灰泰郎
时间:
2019-4-7 19:22
下载学习一下。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1