CAN и ETHERNET(К1921ВК01Т)

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

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

dav
Сообщения: 208
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

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

Сообщение dav »

Сергей писал(а): 21 май 2021, 16:38 Почему при использовании механизма FIFO, для разрешения прерывания по окончании отправки
необходимо выставлять флаги, которые в других режимах используются для разрешения прерывания по приему?

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

	NT_CAN.CAN_MSG[12].MOIPR.bit.RXINP = 3;
	NT_CAN.CAN_MSG[12].MOFCR.bit.RXIE = SET;
	NT_CAN.CAN_MSG[12].MOFCR.bit.OVIE = SET;
Доброго времени суток!
Выставлять флаги надо у всех вспомогательных объектов – фактически они работают на передачу, как и обычные объекты, а очередность передачи ими управляется базовым объектом FIFO-структуры.
Сергей писал(а): 21 май 2021, 16:38 Почему при использовании механизма FIFO, для разрешения прерывания по окончании отправки
необходимо выставлять флаги, которые в других режимах используются для разрешения прерывания по приему?

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

	NT_CAN.CAN_MSG[12].MOIPR.bit.RXINP = 3;
	NT_CAN.CAN_MSG[12].MOFCR.bit.RXIE = SET;
	NT_CAN.CAN_MSG[12].MOFCR.bit.OVIE = SET;
И наоборот.
Связь между базовым и вспомогательными объектами FIFO-структуры осуществляется следующим образом: вспомогательные объекты непосредственно передают данные, а базовый объект от вспомогательных получает информацию для работы FIFO-структуры.

Также следует выставлять флаги MSGVAL и TXRQ после полной настройки объектов, включая регистры данных.
Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

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

Сообщение atom »

Пытаюсь запустить работу двух модулей CAN (CAN0 на пинах G7/E2, CAN1 на пинах F14/F15).
Инициализация CAN | Показать

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

/*******************************************
 * CAN Initialization
 ******************************************/
void CAN_Initialization(void) {
    CAN_0_GpioInit();
    CAN_1_GpioInit();

    /* CAN enable */
    NT_CAN->CLC_bit.DISR = 0;

    /* Wait CAN on */
	while ((NT_CAN->CLC_bit.DISS) & (NT_CAN->PANCTR_bit.PANCMD)) ;

	NT_CAN->FDR = (0x1 << CAN_FDR_DM_Pos) |
			      (0x3FF << CAN_FDR_STEP_Pos); // normal divider mode

	// Enable the change configuration of the CAN node's
	// CAN0 and CAN1 are disconnected from the bus
	NT_CAN->CAN_Node[0].NCR  = CAN_NCR_CCE_Msk | CAN_NCR_INIT_Msk;
	NT_CAN->CAN_Node[0].NBTR = (0x1 << CAN_NBTR_TSEG2_Pos) | (0x6 << CAN_NBTR_TSEG1_Pos) |
						       (0x0 << CAN_NBTR_SJW_Pos)   | (0x9 << CAN_NBTR_BRP_Pos);

//	NT_CAN->CAN_Node[0].NPCR_bit.LBM = 1;

	NT_CAN->CAN_Node[1].NCR  = CAN_NCR_CCE_Msk | CAN_NCR_INIT_Msk;
	NT_CAN->CAN_Node[1].NBTR = (0x1 << CAN_NBTR_TSEG2_Pos) | (0x6 << CAN_NBTR_TSEG1_Pos) |
						       (0x0 << CAN_NBTR_SJW_Pos)   | (0x9 << CAN_NBTR_BRP_Pos);

//	NT_CAN->CAN_Node[1].NPCR_bit.LBM = 1;

	// CAN0, CAN1 is connected with the bus, node's interrupts are enable
	NT_CAN->CAN_Node[0].NCR = CAN_NCR_TRIE_Msk;
	NT_CAN->CAN_Node[1].NCR = CAN_NCR_TRIE_Msk;

	// choosing number lines for node's interrupts
	NT_CAN->CAN_Node[0].NIPR = (0xC << CAN_NIPR_TRINP_Pos);
	NT_CAN->CAN_Node[1].NIPR = (0xF << CAN_NIPR_TRINP_Pos);

	// Энвик interrupts
	Энвик_EnableIRQ(CAN12_IRQn);
	Энвик_EnableIRQ(CAN15_IRQn);
}

/*******************************************
 * GPIO Initialization for CAN 0
 ******************************************/
