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

📄 test.cpp

📁 coldfire5206芯片平台的自捡程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
   *(UCHAR*)MBCR = 0x80;

   // enable MBUS and its interrupt
   //*(UCHAR*)MBCR = 0xc0;

   // Set operation mode to query.
   sMBusInfo.mode = OPMODE_QUERY;

   sMBusInfo.currPackFinished = 1;

   // generate stop signal
   status  = *(UCHAR*)MBCR;
   status &= 0xd7;
   *(UCHAR*)MBCR = status;

}

void MbusInterrupt()
{
	
	asm("     LEA.L       -56(A7),A7");
	asm("     MOVEM.L     D0-D7/A0-A5,(A7)");

	//MBUS interrupt routine
	Mbus_Lisr(0);

	asm("	  MOVEM.L       (A7),D0-D7/A0-A5");
	asm("     LEA.L         56(A7),A7");
	asm("	  RTE  ");

}



/**
 *  PCF8591: read four channel's A/D results.
 *
 *  @param  data    where to save the result
 *
 *  @return  1   if the operation succeed.
 *           0   if the operation failure because packetQue is full.
 */
CHAR  PCF8591ADIn(UNCHAR *data)
{
   static UNCHAR adResult[4];

   MBusPackType  thePack;
   CHAR result, i;

   thePack.txLen1 = 1;
   thePack.txLen2 = 0;
   thePack.rxLen  = 4;
   thePack.rxData = adResult;

   thePack.txData[0] = PCF8591_SLAVE_ADDR | OP_READ;

   thePack.repeatTimes = PCF8591_READ_REPEAT;

   // transfer the pack
/*   if (OPMODE_INTERRUPT == sMBusInfo.mode)
   {
      if (1 == MBusPackQuePut(&gPCF8591ReadPackQue, &thePack))
      {
         EnterInterrupt( );
         result = 1;
      }
      else
         result = 0;
   }
   else
*/    result = MBusTransferByQuery(&thePack);

   // if transfer succeed, copy result to the given memory. 
   if (1 == result)
   {
      for (i = 0; i < 4; i ++)
        data[i] = adResult[i];
   }
   
   return result;
}

/**
 *  Repeat transfer for given times.
 *  processed.
 *
 *  @return  0  if repeat is not need or mbus is busy.
 *  @return  1  if repeat processed.
 */
static SHORT  RepeatTransfer(void)
{

   // if MBUS is not free until function return, transfer stop
   if (0 == WaitForMBusFree())
      return 0;

   if (0 < sMBusInfo.currPack.repeatTimes)
   {
      sMBusInfo.currPack.repeatTimes --;
      ConstructSequence(&sMBusInfo.currPack);
      StartTransfer();
      return 1;
   }
   else
   {
      sMBusInfo.transferFail ++;
      return 0;
   }
}

