Jump to content

    
Sign in to follow this  
DmitryDI

CAN на STM32

Recommended Posts

Все сконфигурировал как в исходниках, но не работает. Чип STM32F107, кварц 25 Мгц, Нужен 1 МГбит/c

 

Настройки

CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq;

CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;

CAN_InitStructure.CAN_Prescaler = 1;

 

Скорость = 25 МГц/(1+16+8) = 1 МГбит/c

 

Обмена данных с проверенным мастером нет. ???

Заранее спасибо за помощь.

 

конфигурация полностью

void CAN_Config(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;

 /* Configure CAN1 and CAN2 IOs **********************************************/
 /* GPIOB, GPIOD and AFIO clocks enable */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB, ENABLE);

 /* Configure CAN1 RX pin */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 GPIO_Init(GPIOD, &GPIO_InitStructure);

 /* Configure CAN2 RX pin */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
 GPIO_Init(GPIOB, &GPIO_InitStructure);

 /* Configure CAN1 TX pin */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOD, &GPIO_InitStructure);

 /* Configure CAN2 TX pin */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 GPIO_Init(GPIOB, &GPIO_InitStructure);

 /* Remap CAN1 and CAN2 GPIOs */
 GPIO_PinRemapConfig(GPIO_Remap2_CAN1 , ENABLE);
 GPIO_PinRemapConfig(GPIO_Remap_CAN2, ENABLE);

 /* Configure CAN1 and CAN2 **************************************************/  
 /* CAN1 and CAN2 Periph clocks enable */
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);  

  /* CAN1 and CAN2 register init */
 CAN_DeInit(CAN1);
 CAN_DeInit(CAN2);

 /* Struct init*/
 CAN_StructInit(&CAN_InitStructure);

 /* CAN1 and CAN2  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 = ENABLE;
 CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
 CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
 CAN_InitStructure.CAN_BS1 = CAN_BS1_16tq;
 CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
 CAN_InitStructure.CAN_Prescaler = 1;//2

 /*Initializes the CAN1  and CAN2 */
 CAN_Init(CAN1, &CAN_InitStructure);
 CAN_Init(CAN2, &CAN_InitStructure);


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

 /* CAN2 filter init */
 CAN_FilterInitStructure.CAN_FilterIdHigh =0x2460;
 CAN_FilterInitStructure.CAN_FilterNumber = 15;
 CAN_FilterInit(&CAN_FilterInitStructure);

 /* Transmit */
 TxMessage.StdId = 0x01;
 TxMessage.ExtId = 0x01;
 TxMessage.RTR = CAN_RTR_DATA;
 TxMessage.IDE = CAN_ID_STD;
 TxMessage.DLC = 8;  
}



/**
 * @brief  Configures the NVIC for CAN.
 * @param  None
 * @retval None
 */
void NVIC_Config(void)
{
 NVIC_InitTypeDef  NVIC_InitStructure;

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

 NVIC_InitStructure.NVIC_IRQChannel = 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 = CAN2_RX0_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;
 NVIC_Init(&NVIC_InitStructure);
}

int main()
{

NVIC_Config();
/* CANs configuration */
 CAN_Config();

 /* IT Configuration for CAN1 */  
 CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);

 /* IT Configuration for CAN2 */  
 CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);

  while(1)
  {
 TxMessage.Data[0] = 0x55;
  CAN_Transmit(CAN1, &TxMessage);
    Delay(1000);

  }
}

Edited by IgorKossak
Оформление кода в [codebox]

Share this post


Link to post
Share on other sites

Вот Вам кусок моей инициализации, проверял с адаптером IXXAT:

 

void CAN_Config(void)
{
 /* 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;

/* 125kb
 CAN_InitStructure.CAN_SJW = CAN_SJW_4tq;	 //1
 CAN_InitStructure.CAN_BS1 = CAN_BS1_12tq;	 //3 		(1..16)
 CAN_InitStructure.CAN_BS2 = CAN_BS2_5tq;	 //5	 	(1..8)
 CAN_InitStructure.CAN_Prescaler = 16;//4
*/

 //1Mbit
 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 = 4;

 CAN_Init(CAN1, &CAN_InitStructure);

/* set BTR register so that sample point is at about 72% bit time from bit start */
 /* TSEG1 = 12, TSEG2 = 5, SJW = 4 => 1 CAN bit = 18 TQ, sample at 72%	*/

/* 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);

  /* transmit */
 TxMessage.StdId = 0x100;
 TxMessage.RTR = CAN_RTR_DATA;
 TxMessage.IDE = CAN_ID_STD;
 TxMessage.DLC = 1;

}

 

