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

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

Related

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

How to send AT commands by UART using stm32 HAL library

I'm trying to send AT commands to my bluetooth and wifi modules connected to my board by UART using stm32 HAL library I am using stm32CubeIDE and using C++ for my language because of the GUI library (TouchGFX) and compiling this on Windows.
To provide the proper context I have used CubeMX to set everything up, all my pins are initialised and prior to putting these HAL functions in the program compiles and runs without errors. It's only when I add
HAL_UART(&huartWifi, "AT+CWJAP=SSID,secretPassword", sizeof("AT+CWJAP=SSID,secretPassword"), HAL_MAX_DELAY);
HAL_UART(&huartBluetooth, "AT+NAMEfriendlyName", sizeof("AT+NAMEfriendlyName"), HAL_MAX_DELAY);
============= Results ================
There are no errors per say when compiling and I do not see any runtime errors either, but it's not working, when I say it's not working using my limited tool set of remote debugging I can see that my simple experiment of changing the bluetooth module name like so:
uint_8 command[] = "AT+NamefriendlyName";
is not working also tried using the return \r and \n on the end of the string. Not sure if there is something in the HAL init functions that need to be initialised?
My expected result is the program compiles and I can pass the AT command without any issues and potentially find a callback so I can read if this was set okay or catch any errors both for this particular call but also in the future when I do advanced HTTP requests.
PLEASE SEE CODE BELOW (this code if in the int main section only of my main.cpp file)
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_ADC3_Init();
MX_CRC_Init();
MX_DCMI_Init();
MX_ETH_Init();
MX_I2C1_Init();
MX_I2C3_Init();
MX_QUADSPI_Init();
MX_RTC_Init();
MX_SAI2_Init();
MX_SDMMC1_SD_Init();
MX_SPDIFRX_Init();
MX_SPI2_Init();
MX_TIM3_Init();
MX_TIM5_Init();
MX_TIM8_Init();
MX_TIM12_Init();
MX_USART1_UART_Init();
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
uint8_t = bluetooth[] = "AT+NAME=AlienAttack\r";
HAL_UART_Transmit(&huart6, (uint8_t *)bluetooth,
sizeof(bluetooth),HAL_MAX_DELAY);
uint8_t = wifi[] = "AT+CWJAP=SSID,secretPassword\r";
HAL_UART_Transmit(&huart1, (uint8_t *)wifi,
sizeof(wifi),HAL_MAX_DELAY);
/* USER CODE END 2 */
/* Initialise the graphical hardware */
GRAPHICS_HW_Init();
/* Initialise the graphical stack engine */
GRAPHICS_Init();
/* 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) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 4096);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
while (1)
{
}
}
================================ UART INIT FUNCTION====================
static void MX_USART6_UART_Init(void)
{
/* USER CODE BEGIN USART6_Init 0 */
/* USER CODE END USART6_Init 0 */
/* USER CODE BEGIN USART6_Init 1 */
/* USER CODE END USART6_Init 1 */
huart6.Instance = USART6;
huart6.Init.BaudRate = 9600;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
// ORIGINAL huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.HwFlowCtl = UART_HWCONTROL_RTS;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
huart6.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart6.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart6) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART6_Init 2 */
/* USER CODE END USART6_Init 2 */
}
==================== HAL UART INIT FUNCTION FOR WIFI ================
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}

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).

Cannot mount SD using FatFS on STM32

I'm trying to write to a MicroSD-Card using STM32F405 chip.
The pins are connected correctly and each pin on the MicroSD-Card slot can be written to by using HAL_GPIO_WritePin. (Messured with ossciloscope) I'm using CubeMX to generate the init code for TrueStudio, so hopefully everything is ok there as well. But when I run the following code, f_mount returns FR_DISK_ERR. The MicroSD-Card can be written to and read from. If I use a different Device number, i.e. "1:", I get FR_INVALID_DRIVE
So my question is: what could cause FR_DISK_ERR except a faulty MicroSD-Card?
Here is my code so far:
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_SDIO_SD_Init();
MX_FATFS_Init();
/* USER CODE BEGIN WHILE */
FATFS fileSystem;
FIL testFile;
uint8_t testBuffer[16] = "SD write success";
UINT testBytes;
FRESULT res;
while((res = f_mount(&fileSystem, SD_MOUNT_PATH, 1)) != FR_OK){
printf("%d", res); //used to debug res, only for TrueStudio Debugger
}
uint8_t path[13] = "testfile.txt";
path[12] = '\0';
res = f_open(&testFile, (char*)path, FA_WRITE | FA_CREATE_ALWAYS);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
res = f_write(&testFile, testBuffer, 16, &testBytes);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
res = f_close(&testFile);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
}
in MX_FATFS_Init() FATFS_LinkDriver(&SD_Driver, SD_Path) is called and returns 0.
Without the SD_MOUNT_PATH macro, does the f_mount call look like this:
f_mount(&fileSystem, "0:", 1) ?'
Are you saying that f_open, f_write return FR_OK even if f_mount fails?!
FR_DISK_ERR usually means disk_read() or disk_write() failed. Try giving 100ms or 1 sec delay before using f_mount() and between between fatfs function calls.

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