Jump to content

    

CAN на STM32

Все сконфигурировал как в исходниках, но не работает. Чип 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

Терминаторы на концах линии установлены?

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this