f_mount() returns FA_DISK_ERR - stm32

I have made few changes in my source code after suggestion form everyone.For connecting FATFS API with SPI interface i have followed this code..
https://github.com/eziya/STM32_SPI_SDCARD/blob/master/Src/fatfs_sd.c
and changed my user_diskio.c accordingly.
After doing all those things then also my SD Card returns FA_DISK_ERROR.
I have changed SD Card slot as well as SD Card. But nothing Changed.
My user_diskio.c look like this:
#include <string.h>
#include "ff_gen_drv.h"
#include "fatfs_sd.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;
/* USER CODE END DECL */
/* Private function prototypes -----------------------------------------------*/
DSTATUS USER_initialize (BYTE pdrv);
DSTATUS USER_status (BYTE pdrv);
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
#if _USE_WRITE == 1
DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
#endif /* _USE_IOCTL == 1 */
Diskio_drvTypeDef USER_Driver =
{
USER_initialize,
USER_status,
USER_read,
#if _USE_WRITE
USER_write,
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};
/* Private functions ---------------------------------------------------------*/
/**
* #brief Initializes a Drive
* #param pdrv: Physical drive number (0..)
* #retval DSTATUS: Operation status
*/
DSTATUS USER_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
/* USER CODE BEGIN INIT */
return SD_disk_initialize(pdrv);
/* USER CODE END INIT */
}
/**
* #brief Gets Disk Status
* #param pdrv: Physical drive number (0..)
* #retval DSTATUS: Operation status
*/
DSTATUS USER_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
/* USER CODE BEGIN STATUS */
return SD_disk_status(pdrv);
/* USER CODE END STATUS */
}
/**
* #brief Reads Sector(s)
* #param pdrv: Physical drive number (0..)
* #param *buff: Data buffer to store read data
* #param sector: Sector address (LBA)
* #param count: Number of sectors to read (1..128)
* #retval DRESULT: Operation result
*/
DRESULT USER_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
/* USER CODE BEGIN READ */
return SD_disk_read(pdrv, buff, sector, count);
/* USER CODE END READ */
}
/**
* #brief Writes Sector(s)
* #param pdrv: Physical drive number (0..)
* #param *buff: Data to be written
* #param sector: Sector address (LBA)
* #param count: Number of sectors to write (1..128)
* #retval DRESULT: Operation result
*/
#if _USE_WRITE == 1
DRESULT USER_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
/* USER CODE BEGIN WRITE */
/* USER CODE HERE */
return SD_disk_write(pdrv, buff, sector, count);
/* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */
/**
* #brief I/O control operation
* #param pdrv: Physical drive number (0..)
* #param cmd: Control code
* #param *buff: Buffer to send/receive control data
* #retval DRESULT: Operation result
*/
#if _USE_IOCTL == 1
DRESULT USER_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
/* USER CODE BEGIN IOCTL */
return SD_disk_ioctl(pdrv, cmd, buff);
/* USER CODE END IOCTL */
}
#endif /* _USE_IOCTL == 1 */
and fatfs_sd.c looks like this:
GO TO THE ABOVE GITHUB LINK
Have no idea where i am going wrong.
Anything on this topic will be helpful.
Thanks in advance.

I've written my own driver using an stm32f7 chip for FatFS before and think I might know what's going on. My guess is that you likely forgot to attach implementations for the disk_write and disk_read functions in diskio.h. Without doing that, the FatFS library has no clue on how to actually interface with the SD card.
You could check out the FatFS documentation/manual as a general resource: here
Pay very close attention to the "Required Functions" section in this app note: here
An example project like yours but for STM32F4: here

Related

What could be the cause of a constant voltage offset on the STM32L041G6 adc

