logo search
HCS12 с применением языка С - royallib

9.5. Пример программирования контроллера msCan Схема включения аппаратных средств для двух отладочных плат Axiom

Рис. 9.32.

В этом разделе, мы рассмотрим простое применение, в котором два МК семейства 68HC12 объединяются в CAN сеть при помощи своих встроенных модулей msCAN12. Сначала мы покажем используемые в примере аппаратные средства (рис. 9.32), а затем представим программы, необходимые для работы обоих контроллеров. Для этого применения, мы выбрали отладочную плату Axiom CMD912 с микроконтроллером MC9S12DP256. Специальная плата была выбрана, чтобы воспользоваться преимуществами трансивера CAN, встроенного в ИС PCA82C259 компании Philips. Каждая плата должна выполнять собственную программу, чтобы реализовать простую связь между двумя msCAN модулями. Первая из программ, показанных ниже, является файлом заголовков (header file) 68hc9s12dp256.h, который содержит описания адресов регистров. Показан только фрагмент этого файла, относящийся к нашим программам CAN.

#define _REG_BASE 0

#define P(off) *(unsigned char volatile *)(_REG_BASE + off)

#define COPCTL _P(0x3C) /*управление сторожевым таймером */

#define CAN0CTL0 _P(0x0140) /*управляющий регистр 0 */

#define CAN0CTL1 _P(0x0141) /*CAN0 регистр управления 1 */

#define CAN0BTR0 _P(0x0142) /*CAN0 регистр синхронизации 0 */

#define CAN0BTR1 _P(0x0143) /*CAN0 регистр синхронизации 1 */

#define CAN0RFLG _P(0x0144) /*CAN0 флаги приема */

#define CAN0TFLG _P(0x0146) /*CAN0 флаги передачи */

#define CAN0TBEL _P(0x014A) /*CAN0 выбор передающего буфера */

#define CAN01DM0 _P(0x0154) /*CAN0 регистр маскирования идентификаторов 0*/

#define CAN01DM1 _P(0x0155) /*CAN0 регистр маскирования идентификаторов 1*/

#define CAN01DM2 _P(0x0156) /*CAN0 регистр маскирования идентификаторов 2*/

#define CAN0IDM3 _P(0x0157) /*CAN0 регистр маскирования идентификаторов 3*/

#define CAN0IDM4 _P(0x015C) /*CAN0 регистр маскирования идентификаторов 4*/

#define CAN0IDM5 _P(0x015D) /*CAN0 регистр маскирования идентификаторов 5*/

#define CAN0IDM6 _P(0x015E) /*CAN0 регистр маскирования идентификаторов 6*/

#define CAN0IDM7 _P(0x015F) /*CAN0 регистр маскирования идентификаторов 7*/

#define CAHORXFG0 _P(0x0160) /*основной буфер RX CAN0 */

#define CAN0RXFG1 _P(0x0161) /*основной буфер RX CAN0 */

#define CAN0RXFG2 _P(0x0162) /*основной буфер RX CAN0 */

#define CAN0RXFG3 _P(0x0163) /*основной буфер RX CAN0 */

#define CAN0RXFG4 _P(0x0164) /*основной буфер RX CAN0 */

#define CAN0RXFG5 _P(0x0165) /*основной буфер RX CAN0 */

#define CAN0RXFG6 _P(0x0166) /*основной буфер RX CAN0 */

#define CAN0RXFG7 _P(0x0167) /*основной буфер RX CAN0 */

#define CAN0RXFG8 _P(0x0168) /*основной буфер RX CAN0 */

#define CAN0RXFG9 _P(0x0169) /*основной буфер RX CAN0 */

#define CAN0RXFGA _P(0x016A) /*основной буфер RX CAN0 */

#define CAM0RXFGB _P(0x016B) /*основной буфер RX CAN0 */

#define CAN0RXFGC _P(0x016C) /*основной буфер RX CAN0 */

#define CAN0RXFGD _P(0x016D) /*основной буфер RX CAN0 */

#define CAN0RXFGE _P(0x016E) /*основной буфер RX CAN0 */

#define CAN0RXFGF _P(0x016F) /*основной буфер RX CAN0 */

#define CAN0TXFG0 _P(0x0170) /*основной буфер TX CAN0 */