P.S. Исходник древний, так что не пинайте если что...

Edited by IgorKossak
Оформление кода в [codebox]

Share this post


Link to post
Share on other sites

Вот мой код (рабочий):

 


CAN_TypeDef * baseCAN1 = (CAN_TypeDef*)((UNSIGNED32)0x40006400);

enum TSystemFrequency
{
SYSTEM_FREQUENCY_12MHz = (12 * 1000000L),
SYSTEM_FREQUENCY_24MHz = (24 * 1000000L),
SYSTEM_FREQUENCY_36MHz = (36 * 1000000L),
SYSTEM_FREQUENCY_48MHz = (48 * 1000000L),
SYSTEM_FREQUENCY_56MHz = (56 * 1000000L),
SYSTEM_FREQUENCY_64MHz = (64 * 1000000L),
SYSTEM_FREQUENCY_72MHz = (72 * 1000000L)
};

enum TCANBaudRate
{
BR_10Kbps	= (UNSIGNED32)10000L,
BR_20Kbps	= (UNSIGNED32)20000L,
BR_50Kbps	= (UNSIGNED32)50000L,
   BR_100Kbps	= (UNSIGNED32)100000L,
BR_125Kbps	= (UNSIGNED32)125000L,
BR_250Kbps	= (UNSIGNED32)250000L,
BR_500Kbps	= (UNSIGNED32)500000L,
BR_800Kbps	= (UNSIGNED32)800000L,
BR_1000Kbps	= (UNSIGNED32)1000000L,
};

struct TCANFrame
{
union
{
	UNSIGNED16	communicationObjectId;  // Поддерживается только 11-битный ID
	struct
	{
		UNSIGNED nodeId : 7;
           UNSIGNED functionCode : 4;
	};
};
bool		isRemoteTransmitionRequest;

UNSIGNED8	dataLength;
union
{
	UNSIGNED8	dataPayload08[8];
	UNSIGNED16	dataPayload16[4];
	UNSIGNED32	dataPayload32[2];
       UNSIGNED64	dataPayload64[1];
};
};



////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void THardwareSTM32::initializeCAN(TCANBaudRate baudRate)
{
CAN_InitTypeDef			CAN_InitStructure;
   CAN_FilterInitTypeDef	CAN_FilterInitStructure;
   NVIC_InitTypeDef		NVIC_InitStructure;

// CAN1 Periph clock enable
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
   GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);

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

// CAN cell init
CAN_InitStructure.CAN_TTCM = DISABLE;			// Time triggered communication mode
CAN_InitStructure.CAN_ABOM = DISABLE;			// Automatic bus-off managemen
CAN_InitStructure.CAN_AWUM = DISABLE;			// Automatic wake-up mode
CAN_InitStructure.CAN_NART = DISABLE;			// No automatic retransmission
CAN_InitStructure.CAN_RFLM = DISABLE;			// Receive FIFO locked mode
CAN_InitStructure.CAN_TXFP = DISABLE;			// Transmit FIFO priority
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;
CAN_InitStructure.CAN_Prescaler = (_systemFrequency / 2 / baudRate / 9); // CAN_SJW_1tq + CAN_BS1_4tq + CAN_BS2_4tq
CAN_Init(CAN1, &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);

// CAN interrupts init
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
   CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);	// FIFO 0 message pending interrupt


// Разрешить прерывания от приемника CAN1
NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

