Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Разное » Помогите сконвертировать С в bascom


Помогите сконвертировать С в bascom

Сообщений 1 страница 11 из 11

1

Здравствуйте господа!!! Имеется кусок кода написанный на С (протокол обмена по RS485) для имеющихся контроллеров, мастером является компьютер и слэйвами соответственно другие контроллеры, возникла необходимость добавить в имеющийся пул из других контроллеров свой, но вот пока только осилил bascom, с С пока не разбирался, в принципе мне не нужен весь протокол, мне необходимо, чтобы мастер мог считать информацию из моего микроконтроллера, помогите понять сам алгоритм или перевести код в Bascom, заранее премного вам благодарен!!!!

Код:
 
[hide=Протокол]
#include <targets/AT91x408xx.h>
#include <ctl_api.h>
#include <stdlib.h>
#include <string.h>
#include "timebase.h"
#include "arm_vers.h"
#include "GalaxyTime.h"
#include "crc16.h"
#include "LanguageDependantStrings.h"
#include "ApplicationData.h"
#include "FlashUpdate.h"
#include "AlarmEventPC.h"
#include "typedefs.h"
#include "cp_util.h"
#include "ProtocolManager.h"
#include "led.h"
#include "menus.h"
#include "internalflash.h"
#include "Watchdog.h"

#define FLAG_PROBLEM            -99999

#define OPCODE_CLOCKSYNC                  0x06
#define OPCODE_CLOCKSYNC2                 0x07
#define OPCODE_PREPARE_BURN               0x08
#define OPCODE_READY_BURN                 0x05
#define OPCODE_BURN_DATA                  0x04
#define OPCODE_ADDR_LIST_VALS             0x0D
#define OPCODE_ADDR_LIST_LVALS            0x0E
#define OPCODE_ADDR_LIST_CH_VALS          0x0F
#define OPCODE_ADDR_LIST_CH_LVALS         0x10
#define OPCODE_GET_INDEX_OF_TIMESTAMP     0x0C
#define OPCODE_DIARY_DATA_FROM_INDEX      0x1C
#define OPCODE_GET_ERROR                  0x20
#define OPCODE_ERROR                      0xFF

#define ERROR_CODE_BAD_CRC          0x01 // Check these with Yifat
#define ERROR_CODE_BAD_LEN          0x02
#define ERROR_CODE_OTHER            0x03

#define BROADCAST_ID                0x00

#define BROADCAST_BACK              0xAA
#define INPUT_QUEUE_SIZE            0x1000
#define OUTPUT_MSG_SIZE             0x1610
#define MIN_MAX_MESSAGE_SIZE        100
#define DEFAULT_MAX_MESSAGE_SIZE    0x0400

unsigned char incoming[INPUT_QUEUE_SIZE]; // enough for two messages, in case...
unsigned char Reply[OUTPUT_MSG_SIZE];
int ReplyLen;
unsigned char Erasing = 0;

#define GOT_CHAR      1
#define TX_READY      2
volatile char InQueue[INPUT_QUEUE_SIZE*2];
unsigned int TakeOut = 0;
const long baudratetable[] = {1200,2400,4800,9600,19200,38400,57600,115200};

#define RXRDY 1
#define TXRDY 2

// The GETTING_DATA state is one which can cause problems - if the length
// received is faulty, we could end up getting data for a long, long time
// before an error is recognized.  We therefore allow getting data for only
// two seconds (the constant below is 2 seconds in units of 4ms.), and this
// will have GETTING_DATA end if something goes wrong, resetting the state
// machine to the beginning.
#define GETTING_DATA_MAX_TIME       500
CTL_TIME_t GettingDataTimeOut;

// The protocol manager is a state machine, which receives a character 
// and processes as far as it can, then goes away until the next.
#define WAITING_FOR_MESSAGE         0
#define GOT_FIRST_SYNC              1
#define GOT_SECOND_SYNC             2
#define HAVE_PC_ID                  3
#define HAVE_CONTROLLER_ID          4
#define HAVE_ECHO_PACKET            5
#define HAVE_LENGTH_LO              6
#define HAVE_LENGTH                 7
#define GETTING_DATA                8
#define GETTING_CSUM1               9
#define GETTING_CSUM2               10
#define RESPONDING                  11
#define HANDLE_OLD_PROTOCOL_MESSAGE 12  

static char ProtocolState = WAITING_FOR_MESSAGE;

#define HAVE_GLOBAL_ERROR   0x01
#define NO_HISTORY          0x10
#define NO_ALARM            0x20
#define NO_EVENT            0x40

unsigned char ProtocolStatus(void)
{
  unsigned char ps = 0;

  if ((GlobalErrorStatus[0] != 0) || (GlobalErrorStatus[1] != 0))
    ps |= HAVE_GLOBAL_ERROR;
  if (OldHist == -1)
    ps |= NO_HISTORY;
  if (OldEvent == -1)
    ps |= NO_EVENT;
  if (OldAlarm == -1)
    ps |= NO_ALARM;
  
  return ps;
}

void ResetRx(void)
{
  TakeOut = 0;
  US0_RCR = 0;
  US0_RPR = (volatile unsigned int)(&InQueue); // start over
  US0_RCR = INPUT_QUEUE_SIZE*2;
  ProtocolState = WAITING_FOR_MESSAGE;
}

void UARTInitialize(void)
{
  unsigned long baudrate;
  
  if ((MyBaudRate < 0) || (MyBaudRate > 7))
  {
    MyID &= 0xFF; // move into legal range if nothing else 
    MyBaudRate = 3; // default to 9600
    MyCommMethod = 0; // default to direct.
  }
  if (MaxMessageSize < MIN_MAX_MESSAGE_SIZE)
    MaxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
  baudrate = baudratetable[MyBaudRate];
  US0_CR = US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS;
  US0_RCR = 0x00000000;
  US0_TCR = 0x00000000;
  US0_IDR = 0xFFFFFFFF;
  US0_IER = 0;  // no more interrupt, only DMA
  PIO_PDR = (1 << PIOTXD0) | (1 << PIORXD0);
  US0_MR = US_CLKS_MCK | US_CHRL_8 | US_PAR_NO | US_NBSTOP_2 | US_CHMODE_NORMAL;
  US0_BRGR = MCK / (16 * baudrate);
  US0_TTGR = 0;
  US0_CR = US_TXEN | US_RXEN;
  ResetRx();
}

void ReplyError(unsigned char ErrorCode)
{
  unsigned short CRC;

  // Reply[0] is filled in already
  ReplyLen = 10;
  Reply[1] = ReplyLen;
  Reply[2] = 0;
  // Reply[3] = OpCode is filled in already.
  Reply[4] = MyID;
  Reply[5] = ProtocolStatus(); 
  Reply[6] = OPCODE_ERROR;
  Reply[7] = ErrorCode;
  CRC = CalcCRC16Bytes(Reply,8);
  memcpy(&Reply[ReplyLen-2],&CRC,sizeof(short));
}

void SendReply(void)
{
  //int i;
  // Yifat doesn't want sync bytes in the messages sent to the center...leave them here if she
  // wants them later.
  // __putchar(0xBE);
  // __putchar(0xEF);
  US0_TPR = (volatile unsigned int)(&Reply);
  US0_TCR = ReplyLen;
  ResetRx();
}

const char OLD_PROT_MESSAGE[] = "\x0A\x00\x0D\x00\x00\x44\x01\x00";

//unsigned char debugrx [255];
//unsigned char debugrxindex = 0;

/* This routine gets a line of Intel Hex.  It parses it, and burns the data in it if
   necessary.  Static variable offset contains the current offset.  Address offset 0
   is burned to 0x20002000, and any address greater than 0x1EDFFF is rejected as out of
   range.  This makes burning addresses 0-1edffff go to 20002000 201EFFFF, which is sectors
   1-37
*/
#define HIGHEST_ADDRESS     0x1EDFFF

