Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите запустить CAN в STM32
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Volldemar
Имеется в наличии две платы с установленными ф205 и ф207. На плате ф207 установлен кварц 25мег, на плате ф205 - 8 мег. Необходимые изменения для умножителей/делителей произведены для получения тактовой ядра 120 мег. На ф207 используется КАН1, на ф205 - КАН2. Трминальные резисторы (120 Ом) висят на концах шины. В режиме CAN_Mode_LoopBack на 207-м происходит вход в прерывание приема, по идее пакеты в шину должны летать и срабатывать прерывание по приему и на 205-м, НО этого не происходит. Прикрепляю файл по расчету коэфициентов, у кого есть возможность, проверте пожалуйста в реальном железе.
Что не правильно денлаю?
дефайны:
CODE
#define CAN1_RCC RCC_APB1Periph_CAN1
#define CAN1_RX_PIN GPIO_Pin_0
#define CAN1_TX_PIN GPIO_Pin_1
#define CAN1_GPIO_PORT GPIOD
#define CAN1_GPIO_RCC RCC_AHB1Periph_GPIOD
#define CAN1_AF_PORT GPIO_AF_CAN1
#define CAN1_RX_SOURCE GPIO_PinSource0
#define CAN1_TX_SOURCE GPIO_PinSource1

#define CAN2_RCC (RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2)
#define CAN2_RX_PIN GPIO_Pin_5
#define CAN2_TX_PIN GPIO_Pin_13
#define CAN2_GPIO_PORT GPIOB
#define CAN2_GPIO_RCC RCC_AHB1Periph_GPIOB
#define CAN2_AF_PORT GPIO_AF_CAN2
#define CAN2_RX_SOURCE GPIO_PinSource5
#define CAN2_TX_SOURCE GPIO_PinSource13

#define MASTER_START_BANK 0
#define SLAVE_START_BANK 14


инит КАН1:
CODE
uint8_t can1_Init(void)
/******************************************************************************
Initialize CAN
INPUT
OUTPUT
******************************************************************************/
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

uint8_t RetStatus;

CAN1_RX0_xQueue = xQueueCreate( 32, sizeof( CanRxMsg ) );
CAN1_RX1_xQueue = xQueueCreate( 32, sizeof( CanRxMsg ) );
CAN1_TX_xQueue = xQueueCreate( 32, sizeof( CanTxMsg ) );

// Enable GPIO clock
RCC_AHB1PeriphClockCmd(CAN1_GPIO_RCC, ENABLE);

// Connect CAN pins to AF9
GPIO_PinAFConfig(CAN1_GPIO_PORT, CAN1_RX_SOURCE, CAN1_AF_PORT);
GPIO_PinAFConfig(CAN1_GPIO_PORT, CAN1_TX_SOURCE, CAN1_AF_PORT);

// Configure CAN RX and TX pins
GPIO_InitStructure.GPIO_Pin = CAN1_RX_PIN | CAN1_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(CAN1_GPIO_PORT, &GPIO_InitStructure);

// CAN configuration
// Enable CAN clock
RCC_APB1PeriphClockCmd(CAN1_RCC, ENABLE);

// CAN register init
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);

CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;//ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;//ENABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
// CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;

//250KBps (CAN 30MHz)
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
CAN_InitStructure.CAN_Prescaler = 11;

RetStatus = CAN_Init(CAN1, &CAN_InitStructure);
if(RetStatus == CAN_InitStatus_Failed)
{
debug_printf("\r\nRetStatus = 0x%xh", RetStatus);
debug_printf("\r\nCAN1_InitStatus_Failed");
return RetStatus;
}
else
{
debug_printf("\r\nRetStatus = 0x%xh", RetStatus);
debug_printf("\r\nCAN1 initial as CAN_Mode_Normal success");
RetStatus=1;
}

//Filter Configuration
CAN_FilterInitStructure.CAN_FilterNumber = MASTER_START_BANK;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;//0xFFFF;//0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;//0xFFFF;//0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

