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;
}