#define CAN0TXFG1 _P(0x0171) /*основной буфер TX CAN0 */

#define CAN0TXFG2 _P(0x0172) /*основной буфер TX CAN0 */

#define CAN0TXFG3 _P(0x0173) /*основной буфер TX CAN0 */

#define CAN0TXFG4 _P(0x0174) /*основной буфер TX CAN0 */

#define CAN0TXFG5 _P(0x0175) /*основной буфер TX CAN0 */

#define CAN0TXFG6 _P(0x0176) /*основной буфер TX CAN0 */

#define CAN0TXFG7 _P(0x0177) /*основной буфер TX CAN0 */

#define CAM0TXFG8 _P(0x0178) /*основной буфер TX CAN0 */

#define CAN0TXFG9 _P(0x0179) /*основной буфер TX CAN0 */

#define CAN0TXFGA _P(0x017A) /*основной буфер TX CAN0 */

#define CAN0TXFGB _P(0x017B) /*основной буфер TX CAN0 */

#define CAN0TXFGC _P(0x017C) /*основной буфер TX CAN0 */

#define CAN0TXFGD _P(0x017D) /*основной буфер TX CAN0 */

#define CAN0TXFGE _P(0x017E) /*основной буфер TX CAN0 */

#define CAN0TXFGF _P(0x017F) /*основной буфер TX CAN0 */

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

Следующая программа выполняется контроллером первой платы, показанной в верхней части рис. 9.32. Эта программа инициализирует связь, а затем непрерывно посылает в сеть 8-байтовый блок данных ($01, $02, $03, $04, $05, $06, $07, и $08).

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

/* CANONE.C Эта программа запускает плату 68HC12 и связывает ее с другой*/

/* платой 68HC12 с помощью контроллера CAN                          */

/* Авторы: Даниэль Пак и Стив Барретт                               */

/* Дата создания: 29 июля 2004                                      */

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

line 0  #include "68HC12DP256.h"

line 1  void main()

line 2  {

line 3   COPCTL=0x00; /*Выключить сторожевой таймер COP*/

line 4   /*установить модуль CAN */

line 5   CAN0CTL1 = CAN0CTL1 | 0x80; /*разрешение для модуля CAN */

line 6   CAN0CTL1 = CAN0CTL1 & 0xEF; /*выключение режима LISTEN*/

line 7   while ((CAN0CTL1 | 0x01) == 0) /*режим инициализации CAN*/

line 8   {

line 9    CAN0CTL0 = CAN0CTL0 | 0x01;

line 10  }

line 11  CAN0BTR0 = 0xC1; /*установка бит синхронизации CAN*/

line 12  CAN0BTR1 = 0xF7;

line 13  CANOCTL0 = CAN0CTL0 & 0xFE;/*выход CAN из режима инициализации*/

line 14  while ((CAN0CTL0 & 0x10) == 0){} /*ожидание синхронизации*/

line 15  CAN0TBEL = 0x01; /*выбор передающего буфера 0 */

line 16  /*установка передающего буфера */

line 17  CAN0TXFG0 = 0xFF;

line 18  CAN0TXFG1 = 0xFF;

line 19  CAN0TXFG2 = 0xFF;

line 20  CAN0TXFG3 = 0xFE; /*RTR = 0 для кадра данных */

line 21  CAN0TXFG4 = 0x01; /*сообщение */

line 22  CAN0TXFG5 = 0x02;

line 23  CAN0TXFG6 = 0x03;

line 24  CAN0TXFG7 = 0x04;

line 25  CAN0TXFG8 = 0x05;

line 26  CAN0TXFG9 = 0x06;

line 27  CAN0TXFGA = 0x07;

line 28  CAN0TXFGB = 0x08;

line 29  CAN0TXFGC = 0x08; /*спецификатор длины данных */

line 30  CAN0TXFGD = 0x00;

line 31  while(1)

line 32  {

line 33   while ((CAN0TFLG & 0x01) == 0) /*ожидание флага окончания передачи */

line 34    CAN0TFLG = CAN0TFLG | 0x01; /*очистка флага */

line 35  }

line36  } /* конец основной программы */

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

