Пытаюсь запустить работу двух модулей 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?