#ifdef DEBUG
CAN_DBGFreeze(CAN1, ENABLE);
#endif
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool THardwareSTM32::sendCANFrame(TCANFrame & frame) 
{
// Ждать освобождения буфера передатчика CAN_PORT1
while ((baseCAN1->TSR & TSR_TME0) != TSR_TME0);

// Transmit mailbox 0 busy?
//	if ((baseCAN1->TSR & TSR_TME0) != TSR_TME0) 
//		return (CANBufferTx.put(frame));

// Разрешить прерывание USB_HP_CAN_TX_IRQ
//	CAN1->IER |= CAN_IT_TME;

// Установить Id (только 11-битный идентификатор)
baseCAN1->sTxMailBox[0].TIR = (frame.communicationObjectId & (UNSIGNED32)0x000007FF) << 21;

// Установить RTR 
if (frame.isRemoteTransmitionRequest)
	baseCAN1->sTxMailBox[0].TIR |= (UNSIGNED32)0x00000002;

// Установить объем передаваемых данных
baseCAN1->sTxMailBox[0].TDTR = (frame.dataLength & 0x0F);

// Скопировать данные
baseCAN1->sTxMailBox[0].TDLR = frame.dataPayload32[0];
baseCAN1->sTxMailBox[0].TDHR = frame.dataPayload32[1];

// Начать передачу
baseCAN1->sTxMailBox[0].TIR |= (UNSIGNED32)0x00000001;

// Разрешить прерывания от передатчика CAN1
//	enableInterrupt(USB_HP_CAN1_TX_IRQn, 0, 0);

return (true);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool THardwareSTM32::getCANFrame(TCANFrame & frame) 
{
CanRxMsg RxMessage;

// Забрать полученный CAN-кадр из буфера принятых сообщений
//	CAN_Receive(portNumber, CAN_FIFO0, &RxMessage);
   CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

// Вычислить Id принятого CAN-кадра (расширенный 29-битный идентификатор урезается до 11-битного)
if (RxMessage.IDE == CAN_ID_STD)
	frame.communicationObjectId = RxMessage.StdId;
else
	frame.communicationObjectId = RxMessage.ExtId;

// Get RTR
if (RxMessage.RTR == CAN_RTR_REMOTE)
	frame.isRemoteTransmitionRequest = true;
else
	frame.isRemoteTransmitionRequest = false;

// Get the DLC
frame.dataLength = RxMessage.DLC;

// Get the data field
frame.dataPayload08[0] = RxMessage.Data[0];
frame.dataPayload08[1] = RxMessage.Data[1];
frame.dataPayload08[2] = RxMessage.Data[2];
frame.dataPayload08[3] = RxMessage.Data[3];
frame.dataPayload08[4] = RxMessage.Data[4];
frame.dataPayload08[5] = RxMessage.Data[5];
frame.dataPayload08[6] = RxMessage.Data[6];
frame.dataPayload08[7] = RxMessage.Data[7];
}

Share this post


Link to post
Share on other sites

Честно сказать – я все-таки не понял – связь скорости с системной частотой – почему в формуле появилась 2 :

CAN_InitStructure.CAN_Prescaler = (_systemFrequency / 2 / baudRate / 9); // CAN_SJW_1tq + CAN_BS1_4tq + CAN_BS2_4tq

 

Edited by IgorKossak
Бездумное цитирование

Share this post


Link to post
Share on other sites

Всем спасибо за отклики - все заработало:

правильные настройки

 

 

..........................................

// 2. Enable ext. high frequency OSC

RCC_HSEConfig(RCC_HSE_ON);

// wait until the HSE is ready

while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

// 3. Init PLL

RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_4); // 100 MHz

RCC_PLLCmd(ENABLE);

// wait until the PLL is ready

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

// 4. Set system clock divders

 

RCC_ADCCLKConfig(RCC_PCLK2_Div8);

RCC_PCLK2Config(RCC_HCLK_Div1);

RCC_PCLK1Config(RCC_HCLK_Div2);

RCC_HCLKConfig(RCC_SYSCLK_Div1);

// Flash 1 wait state

*(vu32 *)0x40022000 = 0x12;

// 5. Clock system from PLL

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

.............................................................................

 

CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq;

CAN_InitStructure.CAN_BS2 = CAN_BS2_4tq;

CAN_InitStructure.CAN_Prescaler = 5;

 

Скорость = 100МГц/2/5/10 = 1 МГбит/с

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this