2024-11-19 02:03 AM
I have the following function to write data to the FM24CL64 memory:
void FM24CLXX_WriteData(uint16_t memAddr, uint8_t *data, uint16_t size) {
uint8_t memAddrData[2] = { (uint8_t)(memAddr >> 8), (uint8_t)(memAddr & 0xFF) };
HAL_StatusTypeDef status = HAL_I2C_Mem_Write(&hi2c1, FM24CLXX_I2C_ADDR, memAddrData[0], I2C_MEMADD_SIZE_8BIT, data, size, 100);
if (status != HAL_OK) {
Error_Handler();
}
}
Symptoms:
This is my full code, I using stm32f405 OpenX05R-C board.
#include "main.h"
#include "cmsis_os.h"
#include <stdio.h>
#include "backup_sram.h"
#include "fm24clxx.h"
#define Avg_slope (2.5F)
#define V_25 (0.76F)
osThreadId_t Task1Handle;
osThreadId_t Task2Handle;
osThreadId_t Task3Handle;
osMutexId_t sharedMutex;
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
I2C_HandleTypeDef hi2c1;
UART_HandleTypeDef huart2;
// Printf with USART
int _write(int file, char *data, int len) {
HAL_UART_Transmit(&huart2, (uint8_t*)data, len, HAL_MAX_DELAY);
return len;
}
uint32_t temperature_value;
volatile uint8_t button_pressed = 0;
#define DEBOUNCE_DELAY 50
#define STABLE_THRESHOLD 4
int is_button_pressed() {
uint8_t counter = 0;
uint8_t i;
uint8_t button_input;
button_input = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
if (button_input != GPIO_PIN_RESET) {
return 0;
}
for (i = 0; i < 10; i++) {
osDelay(5);
button_input = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
if (button_input == GPIO_PIN_SET) {
counter = 0;
} else {
counter++;
}
if (counter >= STABLE_THRESHOLD) {
return 1;
}
}
return 0;
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
if (hadc->Instance == ADC1) {
// float value = HAL_ADC_GetValue(&hadc1);
float value = temperature_value;
float V_sense = (value * 3.0f) / 4095.0f;
temperature_value = (uint32_t)((V_sense - V_25) / Avg_slope + 25.0f);
printf("ADC value: %d, Temperature: %lu\r\n", (int)V_sense, temperature_value);
BKPSRAM_Write(0x00, temperature_value);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
}
}
void Task1_Blink_LED(void *argument) {
while (1) {
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
osDelay(1000);
}
}
void Task2_Read_Temperature(void *argument) {
while(1){
HAL_ADC_Start_DMA(&hadc1, &temperature_value, 1);
osDelay(5000);
uint32_t temp_from_sram = BKPSRAM_Read(0x00);
printf("Temp from Backup SRAM: %lu\r\n", temp_from_sram);
// HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
}
// while (1) {
// HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
// osDelay(1000);
// }
}
void Task3_Button_Check(void *argument) {
static uint8_t button_stable = 0;
while(1){
printf("t3\r\n");
if (is_button_pressed()) {
printf("0.\r\n");
if (!button_stable) {
button_stable = 1;
if (!button_pressed) {
button_pressed = 1;
uint32_t temperature;
printf("1.\r\n");
temperature = BKPSRAM_Read(0x00);
printf("2.%lu\r\n", temperature);
FM24CLXX_WriteData(0x0000, (uint8_t*)&temperature, sizeof(temperature));
printf("Button Pressed, Data written to FM24CLXX: %lu\r\n", temperature);
uint32_t read_temp;
FM24CLXX_ReadData(0x0000, (uint8_t*)&read_temp, sizeof(read_temp));
printf("Data read from FM24CLXX: %lu\r\n", read_temp);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2);
}
}
} else {
if (button_stable) {
button_stable = 0;
button_pressed = 0;
}
}
osDelay(10);
}
}
void RTOS_Tasks_Init() {
osThreadAttr_t task1_attr = {.name = "Task1", .priority = osPriorityNormal, .stack_size = 128 * 4};
osThreadAttr_t task2_attr = {.name = "Task2", .priority = osPriorityNormal, .stack_size = 128 * 4};
osThreadAttr_t task3_attr = {.name = "Task3", .priority = osPriorityHigh, .stack_size = 128 * 4};
Task1Handle = osThreadNew(Task1_Blink_LED, NULL, &task1_attr);
Task2Handle = osThreadNew(Task2_Read_Temperature, NULL, &task2_attr);
Task3Handle = osThreadNew(Task3_Button_Check, NULL, &task3_attr);
}
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_I2C1_Init(void);
static void MX_USART2_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
BKPSRAM_Init();
sharedMutex = osMutexNew(NULL);
osKernelInitialize();
RTOS_Tasks_Init();
osKernelStart();
while (1){
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses 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();
}
}
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
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();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
/**
* @brief USART2 Initialization Function
* @PAram None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, led0_Pin|led1_Pin|led2_Pin|led3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : PA1 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : led0_Pin led1_Pin led2_Pin led3_Pin */
GPIO_InitStruct.Pin = led0_Pin|led1_Pin|led2_Pin|led3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE END 4 */
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM6 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @PAram htim : TIM handle
* @retval None
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM6) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* USER CODE END Callback 1 */
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
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,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Solved! Go to Solution.
2024-11-23 10:37 AM
looks like your memaddress is two bytes? So you have to indicate memaddress as 16bit.. and the data is only 8bits? Is it auto incrementing if you write many bytes? but when you read the data, you may have to set the address and then do a repeat start or stop after address write and do a start with read... There is a HAL document for detailed on each API call for your device. UM1725
2024-11-23 10:37 AM
looks like your memaddress is two bytes? So you have to indicate memaddress as 16bit.. and the data is only 8bits? Is it auto incrementing if you write many bytes? but when you read the data, you may have to set the address and then do a repeat start or stop after address write and do a start with read... There is a HAL document for detailed on each API call for your device. UM1725
2024-11-23 02:50 PM
Thank you so much for your detailed response! As you mentioned, the issue was indeed caused by not configuring the memory address (memaddress) correctly – it needed to be 16-bit. I also realized that reading data requires resetting the address and performing the steps you described (repeat start/stop).
Fortunately, after reviewing the UM1725 document, I gained a better understanding of the HAL API and was able to fix the issue. I really appreciate your help!