|
|
  |
Помогите запустить CAN в STM32, STM32F2xx |
|
|
|
Jan 28 2014, 13:59
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Имеется в наличии две платы с установленными ф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)
Сообщение отредактировал Volldemar - Jan 29 2014, 06:40
Прикрепленные файлы
250k.7z ( 27.24 килобайт )
Кол-во скачиваний: 13
|
|
|
|
|
Jan 29 2014, 08:48
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Цитата(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 режиме)?
Сообщение отредактировал Volldemar - Jan 29 2014, 08:51
|
|
|
|
|
Feb 3 2014, 11:34
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 9-06-12
Пользователь №: 72 244

|
А почему у Вас CAN1 и CAN2 настроены на разные скорости?
|
|
|
|
|
Feb 4 2014, 14:41
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Вот мой "запускатор" прерывания на передачу: Код 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 ) ); Прерывание на передачу не срабатывает, что я делаю не так?
|
|
|
|
|
Feb 4 2014, 18:15
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Цитата(Golikov A. @ Feb 4 2014, 19:44)  есть кому принять сообщение? без ответчика будет перезапуск постоянный Устройства на шине два, так что принять сообщение есть кому. Если отправлять КАН пакеты без прерываний - отправляются, и получатель получает (на приемной стороне срабатывает прерывание на прём).
|
|
|
|
|
Feb 8 2014, 23:16
|

Профессионал
    
Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226

|
Цитата(Volldemar @ Feb 4 2014, 22:15)  Устройства на шине два, так что принять сообщение есть кому. Если отправлять КАН пакеты без прерываний - отправляются, и получатель получает (на приемной стороне срабатывает прерывание на прём). Рекомендую прочитать Reference Manual IT_TME это не прерывание от того что пустой буфер, это прерывание что один из mailbox может принять данные после обработки (RQCPx) Логика программы другая чем для USART Система конечно у STM2-4 не удобная, но что есть то есть
|
|
|
|
|
Feb 9 2014, 15:59
|
Частый гость
 
Группа: Участник
Сообщений: 121
Регистрация: 27-04-09
Из: Украина
Пользователь №: 48 342

|
Цитата(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", что собственно и генерит прерывание на передачу. так получается вроде делаю правильно... Если есть опыт и делали уже такое, подскажите, где косяк???
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|