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

📄 wm430_transmitter.c

📁 MSP430单片机的数据收发程序
💻 C
📖 第 1 页 / 共 2 页
字号:
  }
  if (WM430_TX_pendingMsgs < WM430_TX_QUEUEMSGMAX)
    WM430_TX_pendingMsgs++;                 // Increment pending messages counter
  else
    debug_dropped_messages++;               // Increment dropped messages counter
}

// _______________________________________________________________
// Miller Encoding (Delay Modulation) Scheme: Implementation Logic
// _______________________________________________________________
//
// CURRENT BIT  |   NEXT BIT   |  ACTIONS FOR TIMER ISR (will occur at 100 usec resolution intervals if data needs to be sent)
// ----------------------------------------------------------------------------------------------------------------------------------
//      0       |      0       |  Toggle rfState; set next Timer interrupt for 200 usec later
//
//      0       |      1       |  Toggle rfState; set next Timer interrupt for 300 usec later
//
//      1       |      0       |  Do Nothing; set next Timer interrupt for 100 usec later
//
//      1       |      1       |  Toggle rfState; set next Timer interrupt for 200 usec later
// ----------------------------------------------------------------------------------------------------------------------------------
//
// Timer_A3 Interrupt Service Routine
#pragma vector=TIMERA0_VECTOR
__interrupt void TIMERA0_ISR(void)
{
  unsigned char  temp1, temp2, temp3;

  // This routine sets the timing of the bits transmitted on the RF link.  In order to have
  // low jitter and accurate edge to edge spacing, we want to set the next data state early
  // in this routine and restart the timer for the appropriate width early in this routine.
  // That means we have to have previously calculated them.

  // Determine if RF_DATA pin needs to be set to physical level high or low then set it!
  // To avoid jitter problems, do not move this section of code (leave it at the beginning of the ISR)
  if (WM430_TX_rfState)
    P2OUT |= TX_CTRL2;
  else
    P2OUT &= ~TX_CTRL2;

  // Original Thinking:
  // Restart the timer so the next edge will happen at the right time.
  // To avoid jitter problems, do not move this section of code (leave it at the beginning of the ISR)
  // Latest Thinking:
  // Actually it may not matter whether we restart the timer early. It depends on whether
  // it counts down to negative numbers after the interupt occurs in which case we can add
  // the delta anytime before exiting the ISR with the same results.  On the other hand if it
  // counts down to 0 and stays at 0 it's important to add the new timer value as soon as possible.
  // I think it's the former case, so I moved the timer restart to the end of the routine. The same
  // jitter resulted.
  // FCLK     Nom_bit  JitterBit  HowLongForThisISR   AvgIdd1.5VMovingRefGray   Iddw/oRFboard
  // ---------------------------------------------------------------------------------------
  // 1.0MHz                                           24.8mA                    8.3mA
  // 2.0MHz    205us    >35us pp     <95.2us          24.8mA                    9.7mA
  // 2.2MHz    204us    >37us pp     <82.4us          24.8mA-                   9.7mA
  // 2.5MHz    205us    >28us pp     <72.4us          25.0mA                   10.0mA
  // 3.0MHz    203us    >24us pp     <60.8us          24.1mA                   10.7mA
  // 4.0MHz    206us    >25us pp     <51.0us          25.6mA                   10.6mA

  //  TACCR0 += WM430_TX_rfWidth;       // see end of ISR

  // Now we can take our time and calculate what the next bit state and duration will be.
  // As long as we finish in less than the shortest pulse width (<200us @ 5000 bps) we will be fine

                                            // Check if we're still in the STOP pattern sending phase
  if (WM430_TX_stopPatternBitNum == 0) {    // Stop pattern for current message has finished
    if (WM430_TX_pendingMsgs > 0)           // Make sure mesgs counter is not currently at 0
      WM430_TX_pendingMsgs--;               // Decrement pending mesgs counter only if non-zero (we've finished the message)
    WM430_TX_dataIdle();                    // Return data line to the default IDLE state
                                            // Save last bit history
    TA0V_currentTxBit = WM430_TX_CURRENTTXBITDEFAULT;
    TA0V_currentTxPtr++;                    // Increment current Tx pointer
    if (TA0V_currentTxPtr >= WM430_TX_QUEUEMSGMAX)
      TA0V_currentTxPtr = 0;                // Reset current Tx pointer
    if (WM430_TX_pendingMsgs != 0) {        // Any more messages to send?
                                            // Yes, prepare & create a delay gap before start of next mesg
      WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
                                            // Reset bit counters
      WM430_TX_startPatternBitNum = WM430_TX_STARTPATTERNPREAMBLENUMBITS;
      WM430_TX_syncPatternBitNum = WM430_TX_SYNCPATTERNNUMBITS;
      WM430_TX_stopPatternBitNum = WM430_TX_STOPPATTERNNUMBITS;
      goto isr_exit;                        // Leave the transmitter ON
    }
    else {                                  // No more pending messages
      WM430_TX_disableInt();                // Disable Tx Interrupt for now
      WM430_TX_disableRF();                 // No messages left to send; turn off the Transmitter module
      WM430_TX_dataIdle();                  // Return data line to the default IDLE state
      WM430_TX_dataHI();                    // Leave this variable high for a consistent start pattern
      goto isr_exit;                        // Exit the ISR
    }
  }
  if (WM430_TX_stopPatternBitNum < WM430_TX_STOPPATTERNNUMBITS) {
    if (WM430_TX_stopPatternBitNum > 1)     // Need to start sending stop bits
      WM430_TX_dataToggle();
    else
      WM430_TX_dataLO();                    // The last stop bit will be prematurely squashed to low
                                            // so go low in advance to avoid runt pulses
                                            // Check status of last data bit
    if (WM430_TX_stopPatternBitNum == (WM430_TX_STOPPATTERNNUMBITS-1)) {
        if (WM430_TX_rfState) {             // Next data bit is a logical '1' [1, 1]
        WM430_TX_rfWidth = (TIMERA0_SMCLK_BITPERIOD_05 + TIMERA0_SMCLK_BITPERIOD_10);
      }
      else {                                // Next data bit is a logical '0' [0, 1]
        WM430_TX_rfWidth = (TIMERA0_SMCLK_BITPERIOD_05 + TIMERA0_SMCLK_BITPERIOD_15);
      }
    }
    else {                                  // Remainder of the stop bits (2 thru N)
                                            // will be all 1's so space them equally apart
      WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
    }
    WM430_TX_stopPatternBitNum--;
    goto isr_exit;                          // Exit the ISR
  }

  if (WM430_TX_keyOnPeriodBitNum) {         // Check if new beginning of Tx On Period
    WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
    WM430_TX_dataToggle();                  // To represent Miller encoded 1's
    WM430_TX_keyOnPeriodBitNum--;           // Decrement the # of front-end garbage bits
    goto isr_exit;                          // Exit the ISR
  }

  if (WM430_TX_startPatternBitNum) {        // Check if we're still in the preamble START pattern sending phase
    WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
    WM430_TX_dataToggle();                  // To represent Miller encoded 1's
    WM430_TX_startPatternBitNum--;          // Decrement the # of start bits remaining
    goto isr_exit;                          // Exit the ISR
  }
  else {                                    // Finished sending start pattern bits
    if (WM430_TX_syncPatternBitNum) {       // Still have sync bits to shift out ?
      switch (WM430_TX_syncPatternBitNum) {
        case 6: case 5: case 4: case 2:
          WM430_TX_dataLO();                // Physically set data lineLOW
        break;
        case 3: case 1:
          WM430_TX_dataHI();                // Physically set data line HIGH
        break;
        default: break;
      }
      WM430_TX_syncPatternBitNum--;         // Decrement sync pattern bit number
      WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
      goto isr_exit;                        // Exit the ISR
    }
  }                                         // The variable data part of each packet is shifted out here
                                            // When this part of the ISR is reached, all start/sync/preamble bits have been scheduled
                                            // Look at current & next bits [x, y] to set data line & time interval for next interrupt
  TA0V_nextTxBit = (((WM430_TX_mesgQueue[TA0V_currentTxPtr].byte8bits[TA0V_bytePtr]) << TA0V_shiftCounter) & BIT7);

  if (TA0V_nextTxBit) {                     // Ucoming data bit is a logical '1'.  We definitely toggle now, but if the
                                            // bit after this is a 0 we won't be toggling for that bit, but rather waiting
                                            // an extra 100us.  To avoid use of 100us as a timer value (which allows
                                            // lower CPU clock and lower power),let's check and see whether the next bit is a 0
                                            // If so, we can bump the timer ahead 100us and increment the bit pointer an extra position
    WM430_TX_dataToggle();
    if (TA0V_currentTxBit) {                // Crrent data bit is a logical '1' [1, 1]
      WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
    }
    else {                                  // Crrent data bit is a logical '0' [0, 1]
      WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_15;
    }
  }
  else {                                    // Ucoming data bit is a logical '0'
    if (TA0V_currentTxBit) {                // Crrent data bit is a logical '1' [1, 0]
                                            // If we get here, no toggle due to [1,0] but peek ahead at the next next bit
                                            // First find the "next next" bit and byte position
      temp1 = TA0V_shiftCounter + 1 ;       // Iitialize temp1 variable and increment the value
      temp2 = TA0V_bytePtr;                 // Iitialize temp2 variable
      if (temp1 == WM430_TX_BITSPERBYTE) {
        temp1 = 0;                          // Rset temp1 variable
        temp2++;                            // Icrement temp2 variable
      }
      if (temp2 == TXPACKET_MAXBYTES) {     // Check to see if there is a next,next data bit or not
          TA0V_bytePtr = 0;
                                            // At this point all data in current Tx packet has been sent
                                            // Signal to our own thread that we need to generate STOP condition
                                            // Leave the bit pointers in a state that will trigger
                                            // end of data package detection further down
          temp1 = WM430_TX_BITSPERBYTE - 1;
          temp2 -= 1;
          temp3 = 1;                        // Nte the next next bit will be a 1 (stop bit)
      }
      else {                                // Peek ahead @ next bit - put it in temp3
        temp3 = (((WM430_TX_mesgQueue[TA0V_currentTxPtr].byte8bits[temp2]) << temp1) & BIT7);
      }
      TA0V_shiftCounter = temp1;            // Note for next time which bit we've moved to
      TA0V_bytePtr = temp2;                 // Store byte pointer value
      TA0V_nextTxBit = temp3;               // Store value of next bit to be tx'd
      WM430_TX_dataToggle();                // Physically toggle the data line
      if (temp3 == 0)
                                            // [1,0,0] <half+whole> bit periods
        WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_15;
      else                                  // [1,0,1] <half+one-and-a-half> bit periods
        WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10 << 1;
    }
    else {                                  // Crrent data bit is a logical '0' [0, 0]
      WM430_TX_dataToggle();                // Physically toggle the data line
      WM430_TX_rfWidth = TIMERA0_SMCLK_BITPERIOD_10;
    }
  }

  TA0V_currentTxBit = TA0V_nextTxBit;       // Save last bit history

// *****************************************************************************************

  // Update pointer variables for next start of bit period
  TA0V_shiftCounter++;                      // Increment the shfit counter
  if (TA0V_shiftCounter == WM430_TX_BITSPERBYTE) {
    TA0V_shiftCounter = 0;                  // Reset shift counter (wrap-around)
    TA0V_bytePtr++;                         // Increment byte pointer
    if (TA0V_bytePtr == TXPACKET_MAXBYTES)  {
      TA0V_bytePtr = 0;                     // Reset byte pointer (wrap-around)
                                            // At this point all data in current Tx packet has been sent
      WM430_TX_stopPatternBitNum--;         // Signal to our own thread that we need to generate STOP condition
      TA0V_currentTxBit = WM430_TX_CURRENTTXBITDEFAULT;
    }
    else
      goto isr_exit;                        // Exit the ISR
  }
  else
    goto isr_exit;                          // Exit the ISR

 isr_exit:
  TACCR0 += WM430_TX_rfWidth;               // Add time to the timer so the next interrupt occurs at the right time
                                            // Here's a good place for debug pulses to time the duration of this ISR
}

#else /* _FSKDATAPLUSENCODING */

void WM430_TX_sendDataPacket(unsigned char BUTTON, signed char XDISP, signed char YDISP, signed char ZDISP)
{
  WM430_TX_DataPacket data;

  data.field.button = BUTTON;               // Transfer button data
  data.field.horizontal = XDISP;            // Transfer X displacement value
  data.field.vertical = (~YDISP + 1);       // Convert to 2's complement before sending over
  data.field.zwheel = ZDISP;                // Transfer Z displacement value
  data.field.dummy5 = 0;                    // NOT USED
  data.field.dummy4 = 0;                    // NOT USED
  data.field.dummy3 = 0;                    // NOT USED
  data.field.dummy2 = 0;                    // NOT USED
  data.field.dummy1 = 0;                    // NOT USED
  data.field.dummy0 = 0;                    // NOT USED
  WM430_SYS_delaymsec(1);                   // Delay enough time to allow packet to be transmitted
}

#endif /* _FSKDATAPLUSENCODING */

⌨️ 快捷键说明

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