int HexDigitConv(char d)
{
  if (isxdigit(d))
  {
    if (isdigit(d))
      return d - '0';
    else
      return toupper(d)-'A'+10;
  }
  return -1;
}

int ParseAndBurn(void)
{
  static int offset = 0;
  int addr = 0;
  int reclen,reclenc,rectype,helper,i,csum,csumcomp,extra;
  int inp = 6;
  char data[80];

  if (incoming[inp++] != ':')
    return -1;
  if ((reclen = HexDigitConv(incoming[inp++])) == -1)
    return -1;
  if ((helper = HexDigitConv(incoming[inp++])) == -1)
    return -1;
  reclen = (reclen * 0x10) + helper;
  csum = reclenc = reclen;
  for(i=0;i<4;i++)
  {
    if ((helper = HexDigitConv(incoming[inp++])) == -1)
      return -1;
    addr *= 0x10;
    addr += helper;
  }
  csum += addr & 0xFF;
  csum += (addr >> 8) & 0xFF;
  if ((rectype = HexDigitConv(incoming[inp++])) == -1)
    return -1;
  if ((helper = HexDigitConv(incoming[inp++])) == -1)
    return -1;  
  rectype = (rectype * 0x10) + helper;
  csum += rectype;
  i = 0;
  while (reclen--)
  {
    if ((helper = HexDigitConv(incoming[inp++])) == -1)
      return -1;
    data[i] = helper * 0x10;
    if ((helper = HexDigitConv(incoming[inp++])) == -1)
      return -1;    
    data[i] += helper;
    csum += data[i++];
  }
  if ((csumcomp = HexDigitConv(incoming[inp++])) == -1)
    return -1;
  if ((helper = HexDigitConv(incoming[inp++])) == -1)
    return -1;
  csumcomp = (csumcomp * 0x10) + helper;
  csum = -csum;
  csum &= 0xFF;
  if (csumcomp != csum)
    return -2;
  switch(rectype)
  {
    case 0 : // we have reclenc bytes.  Since we burn words, we need to make sure the
             // address is even and that the number of bytes is even - if not, we massage
             // the start and finish to make it good.
            if (addr & 1) // uneven address, add a byte of 0xFF at the beginning
            {
              helper = 0xFF00 + data[0];
              addr--;
              reclenc--; // one less byte to process later
              BurnProgram(FIRSTFLASHBACKUPADDRESS + offset + addr - INTERNAL_FLASH_START, helper);
              addr += 2;
              extra = 1;
            } else
              extra = 0;

            for(i=0;i<reclenc / 2;i++)
            {
                helper = data[(i*2)+extra+1] * 0x100 + data[(i*2)+extra]; // little endian machine!
                BurnProgram(FIRSTFLASHBACKUPADDRESS + offset + addr - INTERNAL_FLASH_START, helper);
                addr += 2;
            }
            if (reclenc & 1) // odd number of bytes burned in loop above (not necessarily
            {
              helper = data[reclenc] * 0x100 + 0xFF;
              BurnProgram(FIRSTFLASHBACKUPADDRESS + offset + addr - INTERNAL_FLASH_START, helper);
            }
            break;
    case 1 : return -2; // to tell the caller we're done.
    case 4 : offset = ((data[0] * 0x100) + data[1]) << 16; break; // set up the offset 
    default : return -1; break; // including 2, we don't accept them
  }
  return 0;
}

#define SLEEP_DURING_UPLOAD         0
#define NORMAL_SLEEPTIME           10

// History only - messages can have a * for repeated data.  If this is one
// of them, then this returns the size of the actual message (unlike other
// messages, which are fixed size and known by their id).
int RepeatSize(long index,int offset)
{
  char *data = (char *)(HIST_POINTERS[index]);
  char const *Message;
  short EntryNumber;
  int repeatcount;

  EntryNumber = data[5]*0x100 + data[4];
  Message = PCMessageDiary[CurrLang][EntryNumber-FIRSTCOUNT_PCMessageDiary];
  repeatcount = data[offset];
  data = strchr(Message,'*');
  if (data == NULL)
    return 0 ; // this shouldn't happen, only call on a message we know has a *
  data = strchr(data,' ');
  if (data == NULL)
    return 0 ; // this shouldn't happen, only call on a message we know has a *
  data++; // now we're on the type.
  switch(*data)
  {
    case 'b' : return repeatcount;
    case 'l' : return 4*repeatcount;
    default : return 2*repeatcount;
  }
}

int MessageSize(DiaryNames Diary, short EntryNumber)
{
  int TestStar;
  char *data;
  int calc;
  char const *Message = 0;
  int result;
  
  switch(Diary)
  {
    case D_Alarms : 
      data = (char *)ALARM_POINTERS[EntryNumber]; 
      // sanity check
      if ((data < (char *)ALARM_REGION_ADDRESS) || (data >= (char *)EVENT_REGION_ADDRESS))
        return -1;
      calc = data[5]*0x100 + data[4];
      if ((calc >= FIRSTCOUNT_AlarmDiary) && (calc <= (TOTAL_AlarmDiary-FIRSTCOUNT_AlarmDiary)))
        Message = AlarmDiary[CurrLang][calc-FIRSTCOUNT_AlarmDiary]; 
      break;
    case D_Events : 
      data = (char *)EVENT_POINTERS[EntryNumber]; 
      if ((data < (char *)EVENT_REGION_ADDRESS) || (data >= (char *)HIST_REGION_ADDRESS))
        return -1;
      calc = data[5]*0x100 + data[4];
      if ((calc >= FIRSTCOUNT_EventDiary) && (calc <= (TOTAL_EventDiary-FIRSTCOUNT_EventDiary)))
        Message = EventDiary[CurrLang][calc-FIRSTCOUNT_EventDiary]; 
      break;
    case D_ToPC : 
      data = (char *)HIST_POINTERS[EntryNumber]; 
      if ((data < (char *)HIST_REGION_ADDRESS) || (data >= (char *)END_OF_MEMORY))
        return -1;
      calc = data[5]*0x100 + data[4];
      if ((calc >= FIRSTCOUNT_PCMessageDiary) && (calc <= (TOTAL_PCMessageDiary-FIRSTCOUNT_PCMessageDiary)))
        Message = PCMessageDiary[CurrLang][calc-FIRSTCOUNT_PCMessageDiary]; 
      break;
  }
  if (Message)
  {
    if (*Message)
    {
      if (strchr(Message,'*'))
        TestStar = -1;
      else
        TestStar = 1;
    } else
      Message = 0;
  }
  if (Message == 0) // we can't get a good length, something is wrong.  Crash prevention
    return FLAG_PROBLEM;
  result = 6; // always 6 bytes of data passed - the EntryNumber (2) and TimeStamp(4)
  if (calc < 0)
    return result;
  if ((calc > 256) && (Diary != D_ToPC))
    return result;
  if (calc > 999)
    return result;
  while (*Message)
  {
    if (*Message == '%')
    {
      while(1)
      {
        *Message++;
        if (*Message == 0)
          break;
        if (isdigit(*Message))
          continue;
        if (*Message == '.')
          continue;
        if (*Message == 'b')
        {
          result++;
          break;
        }
        if (*Message == 'l')
        {
          result+=4;
          break;
        }
        if ((*Message == 'd') || (*Message == 'u'))
        {
          result+=2;
          break;
        }
        break;
      }
    }
    Message++;
  }
  return result * TestStar; // if there is a star in the string - it returns
                            // a negative value which tells the caller
                            // that it needs to do further calculations.
}

