I am using the stm32mp157C-DK2 board to communicate via FDCAN and my idea is to use it as normal mode to send and receive CAN messages. For this I have created a program in stm32cubeide and I enable FDCAN1 with the following parameters (source clock: 24MHz and FDCAN1 125Kb/s):
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 8;
hfdcan1.Init.NominalSyncJumpWidth = 3;
hfdcan1.Init.NominalTimeSeg1 = 20;
hfdcan1.Init.NominalTimeSeg2 = 3;
hfdcan1.Init.DataPrescaler = 16;
hfdcan1.Init.DataSyncJumpWidth = 6;
hfdcan1.Init.DataTimeSeg1 = 5;
hfdcan1.Init.DataTimeSeg2 = 6;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 1;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 5;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
I have also changed FDCAN1 pins to be able to connect to the board (FDCAN_RX --> PA11 and FDCAN_TX --> PA12). Finally, I have created the program to send message via CAN:
while (1)
{
sprintf ((char *)TxData1, "CAN1: %d", indx++);
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, TxData1)!= HAL_OK)
{
Error_Handler();
}
HAL_Delay (1000);
}
I've tried in external loopback mode and everything is ok, but when I run this program in normal mode, I can't send messages and always get the same error:
HAL_FDCAN_ERROR_FIFO_FULL;
It seems that the FDCAN is not sending messages.
Can somebody help me?
Thanks!
Related
I'm using STM32F103RBT6 Nucleo board with CAN communication for my project. I use Microchip CAN Bus Analyzer(acts as a node) to transmit CAN data.
Project Setup:
CAN message flow from: CAN Bus Analyzer --> CAN Transceiver --> STM board.
I need to receive messages only from 0x581, 0x582, 0x583, 0x584, 0x4A1, 0x4A2, 0X4A3, 0X4A4 IDs. In order to achieve this I have applied filters for the same.
Problem:
In Keil's debugger mode, I'm able to see the CAN messages which are transmitted, getting received in 'RxData' properly. However when I try to send data of 4 bytes length, RxData data bytes from 1 to 4 gets filled with the exact same message that I transmit, but data bytes 5 to 8 also gets filled randomly (In ideal case, bytes 5 to 8 should all be zero). This problem happens only when I send data of byte length 4. I tried sending data bytes of varying length (other than 4), it worked just fine. The problem lies only whenever I try to send data byte of length 4.
I have attached my entire program code below. And attached screenshots of the issue. Please find below.
#include "main.h"
CAN_HandleTypeDef hcan;
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
CAN_FilterTypeDef sFilterConfig;
uint8_t RxData[8];
uint8_t TxData[8];
uint32_t TxMailbox;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN_Init();
while (1)
{
// Empty while.
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 2;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_10TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
uint16_t StdIdArray1 [4] = {0x581, 0x582, 0x583, 0x584}; // 0x58x ID Series
uint16_t StdIdArray2 [4] = {0x4A1, 0x4A2, 0x4A3, 0x4A4}; // 0x4Ax ID Series
uint16_t mask, tmp, i, num;
sFilterConfig.FilterBank = 5;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // Mask Mode
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // 16 Bit
sFilterConfig.FilterIdLow = StdIdArray1[0] << 5; // Filter Id Low
mask = 0x5ff;
num = sizeof (StdIdArray1)/sizeof (StdIdArray1[0]); // Mask code
for (i = 0; i <num; i ++)
{
tmp = StdIdArray1[i]^(~StdIdArray1 [0]);
mask &= tmp;
}
sFilterConfig.FilterMaskIdLow = (mask << 5) | 0x10; // Filter Mask Id Low
sFilterConfig.FilterIdHigh = StdIdArray2[0] << 5; // Filter Id High
mask = 0x4ff;
num = sizeof (StdIdArray2)/sizeof (StdIdArray2[0]); // Mask code
for (i = 0; i <num; i ++)
{
tmp = StdIdArray2[i]^(~ StdIdArray2[0]);
mask &= tmp;
}
sFilterConfig.FilterMaskIdHigh = (mask << 5) | 0x10; // Filter Mask Id High
sFilterConfig.FilterFIFOAssignment = 0; // FIFO 0
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_Start(&hcan) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
/* Receive Callback. Get messages from the CAN bus analyzer */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
}
void assert_failed(uint8_t *file, uint32_t line)
{
}
Screenshots:
Case 1:
ID= 581; DLC= 8;
enter image description here
Case 2:
ID = 581; DLC=6;
enter image description here
Case 3:
ID= 581; DLC=2;
enter image description here
Case 4: (Issue)
ID = 581; DLC=4;
enter image description here
Case 5: (Issue)
ID= 4A1; DLC=4;
enter image description here
This issue is only with data byte of length 4. It could be of great help if someone can help me resolve this!
I am currently trying to send messages via both of my FDCAN transmitters on my Nucleo. But I am only able to transmit via FDCAN1 (classic master) and not via FDCAN 2 (classic slave).
The configuration setup is the same, only FDCAN1 starts sending , while FDCAN 2 gets a buffer overflow after a short time and never sends anything. I am monitoring with CANoe, where I can only see the message send via FDCAN1.
I also know it is not a hardware issue, since I changed my cables and the board and the problem remained the same. My cables are also terminated correctly...
Is there anything obvious I am missing?
Here is my code, I used CubeMx for the first initialisation.
The fdcan.c File:
`
FDCAN_HandleTypeDef hfdcan1;
FDCAN_HandleTypeDef hfdcan2;
/* FDCAN1 init function */
void MX_FDCAN1_Init(void)
{
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.NominalPrescaler = 5;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 11;
hfdcan1.Init.NominalTimeSeg2 = 4;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 8;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 8;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.msgRam.StandardFilterSA = 0;
hfdcan1.msgRam.ExtendedFilterSA = 0;
hfdcan1.msgRam.RxFIFO0SA = 0;
hfdcan1.msgRam.RxFIFO1SA = 0;
hfdcan1.msgRam.RxBufferSA = 0;
hfdcan1.msgRam.TxEventFIFOSA = 0;
hfdcan1.msgRam.TxBufferSA = 0;
hfdcan1.msgRam.TxFIFOQSA = 0;
hfdcan1.msgRam.TTMemorySA = 0;
hfdcan1.msgRam.EndAddress = 0;
hfdcan1.ErrorCode = 0;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = DISABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.NominalPrescaler = 5;
hfdcan2.Init.NominalSyncJumpWidth = 1;
hfdcan2.Init.NominalTimeSeg1 = 11;
hfdcan2.Init.NominalTimeSeg2 = 4;
hfdcan2.Init.DataPrescaler = 1;
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 1;
hfdcan2.Init.DataTimeSeg2 = 1;
hfdcan2.Init.MessageRAMOffset = 0;
hfdcan2.Init.StdFiltersNbr = 0;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.RxFifo0ElmtsNbr = 8;
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxFifo1ElmtsNbr = 0;
hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxBuffersNbr = 0;
hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.TxEventsNbr = 0;
hfdcan2.Init.TxBuffersNbr = 0;
hfdcan2.Init.TxFifoQueueElmtsNbr = 16;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.msgRam.StandardFilterSA = 0;
hfdcan2.msgRam.ExtendedFilterSA = 0;
hfdcan2.msgRam.RxFIFO0SA = 0;
hfdcan2.msgRam.RxFIFO1SA = 0;
hfdcan2.msgRam.RxBufferSA = 0;
hfdcan2.msgRam.TxEventFIFOSA = 0;
hfdcan2.msgRam.TxBufferSA = 0;
hfdcan2.msgRam.TxFIFOQSA = 0;
hfdcan2.msgRam.TTMemorySA = 0;
hfdcan2.msgRam.EndAddress = 0;
hfdcan2.ErrorCode = 0;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}`
and the relevant part of the main.c:
uint8_t TxData[8] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
uint8_t TxData2[8] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB};
uint32_t msgerror=0;
uint32_t msgerror1=0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/**
* #brief The application entry point.
*
* #retval None
*/
int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_FDCAN1_Init();
MX_FDCAN2_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
TxHeader.Identifier = 0x120;
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
HAL_FDCAN_Start(&hfdcan1);
HAL_FDCAN_Start(&hfdcan2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxHeader, TxData) != HAL_OK)
{
/* Transmission request Error */
msgerror++;
}
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData2) != HAL_OK)
{
/* Transmission request Error */
msgerror1++;
}
HAL_Delay(100);
}
After finding the right data sheet, I found the solution. In the configuration for FDCAN2 I need to implement an offset:
hfdcan2.Init.MessageRAMOffset = sizeof(hfdcan1);
After implementing this change transmit and receive are working without problem.
I am developing On STM32F1xx with C language, Until now I am trying to implement CANopen stack using "CANopenNode-master", and I am using 2 interruption.
The first is for timer interruption which process SYNC TPDO and RPDO, the second CAN_Rx_fifo0_msgpendingCallback and in this interruption I manage received message but after doing all configuration needs this interruption (fifo0) does not work.
timer period is 1ms.
I used NVIC to give priority and subpriority and to enable IRQ of each interruption.
I put CAN receive fifo0 with high priority (first).
I did setting of my CAN like it should be (I think), but it does not work unlike the timer interruption which works correctly.
to verify that the callback does not works every time there frame on bus from other node than mine:
I just used a printf inside my callback function and it does not work.
I check all time the value of Instance->RF0R and it equal 0 always.
//HeaderCaninit is pointer to hcan .
CANmodule->CANbaseAddress = *(HeaderCaninit);
CANmodule->CANbaseAddress.Instance = HeaderCaninit->Instance;
switch (CANbitRate)
{
case 1000: CANmodule->CANbaseAddress.Init.Prescaler = 2;
break;
case 500: CANmodule->CANbaseAddress.Init.Prescaler = 4;// in our example we choose a prescaler 4 with other setting to get the 1Mb/s
break;
default:
case 250: CANmodule->CANbaseAddress.Init.Prescaler = 8;
break;
case 125: CANmodule->CANbaseAddress.Init.Prescaler = 16;
break;
case 100: CANmodule->CANbaseAddress.Init.Prescaler = 20;
break;
case 50: CANmodule->CANbaseAddress.Init.Prescaler = 40;
break;
case 20: CANmodule->CANbaseAddress.Init.Prescaler = 100;
break;
case 10: CANmodule->CANbaseAddress.Init.Prescaler = 200;
break;
}
CANmodule->CANbaseAddress.Init.SyncJumpWidth =CAN_SJW_1TQ; // changed by VJ, old value = CAN_SJW_1tq;//chngeD by aziz grib and we follow our CAN setting to get 1Mb/s
CANmodule->CANbaseAddress.Init.TimeSeg1 = CAN_BS1_4TQ; // changed by VJ, old value = CAN_BS1_3tq;// changed by GA to follow CAN transmit example = CAN_BS1_4TQ
CANmodule->CANbaseAddress.Init.TimeSeg2 = CAN_BS2_1TQ; ``
CANmodule->CANbaseAddress.Init.AutoRetransmission= DISABLE; // No Automatic retransmision//AG:if the first transmission fail the seconde is done automatically
CANmodule->CANbaseAddress.Init.Mode = CAN_MODE_NORMAL;
CANmodule->CANbaseAddress.Init.TimeTriggeredMode = DISABLE;
CANmodule->CANbaseAddress.Init.ReceiveFifoLocked = DISABLE;
CANmodule->CANbaseAddress.Init.TransmitFifoPriority = DISABLE;
memset(&CAN_FilterInitStruct, 0, sizeof (CAN_FilterInitStruct));
//CAN_FilterInitStruct.FilterNumber = 0; // for STM32F4
CAN_FilterInitStruct.FilterMaskIdHigh = 0x0000;
CAN_FilterInitStruct.FilterIdLow = 0x0000;
CAN_FilterInitStruct.FilterIdHigh = 0x0000;
CAN_FilterInitStruct.FilterMaskIdLow = 0x0000;
CAN_FilterInitStruct.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN_FilterInitStruct.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_FilterInitStruct.FilterScale = CAN_FILTERSCALE_32BIT;
CAN_FilterInitStruct.FilterActivation = DISABLE;
CAN_FilterInitStruct.FilterBank = 0;
CAN_FilterInitStruct.SlaveStartFilterBank = 14;
if (HAL_CAN_Init(&CANmodule->CANbaseAddress) != HAL_OK)
{
// TRACE_DEBUG_WP("res=%d\n\r", result);
return CO_ERROR_PARAMETERS; /* CO- Return Init failed */
}
HAL_CAN_ConfigFilter(&CANmodule->CANbaseAddress, &CAN_FilterInitStruct);
CAN_OperatingModeRequest(CANmodule->CANbaseAddress, CAN_Mode_Normal);
if (HAL_CAN_Start(&CANmodule->CANbaseAddress) != HAL_OK)
{
/* Start Error */
Error_Handler();
printf("--------------------------CANstart_error-------------
--------");
}
// this is the NVIC setting
static void MX_NVIC_Init(void)
{
/* TIM4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(TIM4_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(TIM4_IRQn);
/* CAN1_RX1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);
/* CAN1_SCE_IRQn interrupt configuration */
HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 1, 2);
HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn);
/* EXTI9_5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 15, 15);
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);
}
//in the main I did
HAL_CAN_ActivateNotification(&CO->CANmodule[0]->CANbaseAddress,CAN_IT_TX_MAILBOX_EMPTY|CAN_IT_RX_FIFO0_MSG_PENDING);
//in the function callback
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
printf("TIMI");// it does not work
/* Get RX message */
CO_CANinterrupt_Rx(CO->CANmodule[0]);
}
expected results:
I put a printf it must be executed.
and the function inside the callback should be executed too.
i resolved that by choosing USB0_CAN_Callback_interrupt on CubeMx instead of Rx0 interrupt than everything is gone right.
I'm trying to make a MPC2515 CAN controller works with an STML053R8 µC.
I'm using this driver/example https://github.com/eziya/STM32_SPI_MCP2515 with just the #include "stm32f1xx_hal.h" changed to #include "stm32l0xx_hal.h".
Here is my condensed code:
#define CAN_CS_Pin GPIO_PIN_5
#define CAN_CS_GPIO_Port GPIOA
extern SPI_HandleTypeDef hspi1;
#define SPI_CAN &hspi1
int CANSPI_Initialize(void)
{
// Some registers def
[...]
// This pass
if(MCP2515_Initialize() != 0)
return 1;
// This fails
if(MCP2515_SetConfigMode() != 0)
return 2;
[...]
}
int MCP2515_Initialize(void)
{
MCP2515_CS_HIGH();
uint8_t loop = 10;
do {
/* SPI Ready ? */
if(HAL_SPI_GetState(SPI_CAN) == HAL_SPI_STATE_READY)
return 0;
loop--;
} while(loop > 0);
return 1;
}
int MCP2515_SetConfigMode(void)
{
/* CANCTRL Register Configuration ?? ?? */
MCP2515_WriteByte(MCP2515_CANCTRL, 0x80);
uint8_t loop = 10;
do {
if((MCP2515_ReadByte(MCP2515_CANSTAT) & 0xE0) == 0x80)
return 0;
loop--;
} while(loop > 0);
return 1;
}
uint8_t MCP2515_ReadByte (uint8_t address)
{
uint8_t retVal;
MCP2515_CS_LOW();
SPI_Tx(MCP2515_READ);
SPI_Tx(address);
retVal = SPI_Rx();
MCP2515_CS_HIGH();
return retVal;
}
void MCP2515_WriteByte(uint8_t address, uint8_t data)
{
MCP2515_CS_LOW();
SPI_Tx(MCP2515_WRITE);
SPI_Tx(address);
SPI_Tx(data);
MCP2515_CS_HIGH();
}
My SPI configuration (generated by STM32 CubeMX):
/* SPI1 init function */
static void MX_SPI1_Init(void)
{
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
and a link to the MPC2515 datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20001801H.pdf
My problem here is in MCP2515_SetConfigMode(), as I set the CANCTRL register, I should read back
this value ('current mode is config mode') in CANSTAT register.
Also I tried to do the same thing for a LSM6DS3 IMU module yesterday and I got the same issue, unable
to read/write registers => unable to communicate with the device. I plugged it in I2C (this IMU got
2 interfaces) and I make it works like a charm.
The driver/example code I use seems very valid to me, I checked ALL the data & registers value from
the datasheet and everything looks OK to me. I suspect I might messed up something in my SPI configuration.
Any help will be gladly appreciated!
EDIT: I don't have a logical analyzer but I downloaded ones for Arduino and got this weird output. Not sure if this is the Arduino fault or my actual output:
I am using the following:
pic18f4550,
xc8 compiler,
mplab x ide v3.20,
a transmitter and receiver module (tested with a main program without any interruptions and works).
LED's connected to RD0,RD1 and RD2 (1 = light up)
Buttons connected to RB0,RB1 and RB2 (0 = button is pressed)//does not matter at this point
Apparently everything in this code works fine but with interrupts "void interrupt SerialComm(void)"
(I have made a program without interrupt and led lights up).
The main does not even load up; I have put "PORTD = 0x0F",
(line 3 of main program).
So if the led lights up it means that at least the 3rd line of the main program works.
(at least until that line, but the led didn't.)
Is there any register I have to disable first that I missed out for this?
Also, i have followed most tutorials could there be something i have missed?,
i have seen many programs with #pragma but i'm not sure if i need then when i am using XC8 compiler.
/*
* File: transmit.c
* Author: steve
*
* Created on September 25, 2016, 12:36 AM
*/
#define _XTAL_FREQ 48000000
#include <xc.h>
#include <pic18f4550.h>
void DelayMs(int x);
char ButtonsChecker();
char ButtonsCheckValue = 0; //returned value
char data_received = 0;
void main(void) {
TRISB = 0x0F;
TRISD = 0b00000000;
TRISCbits.TRISC2 = 0; //TXD Power
TRISCbits.TRISC6 = 0; //RC6
TRISCbits.TRISC7 = 1; //RC7
PORTCbits.RC2 = 1;
RCSTA = 0x90;
TXSTA = 0x20;
SPBRG = 77;
RCREG = 0;
RCIF = 0;
PORTDbits.RD0 = 1;
PORTDbits.RD1 = 1;
PORTDbits.RD2 = 1;
RCIE = 1;
TXIE = 0;
PEIE = 1;
GIE = 1;
while (1) {
while (ButtonsChecker()) {
TXREG = ButtonsChecker();
}
//while (!TRMT); // waiting for a whole data frame to be ready for a transmission
//TXREG = PORTB;
//while (!RCIF); // waiting for a whole data frame to be received
//PORTD = RCREG;
}
}
void DelayMs(int x) {
while (x > 0) {
__delay_ms(1);
x--;
}
}
char ButtonsChecker() {
if (PORTBbits.RB0 == 0) {
ButtonsCheckValue = 1;
} else if (PORTBbits.RB1 == 0) {
ButtonsCheckValue = 2;
} else if (PORTBbits.RB2 == 0) {
ButtonsCheckValue = 4;
}//else if (PORTBbits.RB3 == 0) {
// ButtonsCheckValue = 8;}
else ButtonsCheckValue = 0;
return (ButtonsCheckValue);
}
void interrupt ReceiveData() {
if (RCIF == 1) {
RCIF = 0;
~PORTDbits.RD1;
}
}
Everything looks O.K. except that you didn't enable TX and RC interrupts.
So add at USART initiation:
PIE1bits.RCIE = 1;
PIE1bits.TXIE = 1;
At the end of initiation section also add:
INTCONbits.GIE = 1;
...to enable global interrupts.