void CAN_0_GpioInit(void) {
    GPIO_Init_TypeDef GPIO_InitStruct;

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AltFunc;
    GPIO_InitStruct.GPIO_AltFunc = GPIO_AltFunc_1;

    /* E2 : RX */
    GPIO_InitStruct.GPIO_Out = GPIO_Out_Dis;
    GPIO_InitStruct.GPIO_Dir = GPIO_Dir_In;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(NT_GPIOE, &GPIO_InitStruct);

    /* G7 : TX */
    GPIO_InitStruct.GPIO_Out = GPIO_Out_En;
    GPIO_InitStruct.GPIO_Dir = GPIO_Dir_Out;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
    GPIO_Init(NT_GPIOG, &GPIO_InitStruct);
}

/*******************************************
 * GPIO Initialization for CAN 1
 ******************************************/
void CAN_1_GpioInit(void) {
    GPIO_Init_TypeDef GPIO_InitStruct;

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AltFunc;
    GPIO_InitStruct.GPIO_AltFunc = GPIO_AltFunc_1;

    /* F14 : TX */
    GPIO_InitStruct.GPIO_Out = GPIO_Out_En;
    GPIO_InitStruct.GPIO_Dir = GPIO_Dir_Out;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
    GPIO_Init(NT_GPIOF, &GPIO_InitStruct);

    /* F15 : RX */
    GPIO_InitStruct.GPIO_Out = GPIO_Out_Dis;
    GPIO_InitStruct.GPIO_Dir = GPIO_Dir_In;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
    GPIO_Init(NT_GPIOF, &GPIO_InitStruct);
}
Функции пересылки данных | Показать

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

/*******************************************
 * CAN service functions
 ******************************************/
void CAN_Object_Location(uint32_t obj_first_num, uint32_t obj_last_num,
                         uint32_t list_num)
{
    unsigned int x;

    // LOCATION OBJECTS TO THE LISTS
    for (x = obj_first_num; x <= obj_last_num; x++) {
        // PANCMD_field=0x02-static location objects to one of the CAN-lists
        NT_CAN->PANCTR = (0x2 << CAN_PANCTR_PANCMD_Pos) |
                      (x << CAN_PANCTR_PANAR1_Pos) |
                      (list_num << CAN_PANCTR_PANAR2_Pos);

        while ((NT_CAN->PANCTR_bit.BUSY) | (NT_CAN->PANCTR_bit.RBUSY)) {
        };
    }
}

void CAN_Object_Config(uint32_t obj_num, CAN_Operation_TypeDef op_type,
                       CAN_Message_TypeDef msg_type)
{
    if (op_type == CAN_OPERATION_TX) {
		
        if (msg_type == CAN_MESSAGE_COMMON)
            NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_SETDIR_Msk |
                                         CAN_MOCTR_SETTXEN0_Msk |
                                         CAN_MOCTR_SETTXEN1_Msk;
        else if (msg_type == CAN_MESSAGE_REMOTE)
            NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_RESDIR_Msk |
                                         CAN_MOCTR_SETTXEN0_Msk |
                                         CAN_MOCTR_SETTXEN1_Msk;
										 
    } else if (op_type == CAN_OPERATION_RX) {
		
        if (msg_type == CAN_MESSAGE_COMMON)
            NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_RESDIR_Msk | CAN_MOCTR_SETRXEN_Msk;
        else if (msg_type == CAN_MESSAGE_REMOTE)
            NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_SETDIR_Msk | CAN_MOCTR_SETRXEN_Msk;
		
    } else if (op_type == CAN_OPERATION_TXRX) {
		
        if (msg_type == CAN_MESSAGE_COMMON)
            NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_SETDIR_Msk | CAN_MOCTR_SETTXEN0_Msk |
                                         CAN_MOCTR_SETTXEN1_Msk | CAN_MOCTR_SETRXEN_Msk;
        else if (msg_type == CAN_MESSAGE_REMOTE)
            NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_RESDIR_Msk | CAN_MOCTR_SETTXEN0_Msk |
                                         CAN_MOCTR_SETTXEN1_Msk | CAN_MOCTR_SETRXEN_Msk;
										 
    }
}

void CAN_Object_Transmit(uint32_t obj_num)
{
    NT_CAN->CAN_Msg[obj_num].MOCTR = CAN_MOCTR_SETTXRQ_Msk | CAN_MOCTR_SETMSGVAL_Msk;
}

/*******************************************
 * CAN Write data
 ******************************************/
