主程序
#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);//设置系统中断优先级分组2
KEY_Init();
LED_Init();
TIM1_PWM_Init(9999,335);//50HZ 精度10000
TIM_SetCompare1(TIM1,center_X);//900 500 680 //左小右大center_X//580 790
TIM_SetCompare2(TIM1,center_Y);//900 1230 //上下center_Y
uart_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;//900
if(duty1<-100)duty1=-100;//650
TIM_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)
{//距离需大于等于200
dd=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 1230
return Distance;
}
else
{
TIM_SetCompare2(TIM1,center_Y);//900 1230
return 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 70
int 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);
}
}
/* 若有错误重新等待接收帧头 */
else
state = 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();
#endif
if(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);
}