CAN и ETHERNET(К1921ВК01Т)

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

blessedt
Сообщения: 34
Зарегистрирован: 25 фев 2019, 00:09
Предприятие: АОКБ Импульс

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение blessedt »

Товарищи, объясните неразумному одну вещь, очень прошу =)
123.png
123.png (48.29 КБ) 5179 просмотров
Принимаю из ПК сообщение (нижний график), содержащее структуру

Код: Выделить всё

__packed_struct {
	uint8_t command;<-просто константа 0xAA
	uint32_t data;<-тоже просто константа 0xBBBBBBBB
	uint8_t receiveCounter;<-счетчик пакетов, инкрементируется в ПК
} receiveStruct;
Всё принимается верно. При приеме МК отправляет ответ (верхний график), содержащий структуру

Код: Выделить всё

__packed_struct {
	uint8_t command;<-повторяет первый байт из принимаемого сообщения
	uint8_t transmitCounter;<-счетчик передач, инкрементируется в МК при каждой передаче
} transmitStruct;
Одновременно с сообщением на TX трансивера оно появляется на линии RX трансивера, абсолютно точно такое же за исключением того, что на линии TX отсутствует бит ACK (что вроде как логично). Таких повторений (а соответственно и сообщений, принятых ПК, может быть от одного до... до некоторого количества, например шести или восьми.
Есть ощущение, что принятое контроллером сообщение не очищается в контроллере какое-то произвольное время.
Может, кто-то может подсказать причину такого поведения?
На всякий случай прикладываю код инициализации объектов сообщений для приема и передачи, а также код собственно приема и передачи. Наверняка, косяк где-то там.
| Показать

Код: Выделить всё

void canConfigMailBoxForTransmit(uint16_t mbNum, uint16_t size, uint32_t id) {
	//NT_CAN->CAN_Msg[mbNum].MOCTR = 0x0A080020;
	NT_CAN->CAN_Msg[mbNum].MOCTR = CAN_MOCTR_SETDIR_Msk | CAN_MOCTR_SETTXEN0_Msk | CAN_MOCTR_SETTXEN1_Msk | CAN_MOCTR_SETMSGVAL_Msk;
	
	NT_CAN->CAN_Msg[mbNum].MOFCR = 0x08800000;
	NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC = size;
	
	NT_CAN->CAN_Msg[mbNum].MOAR = 0;
	NT_CAN->CAN_Msg[mbNum].MOAR_bit.PRI = 2;
	NT_CAN->CAN_Msg[mbNum].MOAR_bit.IDE = 0;
	NT_CAN->CAN_Msg[mbNum].MOAR_bit.ID = id;
	
	NT_CAN->CAN_Msg[mbNum].MOAMR = 0x3FFFFFFF;
	NT_CAN->CAN_Msg[mbNum].MOFGPR = 0;
	NT_CAN->CAN_Msg[mbNum].MOIPR = 0;
	
	NT_CAN->CAN_Msg[mbNum].MODATAL = 0;
	NT_CAN->CAN_Msg[mbNum].MODATAH = 0;
	
	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000020;
}

void canConfigMailBoxForReceive(uint16_t mbNum, uint32_t id) {
	NT_CAN->CAN_Msg[mbNum].MOCTR = 0;
	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000800;
	
	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00800000;
	
	NT_CAN->CAN_Msg[mbNum].MOFCR = 0;
	NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC = 0;//size;
	
	NT_CAN->CAN_Msg[mbNum].MOAR = 0;
	NT_CAN->CAN_Msg[mbNum].MOAR_bit.PRI = 2;
	NT_CAN->CAN_Msg[mbNum].MOAR_bit.IDE = 0;
	NT_CAN->CAN_Msg[mbNum].MOAR_bit.ID = id;
	
	NT_CAN->CAN_Msg[mbNum].MOAMR = 0x20000000;	//0x3FFFFFFF;
	NT_CAN->CAN_Msg[mbNum].MOFGPR = 0;
	NT_CAN->CAN_Msg[mbNum].MOIPR = 0;

	NT_CAN->CAN_Msg[mbNum].MODATAL = 0;
	NT_CAN->CAN_Msg[mbNum].MODATAH = 0;

	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000020;
}

void canTransmit(uint16_t mbNum, uint16_t size, void *data) {
	uint8_t* p = (uint8_t *)data;

	NT_CAN->CAN_Msg[mbNum].MODATAL = 0;
	NT_CAN->CAN_Msg[mbNum].MODATAH = 0;
	
	uint8_t *dst = 0x80071010 + 0x20UL * mbNum;
	for (uint32_t i = 0; i < size; i++) {
		dst[i] = *(uint8_t *)(data + i);
	}
	
	NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC = size;
	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x0E080020;
	NOP_7;

	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x01200000;
	__NOP();
}

uint16_t canReceive(uint16_t mbNum, void *data) {
	uint16_t size = 0;
	
	NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00800000;	//?
	//TODO: check fifo
	if (NT_CAN->CAN_Msg[mbNum].MOSTAT & CAN_MOSTAT_RXPND_Msk) {
		NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00800020;
		NOP_7;

		NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000008;
		NOP_7;
		size = NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC;

		uint32_t *p = (uint32_t *)data;
		p[0] = NT_CAN->CAN_Msg[mbNum].MODATAL;
		if (size > 4) p[1] = NT_CAN->CAN_Msg[mbNum].MODATAH;
		
		NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00200000;
		NOP_7;
		
		NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000001;
		__NOP();
	}
	return size;
}
Трансивер 5559ИН14БУ
редактор
Сообщения: 27
Зарегистрирован: 08 ноя 2016, 09:10

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение редактор »

Шина CAN именно так и работает.
Каждый узел прослушивает свое сообщение. Если на этапе передачи ID принятое не совпало с переданным, значит арбитраж прогигран и узел освобождает шину для других.
И АСК для себя узел не формирует, а ждет от других узлов.
В общем - арбитраж и целостность/достоверность данных
blessedt
Сообщения: 34
Зарегистрирован: 25 фев 2019, 00:09
Предприятие: АОКБ Импульс

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение blessedt »

Ну, об этом я догадывался ) вопрос в том, почему контроллер отвечает рандомным количеством сообщений.
blessedt
Сообщения: 34
Зарегистрирован: 25 фев 2019, 00:09
Предприятие: АОКБ Импульс

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение blessedt »

