2019 电子设计大赛 激光炮题目 主程序

2019 电子设计大赛 激光炮题目 写的程序

代码:

main.c

#include "stm32f4xx.h"
#include "usart_all.h"
#include "stdio.h"
#include "math.h"
#include "delay.h"

#include "hmi.h"   //串口屏相关
#include "servo.h" //舵机控制
#include "shoot.h" //充电/发射控制
#include "laser.h" //激光测距
#include "redtube.h"//红外对管
#include "camera.h" //摄像头openMV
#include "speak.h" 	//语音模块

s16 distance_goal = 0, anglex_x_goal = 0;

/*主状态机状态定义 */
#define MODE0_WaitInput      	  0x00
#define MODE1_HandShoot           0x01
#define MODE2_AutoShoot           0x02
#define MODE3_ScanShoot           0x03
#define MODE4_Calibration         0x04
u8 STATE_Main = MODE0_WaitInput;
/*主状态机状态函数声明 */
void Mode1_HandShoot(void);
void Mode2_AutoShoot(void);
void Mode3_ScanShoot(void);

/*二级状态机状态定义 */
#define MODE40_Calibration_WaitInput       0x40
#define MODE41_Calibration_Camera          0x41
#define MODE42_Calibration_Laser           0x42
#define MODE43_Calibration_Volage          0x43
#define MODE44_Calibration_Exit            0x44
u8 STATE_Mode4 = MODE40_Calibration_WaitInput;
/*二级状态机状态函数声明 */
void Mode41_Calibration_Camera(void);
void Mode42_Calibration_Laser(void);
void Mode43_Calibration_Volage(void);
void Mode44_Calibration_Exit(void);


void LED_Init(void) {
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
	
	//静态充电GPIO PA1、放电GPIO PA2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructure);
}
//pc0
void LED_Light(void) {
	PCout(0) = 0;
}

