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

📄 gps source code.txt

📁 用单片机控制GPS模块C51源代码。。希望对大家了解单片机控制GPS有帮助。
💻 TXT
📖 第 1 页 / 共 5 页
字号:

// ****************************************************************************
//   Real-time interrupt.
//

// A counter that ticks every 100mS.
uint8_t timeTicks;

// Counts the number of 1mS interrupts for a 100mS time period.
uint8_t timeInterruptCount;

// Counts the number of 100mS time periods in 1 second.
uint8_t time100ms;

// System time in seconds.
uint8_t timeSeconds;

// System time in minutes.
uint8_t timeMinutes;

// System time in hours.
uint8_t timeHours;

// Desired LED duty cycle 0 to 9.
uint8_t timeDutyCycle;

// Time compare register 1 value.
uint16_t timeCompare;

// The CCP1 timer delta between each interrupt.  1mS for PSK31 and 833uS for 1200 baud APRS
uint16_t timeRate;

// Flag set true once per second.
boolean timeUpdateFlag;

// The current number of interrupts in a 100mS time period.  100 for PSK31 and 120 for 1200 baud APRS.
uint8_t timeInterruptCountRollOver;

// The current time base mode.
TIME_MODE timeMode;

// The change in the CCP_1 register for each interrupt period. 1mS for PSK31, 833uS for 1200 baud APRS, 3.3mS for 300 baud HF-APRS 
#define TIME_RATE_PSK31 1200
#define TIME_RATE_APRS 1000
#define TIME_RATE_HF_APRS 4000

// The number of interrupts in a 100mS time period.
#define TIME_ROLLOVER_PSK31 100
#define TIME_ROLLOVER_APRS 120
#define TIME_ROLLOVER_HF_APRS 30

/**
 *   Running 8-bit counter that ticks every 100mS.
 *
 *   @return 100mS time tick
 */
uint8_t timeGetTicks()
{
    return timeTicks;
}

/**
 *   Initialize the real-time clock.
 */
void timeInit()
{
    timeTicks = 0;
    timeInterruptCount = 0;
    time100mS = 0;
    timeSeconds = 0;
    timeMinutes = 0;
    timeHours = 0;
    timeDutyCycle = TIME_DUTYCYCLE_70;
    timeCompare = TIME_RATE_APRS;
    timeUpdateFlag = false;
    timeRate = TIME_RATE_APRS;
    timeInterruptCountRollOver = TIME_ROLLOVER_APRS;
    timeMode = TIME_MODE_APRS;
    
    // Configure CCP1 to interrupt at 1mS for PSK31 or 833uS for 1200 baud APRS
    CCP_1 = timeRate;
    set_timer1(timeCompare);
    setup_ccp1( CCP_COMPARE_INT );
    setup_timer_1( T1_INTERNAL | T1_DIV_BY_4 );
}

/**
 *   Set the blink duty cycle of the heartbeat LED.  The LED blinks at a 1Hz rate.
 *
 *   @param dutyCycle TIME_DUTYCYCLE_xx constant
 */
void timeSetDutyCycle (uint8_t dutyCycle)
{
    timeDutyCycle = dutyCycle;
}

/**
 *   Set the time base for PSK31 or APRS.
 *
 *   @param mode <i>TIME_MODE_APRS</i> or <i>TIME_MODE_PSK31</i> constant
 */
void timeSetMode (TIME_MODE mode)
{
    // If we are already in the desired mode, we don't need to do anything.
    if (mode == timeMode)
        return;
        
    // Save the new mode.
    timeMode = mode;
    
    // Disable interrupts while we adjust the time information.
    disable_interrupts (INT_CCP1);
    
    switch (timeMode) {
        case TIME_MODE_APRS:
            timeRate = TIME_RATE_APRS;
            timeInterruptCountRollOver = TIME_ROLLOVER_APRS;
            break;
        
        case TIME_MODE_PSK31:
            timeRate = TIME_RATE_PSK31;
            timeInterruptCountRollOver = TIME_ROLLOVER_PSK31;
            break;

        case TIME_MODE_HF_APRS:
            timeRate = TIME_RATE_HF_APRS;
            timeInterruptCountRollOver = TIME_ROLLOVER_HF_APRS;
            break;
    } // END switch
    
    // If the current interrupt count is past the roller over state, move it back.
    // This means we will loose an interrupt period, but we don't really care.
    if (timeInterruptCount >= timeInterruptCountRollOver)
        timeInterruptCount -= timeInterruptCountRollOver;
        
    // Restart the interrupts and we are back on-line.
    enable_interrupts (INT_CCP1);
}

