Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ ARM _ Посылка по CAN в STM32F3

Автор: Jenya7 Aug 17 2018, 09:56

Настраиваю CAN

CODE
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;
CODE
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;
}
Если принимающая сторона не приняла мейлбокс он не освободился ?

Автор: Obam Aug 17 2018, 15:47

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

Автор: esaulenka Aug 17 2018, 16:02

Цитата(Obam @ Aug 17 2018, 18:47) *
листинг ... - перебор

Листинг - это единственная полезная часть исходного сообщения.
Если его выкинуть (спрятать), останется просто бессмысленное "у меня не работает".

Автор: x893 Aug 17 2018, 18:20

Цитата(Jenya7 @ Aug 17 2018, 12:56) *
Настраиваю
...
Если принимающая сторона не приняла мейлбокс он не освободился ?

Да

Автор: Jenya7 Aug 19 2018, 07:31

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

Код
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 и не вижу никаких выходящих сигналов. что происходит? кто может объяснить?

Автор: Jenya7 Sep 13 2018, 13:02

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;
}


Автор: Jenya7 Sep 17 2018, 04:59

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

Автор: Alechek Sep 17 2018, 05:27

Цитата(Jenya7 @ Sep 17 2018, 09:59) *
Другая проблема. При приеме слейв через какое то время отсыхает. Я смотрю на ESR и вижу что TEC увеличивается при каждом принятии пакета, хотя данные пришли, иногда уменьшается но чаще увеличивается. Когда TEC = 0xFF прием отсыхает и LEC = 5.

Ничего тут не напутано? На прием REC работает, на передачу TEC.
Сдается мне, что физически что-то как-то не так подключено.
Физический интерфейс имеется?
Резистор в линии имеется?

Автор: Jenya7 Sep 17 2018, 06:04

Цитата(Alechek @ Sep 17 2018, 10:27) *
Ничего тут не напутано? На прием REC работает, на передачу TEC.
Сдается мне, что физически что-то как-то не так подключено.
Физический интерфейс имеется?
Резистор в линии имеется?


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

Автор: Alechek Sep 17 2018, 10:11

Цитата(Jenya7 @ Sep 17 2018, 11:04) *

CAN контроллер всегда слушает линию. Если вдруг в линии не то, что мы ожидали (коллизия), передатчик сообщает об ошибке.
Доминатное состояние достигается за счет драйвера, рецессивное за счет нагрузки в линии.
Для подтверждения приема служит бит ACK, его генерирует приемник, он контролируется передатчиком.
Передатчик по-умолчанию будет посылать сообщение, пока его кто-нибудь не примет (или достигнется лимит TEC)

Контроллер в STM32 можно настроить так, чтобы сообщение он принял, а АСК бит не выдал и даже не проконтролировал!
Полагаю, где-то тут ваш случай.

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

Автор: Jenya7 Sep 17 2018, 10:35

Цитата(Alechek @ Sep 17 2018, 15:11) *
CAN контроллер всегда слушает линию. Если вдруг в линии не то, что мы ожидали (коллизия), передатчик сообщает об ошибке.
Доминатное состояние достигается за счет драйвера, рецессивное за счет нагрузки в линии.
Для подтверждения приема служит бит ACK, его генерирует приемник, он контролируется передатчиком.
Передатчик по-умолчанию будет посылать сообщение, пока его кто-нибудь не примет (или достигнется лимит TEC)

Контроллер в STM32 можно настроить так, чтобы сообщение он принял, а АСК бит не выдал и даже не проконтролировал!
Полагаю, где-то тут ваш случай.

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


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

Автор: редактор Sep 17 2018, 12:47

Цитата
я что то не нашел где там АСК отменить
wacko.gif
Почитайте спецификацию на CAN?хотя бы в русском переводе.

Автор: Jenya7 Sep 17 2018, 14:11

Цитата(редактор @ Sep 17 2018, 17:47) *
wacko.gif
Почитайте спецификацию на CAN?хотя бы в русском переводе.


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

Автор: adnega Sep 17 2018, 18:48

Цитата(Jenya7 @ Sep 17 2018, 17:11) *
там регистров с гулькин нос. все биты просмотрел.

Может, это
Цитата
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).

Автор: Jenya7 Sep 18 2018, 04:49

Цитата(adnega @ Sep 18 2018, 00:48) *
Может, это


спасибо. попробую.

Автор: Jenya7 Sep 21 2018, 07:21

фигня какая то с этим КАНом.
Прием на мастере и слейве одинаковый

Код
void USB_LP_CAN1_RX0_IRQHandler(void)
{
     can_params.message_received = 1;
     can_params.fifo_num = CAN_FIFO0;
  
      CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
}
посылка тоже
Код
uint8_t CAN_TX(uint8_t mot_id, uint8_t opcode, uint8_t *data, uint32_t data_size)
{
     uint8_t mailbox_num;
    
     TxMessage.RTR = CAN_RTR_DATA;
     TxMessage.IDE = CAN_ID_EXT;  
     TxMessage.ExtId = (opcode << 8) | mot_id;
    
     if (data_size > 8)
         data_size = 8;
    
     TxMessage.DLC = data_size;
     memcpy(&TxMessage.Data[0], data, data_size);
     mailbox_num = CAN_Transmit(CANx, &TxMessage);
    
     return mailbox_num;
}
мастер посылает
Код
void main (void)
{    while(1)    
      {    
          CAN_TX(100, MASTER_COM_WHO_IS, can_data_buf, 0);
      }
}
я вижу четкий прием
Код
void CAN_TX_Slave(uint32_t opcode)
{    
          switch (opcode)    
     {          
             //я сюда попадаю
             case CAN_COM_WHO_IS :
                 size = 0;        
                             //посылка ответа
                  CAN_TX(motor_sys_params.mot_id, CAN_COM_I_AM, data, 0);
             break;
     }
}
но мастер в прерывание приема не заходит. я ставлю паузу на мастере - и тогда он заходит в прерывание приема.
это что мастер должен освободить шину чтоб получить ответ?

в какой то момент на слейве вдруг TEC = 0xFF REC = 0xFF и он отсыхает несмотря на то что CAN1->BTR |= CAN_BTR_SILM;

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

 

Автор: esaulenka Sep 21 2018, 13:04

Не, я понимаю, что читать спецификации не модно, если можно фигачить код и писать вопросы в интернетах...

Но, всё-таки
1) чем вы руководствовались при запуске непрерывной передачи без малейших пауз?
2) слышали ли вы что-то о ACK'ах в кан-шине? И если да, то задумывались ли, кто же будет их выдавать?

Автор: Jenya7 Sep 21 2018, 13:49

Цитата(esaulenka @ Sep 21 2018, 18:04) *
Не, я понимаю, что читать спецификации не модно, если можно фигачить код и писать вопросы в интернетах...

Но, всё-таки
1) чем вы руководствовались при запуске непрерывной передачи без малейших пауз?
2) слышали ли вы что-то о ACK'ах в кан-шине? И если да, то задумывались ли, кто же будет их выдавать?


вобще то на вехнем уровне я жду ответа от слейва. а кроме того USB-CAN Plus молотит тоже без перерыва однако с ним все нормально.
насчет ACK'а я не понял из документации. это же происходит на автоматическом уровне.

и вообще можно без туманностей и напыщенности? а так по нашему по бразильски по человечески.

я помню был проект. правда на TI Delfino. но там пять узлов молотили каждый как бог на душу положит без согласований и арбитражей. и ничего. все получали свои пакеты и я не помню чтоб КАН когда то отсох.

Автор: Alechek Sep 21 2018, 14:17

Цитата(Jenya7 @ Sep 21 2018, 18:49) *
а так по нашему по бразильски по человечески.

По-человечески - возьмите осциллограф или хотя бы лог. анализатор типа клон Saleae Logic.
Возмущений много, а схемы подключения - 0.
Где анализ целостности сигналов?

То что принял один - не значит, что примет другой!

ФИЗИЧЕСКИ что на линии?

--
UPD: Так еще и линия 1 Мбит!
Откуда тактирование? Кварц или RC?
Скорость пробовали уменьшать?
с BTR регистром пробовали играться?

Автор: Jenya7 Sep 21 2018, 14:26

Цитата(Alechek @ Sep 21 2018, 19:17) *
По-человечески - возьмите осциллограф или хотя бы лог. анализатор типа клон Saleae Logic.
Возмущений много, а схемы подключения - 0.
Где анализ целостности сигналов?

То что принял один - не значит, что примет другой!

ФИЗИЧЕСКИ что на линии?


осциллограф показывает обычные пакеты. когда есть ошибки USB-CAN Plus сигнализирует.

ну я вообще то вижу правильные данные при принятии. а что 1 Мбит это большая нагрузка на линию?

тактирование внешний кварц. а BTR с ST примеров. они точно лучше меня знают как его выставлять.

 

Автор: Jenya7 Sep 28 2018, 07:53

ОК. вроде заработало.

настраиваю маску на слейве

Код
    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 = 0x0064;    
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x00FF;
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInit(&CAN_FilterInitStructure);

мастер посылает
Код
TxMessage.ExtId = (opcode << 8) | 0х64;

однако слейв не принимает. без маски и фильтра принимает.

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)