void CAN_write(int CAN_ch, uint32_t ide, uint32_t data_L, uint32_t data_H) {
    uint32_t temp_MOAR;

    while (NT_CAN->PANCTR_bit.BUSY) ;

    if (CAN_ch == 1) {
    	// Location 0 object to the 2 list (1 node)
    	CAN_Object_Location(0, 0, 2);
    	NT_CAN->CAN_Msg[0].MODATAL = data_L;
    	NT_CAN->CAN_Msg[0].MODATAH = data_H;
    } else {
    	// Location 58 object to the 1 list (0 node)
    	CAN_Object_Location(58, 58, 1);
        NT_CAN->CAN_Msg[58].MODATAL = data_L;
        NT_CAN->CAN_Msg[58].MODATAH = data_H;

        NT_CAN->CAN_Node[0].NCR = CAN_NCR_TRIE_Msk;
    }


    temp_MOAR = (0x2 << CAN_MOAR_PRI_Pos) |       // filtration by identifier
                CAN_MOAR_IDE_Msk | ide;           // extended identifier

    if (CAN_ch == 1) {
    	CAN_Object_Config(0, CAN_OPERATION_TX, CAN_MESSAGE_COMMON);
		NT_CAN->CAN_Msg[0].MOAR = temp_MOAR;
		
		// Set lenth of data in the CAN-object, enable interrupts
		NT_CAN->CAN_Msg[0].MOFCR =(0x8 << CAN_MOFCR_DLC_Pos) | CAN_MOFCR_TXIE_Msk | CAN_MOFCR_RXIE_Msk;
		CAN_Object_Transmit(0);
    } else {
    	CAN_Object_Config(58, CAN_OPERATION_TX, CAN_MESSAGE_COMMON);
		NT_CAN->CAN_Msg[58].MOAR = temp_MOAR;
		
		// Set lenth of data in the CAN-object, enable interrupts
		NT_CAN->CAN_Msg[58].MOFCR =(0x8 << CAN_MOFCR_DLC_Pos) | CAN_MOFCR_TXIE_Msk | CAN_MOFCR_RXIE_Msk;
		CAN_Object_Transmit(58);
    }
}
Отправка данных

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

    	CAN_write(0, 0x333, 0xfedcba98, 0x76543210);
    	CAN_write(1, 0x334, 0x67452301, 0xefcdab89);
При отправке данных по CAN1 данные успешно передаются, а по CAN0 данных нет, при этом в регистре NCR устанавливается INIT, а в регистре NSR в поле LEC устанавливается код ошибки 5.
Если оба модуля CAN подключить на внутреннюю шину (установить биты LBM регистров NPCRx), то ошибок не возникает, передача проходит корректно (устанавливается бит TXOK в регистре NSR). Если на внутреннюю шину подключить только модуль CAN0, то при передаче в поле LEC устанавливается код ошибки 3 (что в общем-то тоже корректно, так как в этом случае ACK слать некому).

Подскажите, что я делаю не так? Почему мне не удаётся заставить работать CAN0?
dav
Сообщения: 208
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

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

Сообщение dav »

atom писал(а): 24 май 2021, 14:31 Пытаюсь запустить работу двух модулей CAN (CAN0 на пинах G7/E2, CAN1 на пинах F14/F15).

При отправке данных по CAN1 данные успешно передаются, а по CAN0 данных нет, при этом в регистре NCR устанавливается INIT, а в регистре NSR в поле LEC устанавливается код ошибки 5.
Если оба модуля CAN подключить на внутреннюю шину (установить биты LBM регистров NPCRx), то ошибок не возникает, передача проходит корректно (устанавливается бит TXOK в регистре NSR). Если на внутреннюю шину подключить только модуль CAN0, то при передаче в поле LEC устанавливается код ошибки 3 (что в общем-то тоже корректно, так как в этом случае ACK слать некому).

Подскажите, что я делаю не так? Почему мне не удаётся заставить работать CAN0?
Доброго времени суток!
Код ошибки 5 в поле LEC говорит об отсутствии связи. Проверьте, на линии CAN установлен терминальный резистор номиналом 120 Ом?
Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

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

Сообщение atom »

dav писал(а): 25 май 2021, 16:53 Доброго времени суток!
Код ошибки 5 в поле LEC говорит об отсутствии связи. Проверьте, на линии CAN установлен терминальный резистор номиналом 120 Ом?
Да, резистор установлен. Замечу, что CAN1 подключен к той же самой шине и отлично работает.
dav
Сообщения: 208
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

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

Сообщение dav »