// This function gets called every 1mS.
#INT_CCP1
void timeUpdate()
{
    // Pin used to measure CPU load in interrupt.
    output_high (PIN_B1);

    // Setup the next interrupt for the operational mode.
    timeCompare += timeRate;
    CCP_1 = timeCompare;

    // Call the appropriate time routine.
    if (timeMode == TIME_MODE_PSK31)
        psk31TimeUpdate();
    else
        tncTimeUpdate();

    // Read the GPS serial port and save any incoming characters.
    serialUpdate();

    // Count the number of milliseconds required for the tenth second counter.
    if (++timeInterruptCount == timeInterruptCountRollOver) {
        timeInterruptCount = 0;

        // This timer just ticks every 100mS and is used for general timing.
        ++timeTicks;

        // Roll the counter over every second.
        if (++time100mS == 10) {
            time100mS = 0;

            // We set this flag true every second.
            timeUpdateFlag = true;

            // Maintain a Real Time Clock.
            if (++timeSeconds == 60) {
                timeSeconds = 0;

                if (++timeMinutes == 60) {
                    timeMinutes = 0;
                    ++timeHours;
                } // END if
            } // END if
        } // END if

        // Flash the status LED at timeDutyCycle % per second.  We use the duty cycle for mode feedback.
        if (time100mS > timeDutyCycle)
            output_low (IO_LED);
        else
            output_high (IO_LED);
    } // END if

    // Pin used to measure CPU load in interrupt.
    output_low (PIN_B1);
}

// ****************************************************************************
//   TNC
//
// The number of CCP_1 timer in each bit time.
#define TNC_BIT_RATE 384

// The number of start flag bytes to send before the packet message.  (300mS)
#define TNC_TX_DELAY 45

// The UTC time in seconds to send an APRS packet.
#define TNC_TIMESLOT_1 54
#define TNC_TIMESLOT_2 56
#define TNC_TIMESLOT_3 58

// Modes for the TNC state machine.
#define TNC_TX_READY 0x00
#define TNC_TX_SYNC 0x01
#define TNC_TX_HEADER 0x02
#define TNC_TX_DATA 0x03
#define TNC_TX_END 0x04

// Modes for the packet state machine.
#define TNC_BOOT_MESSAGE 0x10
#define TNC_STATUS 0x11
#define TNC_GGA 0x12
#define TNC_RMC 0x13

// The size of the TNC output buffer.
#define TNC_BUFFER_SIZE 80

// The dwell duration in bits at each idle test tone.
#define TNC_DWELL_TIME 3600

// The packet header.
uint8_t TNC_AX25_HEADER[30] = { 
    'A' << 1, 'P' << 1, 'R' << 1, 'S' << 1, ' ' << 1, ' ' << 1, 0x60, \
    'K' << 1, 'D' << 1, '7' << 1, 'L' << 1, 'M' << 1, 'O' << 1, 0x76, \
    'G' << 1, 'A' << 1, 'T' << 1, 'E' << 1, ' ' << 1, ' ' << 1, 0x60, \
    'W' << 1, 'I' << 1, 'D' << 1, 'E' << 1, '3' << 1, ' ' << 1, 0x67, \
    0x03, 0xf0 };

uint8_t tncLastBit, tncMode, tncBitCount, tncShift, tncIndex, tncLength;
uint8_t tncBitStuff, *tncBufferPnt;
uint8_t tncPacketType, tncBuffer[TNC_BUFFER_SIZE];

// 1200 baud counter that determine which test signal to generate
uint16_t tncTestCount;

void tncInit()
{
    tncLastBit = 0;
    tncMode = TNC_TX_READY;
    tncTestCount = 0;
    tncPacketType = TNC_BOOT_MESSAGE;
}