VOID Mbus_Lisr(int vector)
{
   UCHAR status, ackNotDetected;

   //clear MIF(M-Bus interrupt flag)
   status  = *(UCHAR*)MBSR;

   // return if MIF is not set.
   if (2 != (status&2) )
      return;

   status &= 0xfd;
   *(UCHAR*)MBSR = status;

   // No error detected.
   ackNotDetected = 0;

   sCurrentCmd ++;

   // Check acknowledge signal when current command is not CMD_RECEIVE_STOP,
   // because acknowledge signal will not be generated in the situation.
   if (CMD_RECEIVE_STOP != sMBusCmds[sCurrentCmd])
   {
      if ( 1 == (status&1))
      {
         sMBusInfo.noAckError ++;
         ackNotDetected = 1;

         // cause system to generate stop signal
         sMBusCmds[sCurrentCmd] = CMD_TRANSMIT_STOP;
      }
   }

   switch (sMBusCmds[sCurrentCmd])
   {
     // normal transmit
     case CMD_TRANSMIT:
        *(UCHAR*)MBDR = *sTransmitPtr ++;
        break;

     // a stop after transmitting
     case CMD_TRANSMIT_STOP:
        status  = *(UCHAR*)MBCR;
        status &= 0xd7;             // d7->df, why use d7? TXAK = 0?
        *(UCHAR*)MBCR = status;

        if( (1 == ackNotDetected) && (1 == RepeatTransfer()) )
        {
           // do nothing
        }
        else
        {
           // If work in query mode, don't check packet queue
           if (OPMODE_QUERY == sMBusInfo.mode)
              sMBusInfo.currPackFinished = 1;
	/*
           else
              if (0 == ProcessNext() )
                 sMBusInfo.currPackFinished = 1;
	*/
        }
        break;

     // change to receive mode after transmitted
     case CMD_TRANSMIT_RECEIVE:
        // change to receive mode
        status  = *(UCHAR*)MBCR;
        status &= 0xef;
        *(UCHAR*)MBCR = status;

        if (CMD_RECEIVE_STOP == sMBusCmds[sCurrentCmd+1])
        {
           // don't acknowledge it because it's the last byte to be received
           status  = *(UCHAR*)MBCR;
           status |= 0x8;
           *(UCHAR*)MBCR = status;
        }

        // Dummy read to generate clock signal
        status = *(UCHAR*)MBDR;
        break;

     // restart then transmit
     case CMD_RESTART_TRANSMIT:
        // restart
        status  = *(UCHAR*)MBCR;
        status |= 0x04;
        *(UCHAR*)MBCR = status;

        // then transmit
        *(UCHAR*)MBDR = *sTransmitPtr ++;
        break;

     // receive with acknowledge
     case CMD_RECEIVE_ACK:
        *sReceivePtr ++ = *(UCHAR*)MBDR;
        break;

     // receive without acknowledge
     case CMD_RECEIVE_NOACK:
        // don't generate acknowledge signal
        status  = *(UCHAR*)MBCR;
        status |= 0x08;
        *(UCHAR*)MBCR = status;

        *sReceivePtr ++ = *(UCHAR*)MBDR;
        break;

     // receive then stop
     case CMD_RECEIVE_STOP:
        // generate stop signal
        status  = *(UCHAR*)MBCR;
        status &= 0xd7;             // d7->df, why use d7? TXAK = 0?
        *(UCHAR*)MBCR = status;

        *sReceivePtr ++ = *(UCHAR*)MBDR;

        // If work in query mode, don't check packet queue
        if (OPMODE_QUERY == sMBusInfo.mode)
           sMBusInfo.currPackFinished = 1;
	/*
        else
           if (0 == ProcessNext() )
              sMBusInfo.currPackFinished = 1;
	*/

        break;

     default:
        break;
   }
}



/**
 *  get one  MBusPacket from the given queue and save it to out
 *
 *  @param   theQue  the queue to be manipulated.
 *  @param   out     the address for storing the result
 *
 *  @return  <code>0</code> if queue is empty, operation failed
 *           <code>1</code> if queue isnot empty, operation succeed
 */
INT16  MBusPackQueGet(MBusPackQueType *theQue, MBusPackType** out)
{
   INT  ptr = theQue->getPtr;

   if ( ptr == theQue->putPtr )
      return 0;

   *out = &theQue->packQue[theQue->getPtr];

   ptr ++;
   if (theQue->queueLen <= ptr)
      ptr = 0;

   theQue->getPtr = ptr;
   
   return 1;
}


/**
 *  put one MBusPacket to the queue
 *
 *  @param   theQue  the queue to be manipulated.
 *  @param   in    the MBusPacket for putting
 *
 *  @return  <code>0</code> if queue is full, operation failed,
 *           <code>1</code> if queue is not full, success
 */
INT16  MBusPackQuePut(MBusPackQueType *theQue, MBusPackType* in)
{
   INT  ptr = theQue->putPtr;

   ptr ++;
   if (theQue->queueLen <= ptr)
      ptr = 0;

   if (ptr == theQue->getPtr)
      return 0;

   theQue->packQue[theQue->putPtr] = *in;

   theQue->putPtr = ptr;
   return 1;
}

/**
 *  Wait for some times until MBUS is not busy.
 *
 *  @return    1  if MBUS is free when returned.
 *             0  MBUS is still busy until return
 */
static UCHAR  WaitForMBusFree(VOID)
{
   UCHAR  status;
   UINT16 i;

   // wait for 500 loops
   for (i = 0; i < 500; i ++)
   {
      status = *(UCHAR*)MBSR;
      if (0 == (status&0x20))
         return 1;
   }
   return 0;
}


/**
 *  Wait for some times until MBUS Interrupt is set, which indicate that a data
 *  transfer is completed.
 *
 *  @return    1  if MBUS is free when returned.
 *             0  MBUS is still busy until return
 */
static UCHAR  WaitForMIF(VOID)
{
   UCHAR  status;
   UINT16 i;

   // wait for 500 loops
   for (i = 0; i < 500; i ++)
   {
      status = *(UCHAR*)MBSR;
      if (2 == (status&2))
         return 1;
   }
   return 0;
}

/**
 *  Construct command sequence according to the pack given,
 *  the command sequence will processed in MBus interrupt.
 *
 *  @param pack  the packet to be processed.
 */
