main.c
点击查看代码
/*! ----------------------------------------------------------------------------
* PDOA跟随小车控制板程序
* @author 广州联网科技有限公司
*/
#include <string.h>
#include <stdio.h>
#include "main.h"
#include "delay.h"
#include "Commu.h"
#include "motion.h"
#include "stmflash.h"
#include <usart2.h>
#include <led.h>
#include <stm32f10x.h>
/**************************************/
/* 变量 */
/**************************************/
uint8_t LED2_En = 0; //LED2使能标志
uint8_t LED3_EN = 0; //LED3使能标志
uint8_t ADC_Beep_En = 0; //蜂鸣器使能标志 ADC用
uint8_t COUPLE_Beep_En = 0; //蜂鸣器使能标志 Couple用
uint32_t LED_FLAG=0; //系统指示灯记录标志位
uint8_t Flash_App_Mode; //系统工作模式
u8 led_flag=1;
typedef enum
{
system_findcp_init = 0, //初始配对标签列表(K列表)
system_findcp_ing, //监听标签
system_findcp_fin, //搜索完成
system_couple_working //正常工作
}system_flag_t; //Couple模式下系统的工作状态指示
uint8_t system_flag = system_couple_working;
uint8_t Mode_Single_Flag = 0; //Single模式工作标志位
uint8_t Mode_Couple_Flag = 0; //Couple模式工作标志位
char* Flash_Tag16_ID = "4096"; //标签短ID 固定4096
uint16_t Flash_Tag_Fastfreq = 1; //标签运动发包频率留空 目前值无意义
uint16_t Flash_Tag_Slowfreq = 100; //标签静止发包频率留空 目前值无意义
uint16_t Flash_Tag_Mode = 0; //标签工作模式留空 目前值无意义
uint8_t OLED_Flag = 0; //OLED显示
uint32_t Beep_Flag = 0;
uint8_t comm_move = Motion_Stop; //指示运动
#define ADC_Timeout 50000 //ADC测量电量周期时间
#define ADC_FULL_POWER 12.6 //ADC测量电量最大电压 ADC测量电压为电池电压
#define ADC_LOW_POWER 10.2 //ADC测量电量最小电压 ADC测量电压为电池电压
/**************************************/
/* 函数 */
/**************************************/
static void Mode_Single_App(void); //单一工作模式
static void Mode_Couple_App(void); //配对工作模式
static void Move_Test(void); //运动测试
static void Oled_InitShow(void); //OLED屏幕显示
static void Adc_Event(void); //ADC测量电压
static void Key_Event(void); //按键扫描
/**************************************/
/* 代码开始 */
/**************************************/
/**
* @brief 按键扫描
* @param None
* @retval None
*/
void Key_Event()
{
if(Read_KEY1 == 0)
{
if(time_flag_Key > 30000)
{
LED2_En = 1;
system_flag = system_findcp_init;
time_flag_Key = 0;
}
}
else
time_flag_Key = 0;
}
/**
* @brief 运动测试
会执行直行 左转 右转 用于判断线是否接对
* @param None
* @retval None
*/
void Move_Test(void)
{
Motor_Speed_Change(350);
Motor_Forward();
delay_ms(500);
Motor_Front_TurnLeft();
delay_ms(500);
Motor_Front_TurnRight();
delay_ms(500);
Motor_Stop();
}
/**
* @brief ADC测量
测量电池的ADC电压 如果使用USB供电 将显示USB
* @param None
* @retval None
*/
void Adc_Event(void)
{
double adc_value = 0;
char adc[10] = {'0'};
adc_value = Get_Adc_Average(0,5);
adc_value = adc_value * 3.3 / 4096 * 4 ;
if(adc_value > ADC_FULL_POWER)
adc_value = ADC_FULL_POWER;
if(adc_value < 1) //usb供电 此时由5V供电 电机无法转动
{
sprintf(adc,"%s","USB");
}
else //电池供电 显示电压百分比
{
adc_value = (adc_value - ADC_LOW_POWER) / (ADC_FULL_POWER - ADC_LOW_POWER) * 100;
sprintf(adc,"%d",(uint16_t)adc_value);
strcat(adc,"%");
if(adc_value < 30) //电量小于30
ADC_Beep_En = 1;
else
ADC_Beep_En = 0;
}
OLED_Clear();
Oled_InitShow();
OLED_ShowString(50,38,adc,12,1);
OLED_Refresh();
time_flag_Adc = 0;
}
/**
* @brief OLED屏幕信息显示
* @param None
* @retval None
*/
void Oled_InitShow(void)
{
char temp[20] = {'0'};
char show_num;
char point = '.';
char Mode[30] = "Mode:";
char Battery[9] = "Battery:";
strcpy(temp,APP_NAME);
sprintf(&show_num,"%d",VERSION/10);
strcat(temp,&show_num);
strcat(temp,&point);
sprintf(&show_num,"%d",VERSION%10);
strcat(temp,&show_num);
OLED_ShowString(0,0,temp,12,1);
OLED_ShowString(0,12,APP_AUTHOR,12,1);
if(Flash_App_Mode == MODE_SINGLE)
strcat(Mode,"Single");
if(Flash_App_Mode == MODE_COUPLE)
strcat(Mode,"Couple");
OLED_ShowString(0,24,Mode,12,1);
OLED_ShowString(0,38,Battery,12,1);
OLED_Refresh();
}
/**
* @brief Single模式下工作流程
等待基站上报获取到新标签信息,添加该标签并跟随该标签
会跟随该基站第一个响应到的标签
要求基站的K列表中不存在要跟随的标签
* @param None
* @retval None
*/
void Mode_Single_App()
{
//Step0 等待获取基站上报要跟随的标签ID
if(Mode_Single_Flag == 0)
{
if(Usart_event_flag & (1 << JType_NewTag)) //接收到新标签ID
{
Usart_event_flag &= (0 << JType_NewTag);
Mode_Single_Flag = 1;
}
}
//Step1 指示基站添加该标签的信息
if(Mode_Single_Flag == 1)
{
Command_Result comm;
comm = Commu_Addtag(JNewtag.TagID,Flash_Tag16_ID,Flash_Tag_Fastfreq,Flash_Tag_Slowfreq,Flash_Tag_Mode);
if(comm == Command_Good)
{
Mode_Single_Flag = 2;
// time3_usart1 = 0;
}
}
//Step2 监听是否接收到正确的标签信息
if(Mode_Single_Flag == 2)
{
if(Usart_event_flag & (1 << JType_TagAdded)) //接收到正确返回信息
{
Usart_event_flag &= (0 << JType_TagAdded);
LED2_En = 0; //代表匹配成功
Beep_On;
delay_ms(200);
Beep_Off;
Mode_Single_Flag = 3;
}
}
//Step3 监听TWR信息 并根据其值进行解算和控制电机
if(Mode_Single_Flag == 3)
{
if(Usart_event_flag & (1 << JType_TWR)) //接收到新标签ID
{
Usart_event_flag &= (0 << JType_TWR);
//电机控制
LED3_TOGGLE;
// printf("raw:%d %d %d %d\r\n",JTwrtag.X,JTwrtag.Y,JTwrtag.Dis,JTwrtag.P);
comm_move = Motion_Control(JTwrtag.X,JTwrtag.Y,JTwrtag.Dis,JTwrtag.P);
time_flag = 0;
}
if(comm_move != Motion_Stop)
comm_move = Motion_IR_Control(comm_move);
if(time_flag > 5000) //如果500ms没有收到信息 认为标签已经断电
{
Motion_Init();
comm_move = Motion_Stop;
}
Motion_Act(comm_move);
}
}
/**
* @brief Couple模式下工作流程
分为搜索状态和跟随状态
如果长按Key1按键3秒以上 进入搜索标签状态 等待新标签信号监听然后配对
只支持一对一配对
* @param None
* @retval None
*/
void Mode_Couple_App()
{
/*
配对工作模式
该模式下 控制板会记录基站要配对的标签ID
工作方式:获取标签后让基站保存配置到Flash 下次不用再次添加
*/
uint8_t i;
Command_Result comm;
switch(system_flag)
{
case system_findcp_init: //读取此时K列表并删除所有标签
{
if(Mode_Couple_Flag == 0)
{
comm_move = Motion_Stop;
Motion_Act(comm_move); //防止车辆在动
Mode_Couple_Flag = 1;
}
//获取K列表
if(Mode_Couple_Flag == 1)
{
comm = Commu_GetKList();
if(comm == Command_Good)
Mode_Couple_Flag = 2;
}
//是否获取成功
if(Mode_Couple_Flag == 2)
{
if(Usart_event_flag & (1 << JType_KList))
{
Usart_event_flag &= (0 << JType_KList); //获取好KList信息
comm = Command_Error;
if(KList_num != 0)
Mode_Couple_Flag = 3;
else
Mode_Couple_Flag = 14;
}
}
//删除K列表里面所有标签
if(Mode_Couple_Flag > 2 && Mode_Couple_Flag < 3 + KList_num)
{
for(i=Mode_Couple_Flag;i<KList_num + 3;i++) //删除K列表的标签
{
if(Mode_Couple_Flag == i)
{
if(comm == Command_Error)
{
delay_ms(50); //少量延时配合基站板
comm = Commu_Deltag(KList[i-3].Addr64);
}
else
{
if(Usart_event_flag & (1 << JType_TagDeleted))
{
Usart_event_flag &= (0 << JType_TagDeleted);
if(Mode_Couple_Flag == KList_num + 3 - 1)
Mode_Couple_Flag = 14;
else
Mode_Couple_Flag++;
comm = Command_Error;
}
}
}
}
}
//删除成功 保存当前配置
if(Mode_Couple_Flag == 14)
{
delay_ms(100);
comm = Commu_Save();
if(comm == Command_Good)
{
system_flag = system_findcp_ing;
Mode_Couple_Flag = 20;
COUPLE_Beep_En = 1; //使能蜂鸣器
}
}
break;
}
case system_findcp_ing: //等待搜索标签
{
if(Mode_Couple_Flag == 20)
{
if(Usart_event_flag & (1 << JType_NewTag)) //接收到新标签ID
{
Usart_event_flag &= (0 << JType_NewTag);
Mode_Couple_Flag = 21;
}
}
if(Mode_Couple_Flag == 21)
{
comm = Commu_Addtag(JNewtag.TagID,Flash_Tag16_ID,Flash_Tag_Fastfreq,Flash_Tag_Slowfreq,Flash_Tag_Mode);
if(comm == Command_Good)
{
Mode_Couple_Flag = 22;
}
}
if(Mode_Couple_Flag == 22)
{
if(Usart_event_flag & (1 << JType_TagAdded)) //接收到正确返回信息
{
Usart_event_flag &= (0 << JType_TagAdded);
Mode_Couple_Flag = 23;
delay_ms(100);
}
}
if(Mode_Couple_Flag == 23)
{
comm = Commu_Save();
if(comm == Command_Good)
{
system_flag = system_couple_working; //匹配成功 退出搜索模式
Mode_Couple_Flag = 0;
LED2_En = 0; //代表匹配成功
LED2_ON;
COUPLE_Beep_En = 0;
}
}
}
case system_couple_working:
{
if(Usart_event_flag & (1 << JType_TWR)) //接收到新标签ID
{
// char show[10] = {'0'};
Usart_event_flag &= (0 << JType_TWR);
//电机控制
LED3_TOGGLE;
// printf("raw:%d %d %d %d\r\n",JTwrtag.X,JTwrtag.Y,JTwrtag.Dis,JTwrtag.P);
comm_move = Motion_Control(JTwrtag.X,JTwrtag.Y,JTwrtag.Dis,JTwrtag.P);
time_flag = 0;
}
if(comm_move != Motion_Stop)
comm_move = Motion_IR_Control(comm_move);
if(time_flag > 5000)
{
Motion_Init();
comm_move = Motion_Stop;
}
Motion_Act(comm_move);
break;
}
}
}
/******************************************************************************
主函数
*******************************************************************************/
int main(void)
{
peripherals_init();//初始化外设
// printf("初始化完成!");
// u2_printf("初始化完成!");
FLASH_read(); //读取Flash中保存的参数
Adc_Event(); //先测量一次电压
// Move_Test();
LED2_ON;
LED3_ON;
while(1)
{
Key_Event();
Usart_Fin_Handler();
if(time_flag_Adc > ADC_Timeout) //每ADC_Timeout的时间测量一次电压
Adc_Event();
// Usart_Test();
if(led_flag==1)
{
switch(Flash_App_Mode)
{
case MODE_SINGLE:
{
Mode_Single_App();
break;
}
case MODE_COUPLE:
{
Mode_Couple_App();
break;
}
default:break;
}
}
else
{
Motor_Stop();//报警后,电机停止运动
}
if(LED_FLAG > 100000)
{
LED1_TOGGLE;
if(LED2_En)
LED2_TOGGLE;
if(LED3_EN)
LED3_TOGGLE;
LED_FLAG = 0;
/*报警闪灯*/
if(led_flag==0)
{
LED0=!LED0;
//u2_printf("123\r\n");
}
/*End*/
}
else
LED_FLAG++;
/*蜂鸣器使用*/
// if(ADC_Beep_En || COUPLE_Beep_En)
// {
// if(Beep_Flag > 80000)
// {
// Beep_Toggle;
// Beep_Flag = 0;
// }
// else
// Beep_Flag++;
// }
// else
// Beep_Off;
/*End*/
if(COUPLE_Beep_En)
{
if(Beep_Flag > 80000)
{
Beep_Toggle;
Beep_Flag = 0;
}
else
Beep_Flag++;
}
else
Beep_Off;
}
}