return RetStatus;
}


инит КАН2:
CODE
uint8_t can2_Init(void)
/******************************************************************************
Initialize CAN2
INPUT
OUTPUT = 0-filed; 1- ok
******************************************************************************/
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

uint8_t RetStatus;

CAN2_RX0_xQueue = xQueueCreate( 32, sizeof( CanRxMsg ) );
CAN2_RX1_xQueue = xQueueCreate( 32, sizeof( CanRxMsg ) );
CAN2_TX_xQueue = xQueueCreate( 32, sizeof( CanTxMsg ) );

// Enable GPIO clock
RCC_AHB1PeriphClockCmd(CAN2_GPIO_RCC, ENABLE);

// Configure CAN RX and TX pins
GPIO_InitStructure.GPIO_Pin = CAN2_RX_PIN | CAN2_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(CAN2_GPIO_PORT, &GPIO_InitStructure);

// Connect CAN pins to AF9
GPIO_PinAFConfig(CAN2_GPIO_PORT, CAN2_RX_SOURCE, CAN2_AF_PORT);
GPIO_PinAFConfig(CAN2_GPIO_PORT, CAN2_TX_SOURCE, CAN2_AF_PORT);

// CAN configuration
// Enable CAN clock
RCC_APB1PeriphClockCmd(CAN2_RCC, ENABLE);

// CAN register init
CAN_DeInit(CAN2);
CAN_StructInit(&CAN_InitStructure);

CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = ENABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = ENABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

//500KBps (CAN 30MHz)
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_Prescaler = 4;

RetStatus = CAN_Init(CAN2, &CAN_InitStructure);
if(RetStatus == CAN_InitStatus_Failed)
{
debug_printf("\r\nRetStatus = 0x%xh", RetStatus);
debug_printf("\r\nCAN2_InitStatus_Failed");
return RetStatus;
}
else
{
debug_printf("\r\nRetStatus = 0x%xh", RetStatus);
debug_printf("\r\nCAN2 initial as CAN_Mode_Normal=success");
RetStatus=1;
}

//Filter Configuration
CAN_FilterInitStructure.CAN_FilterNumber = SLAVE_START_BANK;// 0..13 for CAN1, 14..27 for CAN2
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);

NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ITConfig(CAN2, CAN_IT_FMP1, ENABLE);

NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY - 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
CAN_ITConfig(CAN2, CAN_IT_TME, ENABLE);

return RetStatus;
}


Обработчики аналогичные для обоих КАНов:
CODE
void CAN1_RX0_IRQHandler (void)
{
debug_printf("\n\rCAN1_RX0_IRQHandler--OK");

portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

static CanRxMsg RxMsg;

memset(&RxMsg, 0, sizeof(CanRxMsg));

if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET)
{
CAN_Receive(CAN1, CAN_FIFO0, &RxMsg);
xQueueSendFromISR( CAN1_RX0_xQueue, ( void * ) &RxMsg, &xHigherPriorityTaskWoken );
}

debug_printf("\n\rCAN1_RX0_IRQHandler--exit");
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}

Уменя уже идеи кончилисиь, вот и обращаюсь к сообществуза помощью. Ранее тема подымалась аналогичная, изучал, сверял, но "воз и ныне там"...

UP. добавил код инит КАН2
В тактировании учтено, подача клоков и на КАН1, при инициализации КАН2:
#define CAN2_RCC (RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2)
adnega
Цитата(Volldemar @ Jan 28 2014, 17:59) *
Что не правильно денлаю?

Поскольку инициализация для неработающего CAN2 не приведена, осмелюсь предположить, что для CAN2 не настроены фильтры (в CAN1).
demiurg_spb
Где-то проскакивало, что CAN2 не может работать без включения тактирования CAN1.
Volldemar
Цитата(demiurg_spb @ Jan 29 2014, 07:35) *
Где-то проскакивало, что CAN2 не может работать без включения тактирования CAN1.

