主程序
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "encoder.h"
#include "usart.h"
#include "motor.h"
#include "servo.h"
#include "oled.h"
#include "DataScope_DP.h"
#include "myIIC.h"
#include "mpu6050.h"
#include "stmflash.h"
#include "display.h"
#include "timer.h"
#include "2401.h"
#include "ocsct1.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include "adc.h"
//ALIENTEK 探索者STM32F407开发板 实验4
//串口通信实验 -库函数版本
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com
//广州市星翼电子科技有限公司
//作者:正点原子 @ALIENTEK
//要写入到STM32 FLASH的字符串数组
extern int D,A;
extern u8 send_flag,uart_flag;
extern int DISTANCE,Angle;
extern u8 UART_FLAG;
extern int distance;
extern u8 UART_RX3[6];
extern int DDDDD;
extern int x1,y;
extern int X_TINE_COUNT;
extern u8 zc;
extern int CHANG_ANGLE;
extern u8 X_FLAG;
extern u8 TURN_flag;
extern u8 turn_flag;
void find_angle()
{if(x_err>=5 && x_err<=10 && TURN_flag==1){send_flag=1;}if(x_err>=150 && x_err<=155 && TURN_flag==0){send_flag=1;}
}void send_pao()
{if(send_flag==1){send_flag=0;fangdian=0;// 充电前不能开启放电delay_ms(200);chongdian=1;//开始充电delay_ms(1500);chongdian=0;//充电结束delay_ms(300);fangdian=1;//开始放电delay_ms(200);fangdian=0;//放电结束}
}
void init()
{delay_init(168); //延时初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2KEY_Init();LED_Init();TIM1_PWM_Init(9999,335);//50HZ 精度10000TIM_SetCompare1(TIM1,center_X);//900 500 680 //左小右大center_X//580 790TIM_SetCompare2(TIM1,center_Y);//900 1230 //上下center_Yuart_init2(9600);uart_init3(115200);TIM6_Int_Init(100-1,8400-1);OLED_Init();STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)flash_read,SIZE1);D=flash_read[0];A=flash_read[1];
}
int main(void)
{ init();while(1){OLED_ShowCHinese(0,0,0);//电磁炮发射线装置OLED_ShowCHinese(16,0,1);OLED_ShowCHinese(32,0,2);OLED_ShowCHinese(48,0,3);OLED_ShowCHinese(64,0,4);OLED_ShowCHinese(80,0,5);OLED_ShowCHinese(96,0,6);OLED_ShowCHinese(0,2,7);OLED_ShowCHinese(16,2,8);OLED_ShowCHinese(64,2,9);OLED_ShowCHinese(80,2,10);OLED_ShowCHinese(32,4,11);OLED_ShowCHinese(48,4,12);OLED_ShowCHinese(64,4,13);;if(KEY4_PRES==KEY_Scan(0)){OLED_Clear();break;}}while(1){ display();send_pao();if(turn_flag==1){find_angle();}}
}
OLED显示程序
#include "display.h"
#include "oled.h"
#include "key.h"
#include "stmflash.h"
extern int D;
extern int A;//u8 miaozhi=L;//选择基础或者发挥
//u8 bianliang=D_Y;//选择改变D或A选择改变D或A
//void change_data(u8 bb)
//{
// switch(KEY_Scan(0))
// {
// case KEY1_PRES:
// bianliang= D_Y;
// OLED_Clear();
// break;
// case KEY2_PRES:
// bianliang= A_Y;
// OLED_Clear();
// break;
// case KEY3_PRES:
// //OLED_Clear();
// //judge_choose();
// break;
//
// }
//}u8 MODE_FLAG=1;
u8 find_flag=0;
u8 turn_flag=0;
extern u8 UART_FLAG;
void change_mode(u8 aa)
{u8 stop_flag=0;while(1){OLED_ShowString(0,0,"D:");OLED_ShowNum(20,0,D,3,16);OLED_ShowString(0,2,"A:");OLED_ShowNum(20,2,A,3,16);OLED_ShowString(0,4,"find:");OLED_ShowNum(40,4,find_flag,1,16);OLED_ShowString(0,6,"turn:");OLED_ShowNum(40,6,turn_flag,1,16);switch(KEY_Scan(0)){ case KEY2_PRES:if(aa==1){D+=2;if(D>=300)D=300;flash_write[0]=D;}if(aa==2){A+=1;if(A>=30)A=30;flash_write[1]=A;}if(aa==3)find_flag=1;if(aa==4)turn_flag=1;OLED_Clear();break;case KEY3_PRES:if(aa==1){D-=2;if(D<=200)D=200;flash_write[0]=D;}if(aa==2){A-=1;if(A<=-30)A=-30;flash_write[1]=A;}if(aa==3)find_flag=0;if(aa==4)turn_flag=0;OLED_Clear();break;case KEY1_PRES:UART_FLAG=1;//允许执行中断程序stop_flag=1;break;}if(stop_flag==1){STMFLASH_Write(FLASH_SAVE_ADDR,(u32*)flash_write,SIZE1);MODE_FLAG=1;OLED_Clear();break;}}
}extern u8 send_flag;
void display()
{switch(KEY_Scan(0)){ case KEY2_PRES:MODE_FLAG++;if(MODE_FLAG>4)MODE_FLAG=1;OLED_Clear();break;case KEY3_PRES:MODE_FLAG--;if(MODE_FLAG<1)MODE_FLAG=4;OLED_Clear();break;case KEY4_PRES:OLED_Clear();change_mode(MODE_FLAG);break;case KEY5_PRES: send_flag=1;OLED_Clear();break;}OLED_ShowString(0,0,"D:");OLED_ShowNum(20,0,D,3,16);OLED_ShowString(0,2,"A:");OLED_ShowNum(20,2,A,3,16);OLED_ShowString(0,4,"find:");OLED_ShowNum(40,4,find_flag,1,16);OLED_ShowString(0,6,"turn:");OLED_ShowNum(40,6,turn_flag,1,16);if(MODE_FLAG==1)OLED_ShowString(70,0,"1");else if(MODE_FLAG==2)OLED_ShowString(70,2,"1");else if(MODE_FLAG==3)OLED_ShowString(70,4,"1");else OLED_ShowString(70,6,"1");if(send_flag==1)OLED_ShowString(90,6,"ok");
}
云台舵机控制程序
float servo_KP=0,servo_KI=0.085;
int X_servo_PID(int val,int aim)
{static int temp=0,duty=0;static int ThisError=0,LastError=0;static int pError=0,iError=0;static int PWM1;ThisError=(int)(aim-val);pError=ThisError-LastError;iError=ThisError;temp=(int)(servo_KP*pError+servo_KI*iError);LastError=ThisError; duty+=temp;PWM1=duty+center_X;if(PWM1>max_X)PWM1=max_X;if(PWM1<min_X)PWM1=min_X;TIM_SetCompare1(TIM1,PWM1);return center_X+duty;
}int Y_servo_PID(int val,int aim)
{static int temp1=0,duty1=0;static int ThisError1=0,LastError1=0;static int pError1=0,iError1=0;ThisError1=(int)(aim-val);pError1=ThisError1-LastError1;iError1=ThisError1;temp1=(int)(servo_KP*pError1+servo_KI*iError1);LastError1=ThisError1; duty1+=temp1;if(duty1>150)duty1=150;//900if(duty1<-100)duty1=-100;//650TIM_SetCompare2(TIM1,750+duty1);//110 30 68 //左大右小 return duty1;
}
int Y_servo_pwm(int d)
{static int Distance;static int dd,last_dd;if(d>=200){//距离需大于等于200dd=d;if(dd!=last_dd){//云台Y轴模拟三阶比例输出Distance =(int)(-0.000030*d*d*d+0.022546*d*d+-6.417342*d+1809.190229);// Distance=(int)(+0.000154*d*d*d+-0.034523*d*d+1.448813*d+1392.202060);}last_dd=dd;if(Distance<min_Y) Distance=min_Y;if(Distance>center_Y) Distance=center_Y;TIM_SetCompare2(TIM1,Distance);//900 1230return Distance;}else{TIM_SetCompare2(TIM1,center_Y);//900 1230return center_Y;}
}
int X_servo_pwm(int a)
{static int Pwm;static int aa,last_aa=1;aa=a;//云台X轴二阶比例输出if(aa!=last_aa){Pwm=(int)(0.000320*a*a+-5.503297*a+680.118881);}last_aa=aa;if(Pwm>max_X)Pwm=max_X;if(Pwm<min_X)Pwm=min_X;TIM_SetCompare1(TIM1,Pwm);//900 500 700 //左小右大return Pwm;
}// TIM1_PWM_Init(999,3359);
// TIM_SetCompare1(TIM1,70);//110 30 68 //110 30 70int ZCZC=830;
u8 TURN_flag=0;
int TIME_COUNT=0;
int CHANG_ANGLE=680;
extern u8 send_flag;
extern int x_err;
void Turn_servo(int time)
{TIME_COUNT++;if(TIME_COUNT==time){TIME_COUNT=0;if(TURN_flag==0)ZCZC-=5;if(TURN_flag==1)ZCZC+=5;if(ZCZC>830){ZCZC=830;TURN_flag=0;}if(ZCZC<530){ZCZC=530;TURN_flag=1;}TIM_SetCompare1(TIM1,ZCZC);//900 500 680 //左小右大}
}
摄像头串口数据接收程序
void Optical_Flow_Receive_Prepare(u8 data)
{/* 局部静态变量:接收缓存 */static u8 RxBuffer[4];/* 数据长度 *//* 数据数组下标 */static u8 _data_cnt = 0;/* 接收状态 */static u8 state = 0;/* 帧头1 */if(state==0&&data==TITLE1){state=1;}/* 帧头2 */else if(state==1&&data==TITLE2){state=2;_data_cnt = 0;}/* 接收数据租 */else if(state==2){uart_flag=1;//数据校验没问题,开启串口接收标志RxBuffer[++_data_cnt]=data;if(_data_cnt>=2){state = 0;Data_Processing(RxBuffer,_data_cnt);}}/* 若有错误重新等待接收帧头 */elsestate = 0;
}int x_err,y_err;
void Data_Processing(u8 *data_buf,u8 num)
{int theta_org,rho_org;/* 读取偏移角度原始数据 *///theta_org = (int)(*(data_buf+1)<<0) | (int)(*(data_buf+2)<<8) | (int)(*(data_buf+3)<<16) | (int)(*(data_buf+4)<<24) ;//theta_err = theta_org;theta_org = (char)(*(data_buf+1)<<0); //| (char)(*(data_buf+2)<<8); //| (int)(*(data_buf+3)<<16) | (int)(*(data_buf+4)<<24) ;x_err = theta_org;/* 读取偏移尺寸原始数据 *///rho_org = (int)(*(data_buf+5)<<0) | (int)(*(data_buf+6)<<8) | (int)(*(data_buf+7)<<16) | (int)(*(data_buf+8)<<24) ;//rho_err = rho_org;rho_org = (char)(*(data_buf+2)<<0); //| (char)(*(data_buf+4)<<8);//| (int)(*(data_buf+7)<<16) | (int)(*(data_buf+8)<<24) ;y_err = rho_org;}u8 UART_RX2[9];
u8 uart_flag=0;
u8 numzz;
void USART2_IRQHandler(void) //串口1中断服务程序
{u8 Res2;
// u8 t2;
// u8 len2;
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntEnter();
#endifif(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾){//uart_flag=1;Res2 =USART_ReceiveData(USART2);//(USART1->DR); //读取接收到的数据Optical_Flow_Receive_Prepare(Res2);
// if((USART_RX_STA2&0x8000)==0)//接收未完成
// {
// if(USART_RX_STA2&0x4000)//接收到了0x0d
// {
// if(Res2!=0x0a)USART_RX_STA2=0;//接收错误,重新开始
// else USART_RX_STA2|=0x8000; //接收完成了
// }
// else //还没收到0X0D
// {
// if(Res2==0x0d)USART_RX_STA2|=0x4000;
// else
// {
// USART_RX_BUF2[USART_RX_STA2&0X3FFF]=Res2 ;
// USART_RX_STA2++;
// if(USART_RX_STA2>(USART_REC_LEN-1))USART_RX_STA2=0;//接收数据错误,重新开始接收
// }
// }
// }
// if(USART_RX_STA2&0x8000)
// {
// len2=USART_RX_STA2&0x3fff;//得到此次接收到的数据长度
// for(t2=0;t2<len2;t2++)
// {//接收OPENMV1
// UART_RX2[t2]=USART_RX_BUF2[t2];
// USART_RX_BUF2[t2]=0;
// }
// USART_RX_STA2=0;
// } }
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.OSIntExit();
#endif
}
测距模块数据接收程序
u16 UART_RX3[9];
u8 DistanceBuff[6];
u8 numzc=0;
int DDDDD=0;
u8 zc;
extern u8 X_FLAG;
int distance;
void USART3_IRQHandler(void) //串口1中断服务程序
{static u8 seri_count=0;u16 check_sum=0;u8 i;static u8 flag;if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){zc=1;USART_ClearFlag(USART3, USART_FLAG_RXNE);USART_ClearITPendingBit(USART3, USART_IT_RXNE);if(USART_ReceiveData(USART3)==Data_Head){flag=1;}if( flag==1){UART_RX3[seri_count++]=USART_ReceiveData(USART3);if(seri_count == 9){if(UART_RX3[0]==Data_Head && UART_RX3[1]==Data_Head){for(i=0;i<9-1;i++){check_sum+=UART_RX3[i];}if((check_sum & 0x00ff)==UART_RX3[8]){distance=UART_RX3[2]+UART_RX3[3]*256;seri_count=0;flag=0;}}}}}
}
中断处理函数
int x1,y;
extern u8 uart_flag;
extern int D,A;
int DISTANCE,Angle;
u8 UART_FLAG;
u8 TURN_OFF=0;
u8 X_FLAG=1,Y_FLAG;
int X_TINE_COUNT=0;
extern int DDDDD;
extern u8 send_flag;
extern int distance;
void camera_send1(void)
{if(TURN_OFF==1){X_TINE_COUNT++;}if(X_TINE_COUNT==X_TIME){//摄像头循迹关闭,打开激光测距X_FLAG=0;//摄像头循迹关闭,打开激光测距DDDDD= distance;if(DDDDD>330)DDDDD=330;if(DDDDD<230)DDDDD=230;DISTANCE=Y_servo_pwm(DDDDD-30);}if(X_TINE_COUNT==SEND_TIME){X_TINE_COUNT=0;TURN_OFF=0;UART_FLAG=0;if(send_flag==0){send_flag=1;//发射电磁炮}}if(X_FLAG==1){//X轴摄像头循迹打开,关闭激光测距if(uart_flag==1)//接到数据开始处理{//uart_flag=0; x1=X_servo_PID(x_err,X); //X_TINE_COUNT++;TURN_OFF=1; //关闭舵机自动打角 }else{//没有接受到数据,打角找坐标if(TURN_OFF==0){Turn_servo(10);}}}
}extern u8 find_flag;
extern u8 turn_flag;
void TIM6_DAC_IRQHandler(void)
{ if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET){if(UART_FLAG==1){//允许执行中断程序if(find_flag==1){camera_send1();}else if(turn_flag==1){Turn_servo(10);DISTANCE=Y_servo_pwm(255);//1141 }else{DISTANCE=Y_servo_pwm(D);Angle=X_servo_pwm(A);}}}TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
}