void LED_Dark(void) {
	PCout(0) = 1;
}
int main(void) {

	u8 mode4_end = 0;
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	delay_init(168);  //初始化延时函数
	delay_ms(1000);
	
	HMI_Init();	   //串口屏初始化
	delay_ms(5);
	
	HMI_sendCmdEnd();
	HMI_SendCmd("page modemenu");
	SERVO_Init();  //舵机初始化
	SHOOT_Init();  //充电发射系统初始化,1000ms充电时长
	LASER_Init();  //激光测距模块初始化
	REDTUBE_Init();//红外对管初始化
	CAMERA_Init(); //摄像头openMV初始化
	SPEAK_Init();  //语音模块初始化
	LED_Init();
	LED_Dark();
	while(1){
		switch (STATE_Main)
		{
			/*状态0:等待状态选择,1或2 */
			case MODE0_WaitInput:
				HMI_GetMode(&STATE_Main); //直至获得状态成功才退出该语句
				break;

			/*状态1:选择功能1,手动输入距离角度 */
			case MODE1_HandShoot:
				SPEAK_Display(1);				 //语音播报
				SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				HMI_GetAngleAndDis(&anglex_x_goal ,&distance_goal);
				while(!HMI_CheckShootStart());//等待串口屏发射命令
			
				SPEAK_Display(5);				 //语音播报“一键启动”
				Mode1_HandShoot();			  //执行发射函数
				delay_ms(1000);
				SPEAK_Display(6);				 //语音播报“发射完成”
				
			
				while(!HMI_CheckBack());	  //等待串口屏返回命令
				SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				
				HMI_sendCmdEnd();
				HMI_SendCmd("page modemenu"); //串口屏返回主页面,同时反应程序是否正常
				HMI_ClearRX();				  //清空串口屏错误返回信息
				STATE_Main = MODE0_WaitInput; //切换回主状态
				break;

			/*状态2:选择功能2,自动找目标,停止后射击 */
			case MODE2_AutoShoot:
				SPEAK_Display(2);				 //语音播报
				SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				while(!HMI_CheckShootStart());//等待串口屏发射命令
			
				SPEAK_Display(5);				 //语音播报“一键启动”
				Mode2_AutoShoot();			  //执行发射函数
				delay_ms(1000);
				SPEAK_Display(6);				 //语音播报“发射完成”
			
				while(!HMI_CheckBack());	  //等待串口屏返回命令
				SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				
				HMI_sendCmdEnd();
				HMI_SendCmd("page modemenu"); //串口屏返回主页面,同时反应程序是否正常
				HMI_ClearRX();				  //清空串口屏错误返回信息
				STATE_Main = MODE0_WaitInput; //切换回主状态
				break;

			/*状态3:选择功能3,自动找目标,不停止后射击 */
			case MODE3_ScanShoot:
				SPEAK_Display(3);				 //语音播报
				LED_Dark();
				SERVO_X_SetAngle(-30);			 //设置云台初始x角度为-30°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				
				while(!HMI_CheckShootStart());//等待串口屏发射命令
			
				SPEAK_Display(5);				 //语音播报“一键启动”
				Mode3_ScanShoot();			  //执行发射函数
				delay_ms(1000);
				SPEAK_Display(6);				 //语音播报“发射完成”
				
				while(!HMI_CheckBack());	  //等待串口屏返回命令
				SERVO_X_Scan_End();			  //扫描结束
				SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				
				HMI_sendCmdEnd();
				HMI_SendCmd("page modemenu"); //串口屏返回主页面,同时反应程序是否正常
				HMI_ClearRX();				  //清空串口屏错误返回信息
				STATE_Main = MODE0_WaitInput; //切换回主状态
				break;
			
			/*状态4:校准模式 */
			case MODE4_Calibration:
				SPEAK_Display(4);				 //语音播报
				STATE_Mode4 = MODE40_Calibration_WaitInput;
				SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
				SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
				mode4_end = 0;
				while(1) {
					switch(STATE_Mode4) {
						/*状态40:校准模式--等待输入校准对象 */
						case MODE40_Calibration_WaitInput:
							HMI_GetMode(&STATE_Mode4); 					//直至获得状态成功才退出该语句
							break;
						
						/*状态41:校准模式--校准摄像头 */
						case MODE41_Calibration_Camera:
							SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
							SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
							
							HMI_sendCmdEnd();	
							HMI_SendCmd("page camera_sample"); 			//串口屏进入配置页面,同时反应程序是否正常
								
							//状态机函数
							Mode41_Calibration_Camera();

							//状态机函数擦屁股
							CAMERA_ClearRX();
							
							HMI_sendCmdEnd();
							HMI_SendCmd("page calibration"); 			//串口屏返回校准选择页面,同时反应程序是否正常
							HMI_ClearRX();				  				//清空串口屏错误返回信息
							STATE_Mode4 = MODE40_Calibration_WaitInput; //二级状态--校准模式 停留在等待输入校准对象
							break;
						
						/*状态42:校准模式--校准激光器 */
						case MODE42_Calibration_Laser:
							SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
							SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
							
							HMI_sendCmdEnd();
							HMI_SendCmd("page laser"); 					//串口屏进入配置页面,同时反应程序是否正常
							
							//状态机函数
							Mode42_Calibration_Laser();
							
							while(!HMI_CheckBack());	  				//等待串口屏返回命令
							//状态机函数擦屁股
							SERVO_X_Scan_End();
							LASER_Open_Light(0);
							delay_ms(500);
							
							HMI_sendCmdEnd();
							HMI_SendCmd("page calibration"); 			//串口屏返回校准选择页面,同时反应程序是否正常
							HMI_ClearRX();				  				//清空串口屏错误返回信息
							STATE_Mode4 = MODE40_Calibration_WaitInput; //二级状态--校准模式 停留在等待输入校准对象
							break;
						
						/*状态43:校准模式--校准动态充电稳压 */
						case MODE43_Calibration_Volage:
							SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
							SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
							
							HMI_sendCmdEnd();
							HMI_SendCmd("page charge"); 					//串口屏进入配置页面,同时反应程序是否正常
							
							//状态机函数
							Mode43_Calibration_Volage();
						
							while(!HMI_CheckBack());	  				//等待串口屏返回命令
							//状态机函数擦屁股
						
							HMI_sendCmdEnd();
							HMI_SendCmd("page calibration"); 			//串口屏返回校准选择页面,同时反应程序是否正常
							HMI_ClearRX();				  				//清空串口屏错误返回信息
							STATE_Mode4 = MODE40_Calibration_WaitInput; //二级状态--校准模式 停留在等待输入校准对象
							break;
						
						/*状态44:退出校准模式 */
						case MODE44_Calibration_Exit:
							SERVO_X_SetAngle(0);			 //设置云台初始x角度为0°
							SERVO_Y_SetPWM(Servo_Y_ccr_pos0);//设置云台初始y角度为0°
							mode4_end = 1;
							break;
						//其他状态
						default:
							mode4_end = 1;
							break;
					}
					if(mode4_end == 1) {
						break;
					}
				}
				HMI_sendCmdEnd();
				HMI_SendCmd("page modemenu"); //串口屏返回主页面,同时反应程序是否正常
				HMI_ClearRX();				  //清空串口屏错误返回信息
				STATE_Main = MODE0_WaitInput; //切换回主状态
				break;
			//其他状态
			default:
				HMI_sendCmdEnd();
				HMI_SendCmd("page modemenu");
				HMI_ClearRX();
				STATE_Main = MODE0_WaitInput;
				break;
		}
	}
}

void Mode1_HandShoot(void) {
	SHOOT_Elec_Enable();				//开始充电
	SERVO_X_SetAngle(anglex_x_goal);	//控制水平舵机
	SERVO_Y_SetDistance(distance_goal, anglex_x_goal); //控制垂直舵机
	delay_ms(1000);						//等待舵机就位
	while(!SHOOT_CheckElec());					//等待充电完成
	SHOOT_Go();
}