В тактировании учтено, подача клоков и на КАН1, при инициализации КАН2:
#define CAN2_RCC (RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2)
И попутно вопрос к сообществу, если одно устройство будет в режиме CAN_Mode_LoopBack, то второе устройство на шине должно принимать КАН пакеты (при условии, что второе устройство в CAN_Mode_Normal режиме)?
x893
Цитата(Volldemar @ Jan 29 2014, 12:48) *
В тактировании учтено, подача клоков и на КАН1, при инициализации КАН2:
#define CAN2_RCC (RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2)
И попутно вопрос к сообществу, если одно устройство будет в режиме CAN_Mode_LoopBack, то второе устройство на шине должно принимать КАН пакеты (при условии, что второе устройство в CAN_Mode_Normal режиме)?

Нет

В Keil создайте проект с STM32F217IG и смотрите регистры CAN
Нажмите для просмотра прикрепленного файла
Volldemar
Ок, скачиваю кейл, попробую в нём разобраться...
Volldemar
После очередных экспериментов, выяснил следующее, что модуль КАН не получает пины в работу и нет доступа наружу проца,. Вроде иниты пинов правильные....
Кто может просмотрите код инита пинов, н делал же по примерам от СТбиблы...
Log_in
А почему у Вас CAN1 и CAN2 настроены на разные скорости?
Volldemar
Вот мой "запускатор" прерывания на передачу:
Код
uint8_t CAN1_Put( CanTxMsg* TxMess )
{
   uint8_t xReturn;
   if( xQueueSend( CAN1_TX_xQueue, &TxMess, 10 ) == pdPASS )
      {
         xReturn = pdPASS;
         CAN_ITConfig(CAN1, CAN_IT_TME,  ENABLE);
      }
   else
      {
         xReturn = pdFAIL;
      }

   return xReturn;
}


В мейне делаю вот так:
Код
CAN1_Put(&TxMessage);


Ранее объявлена очередь для отправки:
Код
CAN1_TX_xQueue = xQueueCreate( 32, sizeof( CanTxMsg ) );


Прерывание на передачу не срабатывает, что я делаю не так?
Golikov A.
есть кому принять сообщение?
без ответчика будет перезапуск постоянный
Volldemar
Цитата(Golikov A. @ Feb 4 2014, 19:44) *
есть кому принять сообщение?
без ответчика будет перезапуск постоянный

Устройства на шине два, так что принять сообщение есть кому. Если отправлять КАН пакеты без прерываний - отправляются, и получатель получает (на приемной стороне срабатывает прерывание на прём).
x893
Цитата(Volldemar @ Feb 4 2014, 22:15) *
Устройства на шине два, так что принять сообщение есть кому. Если отправлять КАН пакеты без прерываний - отправляются, и получатель получает (на приемной стороне срабатывает прерывание на прём).

Рекомендую прочитать Reference Manual

IT_TME это не прерывание от того что пустой буфер,
это прерывание что один из mailbox может принять данные после обработки (RQCPx)
Логика программы другая чем для USART

Система конечно у STM2-4 не удобная, но что есть то есть
Volldemar
Цитата(x893 @ Feb 9 2014, 01:16) *
Рекомендую прочитать Reference Manual

IT_TME это не прерывание от того что пустой буфер,
это прерывание что один из mailbox может принять данные после обработки (RQCPx)
Логика программы другая чем для USART

Система конечно у STM2-4 не удобная, но что есть то есть

Референс перечитал, там написано следующее, цитирую: "Transmit mailbox 0 becomes empty, RQCP0 bit in the CAN_TSR register set."
Что в моём понимании, т.е. после моего перевода, означает следующее: "передающий майбокс 0 становится пустым и RQCP0 бит в регистре CAN_TSR устанавливаетсяв 1", что собственно и генерит прерывание на передачу. так получается вроде делаю правильно...
Если есть опыт и делали уже такое, подскажите, где косяк???help.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.