unsigned short FindTimeStamp(DiaryNames diary, unsigned long TimeStamp, unsigned short *count, unsigned char *matched)
{
  // binary search the selected diary, until 
  //  a) the correct timestamp is found.  If this happens, look backwards
  //     and forward until we find the first and last.
  //  b) The stepsize is 1, and we are between two values.  In this case,
  //     we choose the closest one which is greater than the timestamp.
  //  c) We reach one end of the array or another (All over/under).  Return
  //     the closest one, being the first/last and all others like it.
  int first,last,stepsize,index,ceindex,max,holdlast,holdfirst;
  unsigned long compare,extracompare;
  unsigned short retval;
  Parray Array;

  switch(diary)
  {
    case D_Alarms :
      Array = ALARM_POINTERS;
      max = ALARM_POINTER_COUNT;
      if (InsertAlarm)
        holdlast = last = InsertAlarm-1;
      else
        holdlast = last = max-1;
      holdfirst = first = OldAlarm;
      break;
    case D_Events :
      Array = EVENT_POINTERS;
      max = EVENT_POINTER_COUNT;
      if (InsertEvent)
        holdlast = last = InsertEvent-1;
      else
        holdlast = last = max-1;
      holdfirst = first = OldEvent;
      break;
    case D_ToPC :
      Array = HIST_POINTERS;
      max = HIST_POINTER_COUNT;
      if (InsertHist)
        holdlast = last = InsertHist-1;
      else
        holdlast = last = max-1;
      holdfirst = first = OldHist;
      break;
  }
  if (holdfirst == -1) // nothing in the table, return emptiness
  {
    *count = 0;
    *matched = 0;
    return 0;
  }
  // This is a binary search in a >>circular<< list.  Remember this when indexing
  if (last >= first) 
    stepsize = (last - first + 1);
  else
    stepsize = (max-first+last-1);
  for(;;)
  {
    stepsize /= 2;
    index = first + stepsize;
    if (index >= max)
      index -= max;
    memcpy(&compare,&Array[index],sizeof(long));
    if (compare == TimeStamp) // found it!
      break;
    else
    {
      if (compare > TimeStamp)
        last = index;
      else // compare < TimeStamp
        first = index;
      if (first == last)
        break;
      if ((first != last) && (stepsize == 0)) // endpoint problem, just do two compares and get out
      {
        memcpy(&compare,&Array[first],sizeof(long));
        memcpy(&extracompare,&Array[last],sizeof(long));
        if (compare == TimeStamp)
          index = first;
        else
        {
          if (extracompare == TimeStamp)
          {
            compare = extracompare;
            index = last;
          }
          else
          {
            if (compare > TimeStamp)
              index = first;
            else
            {
              compare = extracompare;
              index = last;
            }
          }
        }
        break;
      }
    }
  }
  /* Now that we have exited the binary search, we are sitting on a 'good' 
   * timestamp.  We look backwards and forwards for the first and last like
   * this one (again, circular list).  If the timestamp is not exact, there
   * are four options:
   *  1)  We are sitting on a value which is less than the timestamp, and the
   *      next different one is greater.  In this case, we keep the value we 
   *      are on.
   *  2)  We are sitting on a value which is greater than the timestamp, and
   *      the previous different value is less.  In this case, we choose the
   *      previous different value.
   *  3)  We are at the beginning (circular, beginning means the oldest entry).
   *      of the array, and everything is greater.  We choose the oldest entry.
   *  4)  We are at the end (circular, end means newest entry) of the array,
   *      and everything is less.  In this case, we choose the newest entry.
   */

  if (compare != TimeStamp)
  {
    *matched = 0;
    if (compare > TimeStamp) // cases 2 and possibly 4
    {
      ceindex = holdlast; // see if this is possiblity 4
      memcpy(&extracompare,&Array[ceindex],sizeof(long));
      if (extracompare == compare)
        index = ceindex;
      else // backup until the compare is smaller
      {
        while (compare > TimeStamp)
        {
          if (index == holdfirst)
            break;
          if (--index < 0)
            index = max-1;
          memcpy(&compare,&Array[index],sizeof(long));
        }
      }
    }
  } else
    *matched = 1;
  // Now we are at one of the indices we want.  If thera are any of the same
  // value, we look for them now, in both directions.
  TimeStamp = compare;
  while (TimeStamp == compare)
  {
    if (index == holdfirst)
    {
      index--;
      break;
    }
    if (--index < 0)
      index = max-1;
    memcpy(&compare,&Array[index],sizeof(long));
  }
  index++; // This is the first one like that
  retval = index;
  compare = TimeStamp;
  while (TimeStamp == compare)
  {
    if (index == holdlast)
      break;
    if (++index == max)
      index = 0;
    memcpy(&compare,&Array[index],sizeof(long));
  }
  *count = index-retval;
  //if (*count == 0)
  //  *count = 1;
  return retval;
}

void PrepOldStyleReply(void)
{
  Reply[0] = 0xAA;
  Reply[1] = 0x09;
  Reply[2] = 0x00;
  Reply[3] = 0x0D;
  Reply[4] = MyID;
  Reply[5] = ProtocolStatus();
  Reply[6] = 2;
  Reply[7] = 0;
  Reply[8] = (-(0xC2+MyID+ProtocolStatus()))&0xFF;
  ReplyLen = 9;
}

int lengthcheck(int Opcode, int length)
{
  int entries = 0;
  int badlen;

  switch(Opcode)
  {
    case OPCODE_CLOCKSYNC :
      badlen = (length != 4);
      break;
    case OPCODE_PREPARE_BURN : // drop thru
    case OPCODE_READY_BURN :
    case OPCODE_GET_ERROR :
      badlen = (length != 0);
      break;
    case OPCODE_BURN_DATA :
      badlen = (length == 0);
      break;
    case OPCODE_ADDR_LIST_VALS : // drop thru
    case OPCODE_ADDR_LIST_LVALS :
      badlen = (length % 3 != 0);
      entries = length / 3;
      break;
    case OPCODE_ADDR_LIST_CH_VALS :
      badlen = (length % 5 != 0);
      entries = length / 5;
      break;
    case OPCODE_ADDR_LIST_CH_LVALS :
      badlen = (length % 7 != 0);
      entries = length / 7;
      break;
    case OPCODE_GET_INDEX_OF_TIMESTAMP :
      badlen = (length != 5);
      break;
    case OPCODE_DIARY_DATA_FROM_INDEX :
      badlen = (length != 6);
      break;
    default : 
      ResetRx();
      break;
  }
  if (badlen)
  {
    ReplyError(ERROR_CODE_BAD_LEN);
    SendReply();
  } else
  {
    if (length)
    {
      GettingDataTimeOut = ctl_get_current_time();
      ProtocolState = GETTING_DATA;
    }
    else
      ProtocolState = GETTING_CSUM1;
  }
  return entries;
}

void DealWithOpcodeClockSync(void)
{
  unsigned short csum;
  unsigned int y,m,d,h,mi,s;
  unsigned long gtime;

  Reply[1] = 9;
  Reply[2] = 0;
  ReplyLen = 9;
  csum = CalcCRC16Bytes(Reply,7);
  memcpy(&Reply[7],&csum,sizeof(short));
  memcpy(&gtime,&incoming[6],sizeof(long));
  GTimeToYMDHMS(gtime,&y,&m,&d,&h,&mi,&s);
  y -= 2000;
  SetTime(h,mi,s);
  SetDate(y,m,d);
}