Команда на строке 3 выключает функцию сторожевого таймера COP контроллера. Команды на строках от 4 до 20 инициализируют контроллер msCAN12. Сначала, команда по строке 5 включает CAN контроллер. Команда на строке 6 выключает режим LISTEN, используемый для контроллеров, которые только прослушивают данные сетевого трафика, не передавая никаких сообщения. Команды в строках с 7 по 10 используются, чтобы перевести контроллер CAN в режим инициализации. Сразу после инициализации, используются команды на строках 11 и 12, чтобы установить бит синхронизации CAN. Команда на строке 13 подготавливает контроллер CAN к работе с сетевым трафиком. Команда на строке 14 необходима, чтобы синхронизировать контроллер CAN с сетевым трафиком. Команда на строке 15 выбирает передающий буфер 0 для передачи информации, а команды на строках с 16-й по 30-ю готовят содержимое для передающего буфера. Отметим, что мы установили флаги SRR и IDE, выбрав тем самым расширенный формат, и, кроме того, очистили бит RTR, показав, что текущий буфер загружен кадром данных. Начиная со строки 31 до конца программы продолжается передача данных в сеть.

Ниже приведена программа, которая определяет работу второго МК, показанного в нижней части рис. 9.32.

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

/* CANTWO.C Эта программа запускает плату 68HC12 и связывает ее с другой */

/* платой 68HC12 с помощью контроллера CAN                            */

/* Авторы: Даниэль Пак и Стив Барретт                                 */

/* Дата создания: 29 июля 2004                                        */

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

line 0  #include "68HC12DP256.h"

line 1  void main()

line 2  {

line 3   COPCTL=0x00; /*Выключить сторожевой таймер COP */

line 4                /*установить модуль CAN */

line 5   CAN0CTL1 = CAN0CTL1 | 0x80; /*разрешение для модуля CAN */

line 6   CAN0CTL1 = CAN0CTL1 & 0xEF; /*выключение режима LISTEN */

line 7   while ((CAN0CTL1 | 0x01) == 0) /*режим инициализации CAN */

line 8   {

line 9    CAN0CTL0 = CAN0CTL0 | 0x01

line 10  }

line 11  CANOBTR0 = 0xC1; /*установка бита синхронизации CAN*/

line 12  CAN0BTR1 = 0xF7;

line 13  CAN01DM0 = 0xFF; /*прием всех сообщений */

line 14  CAN01DM1 = 0xFF;

line 15  CAN01DM2 = 0xFF;

line 16  CAN01DM3 = 0xFF;

line 17  CAN01DM4 = 0xFF;

line 18  CAN01DM5 = 0xFF;

line 19  CAN01DM6 = 0xFF;

line 20  CAN01DM7 = 0xFF;

line 21  CAN0CTL0 = CAN0CTL0 & 0xFE; /*выход CAN из режима инициализации */

line 22  while ((CAN0CTL0 & 0x10) == 0){} /*ожидание синхронизации */

line 23  /*ожидание сообщения */

line 24  while ((CAN0RFLG & 0x01) == 0){} /*ожидание флага сообщения */

line 25  CAN0RFLG = CAN0RFLG | 0x01; /*очистка флага */

line 26  asm("swi");

line 27 } /* конец основной программы */

Мы видим, что первое отличие этой программы от предыдущей — это спецификация для регистров маскирования приемника в строках с 13-й до 20-ю. Команды устанавливают все биты маскирования в состояние логической 1, игнорируя весь код, поступающий на соответствующие приемные регистры. Таким образом все сообщения с любым содержанием для четырех регистров идентификатора будут приняты CAN контроллером.

Основное различие между двумя программами начинается в строке 23. По команде в строке 24 МК ожидает заполнения приемного буфера, команда в строке 25 очищает флаг приемника. Команда в последней строке останавливает программу, после чего МК мы можем проверить получение данных, рассматривая содержание приемного буфера, размещенного в ячейках от $0160 до $016F.

Приведенные прикладные программы показывают простейший сценарий, в котором действуют только два узла CAN сети. Мы предельно упростили пример, чтобы помочь Вам освоить начальное программирование CAN контроллеров в составе 68HC12. Для простоты мы избегали использования любых прерываний и запрограммировали контроллеры CAN таким образом, чтобы они могли принимать сообщения с любыми идентификаторами битами.