⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 odometer.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
字号:
/****************************************************************
**                                                              *
**  FILE         :  OdoMeter.C                                  *
**  COPYRIGHT    :  (c) 2001 .Xiamen Yaxon NetWork CO.LTD       *
**                                                              *
**                                                              *
**  By : CCH 2002.1.15                                          *
****************************************************************/
#include "includes.h"
#include "bsp.h"
#include "tools.h"
#include "errcode.h"
#include "errtask.h"
#include "ramimage.h"
#include "sensor.h"
#include "timetask.h"
#include "systime.h"
#include "gpsrecer.h"
#include "gpstool.h"
#include "odometer.h"
#include "ZPrint.h"
#if EN_ODOMETER > 0
#include "public.h"
#endif

#define ODOMETER_DEBUG 0
#if ODOMETER_DEBUG
static INT8U tempdata[20],templen;
static INT8U Index=0;
typedef struct
{
   INT8U Lat_C;
   INT8U Long_C;
}SIMULAT_GPS;

static SIMULAT_GPS simulat_gps[4]={ 0x18,0x76,
                                    0x18,0x77,
                                    0x19,0x77,
                                    0x19,0x76
											 };
static void GetGPSdata_(INT8U *data1,INT8U *data2)
{
   data1[0]=simulat_gps[Index].Lat_C;
   data1[1]=0x01;
   data1[2]=0x01;
   data1[3]=0x01;
   data2[0]=simulat_gps[Index].Long_C;
   data2[1]=0x01;
   data2[2]=0x01;
   data2[3]=0x01;
   if(++Index>=4) Index=0;
}
#endif

/*
********************************************************************************
* 定义配置参数
********************************************************************************
*/
#define MAX_METER                   10
#define PERIOD_SCAN                 SECOND,  1              /* 扫描周期 */

#define PERIOD_UPDATE               MINUTE, (2 * 60)        /* 刷新flash时间周期 */


#define MAX_RUN_SECOND              300                   
/*
********************************************************************************
* 定义数据结构
********************************************************************************
*/
typedef struct {
    INT8U       attrib;			      
    BOOLEAN     started;
    INT8U       tag;
    INT32U      space;
    void (*handler)(INT8U tag);
} METER;

/*
********************************************************************************
* 定义状态参数
********************************************************************************
*/
#define MODE_GPS                    0x01

/*
********************************************************************************
* 定义模块局部变量
********************************************************************************
*/
static METER    meter[MAX_METER];//定义里程统计表,每个需要统计里程处便安装一个里程统计表
static TMR_TSK  *scantmr;
static TMR_TSK  *updatetmr;
static INT8U    status;
static INT16U   fraction;
static INT32U   curspace;
static INT8U    pre_lat[4], pre_long[4], cur_lat[4], cur_long[4];


void ClearOdoMeter(void)
{
    odometer.datevalid = false;
    odometer.t_space   = 0;
    StorePubPara(ODOMETER_);
    StoreRamImage(RI_ODOMETER_, (INT8U *)&odometer, sizeof(odometer));
}

INT8U GetOdoMeterDate(INT8U *ptr)//获取里程统计的起始日期
{
    memcpy(ptr, &odometer.startdate, sizeof(odometer.startdate));
    return sizeof(odometer.startdate);
}

INT8U GetOdoMeterData(INT8U *ptr)//获取总里程数据,并转换为ASCII字符
{
    return DecToAscii(ptr, odometer.t_space, 0);
}

static void UpdateTmrProc(void)//定时(2小时)将ODOMETER参数刷新到FLASH中
{
    StartTmr(updatetmr, PERIOD_UPDATE);
    StorePubPara(ODOMETER_);
    StoreRamImage(RI_ODOMETER_, (INT8U *)&odometer, sizeof(odometer));//保存到内存映射区相应位置
}


