I2c CoDeSys

Материал из rrv-wiki
Перейти к навигации Перейти к поиску


Задача

Для использования периферийных устройств, через i2c. Например у меня на контроллере 16 (однобитовых/ключей)входов и 16 выходов. В тестовой плате Beck DB54 таких входов и выходов по восемь. Ну чтож расширим, для этого выполним следующие шаги:

Создание платформы

Отрываем ближайшую подходящую платформу

Откроем в CoDeSys@CHIP IEC Platform Builder тестовую платформу для платы BECK DB54 C:\Program Files\Beck IPC GmbH\CoDeSys@CHIP SDK\samples\Full\DK55\SC23\DK55_FP_CM.xml. Мы делаем так как наша плата почти полностью соответствует этой платформе, иначе придется все создавать с нуля.

Вносим изменения:

General

В оригинале:
http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-orig1.jpg

Меняем:
http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-my1.jpg

Имя (Name) может быть на ваше усмотрение, а вот с ID не все так просто, он должен быть либо из диапазона для тестирования 20300 - 20309 как я и выбрал, либо попросить у компании Beck выделить личный ID.

Теперь переходим на вкладку Device.

Оригинал:
http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-orig2.jpg

Меняем:
http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-my2.jpg Так как на плате с которой сейчас проводится эксперимент есть три порта RS-232 и все они будут заняты внешними устройствами то убираем галочку с RS232, тем самым отключаем управление контроллером через RS-232 порт и оставляем управление только через ethernet.

IO Configuration

Оригинал:
http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-orig3.jpg

Меняем:
http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-my3.jpg Здесь мы создаем две переменные по 8 бит каждая (и того 16 бит) для входных и выходных данных подключенных через i2c. D0_in, D1_in и D0_out, D1_out - это байтовые (8bit)переменные которые будут доступны из программ CoDeSys, как? об этом ниже.

Сохраняем и создаем новую платформу:

Сохраняем платформу в новое место

http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-my-save.jpg

Создаем файлы новой платформы

http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-my-make.jpg

Переходим в папку с вновь созданной платформой

http://rrv.nsk.ru/wiki/images/i2c-PlatfBuil-my-go.jpg

Теперь вносим изменения в myrts.c будущий exe-файл платформы

В RTOS запускается файл myrts.exe читаем тут. Для того что бы заработали все требуемые COM-порты и i2c-устройства были привязаны к определенными нами переменными напишем соответствующие драйверы изменив файл myrts.c он расположен в папке rts которая лежит в папке в которую мы сохранили, а потом создали платформу с помощью CoDeSys@CHIP IEC Platform Builder (см. выше)

Включение трех COM-портов

У меня три COM-порта, активируем их изменив в myrts.c следующие строки:

RHISerPortTypes s_SerialPortTypes =
/* See for a detailed description the RHI Documentation !!! */
{
   RHI_MAXCOMPORTS,     /* NumComPorts */
   {                    /* ComPortUse[RHI_MAXCOMPORTS] */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_COM,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
   },
   RHI_SERPORT_SPI,     /* SPIPortUse: RHI_SERPORT_NAV or RHI_SERPORT_SPI */
   RHI_SERPORT_I2C,     /* I2CPortUse: RHI_SERPORT_NAV or RHI_SERPORT_I2C */
};

на:

RHISerPortTypes s_SerialPortTypes =
/* See for a detailed description the RHI Documentation !!! */
{
   RHI_MAXCOMPORTS,     /* NumComPorts */
   {                    /* ComPortUse[RHI_MAXCOMPORTS] */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_COM,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_COM,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_COM,  /* ComPortUse: RHI_SERPORT_NAV or RHI_SERPORT_COM */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
      RHI_SERPORT_NAV,  /* ComPortUse: RHI_SERPORT_NAV */
   },
   RHI_SERPORT_NAV,     /* SPIPortUse: RHI_SERPORT_NAV or RHI_SERPORT_SPI ОБЯЗАТЕЛЬНО ОТКЛЮЧИТЬ если используются три COM порта иначе система будет выдавать ошибку при загрузке*/
   RHI_SERPORT_I2C,     /* I2CPortUse: RHI_SERPORT_NAV or RHI_SERPORT_I2C */
};

Описание здесь.

Драйвер I2C

Правим секцию
/* IO Access */
В отличии от платы BECK DB54 у меня устройства I2C имеют следующие адреса:
0x40 - младший байт выхода D0_out
0x48 - старший байт выхода D1_out
0x42 - младший байт входа D0_in
0x44 - старший байт входа D1_in

Меняем:

/*****************************************************************************/
/* IO Access */
/*****************************************************************************/
void RHIIOInit (void)
{
   /* TO-DO: add here code to initialize your hardware */
}

#pragma argsused
int RHIIOReadAllInputs (unsigned char *pInputArea)
{
   /* TO-DO: add here code to copy the hardware values into the IEC input area.
      Example:
         RHIInputArea *theInputArea = (RHIInputArea *)pInputArea;
         theInputArea->myByteInput = inportb(0xC00);
         theInputArea->myWordInput = inport(0xC02);
   */
   return 1;
}

#pragma argsused
int RHIIOReadInput (unsigned char *pInputArea, int iFieldOffset)
{
   /* TO-DO: add here code to copy the hardware values into the IEC input area.
      Example:
         RHIInputArea *theInputArea = (RHIInputArea *)pInputArea;
         switch (iFieldOffset)
         {
            case IFID_myByteInput:
               theInputArea->myByteInput = inportb(0xc00);
               return 1;
            case IFID_myWordInput:
               theInputArea->myWordInput = inport(0xc02);
               return 1;
            default:
               return 1;
         }
   */
   return 1;
}