void DealWithOpcodeListVals(unsigned short entries)
{
  unsigned short Addr, shortdat, csum;
  char errorout = 0;
  int i,AddrLim;

  ReplyLen = 9 + entries * sizeof(short);
  memcpy(&Reply[1],&ReplyLen,sizeof(short));
  for(i=0;i<entries;i++)
  {
    memcpy(&Addr,&incoming[7+(i*3)],sizeof(short));
    switch(incoming[6+(i*3)])
    {
      case 'A' : AddrLim = MAX_AV_INDEX; break;
      case 'N' : AddrLim = MAX_NV_INDEX; break;
      case 'P' : AddrLim = MAX_PV_INDEX; break;
      case 'V' : AddrLim = MAX_RV_INDEX; break;
      case 'F' : AddrLim = MAX_F_INDEX; break;
      case 'I' : AddrLim = 0xFFFF; break;
      case 'O' : AddrLim = 0xFFFF; break;
      case 'T' : AddrLim = MAX_SYS_INDEX; break;
      default :  ReplyError(ERROR_CODE_OTHER); errorout = 1;break;
    }
    if (errorout)
      break;
    if (Addr >= AddrLim)
    {
      ReplyError(ERROR_CODE_OTHER);
      errorout = 1;
      break;
    }
    switch(incoming[6+(i*3)])
    {
      case 'A' : shortdat = _AV[Addr]; break;
      case 'N' : shortdat = _NV[Addr]; break;
      case 'V' : shortdat = _RV[Addr]; break;
      case 'P' : shortdat = _PV[Addr]; break;
      case 'F' : shortdat = _F[Addr]; break;
      case 'I' : shortdat = 0; break;
      case 'O' : shortdat = 0; break;
      case 'T' : shortdat = SysVars[Addr]; break;
      default :  ReplyError(ERROR_CODE_OTHER); errorout = 1; break;
    }
    if (errorout)
      break;
    memcpy(&Reply[7+(i*2)],&shortdat,2);
  }
  if (errorout)
    return;
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
}

void DealWithOpcodeListLVals(unsigned short entries)
{
  unsigned short Addr, csum;
  char errorout = 0;
  int i,AddrLim;
  unsigned long longdat;

  ReplyLen = 9 + entries * sizeof(long);
  memcpy(&Reply[1],&ReplyLen,sizeof(unsigned short));
  for(i=0;i<entries;i++)
  {
    memcpy(&Addr,&incoming[7+(i*3)],sizeof(short));
    switch(incoming[6+(i*3)])
    {
      case 'L' : 
        if (Addr < MAX_LRV_INDEX)
          longdat = _LRV[Addr];
        else
        {
          ReplyError(ERROR_CODE_OTHER);
          errorout = 1;
        }
        break;
      case 'M' :                     
        if (Addr < MAX_LPV_INDEX)
          longdat = _LPV[Addr];
        else
        {
          ReplyError(ERROR_CODE_OTHER);
          errorout = 1;
        }
        break;
      default : 
        ReplyError(ERROR_CODE_OTHER);
        errorout = 1;
        break;
    }
    if (errorout)
      break;
    memcpy(&Reply[7+(i*4)],&longdat,sizeof(longdat));
  }
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
}

void DealWithOpcodeListCHVals(unsigned char Opcode, unsigned short entries)
{
  char errorout = 0;
  int i;
  int datasize, AddrLim;
  unsigned short Addr, csum;
  unsigned short shortdat;
  unsigned long longdat;
  char NeedToReconcile = 0;

  ReplyLen = 9;
  Reply[1] = ReplyLen;
  Reply[2] = 0;

  // We must do all the address checks BEFORE we actually write any of
  // the data...an incorrect address in the middle will cause an undefined
  // situation otherwise.
  for(i=0;i<entries;i++)
  {
    if (Opcode == OPCODE_ADDR_LIST_CH_VALS)
      datasize = sizeof(short);
    else
      datasize = sizeof(long);
    memcpy(&Addr,&incoming[7+(i*(3+datasize))],sizeof(short));
    switch(incoming[6+(i*(3+datasize))])
    {
      case 'A' : AddrLim = MAX_AV_INDEX; break;
      case 'N' : AddrLim = MAX_NV_INDEX; break;
      case 'V' : AddrLim = MAX_RV_INDEX; break;
      case 'P' : AddrLim = MAX_PV_INDEX; break;
      case 'F' : AddrLim = MAX_F_INDEX; break;
      case 'I' : AddrLim = 0xFFFF; break;
      case 'O' : AddrLim = 0xFFFF; break;
      case 'T' : AddrLim = MAX_SYS_INDEX; break;
      case 'M' : AddrLim = MAX_LPV_INDEX; break;
      case 'L' : AddrLim = MAX_LRV_INDEX; break;
      default :  ReplyError(ERROR_CODE_OTHER); errorout = 1;break;
    }
    if (errorout)
      break;
    if (Addr >= AddrLim)
    {
      ReplyError(ERROR_CODE_OTHER);
      errorout = 1;
      break;
    }
  }
  if (errorout == 0)
  {
    for(i=0;i<entries;i++)
    {
      memcpy(&Addr,&incoming[7+(i*(3+datasize))],sizeof(short));
      if (datasize == sizeof(short))
        memcpy(&shortdat,&incoming[9+(i*(3+datasize))],datasize);
      else
        memcpy(&longdat,&incoming[9+(i*(3+datasize))],datasize);
      switch(incoming[6+(i*(3+datasize))])
      {
         case 'A' : _AV[Addr] = shortdat; break;
         case 'N' : _NV[Addr] = shortdat; break;
        case 'V' : _RV[Addr] = shortdat; break;
        case 'P' : CopyOfPV[Addr] = shortdat; NeedToReconcile = 1; break;
        case 'F' : _F[Addr] = shortdat; break;
        // case 'I' : shortdat = 0; break;
        case 'O' : shortdat = 0; break;
        case 'T' : SysVars[Addr] = shortdat; break;
        case 'L' : _LRV[Addr] = longdat; break;
        case 'M' : CopyOfLPV[Addr] = longdat; NeedToReconcile = 1; break;
        default :  break; // can't happen, just like completeness in the switch
      }
    }
  }
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
  if (NeedToReconcile)
    ReconcilexPVfromEditorCopy(0,1);
}

DealWithOpcodePrepareBurn(void)
{
  unsigned short csum;

  StatusLine("Uploading new PLC",0);
  ReplyLen = 9;
  Reply[1] = ReplyLen;
  Reply[2] = 0;
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
  Erasing = 1;
#ifdef SYSTEM_RELEASE
  DisableWatchDog();
#endif
  ctl_task_set_priority(&FlashUpdateTask,30);
  ctl_events_set_clear(&FlashEvents,ERASE_APP_BACKUP,0);
}

void DealWithOpcodeReadyBurn(void)
{
  unsigned short csum;

  ReplyLen = 10;
  Reply[1] = ReplyLen;
  Reply[2] = 0;
  if (Erasing)
    Reply[7] = 0;
  else
  {
    Reply[7] = 1;
    ctl_task_set_priority(&FlashUpdateTask,3);
  }
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
}

long DealWithOpcodeBurnData(void)
{
  unsigned short csum;
  static unsigned long TimeOfLastBurnMessage;

  TimeOfLastBurnMessage = ctl_get_current_time();
  ReplyLen = 10;
  Reply[1] = ReplyLen;
  Reply[2] = 0;
  Reply[7] = 0;
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
  return TimeOfLastBurnMessage;
}

void DealWithGetIndexOfTimestamp(void)
{
  unsigned long gtime;
  unsigned short shortdat;
  unsigned short icount;
  unsigned short csum;
  unsigned char imatch;

  memcpy(&gtime,&incoming[7],sizeof(long));
  switch(incoming[6]) 
  {
    case 0x01 : shortdat = FindTimeStamp(D_Events,gtime,&icount,&imatch); break;
    case 0x02 : shortdat = FindTimeStamp(D_Alarms,gtime,&icount,&imatch); break;
    case 0x04 : shortdat = FindTimeStamp(D_ToPC,  gtime,&icount,&imatch); break;
    default : ReplyError(ERROR_CODE_OTHER); SendReply(); return; 
  }
  ReplyLen = 15;
  Reply[1] = ReplyLen;
  Reply[2] = 0;
  Reply[5] = ProtocolStatus();
  if (imatch)
    Reply[5] |= 2;
  memcpy(&Reply[7],&shortdat,sizeof(short));
  Reply[9] = 0; // future version may have bigger indices
  shortdat += icount;
  memcpy(&Reply[10],&shortdat,sizeof(short));
  Reply[12] = 0; // future version may have bigger indices
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
}

void DealWithGetDiaryDataFromIndex(void)
{
  DiaryNames diaryhelper;
  // int NewDataOnly;
  Parray Array;
  int max,insert;
  unsigned long longdat;
  unsigned short shortdat;
  int histindex,ms,rc;
  unsigned short csum;

  switch(incoming[6] & 0x7F)
  {
    case 0x01 : diaryhelper = D_Events; Array = EVENT_POINTERS; max = EVENT_POINTER_COUNT; insert = InsertEvent; break;
    case 0x02 : diaryhelper = D_Alarms; Array = ALARM_POINTERS; max = ALARM_POINTER_COUNT; insert = InsertAlarm; break;
    case 0x04 : diaryhelper = D_ToPC; Array = HIST_POINTERS; max = HIST_POINTER_COUNT; insert = InsertHist; break;
    default : ReplyError(ERROR_CODE_OTHER); SendReply; return;
  }
  // NewDataOnly = incoming[6] & 0x80;
  // longdat gets index, shortdat gets count.
  longdat = incoming[9];
  longdat *= 0x100;
  longdat += incoming[8];
  longdat *= 0x100;
  longdat += incoming[7];
  shortdat = incoming[11];
  shortdat *= 0x100;
  shortdat += incoming[10];
  if (shortdat == 0)
    shortdat = 0x7FFF; // force to maximum
  histindex = 10;
  Reply[5] = ProtocolStatus();
  if (longdat == insert)
  {
    shortdat = longdat & 0xFFFF;
    memcpy(&Reply[7],&shortdat,sizeof(short));
    Reply[9] = 0;
    ReplyLen = 12;
    memcpy(&Reply[1],&ReplyLen,sizeof(short));
    csum = CalcCRC16Bytes(Reply,ReplyLen-2);
    memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
  } else
  {
    while (shortdat--)
    {
        ms = MessageSize(diaryhelper, longdat);
        if ((ms == FLAG_PROBLEM) || (ms == -1) )
        { 
          shortdat = longdat & 0xFFFF;
          memcpy(&Reply[7],&shortdat,sizeof(short));
          Reply[9] = 0;
          ReplyLen = 12;
          memcpy(&Reply[1],&ReplyLen,sizeof(short));
          csum = CalcCRC16Bytes(Reply,ReplyLen-2);
          memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
          break;
        }
        if (ms < 0)
        {
          ms = -ms;
          // work with * messages here
          rc = RepeatSize(longdat,ms);
          ms += rc+1;
        }
        memcpy(&Reply[histindex],(char *)(Array[longdat++]),ms);
        histindex+=ms;
        if (longdat == max)
          longdat = 0;
        if (longdat == insert)
        {
          Reply[5] |= 0x02; // last one.
          break;
        }
        if (histindex + 120 >= MaxMessageSize)
          break; // we're full...another message could break us.
    }
    shortdat = longdat & 0xFFFF;
    memcpy(&Reply[7],&shortdat,sizeof(short));
    Reply[9] = 0; 
    ReplyLen = histindex + 2;
    memcpy(&Reply[1],&ReplyLen,sizeof(short));
    csum = CalcCRC16Bytes(Reply,ReplyLen-2);
    memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
  }
}

void DealWithGetError(void)
{
  unsigned short csum;

  ReplyLen = 17;
  Reply[1] = ReplyLen;
  Reply[2] = 0;
  Reply[7] = GlobalErrorStatus[0] & 0xFF;
  Reply[8] = (GlobalErrorStatus[0] >> 8) & 0xFF;
  Reply[9] = (GlobalErrorStatus[0] >> 16) & 0xFF;
  Reply[10] = (GlobalErrorStatus[0] >> 24) & 0xFF;
  Reply[11] = GlobalErrorStatus[1] & 0xFF;
  Reply[12] = (GlobalErrorStatus[1] >> 8) & 0xFF;
  Reply[13] = (GlobalErrorStatus[1] >> 16) & 0xFF;
  Reply[14] = (GlobalErrorStatus[1] >> 24) & 0xFF;
  csum = CalcCRC16Bytes(Reply,ReplyLen-2);
  memcpy(&Reply[ReplyLen-2],&csum,sizeof(short));
}
void ProtocolManagerTaskCode(void *p)
{
  char msg[2];
  char rx;
  unsigned char Receiver;
  unsigned short i,length,cslen,csum,csumcheck,entries,shortdat;
  unsigned long longdat;
  static unsigned int dblockindex,incomingindex;
  unsigned char Opcode;
  char *datahelper;
  static sleeptime = NORMAL_SLEEPTIME;
  static unsigned long TimeOfLastBurnMessage;
  int NeedToBurn = 0;
  int PABresult;

  UARTInitialize();
  // printf("Protocol Port Active!!\n\r"); // remove this when done debugging.
  for(;;)
  {
    if (US0_RCR+TakeOut == INPUT_QUEUE_SIZE*2) // have no new incoming data
    {
      if (sleeptime)
        ctl_timeout_wait(ctl_get_current_time()+sleeptime);  // sleep 40ms before checking again
      else
      {
        if (ctl_get_current_time() - TimeOfLastBurnMessage > 1250) // 5 seoconds passed without a burn message?
          sleeptime = NORMAL_SLEEPTIME;
      }
      continue;
    }
    rx = InQueue[TakeOut++];
    // TakeOut &= INPUT_QUEUE_SIZE-1;  // wraparound, see comment on PutIn
    switch(ProtocolState)
    {
      case WAITING_FOR_MESSAGE : 
        incomingindex = 0;
        if (rx == 0xBE)
          ProtocolState = GOT_FIRST_SYNC;
        else
        {
          if (rx == MyID) 
          {
            dblockindex = 0;
            ProtocolState = HANDLE_OLD_PROTOCOL_MESSAGE;
          }
        }
        break;
      case GOT_FIRST_SYNC :
        if (rx == 0xEF)
          ProtocolState = GOT_SECOND_SYNC;
        else
          ResetRx();
        break;
      case GOT_SECOND_SYNC :
        incoming[incomingindex++] = rx;
        ProtocolState = HAVE_PC_ID;
        Reply[0] = rx; // place PC ID into Reply[0].
        break;
      case HANDLE_OLD_PROTOCOL_MESSAGE : // the only message I will accept is 0xA 0x0 0xD 0x0 0x0 'D'=0x44 0x1 0x0 csum
        if (OLD_PROT_MESSAGE[dblockindex++] != rx)
        {
          if (dblockindex == 9) // don't check the checksum, just answer
          {
            PrepOldStyleReply();
            SendReply();
          } else
            ResetRx();
        }
        break;
      case HAVE_PC_ID :
        Receiver = rx;        
        if ((Receiver != MyID) && (Receiver != BROADCAST_ID)) // If this is not for me, or a broadcast, return
          ResetRx();
        else
          ProtocolState = HAVE_CONTROLLER_ID;
        incoming[incomingindex++] = Receiver;
        break;
      case HAVE_CONTROLLER_ID :
        ProtocolState = HAVE_ECHO_PACKET;
        incoming[incomingindex++] = Reply[6] = rx;
        break;
      case HAVE_ECHO_PACKET :
        ProtocolState = HAVE_LENGTH_LO;
        incoming[incomingindex++] = length = rx;
        break;
      case HAVE_LENGTH_LO :
        ProtocolState = HAVE_LENGTH;
        incoming[incomingindex++] = rx;
        shortdat = rx;
        length += (unsigned short)((shortdat << 8) & 0xFF00);
        break;
      case HAVE_LENGTH :
        incoming[incomingindex++] = Opcode = rx;
        dblockindex = 0;
        cslen = length-2;
        length -= 8; // remove the length of the overhead, leave the length of the data
        Reply[3] = Opcode;
        Reply[4] = MyID;
        Reply[5] = ProtocolStatus();
        entries = lengthcheck(Opcode, length);
        break;
      case GETTING_DATA :
        if ((ctl_get_current_time() - GettingDataTimeOut) > GETTING_DATA_MAX_TIME)
        {
          ReplyError(ERROR_CODE_OTHER);
          SendReply();
          break;
        }
        incoming[incomingindex++] = rx;
        if (--length == 0)
          ProtocolState = GETTING_CSUM1;
        break;
      case GETTING_CSUM1 :
        incoming[incomingindex++] = rx;
        ProtocolState = GETTING_CSUM2;
        break;
      case GETTING_CSUM2 :
        incoming[incomingindex++] = rx;
        csum = CalcCRC16Bytes(incoming,cslen); 
        csumcheck = incoming[incomingindex-1]*0x100 + incoming[incomingindex-2];
        if (csum != csumcheck)
          ReplyError(ERROR_CODE_BAD_CRC);
        else
        {
          switch(Opcode)
          {
            case OPCODE_CLOCKSYNC :
              DealWithOpcodeClockSync();
              break;
            case OPCODE_ADDR_LIST_VALS :
              DealWithOpcodeListVals(entries);
              break;
            case OPCODE_ADDR_LIST_LVALS :
              DealWithOpcodeListLVals(entries);
              break;
            case OPCODE_ADDR_LIST_CH_VALS :
            case OPCODE_ADDR_LIST_CH_LVALS :
              DealWithOpcodeListCHVals(Opcode,entries);
              break;
            case OPCODE_PREPARE_BURN :
              DealWithOpcodePrepareBurn();
              break;
            case OPCODE_READY_BURN :
              DealWithOpcodeReadyBurn();
              break;
            case OPCODE_BURN_DATA :
              sleeptime = SLEEP_DURING_UPLOAD;
              TimeOfLastBurnMessage = DealWithOpcodeBurnData();
              NeedToBurn = 1;
              break;
#ifdef OLDHIST
            case OPCODE_DIARY_DATA :
              break;
#endif            
            case OPCODE_GET_INDEX_OF_TIMESTAMP :
              DealWithGetIndexOfTimestamp();
              break;
            case OPCODE_DIARY_DATA_FROM_INDEX :
              DealWithGetDiaryDataFromIndex();
              break;
            case OPCODE_GET_ERROR :
              DealWithGetError();
              break;
            default :
              ReplyError(ERROR_CODE_OTHER);
              break;
          }
        }
        SendReply();
        //LED_OFF();
        if(NeedToBurn)
        {
          if (ParseAndBurn() == -2)
          {
            InternalFlashReprogram((unsigned short *)FIRSTFLASHBACKUPADDRESS, FLASHBACKUPLENGTH); // change 29/1/07, doesn't return
            sleeptime = NORMAL_SLEEPTIME;
          }
        }
        ProtocolState = WAITING_FOR_MESSAGE;
        break;
    }
  }
}

[/hide]

Отредактировано maxboot (2009-01-18 22:07:45)

0

2

А что за протокол обмена? Прога?

0

3

Это промышленный еврейский контроллер управляющий климатикой теплиц, что за протокол, понятия не имею, думаю какой-то их, кусок кода не для компьютера - для контроллеров.

Отредактировано maxboot (2009-01-19 09:39:47)

0

4

Да мну все равно, кто его делает, и что для контроллера тоже понял, ты обстоятельства давай, схемы, программу на комп- иначе это просто "какая-то программка". Стессно, прогу сконвертить можно, но .....ля с пляской еще та будет.Только делается это ручками.... Поэтому уж облегчи задачу, все-таки тебе помогаем.... по протоколу похож на разновидность Модбаса но на 232, коды ошибки расписаны в самом начале. со схемой веселее все-таки пойдет.....

Отредактировано Skull (2009-01-20 00:37:21)

0

5

Да действительно, скорее всего, что это для rs232, так как контроллеры объединяются в пул через переходники rs232 - rs485, программу могу конечно выложить, но она защищена hasp ключем, так, что толку от нее будет мало, но как видно из инклудовских файлов, данный алгоритм написан для AT91x408xx, вообще сам контроллер работает под управлением процессора интел 88 и имеет множество различных модулей, в частности один из них для rs232 для AT91x408xx, схем нет, да и этот алгоритм еле выпросил у разработчиков, могу только в общем описать смысл, как видно из программы протокола имеются регистры:

Скрытый текст:

Для просмотра скрытого текста - войдите или зарегистрируйтесь.


A, N, P, V, F, I, O, T именно они и используются в программе компьютера и я их могу в программе настраивать по своему усмотрению, т.е. комп принимает данные приблизительно в виде 1V242 значение; 2V434 значение
где 1 - номер контроллера, V определяет тип регистра, например V это датчики 242 номер регистра и собственно само значение регистра, длину пакета я тоже настраиваю в программе по своему усмотрению. вроде приблизительно описал все, что знаю. Исходников к компьютерной программе нет к сожалению.

0

6

Ну, ты почти прав, тока там есть еще кол-во байт после V и контрольная сумма CRC16, что уже до боли напоминает модбас RTU с кодами ошибок, таймаутами и пр. Чтение регистров функция 3 и 6 в Модбасе, и находятся они на 2й позиции пакета, то это точно модбас. процедура для этих ф-ций(длина пакета 8 байт):

'dimension a buffer for the modbus data
Dim Mbuf(8) As Byte , Modc As Byte , Modt As Byte , Modw As Word

Обработчик:
sbis usr,7
  rjmp urxc_isr                                             ' wait until we can read the byte
  Modt = Udr                                                ' get the byte
  If Modc = 0 Then                                          'if we do not have any data yet
    If Modt = Modbus_slave Then                             'is this the slave adress?
        Modc = Modc + 1                                     'increase the buffer counter
        Mbuf(1) = Modt                                      'store address in location 1
    End If
  Elseif Modc = 1 Then                                      'we received the address already
    If Modt = 6 Or Modt = 3 Then                            'this demo works with function 6 and 3 only
       Mbuf(2) = Modt                                       'store the function
       Modc = Modc + 1                                      'increase buffer counter
    Elseif Modt = Modbus_slave Then                         'test if it is the slave number
       Mbuf(1) = Modt                                       'store it in that case
    Else
       Modc = 0                                             'reset it
    End If
  Else                                                      'we received the address and the function
    Modc = Modc + 1 : Mbuf(modc) = Modt                     ' store the data
    If Modc = 8 Then                                        'we need 8 bytes
       Cls                                                  'clear display
       For Xx = 1 To 8
         Lcd Hex(mbuf(xx)) ; " "                            ' show the data
       Next
       Modw = Makeint(mbuf(7) , Mbuf(8))                    ' create word of reeived crc
       If Modw = Crcmb(mbuf(1) , 6) Then                    ' does the crc match?
          Lowerline : Lcd "match"                           'show it
          ' write the response here
          If Mbuf(2) = 6 Then                               ' function 6 to write data
             'do something here like setting a port
             'portD = mbuf(6) ' lsb of received data
             Printbin Mbuf(1) ; 8                           'just reply the received buffer
          Elseif Mbuf(2) = 3 Then                           ' function 3 to read data
             Mbuf(3) = 2                                    ' byte count
             Mbuf(4) = 0                                    'MSB
             Mbuf(5) = Pind                                 ' LSB return input of port D
             Modw = Crcmb(mbuf(1) , 5)                      ' create checksum
             Mbuf(6) = Low(modw)                            'add to buffer
             Mbuf(7) = High(modw)
             Printbin Mbuf(1) ; 7                           ' write response
          End If
       End If
       Modc = 0
    End If
  End If