static void ScanTmrProc(void)//计算里程,间隔1s
{
    INT8U  i;

    StartTmr(scantmr, PERIOD_SCAN);
 
    if(!odometer.datevalid) {
        if (SysTimeValid()) {
            odometer.datevalid = true;
            GetSysTime_Date(&odometer.startdate);
            StorePubPara(ODOMETER_);
            StoreRamImage(RI_ODOMETER_, (INT8U *)&odometer, sizeof(odometer));
        }
    }

    if (!SensorValid_FILTER(_ACC)) {                /* ACC状态处于OFF,则不进行里程计算 */
        return;
    }
    
         
	#if ODOMETER_DEBUG
    GetGPSdata_(cur_lat,cur_long);
	#else  
    if (!GpsDataValid()) return;                /* GPS数据无效 */
    GetLatitude(cur_lat);                       /* 获取当前位置纬度 */
    GetLongitude(cur_long);                     /* 获取当前位置经度 */
	#endif

    if (CmpString_Byte(pre_lat, sizeof(pre_lat), 0xff)) {
       curspace = 0;
    } else {
       /* 通过前后秒的位置计算出1秒之内行驶的距离 */
       curspace = CalculateGpsSpace(pre_lat, pre_long, cur_lat, cur_long);
	   if(MAX_RUN_SECOND <= curspace ) curspace = 0;
    }
    memcpy(pre_lat,  cur_lat,  sizeof(pre_lat));
    memcpy(pre_long, cur_long, sizeof(pre_long));

    curspace *= 105L;                           /* 加上5%的校正误差 */
    fraction += (curspace % 100L);
    curspace /= 100L;
    
    if (fraction >= 100) {                          /* 小数部分进行进位处理 */
        curspace += fraction / 100;
        fraction %= 100;
    }

    for (i = 0; i < MAX_METER; i++) {
        if (meter[i].started && meter[i].handler != 0) {
            if (meter[i].attrib & _SUM) {
                meter[i].space += curspace;//累加递增方式
            } else {
                if (meter[i].space > curspace) {
                    meter[i].space  -= curspace;//递减方式,减到0则统计完成执行handler函数
                } else {
                    meter[i].started = false;
                    meter[i].handler(meter[i].tag);
                }
            }
        }
    }
    
    odometer.t_space += curspace;
    VirStorePubPara(ODOMETER_);
    StoreRamImage(RI_ODOMETER_, (INT8U *)&odometer, sizeof(odometer));
}

static INT8U FindBlankMeter(void)
{
    INT8U i;
    
    for (i = 0; i < MAX_METER; i++) {
        if (meter[i].handler == 0) return i;
    }
    return 0xff;
}

static void DiagnoseProc(void)
{
    if (GetTmrSwitch(scantmr) != ON) ErrExit(ERR_ODOMETER_TMR);    
    if (GetTmrSwitch(updatetmr) != ON) ErrExit(ERR_ODOMETER_TMR);
}




void InitOdoMeter(void)
{
    INT8U i;

    for (i = 0; i < MAX_METER; i++) {
        meter[i].handler = (void (*)(INT8U)) 0;
    }

    if (RamImageValid(RI_ODOMETER_)) { 
        ResumeRamImage(RI_ODOMETER_, (INT8U *)&odometer, sizeof(odometer));
    } else if(!PubParaValid(ODOMETER_)) {       
        ClearOdoMeter();
    }
    
    scantmr   = CreateTimer(ScanTmrProc, 0);
    updatetmr = CreateTimer(UpdateTmrProc, 0);
    StartTmr(scantmr,   PERIOD_SCAN);
    StartTmr(updatetmr, PERIOD_UPDATE);

    status   = MODE_GPS;                    /* 缺省情况下采用GPS位置信息计算里程数据 */
    memset(pre_lat,  0xff, sizeof(pre_lat));
    memset(pre_long, 0xff, sizeof(pre_long));
    InstallDiagProc(DiagnoseProc);
}

INT8U InstallMeter(void (*handler)(INT8U), INT8U tag)
{
    INT8U id;

    if ((id = FindBlankMeter()) == 0xff) {
        ErrExit(ERR_ODOMETER_INSTALL);
        return 0xff;
    } else {
        meter[id].started = false;
        meter[id].tag     = tag;
        meter[id].handler = handler;
        return id;
    }
}

void RemoveMeter(INT8U id)
{
    if (id >= MAX_METER) {
        ErrExit(ERR_ODOMETER_ID);
    } else {
        meter[id].handler = (void (*)(INT8U)) 0;
    }
}

void ChangeMeterTag(INT8U id, INT8U tag)
{
    if (id >= MAX_METER) {
        ErrExit(ERR_ODOMETER_ID);
    } else {
        meter[id].tag = tag;
    }
}

void StartMeter(INT8U id, INT8U attrib, INT16U space)
{
    HWORD_UNION temp;
    
    if (id >= MAX_METER) {
        ErrExit(ERR_ODOMETER_ID);
    } else {
        meter[id].attrib  = attrib;
        meter[id].started = true;
        attrib   &= ~_SUM;
        temp.hword = space;
        if (attrib == _DM) {
            meter[id].space = temp.bytes.low * 10 + temp.bytes.high * 1000;
        } else if (attrib == _KM) {
            meter[id].space = (temp.bytes.high * 100 + temp.bytes.low) * 1000L;
        } else {
            ErrExit(ERR_ODOMETER_ATTRIB);
        }
    }
}

void StopMeter(INT8U id)
{
    if (id >= MAX_METER) {
        ErrExit(ERR_ODOMETER_ID);
    } else {
        meter[id].started = false;
    }
}

INT32U GetMeterSpace(INT8U id)
{
    if (id >= MAX_METER) {
        ErrExit(ERR_ODOMETER_ID);
        return 0;
    } else {
        return meter[id].space;
    }
}

void ClearMeter(INT8U id)
{
    if (id >= MAX_METER) {
        ErrExit(ERR_ODOMETER_ID);
    } else {
        meter[id].space = 0;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -