Перейти к содержанию
    

Настраиваю CAN

void CAN_Setup(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;
NVIC_InitTypeDef  NVIC_InitStructure;
CAN_InitTypeDef		CAN_InitStructure;
CAN_FilterInitTypeDef  CAN_FilterInitStructure;

/* CAN GPIOs configuration **************************************************/

/* Enable GPIO clock */
RCC->AHBENR |= RCC_AHBPeriph_GPIOB;

/* Connect CAN pins to AF9 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_9);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_9); 

/* Configure CAN RX and TX pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8| GPIO_Pin_9;
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(CAN_GPIO_PORT, &GPIO_InitStructure);

/* NVIC configuration *******************************************************/
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

 /* CAN configuration ********************************************************/  
 /* Enable CAN clock */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

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

 // CAN cell init 
 CAN_InitStructure.CAN_TTCM = DISABLE;
 CAN_InitStructure.CAN_ABOM = DISABLE;
 CAN_InitStructure.CAN_AWUM = DISABLE;
 CAN_InitStructure.CAN_NART = DISABLE;
 CAN_InitStructure.CAN_RFLM = DISABLE;
 CAN_InitStructure.CAN_TXFP = DISABLE;
 CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

 /* CAN Baudrate = 1MBps (CAN clocked at 36 MHz) */
 CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;
 CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
 CAN_InitStructure.CAN_Prescaler = 2;
 CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
 //CAN_InitStructure.CAN_BS1 = CAN_BS1_3tq;
 //CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;
 //CAN_InitStructure.CAN_Prescaler = 39;	  
 //CAN_InitStructure.CAN_SJW = 2;

 CAN_Init(CANx, &CAN_InitStructure);

 /* CAN filter init */
 CAN_FilterInitStructure.CAN_FilterNumber = 0;
 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 = 0;
 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
 CAN_FilterInit(&CAN_FilterInitStructure);

 /* Enable FIFO 0 message pending Interrupt */
 CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
 /* Enable FIFO 1 message pending Interrupt */
 CAN_ITConfig(CANx, CAN_IT_FMP1, ENABLE);
}

Посылаю

    TxMessage.StdId = ( (0x100 *(i+1)) + CAN_COM_WHO_IS);
    TxMessage.DLC = 1;
    TxMessage.RTR = CAN_RTR_DATA;
    TxMessage.IDE = CAN_ID_STD;
     CAN_Transmit(CAN1, &TxMessage);

В функции посылки - все мейлбоксы заняты - я попадаю в transmit_mailbox = CAN_TxStatus_NoMailBox;

uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
{
 uint8_t transmit_mailbox = 0;
 /* Check the parameters */
 assert_param(IS_CAN_ALL_PERIPH(CANx));
 assert_param(IS_CAN_IDTYPE(TxMessage->IDE));
 assert_param(IS_CAN_RTR(TxMessage->RTR));
 assert_param(IS_CAN_DLC(TxMessage->DLC));

 /* Select one empty transmit mailbox */
 if ((CANx->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
 {
transmit_mailbox = 0;
 }
 else if ((CANx->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
 {
transmit_mailbox = 1;
 }
 else if ((CANx->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
 {
transmit_mailbox = 2;
 }
 else
 {
transmit_mailbox = CAN_TxStatus_NoMailBox;
 }

 if (transmit_mailbox != CAN_TxStatus_NoMailBox)
 {
/* Set up the Id */
CANx->sTxMailBox[transmit_mailbox].TIR &= TMIDxR_TXRQ;
if (TxMessage->IDE == CAN_Id_Standard)
{
  assert_param(IS_CAN_STDID(TxMessage->StdId));  
  CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->StdId << 21) | \
											  TxMessage->RTR);
}
else
{
  assert_param(IS_CAN_EXTID(TxMessage->ExtId));
  CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId << 3) | \
											  TxMessage->IDE | \
											  TxMessage->RTR);
}

/* Set up the DLC */
TxMessage->DLC &= (uint8_t)0x0000000F;
CANx->sTxMailBox[transmit_mailbox].TDTR &= (uint32_t)0xFFFFFFF0;
CANx->sTxMailBox[transmit_mailbox].TDTR |= TxMessage->DLC;

/* Set up the data field */
CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) | 
										 ((uint32_t)TxMessage->Data[2] << 16) |
										 ((uint32_t)TxMessage->Data[1] << 8) | 
										 ((uint32_t)TxMessage->Data[0]));
CANx->sTxMailBox[transmit_mailbox].TDHR = (((uint32_t)TxMessage->Data[7] << 24) | 
										 ((uint32_t)TxMessage->Data[6] << 16) |
										 ((uint32_t)TxMessage->Data[5] << 8) |
										 ((uint32_t)TxMessage->Data[4]));
/* Request transmission */
CANx->sTxMailBox[transmit_mailbox].TIR |= TMIDxR_TXRQ;
 }
 return transmit_mailbox;
}

Если принимающая сторона не приняла мейлбокс он не освободился ?

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Коллега, вы хрензнает сколько лет на форуме, листинг в (1024 по вертикали) 4 экрана - перебор. Ну хоть чуть-чуть уважения к окружающим.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