Сергей писал(а): 20 май 2021, 15:45 Таким образом передается 20000 единиц данных 32 разрядных,
при этом не все данные доходят до адресата.
1. В чем может быть проблема? Что делаю не так?
Прерывание FIFO генерируется, когда указатель на текущую область CUR достигает значения поля TOP, то есть перед передачей последнего объекта из списка FIFO.

В обработке этого прерывания по программе перезагружаются данные в регистрах и флаги на передачу вспомогательных объектов FIFO, в том числе и того самого, последнего(32-го). В результате возникают ошибки.
Поэтому, для перезагрузки данных и флагов на передачу предлагаем использовать прерывание на передачу последнего(32-го) вспомогательного объекта fifo.
Пример настройки прерывания по передачи последнего (32) слова:

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

NT_CAN.CAN_MSG[32].MOIPR.bit.TXINP = 2; // Для примера выбрана 2-я линия прерываний
Пример кода обработчика для 2-ой линии прерываний:

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

void CAN2_IRQHandler(void)
{
//При возникновении прерывания делается следующее:
//загружаются данные в регистры данных объектов и инициируется передача
  for(uint32_t ind = 0; ind < 20; ind++)
  NT_CAN.CAN_MSG[ind + 13].MOCTR.all = MOCTR_TXRQ_SET;
  //если больше не нужно отправлять данные то просто выходим из прерывания.
}
Аватара пользователя
atom
Сообщения: 11
Зарегистрирован: 26 фев 2016, 11:03
Предприятие: Алмаз-Фазотрон
Откуда: Саратов

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

Сообщение atom »

atom писал(а): 24 май 2021, 14:31 Подскажите, что я делаю не так? Почему мне не удаётся заставить работать CAN0?
Проблема была в приёмопередатчике CAN. После его замены всё заработало
serg_vega
Сообщения: 96
Зарегистрирован: 20 июл 2020, 15:50
Предприятие: АО "ВНИИ "Вега"

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

Сообщение serg_vega »

Читаю РП, раздел CAN формула 18.1. fin = n×Ntq, это что? Частота в Герцах равна времени в секундах? Где взять расчет скорости работы CAN? Подаем 100МГц, ставим STEP= 0x3ff; скорость равна 1МБит/сек. Так? А если я хочу нестандартную, напимер 666кБит/сек, то что? Из подаренного мне примера К1921ВК01Т_MultiCan видно что в нормальном режиме поддерживаются 500кБит/сек, 250 и 125. Как они получаются?
dav
Сообщения: 208
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

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

Сообщение dav »

serg_vega писал(а): 12 июл 2021, 15:01 Читаю РП, раздел CAN формула 18.1. fin = n×Ntq, это что? Частота в Герцах равна времени в секундах? Где взять расчет скорости работы CAN? Подаем 100МГц, ставим STEP= 0x3ff; скорость равна 1МБит/сек. Так? А если я хочу нестандартную, напимер 666кБит/сек, то что? Из подаренного мне примера К1921ВК01Т_MultiCan видно что в нормальном режиме поддерживаются 500кБит/сек, 250 и 125. Как они получаются?
Доброго времени суток!
В формуле 18.1 допущены неточности. Более корректно следующее: Tin = n * tq, где Tin - период сигнала тактирования CAN. Основной смысл формулы изложен в первом предложении: "Задаваемое значение входной частоты fin зависит от длительности передачи одного бита информации и должно быть n-кратно ей..."

Примеры расчета частот для CAN можно посмотреть в теме К1921ВК01Т, 1921ВК01Т1 - FAQ: viewtopic.php?f=37&t=931&p=4582#p4582
serg_vega
Сообщения: 96
Зарегистрирован: 20 июл 2020, 15:50
Предприятие: АО "ВНИИ "Вега"

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

Сообщение serg_vega »

Скажите, а Вы LBM (петлю) сами пробовали? Она работает?
serg_vega
Сообщения: 96
Зарегистрирован: 20 июл 2020, 15:50
Предприятие: АО "ВНИИ "Вега"

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

Сообщение serg_vega »

Вот я взял проект из папочки NIIET_Examples/can, заменил в нем ноги на B14 - CAN0_TX, B15 - CAN0_RX; F14 - CAN1_TX, F15 - CAN1_RX, добавил
NT_CAN->CAN_Node[0].NPCR=1<<CAN_NPCR_LBM_Pos; // Loop back mode
NT_CAN->CAN_Node[1].NPCR=1<<CAN_NPCR_LBM_Pos; // Loop back mode,
так как на плате вектора только один CAN, скомпилировал и.... не работает. Просто не входит в прерывания по CAN. Что я делаю не так?!!!
Ответить

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