void Mode2_AutoShoot(void) {
	u16 distance = 200;
	u16 goal_pwm = 0;
	s8 goal_erro = 60;
	u8 p = 10;
	u8 i;
	u8 times = 0;
	SERVO_X_SetAngle(-30); //云台y方向设置为瞄准250cm
	SHOOT_Elec_Enable();	  //开始充电
	delay_ms(2000);
	CAMERA_ClearRX();		  //清除之前openMV发送的数据
	delay_ms(10);
	//获得角度的循环
	while(1) {
		
		CAMERA_Get_GoalErro(&goal_erro); //获取最近数据
		if(abs(goal_erro)>30) {			 //摄像头返回目标差距较大,粗调
			SERVO_X_ChangeAngle(goal_erro);	
			delay_ms(abs(goal_erro)*p);
		} else {						 //摄像头返回目标差距较小,细调
			SERVO_X_ChangeAngle(goal_erro>0?1:(-1)); //线性改变pwm,步进为1
			delay_ms(20);
			times++;
			if(abs(goal_erro)<=0) {					 //摄像头返回目标差距小于等于1
				goal_pwm = Servo_X_ccr_Laster; 		 //记住摄像头瞄准时的pwm
				break;								 //跳出获得角度循环
			} 
			if(times > 8) {
				if(abs(goal_erro)<=1) {					 //摄像头返回目标差距小于等于1
					goal_pwm = Servo_X_ccr_Laster; 		 //记住摄像头瞄准时的pwm
					break;								 //跳出获得角度循环
				} 
			}
		}
		if(Servo_X_ccr_Laster>Servo_X_ccr_pos30) {
			//从-30°到30°没找到,就返回转
			goal_erro = -goal_erro;
		} else if(Servo_X_ccr_Laster < Servo_X_ccr_neg30) {
			//从30°到-30°没找到,就返回转
			goal_erro = -goal_erro;
		}
	}
	
	//获得距离的循环
	LASER_get_distance(&distance);	//获得引导标识的距离
	distance = distance - 30;		//获得靶心的距离
	if(distance > 190 && distance < 310) { 
		//获得距离成功
	} else {
//		//获得距离失败
//		for(i=0; i<20; i++) {
//			SERVO_X_SetPWM(goal_pwm-20+i*2);			//设置角度
//			delay_ms(400);
//			LASER_get_distance(&distance);	//获得引导标识的距离
//			distance = distance - 30;		//获得靶心的距离
//			if(distance > 190 && distance < 310) { 
//				//获得距离成功
//				break;
//			}
//		}
		distance = 250;
	}
	
//	SERVO_X_SetPWM(goal_pwm-5);			//设置角度
//	if(Servo_X_ccr_Laster>Servo_X_ccr_pos0) {
//		SERVO_X_ChangeAngle(-2);
//	}
	SERVO_Y_SetDistance(distance, SERVO_X_PWM2Angle(goal_pwm));		//设置高度
	delay_ms(1000);						//等待建立
	while(!SHOOT_CheckElec());			//等待充电完成
	SHOOT_Go();							//发射炮弹
}

void Mode3_ScanShoot(void) {
	s8 goal_erro = 30;
	u8 delta1 = 1;
	u8 delta2 = 13;
	LED_Dark();
	SHOOT_Elec_Enable();	  	  //开始充电
	SERVO_Y_SetDistance(250, 0);  //云台y方向设置为瞄准250cm
	
	SERVO_X_Scan_Start(Angle2PWMX[-30+30]-18, Angle2PWMX[30+30]+18, 2, 1, 1);
	CAMERA_ClearRX();		  //清除之前openMV发送的数据
	while(!SHOOT_CheckElec());//直至充满电
	while(1) {
		CAMERA_Get_GoalErro(&goal_erro);
		if(Servo_X_ccr_Laster>Angle2PWMX[0+30]) {
			//转到左半部分
			LED_Light();
			if(abs(goal_erro)<=delta1) {
				LED_Light();
				SHOOT_Go();
				LED_Dark();
				break;
			} else if(Servo_X_ccr_Laster>Angle2PWMX[28+30]) {
				if(abs(goal_erro)<=delta2) {
					LED_Light();
					SHOOT_Go();
					LED_Dark();
					break;
				}
			}
		} else if(Servo_X_Scan_Times==1){
			//回转第二个单程
			if(abs(goal_erro)<=delta1) {
				LED_Light();
				SHOOT_Go();
				LED_Dark();
				break;
			}
		} else if(Servo_X_Scan_Times==2) {
			//当转到两圈自动发射
			SHOOT_Go();
			break;
		}
	}
}

void Mode41_Calibration_Camera(void) {
	HMI_ConfigCamera();
}

//未完成
void Mode42_Calibration_Laser(void) {
	LASER_Open_Light(1);			//打开可见激光
	delay_ms(500);
	while(!HMI_CheckShootStart());	//等待串口屏发送开始扫描
	SERVO_X_Scan_Start(Angle2PWMX[-30+30], Angle2PWMX[30+30], 3, 2, 1);//-30°~30°循环扫描看是否水平
}
void Mode43_Calibration_Volage(void) {
	SHOOT_Elec_Enable();			//开始充电	
	while(!HMI_CheckShootStart());	//等待串口屏发射命令
	SHOOT_Go();				//按下放电按钮,放电
}
void Mode44_Calibration_Exit(void) {
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

匿名匿名匿名11

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值