Никто не подскажет? ))
редактор
Сообщения: 27
Зарегистрирован: 08 ноя 2016, 09:10

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение редактор »

вопрос в том, почему контроллер отвечает рандомным количеством сообщений.
Ваш вопрос никак не связан ни с трансивером 5559ИН14БУ, ни с битом ACK.
Наличие передачи от МК говорит о том, сто программа активирует объект CAN для передачи. Возможно, что при старте одного сообщения активируется цепочка.
Объекты сообщений могут объединяться в классы, с разными уровнями приоритета, могут объединяться для
построения структур FIFO произвольных размеров (до 256 объектов в одной структуре).
Возможно, именно такое FIFO у вас и организовалось. Ну п.18.9 может быть поможет.
Ваш код не смотрел. Поэтому других подсказок дать не могу.
dav
Сообщения: 209
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение dav »

blessedt писал(а): 10 ноя 2021, 20:22 Товарищи, объясните неразумному одну вещь, очень прошу =)

Принимаю из ПК сообщение (нижний график), содержащее структуру

Одновременно с сообщением на TX трансивера оно появляется на линии RX трансивера, абсолютно точно такое же за исключением того, что на линии TX отсутствует бит ACK (что вроде как логично). Таких повторений (а соответственно и сообщений, принятых ПК, может быть от одного до... до некоторого количества, например шести или восьми.
Есть ощущение, что принятое контроллером сообщение не очищается в контроллере какое-то произвольное время.
Может, кто-то может подсказать причину такого поведения?
На всякий случай прикладываю код инициализации объектов сообщений для приема и передачи, а также код собственно приема и передачи. Наверняка, косяк где-то там.

Трансивер 5559ИН14БУ
Доброго времени суток!

Из приведенных фрагментов кода программы не ясно, в передачах-приемах участвуют одни и те же объекты сообщений? Как в программе реализована последовательность передач-приемов, выбор объектов для их осуществления? От чего зависит «случайность» количества передач? Что при этом меняется? Одна и та же программа при одних и тех же условиях выдает разное количество передач?

На приведенной диаграмме фреймы на линиях внешне корректные, вопросов не вызывают. Проблема с разным количеством передач, возможно, из-за несвоевременных сброса /установки битов NEWDAT и MSGVAL. Также можно проверять значение бита RTSEL. В целом для отлаживания и выявления ошибок после передач удобно проверять состояние статусного регистра MOSTAT интересуемого объекта. Также для выявления ошибок транзакций можно выводить статусные регистры узлов NSR.

На всякий случай, пояснения по битам CAN:
Когда содержимое объекта сообщения передано во внутренний буфер передачи узла CAN, бит NEWDAT очищается аппаратно.
Когда передача кадра проходит успешно и NEWDAT все еще очищен, TXRQ автоматически очищается аппаратно.
Если бит NEWDAT был снова установлен программно, TXRQ не очищается.
Бит MSGVAL должен устанавливаться всякий раз для передачи сообщения объектом.
Бит TXRQ очищается аппаратно в конце успешной передачи, за исключением случаев, когда необходимо передать новые данные (обозначенные NEWSDATA=1).

Предположение другого пользователя о том, что в Вашем случае, возможно, случайно организовалась fifo-структура, маловероятно, так как для ее организации необходимы специальные настройки регистров, которых не видно в программе, во всяком случае, в представленных фрагментах кода.

Ниже приведен Ваши фрагменты кода с нашими комментариями (возможно, будут полезны), обозначенные знаком «!!!».

Код: Выделить всё

void canConfigMailBoxForTransmit(uint16_t mbNum, uint16_t size, uint32_t id) {
        //NT_CAN->CAN_Msg[mbNum].MOCTR = 0x0A080020;//
        NT_CAN->CAN_Msg[mbNum].MOCTR = CAN_MOCTR_SETDIR_Msk | CAN_MOCTR_SETTXEN0_Msk | CAN_MOCTR_SETTXEN1_Msk | CAN_MOCTR_SETMSGVAL_Msk;
        NT_CAN->CAN_Msg[mbNum].MOFCR = 0x08800000;
        NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC = size;
        NT_CAN->CAN_Msg[mbNum].MOAR = 0;
        NT_CAN->CAN_Msg[mbNum].MOAR_bit.PRI = 2;
        NT_CAN->CAN_Msg[mbNum].MOAR_bit.IDE = 0;
        NT_CAN->CAN_Msg[mbNum].MOAR_bit.ID = id;
        NT_CAN->CAN_Msg[mbNum].MOAMR = 0x3FFFFFFF;
        NT_CAN->CAN_Msg[mbNum].MOFGPR = 0;
        NT_CAN->CAN_Msg[mbNum].MOIPR = 0;
        NT_CAN->CAN_Msg[mbNum].MODATAL = 0;
        NT_CAN->CAN_Msg[mbNum].MODATAH = 0;
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000020;
}

void canConfigMailBoxForReceive(uint16_t mbNum, uint32_t id) {
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0;//!!!Нет смысла
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000800; //
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00800000;
        NT_CAN->CAN_Msg[mbNum].MOFCR = 0;
        NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC = 0;//size;
        NT_CAN->CAN_Msg[mbNum].MOAR = 0;
        NT_CAN->CAN_Msg[mbNum].MOAR_bit.PRI = 2;
        NT_CAN->CAN_Msg[mbNum].MOAR_bit.IDE = 0;
        NT_CAN->CAN_Msg[mbNum].MOAR_bit.ID = id;
        NT_CAN->CAN_Msg[mbNum].MOAMR = 0x20000000;    //0x3FFFFFFF;
        NT_CAN->CAN_Msg[mbNum].MOFGPR = 0;
        NT_CAN->CAN_Msg[mbNum].MOIPR = 0;
        NT_CAN->CAN_Msg[mbNum].MODATAL = 0;
        NT_CAN->CAN_Msg[mbNum].MODATAH = 0;
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000020;
}

void canTransmit(uint16_t mbNum, uint16_t size, void *data) {
        uint8_t* p = (uint8_t *)data;
        NT_CAN->CAN_Msg[mbNum].MODATAL = 0;
        NT_CAN->CAN_Msg[mbNum].MODATAH = 0;

        uint8_t *dst = 0x80071010 + 0x20UL * mbNum;
        for (uint32_t i = 0; i < size; i++) {
               dst[i] = *(uint8_t *)(data + i);
        }

        NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC = size;
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x0E080020;//!!! Если //проинициализирован на передачу, не надо повторно устанавливать //DIR,TXEN0,TXEN1,   
        NOP_7;
        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x01200000;
        __NOP();
}

uint16_t canReceive(uint16_t mbNum, void *data) {
        uint16_t size = 0;

        NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00800000;//!!!Не нужна строка,если //объект уже инициализирован на прием
        //TODO: check fifo//
        if (NT_CAN->CAN_Msg[mbNum].MOSTAT & CAN_MOSTAT_RXPND_Msk) {
               NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00800020;//!!!Нет нужды в //установке RXEN снова
               NOP_7;
               NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000008;
               NOP_7;//!!!проверить, сброшен ли NEWDAT,считав в MOSTAT бит //NEWDAT
               size = NT_CAN->CAN_Msg[mbNum].MOFCR_bit.DLC;

               uint32_t *p = (uint32_t *)data;
               p[0] = NT_CAN->CAN_Msg[mbNum].MODATAL;
               if (size > 4) p[1] = NT_CAN->CAN_Msg[mbNum].MODATAH;

               NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00200000;//!!! Поменять //местами со строкой ниже –очисткой бита RXPND
               NOP_7;
               NT_CAN->CAN_Msg[mbNum].MOCTR = 0x00000001;//!!!Поменять местами со строкой выше(с установкой бита MSGVAL)
               __NOP();
        }
        return size;
}
blessedt
Сообщения: 34
Зарегистрирован: 25 фев 2019, 00:09
Предприятие: АОКБ Импульс

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение blessedt »

dav писал(а): 17 ноя 2021, 10:28 Доброго времени суток!
Спасибо за ответ!
Проблема крылась в отсутствии строк

Код: Выделить всё

if (NT_CAN->CAN_Node[mbNum & 0x80].NSR & CAN_NSR_RXOK_Msk) {
	NT_CAN->CAN_Node[mbNum & 0x80].NSR &= ~CAN_NSR_RXOK_Msk;
За комментарии отдельное спасибо, помогут лучшему пониманию работы с CAN.

P.S.: Всё же очень хотелось бы описание работы с CAN, разжёванное для тупых типа меня ^_^
Аватара пользователя
Eugene
Сообщения: 8
Зарегистрирован: 14 июл 2022, 12:58
Предприятие: ООО Диаконт

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение Eugene »

Лашкевич писал(а): 12 апр 2019, 11:41 А модуль CAN включен? Наш драйвер начинается так:

Код: Выделить всё

//ставим запрос на включение модуля CAN (без этого даже к регистрам обратиться нельзя)
  NT_CAN->CLC_bit.DISR = 0;
  //ожидаем выполения запроса
  while (NT_CAN->CLC_bit.DISS == 1)
    ; //   DELAY
  //на всякий случай ожидаем освобождения панели команд для управления списками
  while (NT_CAN->PANCTR_bit.BUSY != 0 || NT_CAN->PANCTR_bit.RBUSY != 0)
    ; // DELAY
А где можно посмотреть целиком ваш драйвер?
Даже самую простую задачу можно сделать невыполнимой, если провести достаточное количество совещаний.
Аватара пользователя
Лашкевич
Сообщения: 373
Зарегистрирован: 13 май 2015, 13:10
Предприятие: ООО "НПФ Вектор"
Откуда: Москва
Контактная информация:

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение Лашкевич »

Наш драйвер CANOpen не публикуется в исходных кодах.
С уважением,
Лашкевич Максим.
Инженер-программист ООО "НПФ Вектор", Москва.
http://motorcontrol.ru/
Аватара пользователя
Eugene
Сообщения: 8
Зарегистрирован: 14 июл 2022, 12:58
Предприятие: ООО Диаконт

Re: CAN и ETHERNET(К1921ВК01Т)

Сообщение Eugene »

Но мне нужен просто драйвер CAN, кусок из которого в этой ветке опубликован. Где его можно найти?
Даже самую простую задачу можно сделать невыполнимой, если провести достаточное количество совещаний.
Ответить

Вернуться в «32-разрядные микроконтроллеры»