I have been testing the ADC on my STM32L0 with 12-bit resolution and for some reason, every measurement I take has a 0.048 V offset. I've tried a different supply voltage (from 1.8 V to 3.3 V), but the offset stays there.
This offset starts at the first count, when I apply 0 V to the ADC input and read 130 counts (with 1.8 V Vdda) it stays for the whole range.
My voltage source is very stable and I've verified my ADC input voltage and the STM32 supply voltage with 3 different accurate pieces of measuring equipment.
The voltage is applied to the circuit through a bnc connector connected to a signal generator, in my case I use the Dc output option with high impedance on a normal signal generator. As for the code, I used stm32cubemx to generate some of the code but I didn't use any calibration function, so unless it is enabled by default, I dont do any calibration. As for the adc pin, I just used cubemx to set-up IN0 as an adc input and didn't touch anything else. Then to read the adc, I used 2 hal function "HAL_ADC_START()" and "HAL_ADC_PollForConversion()". Then I send the result to be read by uart.
The board I'm using is a custom PCB, but I only placed the STM32 and some passive components to get it to function (coupling capacitors and reset pull-up).
I also tested multiple boards with different configurations and I always get this offset voltage. I outputed Vrefint and measured it, and I got 1.225 V (specified is 1.224 V) so the ADC reference seems fine too.
I was wondering if someone has a suggestion on the possible cause of this offset error? I've been looking for a solution but I'm having no luck so far, so I would really appreciate the input of more experienced developers.
Here is a simplified version of the code I use :
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file adc.c
* #brief This file provides code for the configuration
* of the ADC instances.
******************************************************************************
* #attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "adc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
ADC_HandleTypeDef hadc;
/* ADC init function */
void MX_ADC_Init(void)
{
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = ENABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */
/* USER CODE END ADC_Init 2 */
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC GPIO Configuration
PA0-CK_IN ------> ADC_IN0
*/
GPIO_InitStruct.Pin = SENSOR_ANALOG_IN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SENSOR_ANALOG_IN_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC GPIO Configuration
PA0-CK_IN ------> ADC_IN0
*/
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
And here is the main file where I call the function to read the adc and send it to uart to be read :
#include "main.h"
#include "gpio.h"
#include "adc.h"
#include "usart.h"
#include <stdlib.h>
extern "C"
void execute(){
HAL_Delay(10);
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
const auto value = HAL_ADC_GetValue(&hadc);
char buffer [5];
itoa(value, buffer, 10);
HAL_UART_Transmit(&huart2, reinterpret_cast<uint8_t*>(buffer), 5, HAL_MAX_DELAY);
}
Here is the schematic, as I said, the test circuit only had the mcu and some passive components : https://im.ge/i/FbQPIp

EEPROM emulator on STM32L053

I known that isn't normal to use EEPROM emulator on a STM32L053, because it has is own EEPROM, but nowadays with the chip shortage, i was forcedto use an alternative MCU (STM32L053R8T6) instead of the "original design" (STM32F030C8T6), so i want to use the same code for both MCU, so the EEPROM emulator on the STM32L053R8T6.
But i'm having some difficulty using the EEPROM emulator on the STM32L053, the compiler didn't give any error, and the code run normmally, but didn't save any value to the EEPROM.
Header File:
#define ADDR_FLASH_PAGE_60 ((uint32_t)0x0800F000) /* Base # of Page 60, 1 Kbytes */
#define ADDR_FLASH_PAGE_61 ((uint32_t)0x0800F400) /* Base # of Page 61, 1 Kbytes */
#define ADDR_FLASH_PAGE_62 ((uint32_t)0x0800F800) /* Base # of Page 62, 1 Kbytes */
/* Define the size of the sectors to be used */
#define PAGE_SIZE (uint32_t) FLASH_PAGE_SIZE /* Page size */
/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS ((uint32_t) ADDR_FLASH_PAGE_60) /* EEPROM emulation start address */
/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
#define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
#define PAGE1_BASE_ADDRESS ((uint32_t)(ADDR_FLASH_PAGE_61))
#define PAGE1_END_ADDRESS ((uint32_t)(ADDR_FLASH_PAGE_61 + PAGE_SIZE - 1))
/* Used Flash pages for EEPROM emulation */
#define PAGE0 ((uint16_t) 0x0000)
#define PAGE1 ((uint16_t)((PAGE1_BASE_ADDRESS-PAGE0_BASE_ADDRESS)/PAGE_SIZE)) /* Virtual page nb between PAGE0_BASE_ADDRESS & PAGE1_BASE_ADDRESS*/
/* No valid page define */
#define NO_VALID_PAGE ((uint16_t)0x00AB)
/* Page status definitions */
#define ERASED ((uint16_t)0xFFFF) /* Page is empty */
#define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
#define VALID_PAGE ((uint16_t)0x0000) /* Page containing valid data */
/* Valid pages in read and write defines */
#define READ_FROM_VALID_PAGE ((uint8_t)0x00)
#define WRITE_IN_VALID_PAGE ((uint8_t)0x01)
/* Page full define */
#define PAGE_FULL ((uint8_t)0x80)
void EE_ReadData(void);
uint16_t EE_Init(void);
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);
#endif /* __EEPROM_H */
EEPROM Write Variable Function:
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
{
uint16_t Status = 0;
/* Write the variable virtual address and value in the EEPROM */
Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
/* In case the EEPROM active page is full */
if (Status == PAGE_FULL)
{
/* Perform Page transfer */
Status = EE_PageTransfer(VirtAddress, Data);
}
/* Return last operation status */
return Status;
}