листинг ... - перебор

Листинг - это единственная полезная часть исходного сообщения.

Если его выкинуть (спрятать), останется просто бессмысленное "у меня не работает".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Настраиваю

...

Если принимающая сторона не приняла мейлбокс он не освободился ?

Да

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

для отладки я изменил случай когда все мейлбоксы заняты

else
  {
    transmit_mailbox = CAN_TxStatus_NoMailBox;
    
    //force pending messages to be sent anyway
    CANx->sTxMailBox[0].TIR |= TMIDxR_TXRQ;
    CANx->sTxMailBox[1].TIR |= TMIDxR_TXRQ;
    CANx->sTxMailBox[2].TIR |= TMIDxR_TXRQ;
  }

 

я становлюсь скопом на ножку CAN_TX и не вижу никаких выходящих сигналов. что происходит? кто может объяснить?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

CAN по прежнему не работает.Вопрос - нужно ли чистить флаги в прерывании? я за основу взял пример где флаги не чистяться.

void USB_LP_CAN1_RX0_IRQHandler(void)
{
  can_params.message_received = 1;
  can_params.fifo_num = CAN_FIFO0;
}

void CAN1_RX1_IRQHandler(void)
{
  can_params.message_received = 1;
  can_params.fifo_num = CAN_FIFO1;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

CAN заработал. надо было перемычку замкнуть на пин 8 конвертора.

Другая проблема. При приеме слейв через какое то время отсыхает. Я смотрю на ESR и вижу что TEC увеличивается при каждом принятии пакета, хотя данные пришли, иногда уменьшается но чаще увеличивается. Когда TEC = 0xFF прием отсыхает и LEC = 5.

Как бороться с этой бедой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Другая проблема. При приеме слейв через какое то время отсыхает. Я смотрю на ESR и вижу что TEC увеличивается при каждом принятии пакета, хотя данные пришли, иногда уменьшается но чаще увеличивается. Когда TEC = 0xFF прием отсыхает и LEC = 5.

Ничего тут не напутано? На прием REC работает, на передачу TEC.

Сдается мне, что физически что-то как-то не так подключено.

Физический интерфейс имеется?

Резистор в линии имеется?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ничего тут не напутано? На прием REC работает, на передачу TEC.

Сдается мне, что физически что-то как-то не так подключено.

Физический интерфейс имеется?

Резистор в линии имеется?

 

я вижу приходящие сообщения от мастера. слейв ему отвечает и ответ я тоже вижу. Вы говорите TEC - это значит слейв послал с ошибкой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

CAN контроллер всегда слушает линию. Если вдруг в линии не то, что мы ожидали (коллизия), передатчик сообщает об ошибке.

Доминатное состояние достигается за счет драйвера, рецессивное за счет нагрузки в линии.

Для подтверждения приема служит бит ACK, его генерирует приемник, он контролируется передатчиком.

Передатчик по-умолчанию будет посылать сообщение, пока его кто-нибудь не примет (или достигнется лимит TEC)

 

Контроллер в STM32 можно настроить так, чтобы сообщение он принял, а АСК бит не выдал и даже не проконтролировал!

Полагаю, где-то тут ваш случай.

 

Передачу данных очень наглядно отображает даже дешевый логический анализатор.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

CAN контроллер всегда слушает линию. Если вдруг в линии не то, что мы ожидали (коллизия), передатчик сообщает об ошибке.

Доминатное состояние достигается за счет драйвера, рецессивное за счет нагрузки в линии.

Для подтверждения приема служит бит ACK, его генерирует приемник, он контролируется передатчиком.

Передатчик по-умолчанию будет посылать сообщение, пока его кто-нибудь не примет (или достигнется лимит TEC)

 

Контроллер в STM32 можно настроить так, чтобы сообщение он принял, а АСК бит не выдал и даже не проконтролировал!

Полагаю, где-то тут ваш случай.

 

Передачу данных очень наглядно отображает даже дешевый логический анализатор.

 

с анализатором (USB-CAN Plus) мастер работает нормально. да и данными мастер-слейв вроде как обмениваются. бес его знает что там CANу не нравиться.

я что то не нашел где там АСК отменить. я отменил бесперерывную посылку (NART =1). послал один раз и все, не фиг линию грузить.

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я что то не нашел где там АСК отменить
:wacko:

Почитайте спецификацию на CAN?хотя бы в русском переводе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

:wacko:

Почитайте спецификацию на CAN?хотя бы в русском переводе.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

там регистров с гулькин нос. все биты просмотрел.

Может, это

Silent mode

The bxCAN can be put in Silent mode by setting the SILM bit in the CAN_BTR register.

In Silent mode, the bxCAN is able to receive valid data frames and valid remote frames, but

it sends only recessive bits on the CAN bus and it cannot start a transmission. If the bxCAN

has to send a dominant bit (ACK bit, overload flag, active error flag), the bit is rerouted

internally so that the CAN Core monitors this dominant bit, although the CAN bus may

remain in recessive state. Silent mode can be used to analyze the traffic on a CAN bus

without affecting it by the transmission of dominant bits (Acknowledge Bits, Error Frames).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...