How do I use the STM32CUBEF4 HAL library to read out the sensor data with i2c? - stm32

I want to use the latest HAL library instead of Standard Peripheral Library.
And i want to readout the BMA250E G-sensor's chip_id, but it doesn't work.
Value of aRxBuffer always keep at 0x00. But it should be 0xf9!
What's wrong in my code?
‪#‎include‬ "stm32f4xx_hal.h"
#define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SDA_PIN GPIO_PIN_9
#define I2Cx_SDA_GPIO_PORT GPIOB
#define I2Cx_SDA_AF GPIO_AF4_I2C1
#define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SCL_PIN GPIO_PIN_6
#define I2Cx_SCL_GPIO_PORT GPIOB
#define I2Cx_SCL_AF GPIO_AF4_I2C1
#define I2Cx_CLK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE()
#define I2Cx_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define I2Cx_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
‪#‎define‬ I2C_ADDRESS 0x18
static void SystemClock_Config(void);
uint8_t aTxBuffer[2],aRxBuffer;
int main()
{
HAL_Init();
SystemClock_Config();
I2C_HandleTypeDef I2cHandle;
I2cHandle.Instance = I2C1;
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2cHandle.Init.ClockSpeed = 400000;
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2cHandle.Init.OwnAddress1 = 0;
I2cHandle.Init.OwnAddress2 = 0;
HAL_I2C_Init(&I2cHandle);
aTxBuffer[0]=0x00;
HAL_I2C_Master_Transmit(&I2cHandle, I2C_ADDRESS,aTxBuffer, 1, 10000);
HAL_I2C_Master_Receive(&I2cHandle,I2C_ADDRESS|0x01 ,&aRxBuffer, 1, 10000);
HAL_Delay(1000);
}
static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 360;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType =
(RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct;
I2Cx_SCL_GPIO_CLK_ENABLE();
I2Cx_SDA_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = I2Cx_SCL_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = I2Cx_SCL_AF;
HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = I2Cx_SDA_PIN;
GPIO_InitStruct.Alternate = I2Cx_SDA_AF;
HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c)
{
I2Cx_FORCE_RESET();
I2Cx_RELEASE_RESET();
HAL_GPIO_DeInit(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN);
HAL_GPIO_DeInit(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN);
}

First, I would advise you to use STMCube. It will set up the clock and the I2C bus for you.
It is very good practice to check what the HAL functions return. If you don't have HAL_OK, something went wrong.
Try at 100KHz first, and then increase to 400KHz.
The I2C address of the device is 0x18 (if SDO is grounded, which I assume it is). But in the HAL driver, you have to define:
#‎define‬ I2C_ADDRESS (0x18<<1)
What you want to do is to read a register, so don't use HAL_I2C_Master_Receive or HAL_I2C_Master_Transmit, but HAL_I2C_Mem_Read or HAL_I2C_Mem_Write, like this:
#define REG_CHIP_ID 0x00
HAL_I2C_Mem_Read(&I2cHandle, I2C_ADDRESS, REG_CHIP_ID, I2C_MEMADD_SIZE_8BIT, &aRxBuffer, 1, 10000);
Also, note that the HAL takes care of the R/W bit of the address, so you don't need to do:
I2C_ADDRESS|0x01

Related

stm32 HAL CAN receive massage in normal mode, it receives but does not come out of interrupt