#pragma argsused
int RHIIOWriteAllOutputs (unsigned char *pOutputArea)
{
   /* TO-DO: add here code to copy the IEC output area values to the hardware.
      Example:
         RHIOutputArea *theOutputArea = (RHIOutputArea *)pOutputArea;
         outportb(0xC00, theOutputArea->myByteOutput);
         outport (0xC02, theOutputArea->myWordOutput);
   */
   return 1;
}

#pragma argsused
int RHIIOWriteOutput (unsigned char *pOutputArea, int iFieldOffset)
{
   /* TO-DO: add here code to copy the IEC output area values to the hardware.
      Example:
         RHIOutputArea *theOutputArea = (RHIOutputArea *)pOutputArea;
         switch (iFieldOffset)
         {
            case OFID_myByteOutput:
               outportb(0xC00, theOutputArea->myByteOutput);
               return 1;
            case OFID_myWordOutput:
               outport (0xC02, theOutputArea->myWordOutput);
               return 1;
            default:
               return 1;
         }
   */
   return 1;
}

На:

/*****************************************************************************/
/* IO Access */
/*****************************************************************************/
void RHIIOInit (void)
{
   /* Example for DK55 Board, see also DK55 Dokumentation */
   /* Init I2C-Port */
   I2C_select_data_pin  (0);  /* Use HW_I2C Interface */
   I2C_select_clock_pin (0);
   I2C_init ();

   I2C_transmit_char (0x40, 0xFF);  /* Preset Out register 0-7 D0_out */
   I2C_release ();
   I2C_transmit_char (0x48, 0xFF);  /* Preset Out register 8-15 D1-out*/
   I2C_release ();
}

#pragma argsused
int RHIIOReadAllInputs (unsigned char *pInputArea)
{
   unsigned char B;
   unsigned char C;

   /* Example for DK55 Board, see also DK55 Dokumentation */
   RHIInputArea *theInputArea = (RHIInputArea *)pInputArea;
   I2C_receive_char (0x42, &((char)B), 0); /* Read one Byte */
   I2C_release ();
   theInputArea->D0_in = ~(B);

   I2C_receive_char (0x44, &((char)C), 0); /* Read one Byte */
   I2C_release ();
   theInputArea->D1_in = ~(C);

   return 1;
}

#pragma argsused
int RHIIOReadInput (unsigned char *pInputArea, int iFieldOffset)
{
  unsigned char B;
  unsigned char C;

  RHIInputArea *theInputArea = (RHIInputArea *)pInputArea;
   switch (iFieldOffset)
   {
      case IFID_D0_in:
         I2C_receive_char (0x42, &((char)B), 0); /* Read one Byte */
         I2C_release ();
         theInputArea->D0_in = ~(B);
         return 1;
      case IFID_D1_in:
         I2C_receive_char (0x44, &((char)C), 0); /* Read one Byte */
         I2C_release ();
         theInputArea->D1_in = ~(C);
         return 1;
      default:
         return 1;
   }
}

#pragma argsused
int RHIIOWriteAllOutputs (unsigned char *pOutputArea)
{
   RHIOutputArea *theOutputArea = (RHIOutputArea *)pOutputArea;
   I2C_transmit_char(0x40, ~(theOutputArea->D0_out)); /* Write one Byte */
   I2C_transmit_char(0x48, ~(theOutputArea->D1_out)); /* Write one Byte */
   I2C_release ();
   return 1;
}

#pragma argsused
int RHIIOWriteOutput (unsigned char *pOutputArea, int iFieldOffset)
{
   RHIOutputArea *theOutputArea = (RHIOutputArea *)pOutputArea;
   switch (iFieldOffset)
   {
      case OFID_D0_out:
         I2C_transmit_char(0x40, ~(theOutputArea->D0_out)); /* Write one Byte */
         return 1;
      case OFID_D1_out:
         I2C_transmit_char(0x48, ~(theOutputArea->D1_out)); /* Write one Byte */
         return 1;
      default:
         return 1;
   }
}

Все по аналогии из примера.

Компиляция

Теперь откомпилируем, открыв файл myRts.pdl (находится в той же папке что и myrts.c) в Paradigm C++ Beck IPC Edition.
Если не было ошибок то в папке rts (в которой лежит файл myrts.c) появляется папка bin, а в ней файл myrts.exe. Этот файл надо скопировать в контроллер (в корень диска a или куда нибудь еще, главное что бы потом указать правильный путь AUTOEXEC.BAT)и запускать при старте через a:\AUTOEXEC.BAT (диск a находится в контроллере, о записи в контроллер читать тут).

Таким образом в a:\AUTOEXEC.BAT последней строчкой должно быть:

myrts.exe

Создание платформы в CoDeSys

Для того что бы CoDeSys видел нашу платформу требуется выполнить:

tsp\install.bst /f 

ключ f заменит платформу если она уже существует.

Папка tsp лежит там же где и папка rts.


Использование

Открываем CoDeSys V2.3 (C:\Program Files\3S Software\CoDeSys V2.3\Codesys.exe) создаем новый проект и выбираем созданную ранее платформу.

И создаем следующую программу:

http://rrv.nsk.ru/wiki/images/i2c-test-program-codesys.jpg

Здесь %IB0 и %IB1 это входные байты соответствуют D0_in D1_in, а %QB0, %QB1 соответствуют D0_out и D1_out. Так же можно обратится к конкретному биту например нулевой бит IB0 соответствует переменная IX0.0. В общем смотрим "Конфигурация ПЛК".

Эта простая программа считывает все входы и выводит эти значения на выход один раз в секунду.