/**
 *  Determine if the hardware if ready to transmit a 1200 baud packet.
 *
 *  @return true if ready; otherwise false
 */
boolean tncIsFree()
{
    if (tncMode == TNC_TX_READY)
        return true;

    return false;
}

// This ISR is called when the timer register matches the compare register.
// The interrupt rate is programmed to 833uS or 1 bit time at 1200 baud.
void tncTimeUpdate()
{
    // Set the A-FSK frequency.
    ddsAFSK ((tncLastBit == 0x00 ? false : true));

    switch (tncMode) {
        case TNC_TX_READY:
            // Generate a test signal alteranting between high and low tones.
            tncLastBit = (tncLastBit == 0 ? 1 : 0);
            break;

        case TNC_TX_SYNC:
            // The variable tncShift contains the lastest data byte.
            // NRZI enocde the data stream.
            if ((tncShift & 0x01) == 0x00)
                if (tncLastBit == 0)
                    tncLastBit = 1;
                else
                    tncLastBit = 0;
                    
            // When the flag is done, determine if we need to send more or data.
            if (++tncBitCount == 8) {
                tncBitCount = 0;
                tncShift = 0x7e;

                // Once we transmit x mS of flags, send the data.
                // txDelay bytes * 8 bits/byte * 833uS/bit = x mS
                if (++tncIndex == TNC_TX_DELAY) {
                    tncIndex = 0;
                    tncShift = TNC_AX25_HEADER[0];
                    tncBitStuff = 0;
                    tncMode = TNC_TX_HEADER;
                } // END if
            } else
                tncShift = tncShift >> 1;
            break;

        case TNC_TX_HEADER:
            // Determine if we have sent 5 ones in a row, if we have send a zero.
            if (tncBitStuff == 0x1f) {
                if (tncLastBit == 0)
                    tncLastBit = 1;
                else
                    tncLastBit = 0;

                tncBitStuff = 0x00;
                return;
            }    // END if

            // The variable tncShift contains the lastest data byte.
            // NRZI enocde the data stream.
            if ((tncShift & 0x01) == 0x00)
                if (tncLastBit == 0)
                    tncLastBit = 1;
                else
                    tncLastBit = 0;

            // Save the data stream so we can determine if bit stuffing is 
            // required on the next bit time.
            tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;

            // If all the bits were shifted, get the next byte.
            if (++tncBitCount == 8) {
                tncBitCount = 0;

                // After the header is sent, then send the data.
                if (++tncIndex == sizeof(TNC_AX25_HEADER)) {
                    tncIndex = 0;
                    tncShift = tncBuffer[0];
                    tncMode = TNC_TX_DATA;
                } else
                    tncShift = TNC_AX25_HEADER[tncIndex];

            } else
                tncShift = tncShift >> 1;

            break;

        case TNC_TX_DATA:
            // Determine if we have sent 5 ones in a row, if we have send a zero.
            if (tncBitStuff == 0x1f) {
                if (tncLastBit == 0)
                    tncLastBit = 1;
                else
                    tncLastBit = 0;

                tncBitStuff = 0x00;
                return;
            }    // END if

            // The variable tncShift contains the lastest data byte.
            // NRZI enocde the data stream.
            if ((tncShift & 0x01) == 0x00)
                if (tncLastBit == 0)
                    tncLastBit = 1;
                else
                    tncLastBit = 0;

            // Save the data stream so we can determine if bit stuffing is 
            // required on the next bit time.
            tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;

            // If all the bits were shifted, get the next byte.
            if (++tncBitCount == 8) {
                tncBitCount = 0;

                // If everything was sent, transmit closing flags.
                if (++tncIndex == tncLength) {
                    tncIndex = 0;
                    tncShift = 0x7e;
                    tncMode = TNC_TX_END;
                } else
                    tncShift = tncBuffer[tncIndex];

            } else
                tncShift = tncShift >> 1;

            break;

        case TNC_TX_END:
            // The variable tncShift contains the lastest data byte.
            // NRZI enocde the data stream. 
            if ((tncShift & 0x01) == 0x00)
                if (tncLastBit == 0)
                    tncLastBit = 1;
                else
                    tncLastBit = 0;

            // If all the bits were shifted, get the next one.
            if (++tncBitCount == 8) {
                tncBitCount = 0;
                tncShift = 0x7e;
    
                // Transmit two closing flags.
                if (++tncIndex == 2) {
                    tncMode = TNC_TX_READY;

                    // Turn off the DDSS and PA (PTT).
                    ddsPTT (false);
                    sysPAOutput (false);
                    return;
                } // END if
            } else
                tncShift = tncShift >> 1;

            break;
    } // END switch
}