I wrote a simple code as below for receiving data via can bus.
I have a board and a can bus analyzer for testing. I send data from analyzer to the board.
in debug mode I saw that the data is received correctly, the "data_received" variable is set to '1' too, but the "b" variable has not changed.
it seems that we dont come out of the interrupt function and dont come to while(1)
#include "main.h"
CAN_HandleTypeDef hcan1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN1_Init(void);
CAN_RxHeaderTypeDef RxHeader;
uint8_t data[2];
volatile int data_received=0;
volatile int b=0;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if(hcan->Instance==CAN1)
{
HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RxHeader,data);
}
if (RxHeader.DLC==2)
{
data_received=1;
}
else
{
data_received=0;
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN1_Init();
if (HAL_CAN_Start(&hcan1) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING)!= HAL_OK)
{
Error_Handler();
}
while (1)
{
if (data_received==1)
{
b=1;
data_received=0;
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
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_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
static void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 3;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_11TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
CAN_FilterTypeDef canfilterconfig;
canfilterconfig.FilterActivation = CAN_FILTER_ENABLE;
canfilterconfig.FilterBank = 18;
canfilterconfig.FilterFIFOAssignment = CAN_RX_FIFO0;
canfilterconfig.FilterIdHigh = 0x103<<5;
canfilterconfig.FilterIdLow = 0x0000;
canfilterconfig.FilterMaskIdHigh = 0x103<<5;
canfilterconfig.FilterMaskIdLow = 0x0000;
canfilterconfig.FilterMode = CAN_FILTERMODE_IDMASK;
canfilterconfig.FilterScale = CAN_FILTERSCALE_32BIT;
canfilterconfig.SlaveStartFilterBank = 20;
HAL_CAN_ConfigFilter(&hcan1, &canfilterconfig);
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11, GPIO_PIN_SET);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
Have a look inside HAL_CAN_GetRxMessage function, all eight data array bytes are always initialized:
aData[0] = (uint8_t)((CAN_RDL0R_DATA0 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA0_Pos);
aData[1] = (uint8_t)((CAN_RDL0R_DATA1 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA1_Pos);
aData[2] = (uint8_t)((CAN_RDL0R_DATA2 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA2_Pos);
aData[3] = (uint8_t)((CAN_RDL0R_DATA3 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA3_Pos);
aData[4] = (uint8_t)((CAN_RDH0R_DATA4 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA4_Pos);
aData[5] = (uint8_t)((CAN_RDH0R_DATA5 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA5_Pos);
aData[6] = (uint8_t)((CAN_RDH0R_DATA6 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA6_Pos);
aData[7] = (uint8_t)((CAN_RDH0R_DATA7 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA7_Pos);
Yet your data array is only two bytes long. HAL_CAN_GetRxMessage overrites other variables. This might not be your problem, but it's an obvious bug that will bite you eventually.
Note, that after compilation, order of the variables might not be the same as in the source. You might think that data_received is getting overriten, but it might not. To find out actual order of the variables you can look at the map file.

DMA in EVE board 3

I am trying to do DMA in eve3-43inch LCD TFT ( matrix orbital), TFT screen working without DMA but as soon I add DMA settings DMA does not respond ing. What might be the reason? I using EVE81.h library. These codes I have added to make SPI initialization with DMA.
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA2_Stream0;
hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
/* SPI1_TX Init */
hdma_spi1_tx.Instance = DMA2_Stream3;
hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_CIRCULAR; //DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;//DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
Here I am transmitting as DMA or normal way. These codes working without DMA. After making it to transmit or receive through DMA LCD not responding.
void HAL_SPI_WriteBuffer(uint8_t *Buffer, uint32_t Length)
{
HAL_SPI_Enable();
volatile int result = HAL_SPI_Transmit(&hspi1, Buffer, Length, 1000);
//volatile int result = HAL_SPI_Transmit_DMA(&hspi1, Buffer, Length);
HAL_SPI_Disable();
}
void HAL_SPI_ReadBuffer(uint8_t *Buffer, uint32_t Length)
{
//EVE requires one dummy read/write before actual data can be read
Buffer[0] = 0;
volatile int result = HAL_SPI_Transmit(&hspi1, Buffer, 1, 1000);
HAL_SPI_Receive(&hspi1, Buffer, Length,1000);
//volatile int result = HAL_SPI_Transmit_DMA(&hspi1, Buffer, 1);
//HAL_SPI_Receive_DMA(&hspi1, Buffer, Length);
}
uint8_t HAL_SPI_Write(uint8_t data)
{
//volatile int result = HAL_SPI_Transmit(&hspi1, &data, 1, 1000);
volatile int result = HAL_SPI_Transmit_DMA(&hspi1, &data, 1);
return 0;
}

I2c SLAVE HAL Transmit

I'm tring to transmit as a slave to the master with I2C in a STM32F446RE but i can't get to it.
When there is no code running on the MCU i can see the master requesting me to write on the osciloscope. But when I use this code:
if(HAL_I2C_Slave_Receive_IT(&I2CxHandle, (uint8_t*)&T2, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
while(HAL_I2C_Slave_Transmit_IT(&I2CxHandle, (uint8_t*)&T1, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
The SDA goes high and the SCL goes low.
Also when I remove the Recieve line and add a delay at the end of about 100ms the master recieves the messages but only during a limited time (not a constant time, sometimes 3-4s and sometimes almost a second) but it shouldn't do it because it does not consider the request from the master.
Any idea? I haven't checked any flag bacause I don't know how to.
Complete Code:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#define I2C_ADDRESS 0x2E
I2C_HandleTypeDef I2CxHandle;
static GPIO_InitTypeDef GPIO_InitStruct;
static void SystemClock_Config(void);
static void Error_Handler(void);
int main(void)
{
HAL_Init();
/* Configure the system clock to 180 MHz */
SystemClock_Config();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Configure LED2 */
BSP_LED_Init(LED2);
/*##-1- Configure the I2C peripheral #######################################*/
I2CxHandle.Instance = I2Cx;
I2CxHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2CxHandle.Init.ClockSpeed = 100000;
I2CxHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2CxHandle.Init.DutyCycle = I2C_DUTYCYCLE_2;
I2CxHandle.Init.GeneralCallMode = I2C_GENERALCALL_ENABLE;
I2CxHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
I2CxHandle.Init.OwnAddress1 = I2C_ADDRESS;
I2CxHandle.Init.OwnAddress2 = 0;
if(HAL_I2C_Init(&I2CxHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
HAL_Delay(100);
while(1)
{
if(HAL_I2C_Slave_Receive_IT(&I2CxHandle, (uint8_t*)&T2, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
while(HAL_I2C_Slave_Transmit_IT(&I2CxHandle, (uint8_t*)&T1, 1)!= HAL_OK);
while ( HAL_I2C_GetState(&I2CxHandle) != HAL_I2C_STATE_READY) { }
T1++;
//HAL_Delay(100);
}
}
static void Error_Handler(void)
{
/* Turn LED2 ON if error */
//BSP_LED_On(LED2);
while(1)
{
}
}
/**
* #brief System Clock Configuration
* The system Clock is configured as follows:
* System Clock source = PLL (HSI)
* SYSCLK(Hz) = 180000000
* HCLK(Hz) = 180000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSI Frequency(Hz) = 16000000
* PLL_M = 16
* PLL_N = 360
* PLL_P = 2
* PLL_Q = 7
* PLL_R = 6
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
* #param None
* #retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Enable HSI Oscillator and activate PLL with HSI as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 0x10;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 360;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
RCC_OscInitStruct.PLL.PLLR = 6;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Activate the OverDrive to reach the 180 MHz Frequency */
ret = HAL_PWREx_EnableOverDrive();
if(ret != HAL_OK)
{
while(1) { ; }
}
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief I2C error callbacks
* #param I2cHandle: I2C handle
* #note This example shows a simple way to report transfer error, and you can
* add your own implementation.
* #retval None
*/
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
/* Toggle LED2: error */
while(1)
{
// BSP_LED_On(LED2);
// HAL_Delay(500);
//BSP_LED_Off(LED2);
//HAL_Delay(500);
}
}
#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 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) */
/* Infinite loop */
while (1)
{
}
}
#endif

Why USART transmits incorrect data as the APB1 frequency changes. (RCC <= 21MHz)

I want to use the USART communication protocol in my project. Communication is provided but incorrect data is sent (STM> PC).
I'd try:
Boundrade bands are the same.
Suitable combinations of PLL Source Mux (HSI-HSE) and System Clock Mux (HSI-HSE-PLLCLK) were tested. Available: HSE and PLLCLK
APB1 Clock frequency was changed within the allowed range. It was observed that the data obtained at each change also changed. Sometimes STM sent very fast data.
The STM card was fed from a different source and tested by ground equalization.
Note-1: Codes do not include the entire project. In this case, the problem that I mentioned occurs.
#include "main.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "stm32f4xx_hal.h"
#include "defines.h"
#include "tm_stm32_disco.h"
#include "tm_stm32_delay.h"
#include "tm_stm32_lis302dl_lis3dsh.h"
#include "stm32f4xx.h"
#include "arm_math.h"
#define PID_PARAM_KP 100
#define PID_PARAM_KI 0.025
#define PID_PARAM_KD 0
float pid_error;
extern UART_HandleTypeDef huart1;
char* bufftr="Hello\n\r";
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
TM_LIS302DL_LIS3DSH_t Axes_Data;
MX_GPIO_Init();
MX_TIM1_Init();
MX_SPI1_Init();
MX_USART1_UART_Init();
__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
SystemInit();
TM_DELAY_Init();
TM_DISCO_LedInit();
if (TM_LIS302DL_LIS3DSH_Detect() == TM_LIS302DL_LIS3DSH_Device_LIS302DL) {
TM_DISCO_LedOn(LED_GREEN | LED_RED);
TM_LIS302DL_LIS3DSH_Init(TM_LIS302DL_Sensitivity_2_3G, TM_LIS302DL_Filter_2Hz);
} else if (TM_LIS302DL_LIS3DSH_Detect() == TM_LIS302DL_LIS3DSH_Device_LIS3DSH) {
TM_DISCO_LedOn(LED_BLUE | LED_ORANGE);
TM_LIS302DL_LIS3DSH_Init(TM_LIS3DSH_Sensitivity_2G, TM_LIS3DSH_Filter_800Hz);
} else {
TM_DISCO_LedOn(LED_GREEN | LED_RED | LED_BLUE | LED_ORANGE);
while (1);
}
Delayms(300);
TM_DISCO_LedOff(LED_ORANGE);
TM_DISCO_LedOff(LED_BLUE);
arm_pid_instance_f32 PID;
PID.Kp = PID_PARAM_KP;
PID.Ki = PID_PARAM_KI;
PID.Kd = PID_PARAM_KD;
arm_pid_init_f32(&PID, 1);
TM_GPIO_SetPinLow(GPIOD, GPIO_Pin_12);
TM_GPIO_SetPinLow(GPIOD, GPIO_Pin_14);
while (1){
HAL_UART_Transmit_IT(&huart1, (uint8_t *)bufftr, 8);
HAL_Delay(500);
}
void SystemClock_Config(void){
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
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_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){
Error_Handler();
}
}
static void MX_USART1_UART_Init(void){
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;
if (HAL_UART_Init(&huart1) != HAL_OK){
Error_Handler();
}
}
static void MX_GPIO_Init(void){
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
void Error_Handler(void){
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line){
}
#endif
Note-2: The problem does not occur when I create and run a project containing only USART when all the conditions are the same.
Note-3: I do not receive any error messages or warning messages.
SystemInit() should be called in the reset handler only
This function is supposed to reset the system clock to a default state, running directly from HSI at 16 MHz.
You are calling it in the middle of main(), when USART1 is already configured assuming a higher clock speed. There is no telling what the peripheral would do when its clock source is changed on the fly.

STM32F401RE-Nucleo LED and BUTTON's example

I am trying to run a simple program on my new Nucleo board,
I made this program in order to turn on and off the green led when I press the user's button (the blue one),
#include "stm32f4xx.h"
#include "stm32f4xx_nucleo.h"
#include "system_stm32f4xx.h"
#include "stm32f4xx_hal_gpio.h"
#include "stm32f4xx_hal_rcc.h"
GPIO_InitTypeDef GPIO_InitStructure;
int main(void) {
HAL_Init();
__GPIOA_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_5;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
__GPIOC_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_13;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLDOWN;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
while (1) {
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}
}
}
But I am getting wrong result:
when I press the user's button, nothing happen,
when I keep pressing the user's button and I restart (by pressing the black button), I get good result,
It seems like the program checks the state of the blue button only at the first run, I don't know why,
Please help me if you have any ideas of what the problem comes from, or if you have a running program that switch the led on button press.
I had the same issue this is how I solve it:
while (1) {
int stateOfPushButton = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);
if ( stateOfPushButton == 1 ) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}
}
Set your button's GPIO Pull to PULLUP:
#include "stm32f4xx.h"
#include "stm32f4xx_nucleo.h"
#include "system_stm32f4xx.h"
#include "stm32f4xx_hal_gpio.h"
#include "stm32f4xx_hal_rcc.h"
GPIO_InitTypeDef GPIO_InitStructure;
int main(void) {
HAL_Init();
__GPIOA_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_5;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
__GPIOC_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_13;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
while (1) {
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}
}
}
Change the GPIO_PULLDOWN mode to GPIO_FLOATING (or something similar)!
This bit of code is what you want to use if your buttons are of the higher current variety like my mechanical 2 state switches:
GPIO_InitStructure.Pull = GPIO_PULLUP;
and adding an int variable also wouldn't hurt, just make sure to do the initialization of your variables only once before starting the main while function, otherwise you end up with leaky memory.
also i see you are not familiar with functions, try the following:
int main(void) {
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
HAL_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* start your stuff*/
/* doping stuff*/
/* end your stuff*/
}
}
/* System Clock Configuration*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
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_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pins : P_BUT_Pin R_BUT_Pin O_BUT_Pin I_CSW_Pin */
GPIO_InitStruct.Pin = P_BUT_Pin|R_BUT_Pin|O_BUT_Pin|I_CSW_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : P_LED_Pin R_LED_Pin O_LED_Pin C_LED_Pin */
GPIO_InitStruct.Pin = P_LED_Pin|R_LED_Pin|O_LED_Pin|C_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, P_LED_Pin|R_LED_Pin|O_LED_Pin|C_LED_Pin,
GPIO_PIN_RESET);
}
or if you are not confident, consider using a tool such as this:[http://www.st.com/en/development-tools/stm32cubemx.html]
Whenever you download code to your board the micro stays in a RESET mode which is why your code appears to not work. Once you press the BLACK RESET button it will run your code from main() and everything will work fine.
Just remember to RESET every time you flash new code on your micro.
If you using Keil MDK, go to your Target options -> Debug -> Select the debugger you are using and click Settings -> In download functions check 'Reset and Run', so the code resets and runs every time you flash it on your Nucleo board.
Your code and GPIO setup works on CubeMX IDE with my Nucleo-F401RE, you just have to enable 'Reset and Run' in Keil if that's the IDE you are using.