2022-06-30 03:27 AM
STM32F469I-disco :
https://os.mbed.com/platforms/ST-Discovery-F469NI/
https://www.st.com/en/evaluation-tools/32f469idiscovery.html
STM32F302R8 : https://os.mbed.com/platforms/ST-Nucleo-F302R8/
CAN shield : https://www.amazon.it/AptoFun-Receiver-Protocol-Controller-Development/dp/B082B9JKH1
Hello everyone, I’m still inexperienced and I have to use the CAN with the F469I screen, but I was unable to operate the built-in CAN1 and CAN2 (honestly, I still don’t understand why CAN2 doesn’t work.). So I decided to use a CAN shield (SPI-CAN) but I can’t figure out what I’m doing wrong.
In particular, I use this library : https://github.com/eziya/STM32_SPI_MCP2515
This is the main.c
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "app_touchgfx.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "../Components/otm8009a/otm8009a.h"
#include "stm32469i_discovery_sdram.h"
#include "stm32469i_discovery_qspi.h"
#include "CANSPI.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* DISPLAY */
#define LCD_ORIENTATION_LANDSCAPE 0x01
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CRC_HandleTypeDef hcrc;
DMA2D_HandleTypeDef hdma2d;
DSI_HandleTypeDef hdsi;
I2C_HandleTypeDef hi2c1;
LTDC_HandleTypeDef hltdc;
QSPI_HandleTypeDef hqspi;
SPI_HandleTypeDef hspi2;
SDRAM_HandleTypeDef hsdram1;
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for TouchGFXTask */
osThreadId_t TouchGFXTaskHandle;
const osThreadAttr_t TouchGFXTask_attributes = {
.name = "TouchGFXTask",
.stack_size = 4096 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* USER CODE BEGIN PV */
HAL_StatusTypeDef status = HAL_ERROR;
int value = 0,
err = 0,
data = 150,
delay = 0,
tick = 0;
uCAN_MSG txMessage, rxMessage;
bool statusTx = false,
statusRx = false;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CRC_Init(void);
static void MX_DMA2D_Init(void);
static void MX_DSIHOST_DSI_Init(void);
static void MX_FMC_Init(void);
static void MX_LTDC_Init(void);
static void MX_QUADSPI_Init(void);
static void MX_I2C1_Init(void);
static void MX_SPI2_Init(void);
void StartDefaultTask(void *argument);
extern void TouchGFX_Task(void *argument);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CRC_Init();
MX_DMA2D_Init();
MX_DSIHOST_DSI_Init();
MX_FMC_Init();
MX_LTDC_Init();
MX_QUADSPI_Init();
MX_I2C1_Init();
MX_SPI2_Init();
MX_TouchGFX_Init();
/* USER CODE BEGIN 2 */
if (!CANSPI_Initialize()) {
Error_Handler();
}
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of TouchGFXTask */
TouchGFXTaskHandle = osThreadNew(TouchGFX_Task, NULL, &TouchGFXTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
[...]
/**
* @brief SPI2 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
[...]
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
statusRx = CANSPI_Receive(&rxMessage);
if(statusRx)
{
txMessage.frame.idType = rxMessage.frame.idType;
txMessage.frame.id = rxMessage.frame.id;
txMessage.frame.dlc = rxMessage.frame.dlc;
txMessage.frame.data0++;
txMessage.frame.data1 = rxMessage.frame.data1;
txMessage.frame.data2 = rxMessage.frame.data2;
txMessage.frame.data3 = rxMessage.frame.data3;
txMessage.frame.data4 = rxMessage.frame.data4;
txMessage.frame.data5 = rxMessage.frame.data5;
txMessage.frame.data6 = rxMessage.frame.data6;
txMessage.frame.data7 = rxMessage.frame.data7;
value++;
statusTx = CANSPI_Transmit(&txMessage);
}
txMessage.frame.idType = dSTANDARD_CAN_MSG_ID_2_0B;
txMessage.frame.id = 0x0A;
txMessage.frame.dlc = 8;
txMessage.frame.data0 = 0;
txMessage.frame.data1 = 1;
txMessage.frame.data2 = 2;
txMessage.frame.data3 = 3;
txMessage.frame.data4 = 4;
txMessage.frame.data5 = 5;
txMessage.frame.data6 = 6;
txMessage.frame.data7 = 7;
statusTx = CANSPI_Transmit(&txMessage);
osDelay(100);
}
[...]
Together with the display, I use an F302R8 as the second CAN node. This node is sure that it works and that it is configured well (already tested) but if you need poss or post the code.
I tried with many combinations, even changing SPI of the F469 or jumpers but it doesn’t work anyway.
Could it be Baudrate’s problem? I am now using a 1Mbit/s baudrate, I used datasheet formulas (MCP2515) whereas the CAN shield is 8Mhz.
/*
* tq = 2 * (brp(0) + 1) / 8000000 = 0.25us
* tbit = (SYNC_SEG(1 fixed) + PROP_SEG + PS1 + PS2)
* tbit = 1tq + 5tq + 6tq + 4tq = 16tq
* 16tq = 4us = 1000kbps
*/
If you have examples of SPI-CAN (or only CAN) used with the F469I-disc they would be very useful. I am still very inexperienced with the STM.
Here also the hardware connections & STM ioc configuration :
2022-07-06 02:16 AM
Hello Klaus,
I can't help much about your issue sorry, but it doesn't seem to be related to TouchGFX Designer from what I see.
Good luck!
/Osman