/**
 *    Write <b>value</b> to the TNC buffer.  Maintain the pointer
 *    and length to the buffer.  The pointer tncBufferPnt and tncLength
 *    must be set before calling this function for the first time.
 * 
 *    @param value to save to telemetry buffer
 */
void tncTxByte (uint8_t value)
{
    *tncBufferPnt++ = value;
    ++tncLength;
}

/** 
 *    Prepare an AX.25 data packet.  Each time this method is called, it automatically
 *    rotates through 1 of 4 messages.
 */
void tncTxPacket()
{
    uint8_t satCount;
    uint16_t crc, altitude, temp;

    // Only transmit if there is not another message in progress and PSK 31 isn't using the hardware.
    if (tncMode != TNC_TX_READY || !psk31IsFree())
        return;

    // Set a pointer to our TNC output buffer.
    tncBufferPnt = tncBuffer;

    // Set the message length counter.
    tncLength = 0;

    // Determine the contents of the packet.
    switch (tncPacketType) {
        case TNC_BOOT_MESSAGE:
            printf (tncTxByte, ">ANSR PSK31/APRS Beacon eXtreme - V1.03");

            // Next packet to generate.
            tncPacketType = TNC_STATUS;
            break;

        case TNC_STATUS:
            // Get the GPS information to provide altitude and GPS tracking info.
            if (gpsWaitMessage (GPS_GGA_MSG)) {
                altitude = gpsParseAltitude();
                temp = gpsParseDOP();
                satCount = gpsParseSatCount();
            } else
                satCount = 255;

            // Display the telemetry header.
            printf (tncTxByte, ">Balloon ");

            // Display the flight time.
            printf (tncTxByte, "%02U:%02U:%02U ", timeHours, timeMinutes, timeSeconds);

            // If satCount was set to 255, then we didn't receive GPS data.
            if (satCount != 255) {
                if (altitude != 0)
                    printf (tncTxByte, "%lu0' ", altitude);
                else
                    printf (tncTxByte, "0' ");

                printf (tncTxByte, "%lu.%ludop ", temp / 10, temp % 10);
                printf (tncTxByte, "%02utrk ", satCount);
            } else
                printf (tncTxByte, "-----' -.-hdop --trk ");

            // Print web address link.
            printf (tncTxByte, "www.kd7lmo.net");

            // Add <CR><LF> to make it the same as the GPS NMEA messages.
            printf (tncTxByte, "\015");

            // Next packet to generate.
            tncPacketType = TNC_GGA;

            gpsState = GPS_WAIT_MSG;
            break;

        case TNC_GGA:
            if (gpsWaitMessage(GPS_GGA_MSG))
                printf (tncTxByte, gpsBuffer);
            else
                printf (tncTxByte, ">Invalid GPS $GPGGA message");

            tncPacketType = TNC_RMC;
            gpsState = GPS_WAIT_MSG;
            break;

        case TNC_RMC:
            if (gpsWaitMessage(GPS_RMC_MSG))
                printf (tncTxByte, gpsBuffer);
            else
                printf (tncTxByte, ">Invalid GPS $GPRMC message");

            // Next packet to generate.
            tncPacketType = TNC_STATUS;

            gpsState = GPS_WAIT_MSG;
            break;
    }

    // Add the end of message character.
    printf (tncTxByte, "\015");

    // Calculate the CRC for the header and message.
    crc = sysCRC16(TNC_AX25_HEADER, sizeof(TNC_AX25_HEADE

⌨️ 快捷键说明

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