Return

0

7

Огромное спасибо, попробую действительно прикрутить стандартный модбус, надо будет поэкспериментировать в proteusе с виртуальным портом. О результатах отпишусь!!!! Еще раз большое спасибо за помощь!!!!

0

8

Ты тока не обольщайся, там ПОХОЖИЙ протокол, но обработчик я тебе дал, его можно заточить как хочешь. Если чего - свисти.

0

9

У меня вот только еще один вопрос, как правильно прикрутить протокол или буфер к прерываниям по rs, я так понмаю по принципу on urxc label, но в данном случае я не могу использовать buffer, если использую прерывания, а без буфера ведь можно кусок данных и пропустить, если возможно не мог бы ты поделиться куском кода в котором показано как рабоать с прерыванием и параллельно с inputbin? Заранее биг сенкс!!!

0

10

Разместить ссылку не мгу, придется в пост пихать.......меня Админ проклянет, и отлучит нафиг от форума :)
'----------------------------------------------------------------------------------
Не прокляну. Пользуйтесь тегами "код". Админ

Код:
 

программуля нам нужна была чтоб соснифить протокол датчика расхода..........Это передатчик

$regfile = "m32def.dat"                                     '

'    UART:
$baud = 9600                                                'скорость 9.6 кБ
$crystal = 8000000                                          'при кварце 8 МГц
$lib "modbus.lbx"
'---------------------
Dim I As Byte
Dim Rs As Byte                                              'указатель буфера передаваемых символов
Dim Buft(7) As Byte                                         'передаваемая строка
' ......
Config Portd.4 = Output

'---------------------

      Enable Urxc                                           'разрешить прерывание приемника UART
      Enable Utxc                                           'разрешить прерывание передатчика UART
    Enable Interrupts                                       'разрешить прерывания
'---------------------
 Wait 2
' ......
    Buft(1) = &H05                                          ' Данные на передачу
    Buft(2) = &H11                                          ' Данные на передачу
    Buft(3) = 5                                             ' Данные на передачу
    Buft(4) = &H0F                                          ' Данные на передачу
    Buft(5) = &HD6                                          ' Данные на передачу
    Buft(6) = 0                                             'заполнение (неизвестно зачем, но работает)
    Buft(7) = 0                                               'заполнение (неизвестно зачем, но работает)

' ......

Do
For I = 1 To 7                                              'начало цикла передачи
Portd.4 = 1                                                 'Вкл трансивер МАХ485
Gosub Txd_int                                               'Уйти в обработчик передачи
Portd.4 = 0                                                 'Выкл трансивера МАХ485
                                                             'конец цикла передачи
 Next
Ucr = &B11010000                                            'обнуляем ТХС-запрет ТХ
nop                                                         ' и так понятно
Ucr = &B11011000                                            'разрешение ТХ


Toggle Portb.4                                              'баловство с портом
Wait 3                                                      'ждем 3с


Loop                                                        'завершение основного цикла


'----------------------------------------------
' обработка передатчика UART

Txd_int:                                                    'Обработчик передачи


sbis USR, 5                                                 'Ждать флаг готовности принять данные
rjmp Txd_int                                                ' Ждать флаг готовности принять данные
Udr = Buft(i)                                               'переписываем данные в UDR

Return                                                      ' возврат в основной цикл


Это приемник:


За сохранность можешь не переживать- ты не гигабайты обрабатываешь, и флаг прерывания сохраняется . Буфер в баскоме программный, если не ошибаюсь. А аппаратный (1байт) задействован. (UDR)





Urxc_isr:
'  Bled = 0
   sbis usr,7
  rjmp urxc_isr
     Incr Ii
   Modc(ii) = Udr

'   Bled = 1

If Ii = 1 And Modc(1) <> 5 Then Ii = 0
If Ii = 2 And Modc(2) <> Modbus_slave Then Ii = 0
If Ii = 5 Then
Disable Interrupts
 Gosub Sum__5
 End If
'   Enable Urxc
'Enable Int0
Enable Interrupts
Return
Return

0

11

Всем привет, я тут новенький, так что сильно не пинайте. :)
Имееться код на C который я пытаюсь конвертировать на ваську. Так как я в этом только начинающий - то получаеться корявенько.
Вот код на C:

Код:
//------------------------------------------------------------------------
// Окончательный вариант программы для простого мобильного робота
// http://projects.roboclub.ru/index.shtml?attempt
// (с) RodoClub.ru 2003
//------------------------------------------------------------------------

#include <inttypes.h>
#include <io.h>
#include <sig-avr.h>
#include <interrupt.h>
#include <stdlib.h>

// назначение определений для удобства работы с периферией
#define OUT PORTB
#define L_MOTOR_F  PB7
#define L_MOTOR_B  PB6
#define R_MOTOR_F  PB5
#define R_MOTOR_B  PB4

#define IN PIND
#define LIGHT_R  PD0
#define LIGHT_L  PD1
#define BUMPER_F PD2
#define BUMPER_B PD3

// Возможные режимы движения
enum {STOP, F, FR, FL, B, BR, BL};

//------------------------------------------------------------------------------
// Задержка t х 10ms
//------------------------------------------------------------------------------
#define F_CPU 4000000
#define K_DELAY_10ms    F_CPU/600
void Delay_10ms(unsigned char t) {
  unsigned int i;
  if (t==0) return;
  while (t--) for(i=0;i<K_DELAY_10ms; i++);
}

// таблица вероятностей для выбора направления движения
// исходя из текущего направления движения
unsigned char p[7][7] = {
{14,    43,    57,    71,    86,    93,    100},
{7,    43,    71,    100,    100,    100,    100},
{7,    50,    93,    100,    100,    100,    100},
{7,    50,    57,    100,    100,    100,    100},
{29,    29,    29,    29,    57,    79,    100},
{36,    36,    36,    36,    71,    93,    100},
{36,    36,    36,    36,    71,    79,    100},
};

// текущее направление движения
unsigned char this_move; 

//------------------------------------------------------------------------------
// Включение комбинации моторов для движения в заданном направлении
//------------------------------------------------------------------------------
void go(unsigned char direction){

  switch (direction) {
  case STOP:
    cbi(OUT, L_MOTOR_F);
    cbi(OUT, L_MOTOR_B);
    cbi(OUT, R_MOTOR_F);
    cbi(OUT, R_MOTOR_B);
    break;

  case F:
    sbi(OUT, L_MOTOR_F);
    cbi(OUT, L_MOTOR_B);
    sbi(OUT, R_MOTOR_F);
    cbi(OUT, R_MOTOR_B);
    break;

  case FR:
    sbi(OUT, L_MOTOR_F);
    cbi(OUT, L_MOTOR_B);
    cbi(OUT, R_MOTOR_F);
    cbi(OUT, R_MOTOR_B);
    break;

  case FL:
    cbi(OUT, L_MOTOR_F);
    cbi(OUT, L_MOTOR_B);
    sbi(OUT, R_MOTOR_F);
    cbi(OUT, R_MOTOR_B);
    break;

  case B:
    cbi(OUT, L_MOTOR_F);
    sbi(OUT, L_MOTOR_B);
    cbi(OUT, R_MOTOR_F);
    sbi(OUT, R_MOTOR_B);
    break;

  case BR:
    cbi(OUT, L_MOTOR_F);
    sbi(OUT, L_MOTOR_B);
    cbi(OUT, R_MOTOR_F);
    cbi(OUT, R_MOTOR_B);
    break;

  case BL:
    cbi(OUT, L_MOTOR_F);
    cbi(OUT, L_MOTOR_B);
    cbi(OUT, R_MOTOR_F);
    sbi(OUT, R_MOTOR_B);
    break;
  }
}