static VOID ConstructSequence(MBusPackType  *pack)
{
   INT16  i, cmdNumber;

   // The number of commands is 0
   cmdNumber = 0;

   // Commands are type of CMD_TRANSMIT at early.
   for ( i = 0; i < pack->txLen1 - 1; i ++)
      sMBusCmds[cmdNumber++] = CMD_TRANSMIT;

   // If txLen2 is greater than 0, it means that there is a RESTART signal
   // should insert here.
   if (0 < pack->txLen2)
   {
      sMBusCmds[cmdNumber++] = CMD_RESTART_TRANSMIT;

      // copy the other TRANSMIT command, remember here: the RESTART command
      // was connected with a TRANSMIT command, so (pack->txLen2 - 1) is
      // present here.
      for ( i = 0; i < pack->txLen2 - 1; i ++)
         sMBusCmds[cmdNumber++] = CMD_TRANSMIT;
   }

   // If want receive some characters.
   if (0 < pack->rxLen)
   {
      // The last command is change mode to receive
      sMBusCmds[cmdNumber++] = CMD_TRANSMIT_RECEIVE;

      // If only receive one character, STOP after RECEIVE
      if (1 == pack->rxLen)
         sMBusCmds[cmdNumber++] = CMD_RECEIVE_STOP;
      else
      {
         for ( i = 0; i < pack->rxLen - 2; i ++)
            sMBusCmds[cmdNumber++] = CMD_RECEIVE_ACK;

         // The second last command is CMD_RECEIVE_NOACK
         sMBusCmds[cmdNumber++] = CMD_RECEIVE_NOACK;

         // The last command is CMD_RECEIVE_STOP
         sMBusCmds[cmdNumber++] = CMD_RECEIVE_STOP;
      }
   }
   // Don't want receive any character, change the last command from
   // TRANSMIT to TRANSMIT_STOP
   else
      sMBusCmds[cmdNumber++] = CMD_TRANSMIT_STOP;

   sCurrentCmd  = -1;
   sTransmitPtr = &pack->txData[0];
   sReceivePtr  = pack->rxData;
}


/**
 *  Start a MBUS data transfer procedure.
 */
static VOID StartTransfer(VOID)
{
   UCHAR status;
   
   //clear MIF(M-Bus interrupt) flag
   status  = *(UCHAR*)MBSR;
   status &= 0xfd;
   *(UCHAR*)MBSR = status;

   status  = *(UCHAR*)MBCR;

   // transmit mode selected
   status |= 0x10;
   *(UCHAR*)MBCR = status;

   // master mode selected.
   status |= 0x20;
   *(UCHAR*)MBCR = status;

   *(UCHAR*)MBDR = *sTransmitPtr ++;
}


/**
 *  MBUS: Transfer a packet by query.
 *
 *  @param   thePack   the packet to be transfered
 *
 *  @return  1   if the operation succeed.
 *           0   if the operation failure because packetQue is full.
 */
static CHAR  MBusTransferByQuery(MBusPackType *thePack)
{

   // if MBUS working not in query mode, return
   if (OPMODE_QUERY != sMBusInfo.mode)
      return 0;

   // Don't goto the following code if there another task using it.
   // use the statement to protect the following code being used exclusively.
   if (1 != sMBusInfo.currPackFinished)
      return 0;

   // packet has not been transfered
   sMBusInfo.currPackFinished = 0;

   // Remember the pack being transfered.
   sMBusInfo.currPack = *thePack;

   // construct command sequence
   ConstructSequence(thePack);

   // if MBUS is not free until function return, transfer stop
	
   if (0 == WaitForMBusFree())
	{
		sMBusInfo.currPackFinished = 1;

      return 0;
   }

   StartTransfer();

   do
   {
      // if MIF has not been set until function return, transfer stop
      if (0 == WaitForMIF())
		{
		  sMBusInfo.currPackFinished = 1;

        return 0;
		}

      // currPackFinished will be set to 1 if the packet transfered in MBusLisr
      Mbus_Lisr(0);
   }while (0 == sMBusInfo.currPackFinished);


   return 1;
}


/**
 *  CAT24C021: read several bytes.
 *
 *  @param  baseAddr   the first byte address
 *  @param  byteNum    the number of bytes to be read
 *  @param  dataAddr   where to store result
 *
 *  @return  1   if the operation succeed.
 *           0   if the operation failure because packetQue is full
 *               or byteNum is improper.
 *  @note  A NU_Sleep will be called if MBUS operated in interupt mode. 
 */
CHAR  CAT24C021ReadSeqByte(UINT16 baseAddr, UINT16 byteNum, UCHAR *dataAddr)
{
   MBusPackType  thePack;
   UCHAR         sect_addr;
	int				k;

   if (1 > byteNum || 2048 < (baseAddr + byteNum) )

⌨️ 快捷键说明

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