LoRaWAN join after standby

I'm sending some information using LoRaWAN on a STM32WB and after that, I enter standby mode.
The problem is that after my standby, a new join is done.
I have heard that my join could be keep in memory using MIB functions but I don't manage to use them properly and continue to do a join do not make a join at all...
Does somebody know how to use them or a good tutorial somewhere? (I didn't find anything for the moment)
Here is what I am trying actually :
uint32_t last_time = 0;
int main(void)
{
/* USER CODE BEGIN 1 */
data_t data;
LoraFlagStatus join_status = LORA_RESET;
/* 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_DMA_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_LPTIM1_Init();
MX_LPUART1_UART_Init();
MX_RF_Init();
HW_RTC_Init();
MX_SPI1_Init();
MX_I2C3_Init();
MX_SPI2_Init();
/* USER CODE BEGIN 2 */
/* Reduce the System clock to below 2 MHz */
SystemClock_Decrease();
/* Set regulator voltage to scale 2 */
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
HAL_PWREx_EnableLowPowerRunMode();
float iaq;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_ACTIVATION;
LoRaMacMibGetRequestConfirm( &mibReq );
if( mibReq.Param.NetworkActivation == ACTIVATION_TYPE_NONE )
{
lora_init();
join_status = lora_join();
}
while (1)
{
//sensor code and lora send
lora_update(); /* Must be called for the LoRa stack to work */
pres = false;
/* Enable and set RTC_WKUP_IRQ */
HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
/* Check if the system was resumed from StandBy mode */
/* Note: On STM32WB, both CPU1 and CPU2 must be in standby mode to set the entire system in standby mode */
if( (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
&& (__HAL_PWR_GET_FLAG(PWR_FLAG_C2SB) != RESET)
)
{
/* Clear Standby flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_C2SB);
}
/* Insert 5 seconds delay */
HAL_Delay(5000);
/* Disable all used wakeup sources*/
HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
/* Clear all related wakeup flags */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* Re-enable wakeup source */
/* ## Setting the Wake up time ############################################*/
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, 60, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);;
/* Specific procedure on STM32WB, in case of initial power-up and RF stack no started */
if( (LL_PWR_IsActiveFlag_C1SB() == 0)
|| (LL_PWR_IsActiveFlag_C2SB() == 0)
)
{
/* Set the lowest low-power mode for CPU2: shutdown mode */
LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
}
/* Enter the Standby mode */
HAL_PWR_EnterSTANDBYMode();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
/**
* #brief System Clock Speed decrease
* The system Clock source is shifted from HSI to MSI
* while at the same time, MSI range is set to RCC_MSIRANGE_5
* to go down to 2MHz
* #param None
* #retval None
*/
void SystemClock_Decrease(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* Select MSI as system clock source */
/* Note: Keep AHB and APB prescaler settings from previous structure initialization */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Disable PLL to reduce power consumption since MSI is used from that point */
/* Change MSI frequency */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
}
/* USER CODE END 4 */

STM32 HAL - writing to EEPROM (I2C)

I'm learning to program in HAL and today I wanted to save some data to an external I2C EEPROM. The problem is that I cannot get the EEPROM to send an ACK after I send the address. I tried it using an Arduino (on 5V and also 3V) and the IC responded with an ACK. I tried to connect an MLX90614 I2C IR sensor and it worked fine (I got the response and I could send and receive data both in Arduino and STM32). I also swapped the SDA and SCL leads thinking that I might have mixed them, but this was not the case. I used a logic analyzer and as You can see I got only an NACK. I don't think that the EEPROM IC (ATMLU036/2EB - AT24C256B) doesn't like 3V because it worked in Arduino and the datasheet says that it will work fine even at lower voltages. I have no clue why it is not working and why other I2C peripherals (such as IR sensor) worked just fine. I am using STM32F429ZI - DISC1. Here is my code: (in short I used pins PB8 for SCL and PB9 for SDA, I tried 100kHz, 10kHz, 1kHz scl frequency, but it didn't help. In STM32CubeMX I didn't change anything - the lines have internal pull-up resistors)
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
*
* #retval None
*/
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_I2C1_Init();
/* USER CODE BEGIN 2 */
uint8_t d = 0xfc;
HAL_I2C_Mem_Write( &hi2c1, (0b1010000 << 1), 0x00, I2C_MEMADD_SIZE_8BIT, &d, I2C_MEMADD_SIZE_8BIT, 1000 );
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1){
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/**Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* I2C1 init function */
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 10000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/** Pinout Configuration
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #param file: The file name as string.
* #param line: The line in file as a number.
* #retval None
*/
void _Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/**
* #}
*/
/**
* #}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
I have read somewhere, that this might be caused by the IC writing something, but in my example it isn't. I just wanted the device to answer, I didn't write anything to EEPROM cells. I have also written a simple I2C address scanner (for STM32 and I tried an Arduino I2C address scanner) and it's the same story: IR sensor responded with ACK (on address 0x5A) and EEPROM responded with NACK on every possible 7-bit address :\ (also on 0x50, the A0, A1, A2 address pins are tied to GND, I also tried it with external pull-up resistors, but as You can guess, It didn't work). Please help me or give me a hint why this setup is not working. I2C data transmission
Sorry for my grammar mistakes, I'm still learning English.
I think that I have found the answer. And the problem was: (drum rolls) huge capacitance. I plugged SDA and SCL into my oscilloscope and I saw this. Then I unplugged SDA and SCL cables from my breadboard and inserted them directly into oscilloscope. (Some buses are low at start, because I restarted STM32). After this I added 1K pull-up resistors (instead of the built into STM32 and (in testing) external 10K) and got this nice data transmission. Next I confirmed that everything works using PulseView. Thanks to everyone that have read my problem and spend some time tinkering why this was not working. I guess that MLX90614esf is less sensitive to big capacitance (or it has lower value resistors for internal pull-up).

STM32F429 is not receiving the CAN Message

I am using STM32F429 Microcontroller and need to implement CAN Bus Communication between CAN2 and PCAN View.I am able to transmit the message from CAN2 but I am not able to receive any message.I am using TJA1041A CAN transreceiver in the microcontroller.The Problem is that during debugging my CAN bus are properly initalized but it doesn't go to the receive command although I have initalized FIFO0.Herewith I am attching the program for further reference.I have used STM32 HAL Cube for programming.
/**
******************************************************************************
* File Name : main.c
* Date : 05/12/2014 09:43:55
* Description : Main program body
******************************************************************************
*
* COPYRIGHT(c) 2014 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
CAN_HandleTypeDef hcan1;
CAN_HandleTypeDef hcan2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
static void MX_CAN2_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
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();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN1_Init();
MX_CAN2_Init();
/* USER CODE BEGIN 2 */
__GPIOD_CLK_ENABLE();
GPIO_InitTypeDef GPIO_Initpins;
GPIO_Initpins.Mode = GPIO_MODE_OUTPUT_PP ;
GPIO_Initpins.Pin = GPIO_PIN_5|GPIO_PIN_7;
GPIO_Initpins.Pull = GPIO_NOPULL ;
HAL_GPIO_Init(GPIOD, &GPIO_Initpins);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5|GPIO_PIN_7, GPIO_PIN_SET);
/* USER CODE END 2 */
/* USER CODE BEGIN 3 */
/* Infinite loop */
CanTxMsgTypeDef TxMess;
TxMess.StdId = 0x123;
TxMess.DLC = 0x0;
TxMess.Data[0] = 0x12;
TxMess.IDE = 0;
TxMess.RTR = 0;
hcan2.pTxMsg = &TxMess;
HAL_CAN_Transmit(&hcan2,50);
HAL_Delay(500);
/* USER CODE END 2 */
CanRxMsgTypeDef RMess;
RMess.FIFONumber = CAN_FIFO1;
RMess.FMI = 14;
RMess.StdId = 0x541;
RMess.DLC = 0;
RMess.RTR = 0;
RMess.IDE = CAN_ID_STD;
hcan2.pRxMsg = &RMess;
HAL_CAN_Receive_IT(&hcan2,CAN_FIFO1);
/* USER CODE BEGIN 3 */
/* Infinite loop */
while (1)
{
HAL_CAN_Receive(&hcan2,CAN_FIFO1,0);
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}
/* CAN1 init function */
void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 16;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_1TQ;
hcan1.Init.BS2 = CAN_BS2_1TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = DISABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;
HAL_CAN_Init(&hcan1);
/*CAN_FilterConfTypeDef CAN_Filters;
CAN_Filters.BankNumber = 0;
CAN_Filters.FilterActivation = ENABLE;
CAN_Filters.FilterFIFOAssignment = CAN_FILTER_FIFO0 ;
CAN_Filters.FilterIdHigh = 0x00;
CAN_Filters.FilterIdLow = 0x00;
CAN_Filters.FilterMaskIdHigh = 0x00;
CAN_Filters.FilterMaskIdLow = 0x00;
CAN_Filters.FilterMode = CAN_FILTERMODE_IDMASK;
CAN_Filters.FilterNumber = 0;
CAN_Filters.FilterScale = CAN_FILTERSCALE_32BIT;
HAL_CAN_ConfigFilter(&hcan1, &CAN_Filters);*/
}
/* CAN2 init function */
void MX_CAN2_Init(void)
{
hcan2.Instance = CAN2;
hcan2.Init.Prescaler = 2;
hcan2.Init.Mode = CAN_MODE_NORMAL;
hcan2.Init.SJW = CAN_SJW_1TQ;
hcan2.Init.BS1 = CAN_BS1_5TQ;
hcan2.Init.BS2 = CAN_BS2_2TQ;
hcan2.Init.TTCM = DISABLE;
hcan2.Init.ABOM = DISABLE;
hcan2.Init.AWUM = DISABLE;
hcan2.Init.NART = DISABLE;
hcan2.Init.RFLM = DISABLE;
hcan2.Init.TXFP = DISABLE;
HAL_CAN_Init(&hcan2);
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__GPIOH_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
/**
* #}
*/
/**
* #}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Thanks
If CAN2 can send messages, the clock and master-slave configurations between CAN1 (master) and CAN2 (slave) are ok.
If there are receiving issues these should be related to the FIFO config or the acceptance filter config.
You configured the FIFO, but it looks like you did not configure the "CAN2StartBank".
CAN1 and CAN2 share also the filter banks and by default the banks are divided in half, so the first half is used for CAN1 and the second half for CAN2.
From the reference manual chapter "CAN Filter Registers":
CAN filter master register (CAN_FMR)
Address offset: 0x200 Reset value: 0x2A1C 0E01 All bits of this
register are set and cleared by software.
...
CAN2SB[5:0]: CAN2 start bank These bits are set and cleared by
software. They define the start bank for the CAN2 interface (Slave) in
the range 0 to 27. Note: When CAN2SB[5:0] = 28d, all the filters to
CAN1 can be used. When CAN2SB[5:0] is set to 0,no filters are assigned
to CAN1.
You set the
CAN_Filters.BankNumber = 0;
but you should choose a bank from the second half with default settings or change the CAN2StartBank value to 0 if you don't need CAN1.
You also have to make sure, that the Filters an in initialisation mode during filter configuration.
CAN filter master register (CAN_FMR)
Bit 0 FINIT : Filter init mode Initialization mode for filter banks
0: Active filters mode.
1: Initialization mode for the filters
Sadly I have no hardware right now to test this by my self.
You should take a FilterNumber 14 for the CAN2 interface; by default after RESET the bits CAN2SB[5:0] initilized with 01110 = dec 14 - so the CAN1 interface is supposed to use filters 0..13 and CAN2 14..27. you can change the start bank from 14 to any value within 1..27 by the method CAN_SlaveStartBank(uint_8).
Try to set Filterbank to more than 14 for the CAN2 interface, it seems there is a bug about bank setting.We have the same issue, but after setting 15,it works.
Check CAN FMR register. Value CAN2SB is 0x0E by default in CAN1 and CAN2 peripheral registers. You should set CAN1FMR->CANS2B to 0x00, and CAN2FMR->CANS2B to 0x0E (anythyng but not same numbers). So you split filterbanks in half and it works fine