//------------------------------------------------------------------------------
// Выбор направления движения в следующем шаге по таблице вероятностей
//------------------------------------------------------------------------------
unsigned char next_move(void){
   unsigned char pp, i;

   pp = rand()/327;     // получаем случайное число 0..99
   for (i=0;i<7;i++){   // ищем соответствие в таблице вероятностей
      if (p[this_move][i] > pp) break;
   }
   this_move = i;       // записываем новое полученное направление как текущее
   return(i);
}

//------------------------------------------------------------------------------
// Обработка прерывания от переднего бампера (INT0 = PD2)
//------------------------------------------------------------------------------
SIGNAL(SIG_INTERRUPT0)
{
   if(this_move==FR) go(BL);
   if(this_move==FL) go(BR);
   else go(B);
   Delay_10ms(250);    // отъезд в течение 2.5 х 2 сек
   Delay_10ms(250);
   this_move=B;
}

//------------------------------------------------------------------------------
// Обработка прерывания от заднего бампера (INT1 = PD3)
//------------------------------------------------------------------------------
SIGNAL(SIG_INTERRUPT1)
{
   if(this_move==BR) go(FL);
   if(this_move==BL) go(FR);
   else go(F);
   Delay_10ms(250);    // отъезд в течение 2.5 х 2 сек
   Delay_10ms(250);
   this_move=F;
}

//------------------------------------------------------------------------------
// "Случайное блуждание"
//------------------------------------------------------------------------------
unsigned char walk(void){
   // этот цикл организует "свободное блуждание" пока
   // нет сигнала ни от одного из датчиков освещенности
   while((bit_is_set(IN, LIGHT_R)) && (bit_is_set(IN, LIGHT_L))){
       go(next_move());   // получаем следующее направление движения и
       Delay_10ms(250);   // движемся в этом направлении 2.5 сек
   }
   // этот цикл организует движение на свет, пока
   // есть сигнал хотя бы от одного из датчиков освещенности
   while((bit_is_clear(IN, LIGHT_R)) || (bit_is_clear(IN, LIGHT_L))){
       if((bit_is_clear(IN, LIGHT_R)) && (bit_is_clear(IN, LIGHT_L))) go(F);
       else if(bit_is_clear(IN, LIGHT_R)) go(FR);
       else if(bit_is_clear(IN, LIGHT_L)) go(FL);
   }

   return(0);
}

//------------------------------------------------------------------------------
// Главная программа
//------------------------------------------------------------------------------
int main(void)
{
  DDRB  = 0xff;  // назначаем все линии порта B на выход
  PORTB = 0x00;  // и устанавливаем на них низкий уровень

  DDRD  = 0x00;  // назначаем все линии порта D на вход
  PORTD = 0xff;  // подключаем внутренние нагрузочные резисторы

  // разрешаем прерывания int0 и int1
  outb(GIMSK, (1<<INT0)|(1<<INT1)); 

  // запрос на прерывание - по спадающим фронтам на int0 и int1
  outb(MCUCR, (1<<ISC01)|(1<<ISC11));

  // разрешаем прерывания
  sei();          

  // запускаем главный цикл
  while(1) walk();

}

А вот что у меня получилось:

Код:
$regfile = "ATtiny2313.DAT"
$crystal = 4000000
Config Pind.0 = Input : Foto_l Alias Pind.0
Config Pind.1 = Input : Foto_r Alias Pind.1

'Config Pind.2 = Input : Bump_f Alias Pind.2
'Config Pind.3 = Input : Bump_b Alias Pind.3

Config Pinb.4 = Output : M_l_b Alias Portb.4
Config Pinb.5 = Output : M_l_f Alias Portb.5
Config Pinb.6 = Output : M_r_b Alias Portb.6
Config Pinb.7 = Output : M_r_f Alias Portb.7


'Dim Rand As Word
Dim Stp As Word : Stp = 0
Dim F As Word : F = 1
Dim Fl As Word : Fl = 2
Dim Fr As Word : Fr = 3
Dim B As Word : B = 4
Dim Bl As Word : Bl = 5
Dim Br As Word : Br = 6

Dim Move As Word
 Enable Interrupts
Enable Int0
Enable Int1
On Int0 Bumper_f
On Int1 Bumper_b
Move = Stp
'-------------------------------------------------------------------------------
Do
'Rand = Rnd(5)

If Foto_l = 1 And Foto_r = 1 Then Gosub Stp                 'Move = Stp
If Foto_l = 0 And Foto_r = 0 Then Gosub Front               'Move = F
If Foto_l = 0 And Foto_r = 1 Then Gosub Front_l             'Move = Fl
If Foto_l = 1 And Foto_r = 0 Then Gosub Front_r             'Move = Fr
Loop

Bumper_f:                                                   'Передний бампер

   If Move = Stp Then Gosub Stp
   If Move = F Then Gosub Back
   If Move = Fl Then Gosub Back_r
   If Move = Fr Then Gosub Back_l
   Wait 2
  Return

Bumper_b:                                                   'Задний бампер
   If Move = Stp Then Gosub Stp
   If Move = B Then Gosub Front
   If Move = Bl Then Gosub Front_r
   If Move = Br Then Gosub Front_l
   Wait 2
  Return


Stp:                                                        'Стоим
Move = Stp
M_l_f = 0 : M_r_f = 0
M_l_b = 0 : M_r_b = 0
Return

Front:                                                      'Вперёд
Move = F
M_l_f = 1 : M_r_f = 1
M_l_b = 0 : M_r_b = 0
Return

Front_l:                                                    'Вперед_Влево
Move = Fl
M_l_f = 0 : M_r_f = 1
M_l_b = 1 : M_r_b = 0
Return

Front_r:                                                    'Вперёд_Вправо
Move = Fr
M_l_f = 1 : M_r_f = 0
M_l_b = 0 : M_r_b = 1
Return

Back:                                                       'Назад
Move = B
M_l_f = 0 : M_r_f = 0
M_l_b = 1 : M_r_b = 1
Return

Back_l:                                                     'Назал_Влево
Move = Bl
M_l_f = 0 : M_r_f = 1
M_l_b = 1 : M_r_b = 0
Return

Back_r:                                                     'Назад_Вправо
Move = Br
M_l_f = 1 : M_r_f = 0
M_l_b = 0 : M_r_b = 1
Return
End

Очень прошу:
Исправить мой код, если что не так или можно сделать лучше.
Портануть и внедрить в код рандом и таблицу из С, чтоб работал режим "Случайное блуждание". А еще лучше всё что я не сделал  :D

Всем заранее Огромное Спасибо, и извиняюсь если не туда, или что-то не так написал, или как-то не так попросил))))))

Добавлено позже: Чуток подправил...
P.S. Мне на помощь расчитывать? Напишите сразу плиз.
И просто умоляю, сделайте пожалуйста блуждание...
Заранее спс...

Отредактировано WolFenstein (2009-10-31 01:46:50)

0


Вы здесь » Программирование ATMEL в BASCOM. » Разное » Помогите сконвертировать С в bascom