I have a NUCLEO STM32L152RE. I want to use the low power features of this board and wrote this easy example. I use CubeMX to configure the board.
I want to wake up every 3 minutes, but 6 minutes later the system freezes.
/* Private variables */
ADC_HandleTypeDef hadc;
I2C_HandleTypeDef hi2c1;
RTC_HandleTypeDef hrtc;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim11;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_ADC_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM3_Init(void);
static void MX_TIM11_Init(void);
static void MX_USART3_UART_Init(void);
uint8_t data[]={3,3};
uint8_t data2[]={2,3};
uint8_t data3[]={5,6};
uint8_t dataS4[]={4,4};
uint8_t dataS5[]={5,5};
uint8_t dataS6[]={6,6};
uint8_t dataS7[]={9,9};
uint8_t dataD[]={7,7};
uint8_t dataS1[]={1,1};
uint8_t command1[]="default;"; //
uint8_t command2[]="up;"; // THE SYSTEM UP
int i = 0;
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
HAL_PWR_EnableBkUpAccess(); //enable PWR backup domain access (RTC,BKReg)
__HAL_RCC_RTC_ENABLE(); //Enable RTC. not created by cube because the RTC can run.
/* 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_RTC_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_ADC_Init();
MX_I2C1_Init();
MX_TIM3_Init();
MX_TIM11_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart2,data,2,1000);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// here i have code.......
HAL_Delay(500);
HAL_UART_Transmit(&huart2,dataS7,2,1000);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI); // stop mode
}
}
RTC Initialization
/* RTC init function */
static void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RTC_AlarmTypeDef sAlarm;
/**Initialize RTC Only */
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/**Initialize RTC and set the Time and Date */
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/**Enable the Alarm A */
sAlarm.AlarmTime.Hours = 0x0;
sAlarm.AlarmTime.Minutes = 0x3;
sAlarm.AlarmTime.Seconds = 0x0;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask =RTC_ALARMMASK_NONE;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 0x1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
}
Here I have the code for handling the interrupt:
/* interrupt callback */
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){
RTC_AlarmTypeDef sAlarm;
HAL_RTC_GetAlarm(hrtc,&sAlarm,RTC_ALARM_A,FORMAT_BIN);
if(sAlarm.AlarmTime.Minutes>58){
sAlarm.AlarmTime.Minutes=0;
}else{
sAlarm.AlarmTime.Minutes=sAlarm.AlarmTime.Minutes+1;
}
while(HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, FORMAT_BIN)!=HAL_OK){}
SystemClock_Config(); // UP THE SYSTEM
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5); //TAGGLE THE LED
HAL_UART_Transmit(&huart2,data3,2,1000);
HAL_UART_Transmit(&huart1,command2,sizeof(command2),1000);
}
I want that every 3 minutes the system wakes up and later goes in stop mode, but the system doesn't work. After 60 minutes the system doesn't do anything. Can you help me?
Related
I am implementing the bmi160 and bmm150 drivers from Bosch in order to get data from the BMX160 (pinout board made by DFRobot) because from what I have gathered. I changed the chip id to match the bmx160 chip id. Upon all the initializations I am given valid returns of 0 yet when I get to reading the data, I do not get good data from the chip. I have made sure the device is getting voltage and is found by my board (STM32F0). I2C clock is set to the standard mode with a default clock speed.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file : main.c
* #brief : Main program body
******************************************************************************
* #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 "main.h"
#include "bmm150.h"
#include "bmi160.h"
#include <stdio.h>
// #include "stm32f0xx_hal_uart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
// UART_HandleTypeDef huart1;
struct bmi160_dev bmi;
struct bmm150_dev bmm;
struct bmm150_settings bmm_settings;
struct bmm150_mag_data mag;
struct bmi160_sensor_data accel;
struct bmi160_sensor_data gyro;
int8_t rslt, rslt1, rslt2, rslt3, rslt4, rslt5, rslt6, rslt7;
int8_t rslt_data, rslt_data1, rslt_data2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
// static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Auxiliary function declarations */
int8_t bmm150_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, void *intf_ptr);
int8_t bmm150_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, void *intf_ptr);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t Buffer[25] = {0};
uint8_t Space[] = " - ";
uint8_t StartMSG[] = "Starting I2C Scanning: \r\n";
uint8_t EndMSG[] = "Done! \r\n\r\n";
int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
HAL_StatusTypeDef status = HAL_OK;
while (HAL_I2C_IsDeviceReady(&hi2c1, (uint8_t)(id << 1), 3, 100) != HAL_OK)
{
rslt = 0;
}
status = HAL_I2C_Master_Transmit(&hi2c1, (uint8_t)(id << 1), ®_addr, 1, 1000);
if (status != HAL_OK)
{
rslt = (-1);
}
HAL_Delay(100);
status = HAL_I2C_Master_Receive(&hi2c1, (uint8_t)(id << 1), data, len, 10000);
if (status != HAL_OK)
{
rslt = (-1);
}
return rslt;
}
int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
HAL_StatusTypeDef status = HAL_OK;
while (HAL_I2C_IsDeviceReady(&hi2c1, (uint8_t)(id << 1), 3, 100) != HAL_OK)
{
}
uint8_t tx_buffer[len + 1];
tx_buffer[0] = reg_addr;
memcpy(&tx_buffer[1], data, len);
status = HAL_I2C_Master_Transmit(&hi2c1, (uint8_t)(id << 1), tx_buffer, len + 1, 1000);
if (status != HAL_OK)
{
rslt = (-1);
}
return rslt;
}
void user_delay_ms(uint32_t period)
{
HAL_Delay(period);
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t i = 0, ret;
/* 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();
// rslt = i2c_ping_device(&hi2c1, 0x00);
/* USER CODE BEGIN 2 */
bmi.id = BMI160_I2C_ADDR;
bmi.chip_id = BMI160_CHIP_ID;
bmi.intf = BMI160_I2C_INTF;
bmi.read = &user_i2c_read;
bmi.write = &user_i2c_write;
bmi.delay_ms = &user_delay_ms;
bmm.chip_id = BMM150_DEFAULT_I2C_ADDRESS;
bmm.intf = BMM150_I2C_INTF;
bmm.read = (bmm150_read_fptr_t)bmm150_aux_read;
bmm.write = (bmm150_write_fptr_t)bmm150_aux_write;
bmm.delay_us = &user_delay_ms;
bmm.intf_ptr = bmm.chip_id;
rslt = bmi160_init(&bmi);
// pingStatus = i2cs_ping_device(BMI160_I2C_ADDR);
bmi.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
bmi.aux_cfg.aux_i2c_addr = bmm.chip_id;
bmi.aux_cfg.manual_enable = BMI160_ENABLE;
bmi.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3;
rslt1 = bmi160_aux_init(&bmi);
rslt2 = bmm150_init(&bmm);
bmi.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
bmi.accel_cfg.range = BMI160_ACCEL_RANGE_2G;
bmi.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
bmi.gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
bmi.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS;
bmi.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
bmi.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
rslt3 = bmi160_set_sens_conf(&bmi);
bmm_settings.preset_mode = BMM150_PRESETMODE_REGULAR;
rslt4 = bmm150_set_presetmode(&bmm_settings, &bmm);
bmm_settings.pwr_mode = BMM150_POWERMODE_FORCED;
rslt5 = bmm150_set_op_mode(&bmm_settings, &bmm);
uint8_t aux_addr = 0x42;
uint8_t mag_data[8] = {0};
uint8_t index;
bmi.aux_cfg.aux_odr = 8;
rslt6 = bmi160_config_aux_mode(&bmi);
rslt7 = bmi160_set_aux_auto_mode(BMM150_REG_CHIP_ID, &bmi);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
user_delay_ms(100);
rslt_data = bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &accel, &gyro, &bmi);
rslt_data1 = bmi160_read_aux_data_auto_mode(mag_data, &bmi);
rslt_data2 = bmm150_aux_mag_data(mag_data, &mag, &bmm);
/* USER CODE END WHILE */
printf("****************\n");
printf("ACC X: %d, Y: %d, Z: %d\n", accel.x, accel.y, accel.z);
printf("GYRO X: %d, Y: %d, Z: %d\n", gyro.x, gyro.y, gyro.z);
printf("MAG X : %d Y : %d Z : %d\n", mag.x, mag.y, mag.z);
printf("################\n");
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** 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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
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.Timing = 0x200009FE;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
// 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;
// huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
// huart1.Init.OverSampling = UART_OVERSAMPLING_16;
// if (HAL_UART_Init(&huart1) != HAL_OK)
// {
// Error_Handler();
// }
// /* USER CODE BEGIN USART1_Init 2 */
// /* USER CODE END USART1_Init 2 */
// }
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
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.
* #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 */
}
int8_t bmm150_aux_read(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, void *intf_ptr)
{
int8_t rslt;
rslt = bmi160_aux_read(reg_addr, reg_data, len, &bmi);
return rslt;
}
int8_t bmm150_aux_write(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, void *intf_ptr)
{
int8_t rslt;
rslt = bmi160_aux_write(reg_addr, reg_data, len, &bmi);
return rslt;
}
#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 */
The print statements in the while loop are supposed to provide the results. The Accel data and Gyro data both are 0 for x,y,z and 0 on the sensor time. The mag data provides -32768 for the x,y,z values. I have checked that all functions return 0 several times but still I am confused on why I am not getting good data. I am also using the latest code from Bosch's github repo for both the bmi160 and bmm150.
Here is the I2C configure that is called by the MX_12C1_INIT().
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (hi2c->Instance == I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
This is using a STM32F030R8T6 Processor that is supplied voltage by a st-link-v2.
When creating circuitry, a number of issues could arise during the process which we are not aware of. A common issue is powering one are of the circuit with one voltage and communicating with the circuit using a different voltage. Both sensor and PLC need to be running on same voltage over the comms channel / pins.
The next step to debugging a circuit in this case would be to ensure that your "breakout board" or the sensor have pull up resistors. I have always found (40-50 different samples) that I do not need to add pull up resistors to break out boards. I have never had to add any.
The next issue I usually run into is addressing. Most ICs / sensors have a mechanism which allows you to select which address to use. If you hold the voltage low (0v), it will have a certain address while if you hold the voltage high (3.3v or 5v or whatever) it might be a different address. If you failed to add any connector to the pin (floating), it will be invalid and sensor will not start.
Another common issue is protocol. Some chips enable certain protocols by default and you may need to modify the internal settings in order to change them. By protocol, I am referring to either I2C, SPI or U(S)ART. This is unlikely but I've added it for completeness.
The issue most people think is happening is that the sensor is fried due to ESD. The likelyhood of your circuit being damaged is wildly low and it is certainly stronger than you think. I doubt you have damaged the circuit in any way.
To answer further, i would certainly require a picture of your circuit as the driver code should not be an issue at all. I generally find that driver code, even when outdated or for an earlier model, will generally still gather simple data relative to the ealier model.
I have been trying to read values from two potentiometers connected to channel1 and channel2 in ADC1 and read the values through UART in a serial Terminal,but unable to do it. It either comes random value or a same value for both the POTS. ADC works perfectly for a single channel.
The board I am using is STM32F103(Bluepill).
I have my own UART library that I am using to read.
ADC initialisation
in the regular channel configurations, I made two different functions of both thechannels
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 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
For configuring the regular channels I made two different functions as these will be called in other functions with a multiplication factor.
void ADC_SET_CH1()
{
//MX_ADC1_Init();
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_NVIC_EnableIRQ(ADC1_IRQn);
}
void ADC_SET_CH2()
{
//MX_ADC1_Init();
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_2;
sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_NVIC_EnableIRQ(ADC1_IRQn);
}
The different functions that I made in order to call them in the while loop to read the values in serial terminal:
float read_value1()
{
ADC_SET_CH1();
//rawData=0.1525*readAdc(0x01);
// HAL_ADC_Start_IT(&hadc1);
rawdata1=0.1525*HAL_ADC_GetValue(&hadc1);
return rawdata1;
}
float read_value2()
{
ADC_SET_CH2();
//rawData1=0.1525*readAdc(0x02);
//HAL_ADC_Start_IT(&hadc1);
rawData=0.1525*HAL_ADC_GetValue(&hadc1);
return rawData;
}
MAIN:
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "uart.h"
#include "stm32f1xx_it.h"
char *readbuffer;
float rawData=0.0f;
float potValue=0.0f;
char *readbuffer1;
float rawdata1=0.0f;
float potvalue1=0.0f;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_IT(&hadc1);
while 1:
while (1)
{
potValue=read_value1();
readbuffer=(convertIntToString(potValue));
writeString1("pot0:");
writeString1(readbuffer);
//writeString1("\n");
HAL_Delay(500);
writeString1(" ");
potvalue1= read_value2();
readbuffer1=convertIntToString(potvalue1);
writeString1("pot1:");
writeString1(readbuffer1);
writeString1("\n");
}
}
The IRQ function:
void ADC1_2_IRQHandler(void)
{
/* USER CODE BEGIN ADC1_2_IRQn 0 */
adcValue=ADC1->DR;
//HAL_ADC_Start_IT(&hadc1);
/* USER CODE END ADC1_2_IRQn 0 */
HAL_ADC_IRQHandler(&hadc1);
/* USER CODE BEGIN ADC1_2_IRQn 1 */
/* USER CODE END ADC1_2_IRQn 1 */
}
I'm try to read acceleration from KX132 accelerometer with a STM32F446ZE through I2C with DMA. I create a project with STMCubeMX and enable DMA and interruptions.
The accelerometer has six register each one of 1 byte where save acceleration in this format: XOUT_L,XOUT_H, YOUT_L, YOUT_H, ZOUT_L, ZOUT_H.
I want to read this registers continously with I2C DMA but I have a problem, only can read once time and never jump the complete transfer interruption again. I'll leave parts of my code so you can understand what i'm doing.
This configuration it was create by STMCubeMX. I choose DMA_CIRCULAR mode to repeat reading by DMA but doesn't work.
i2c.c
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "i2c.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
I2C_HandleTypeDef hi2c2;
DMA_HandleTypeDef hdma_i2c2_rx;
DMA_HandleTypeDef hdma_i2c2_tx;
/* I2C2 init function */
void MX_I2C2_Init(void)
{
/* USER CODE BEGIN I2C2_Init 0 */
/* USER CODE END I2C2_Init 0 */
/* USER CODE BEGIN I2C2_Init 1 */
/* USER CODE END I2C2_Init 1 */
hi2c2.Instance = I2C2;
hi2c2.Init.ClockSpeed = 100000;
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C2_Init 2 */
/* USER CODE END I2C2_Init 2 */
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspInit 0 */
/* USER CODE END I2C2_MspInit 0 */
__HAL_RCC_GPIOF_CLK_ENABLE();
/**I2C2 GPIO Configuration
PF0 ------> I2C2_SDA
PF1 ------> I2C2_SCL
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
/* I2C2 clock enable */
__HAL_RCC_I2C2_CLK_ENABLE();
/* I2C2 DMA Init */
/* I2C2_RX Init */
hdma_i2c2_rx.Instance = DMA1_Stream2;
hdma_i2c2_rx.Init.Channel = DMA_CHANNEL_7;
hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_i2c2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_ENABLE;
hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c2_rx.Init.Mode = DMA_CIRCULAR;
hdma_i2c2_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_i2c2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_i2c2_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2cHandle,hdmarx,hdma_i2c2_rx);
/* I2C2_TX Init */
hdma_i2c2_tx.Instance = DMA1_Stream7;
hdma_i2c2_tx.Init.Channel = DMA_CHANNEL_7;
hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_i2c2_tx.Init.Mode = DMA_CIRCULAR;
hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_i2c2_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
if (HAL_DMA_Init(&hdma_i2c2_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2cHandle,hdmatx,hdma_i2c2_tx);
/* I2C2 interrupt Init */
HAL_NVIC_SetPriority(I2C2_EV_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
HAL_NVIC_SetPriority(I2C2_ER_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(I2C2_ER_IRQn);
/* USER CODE BEGIN I2C2_MspInit 1 */
/* USER CODE END I2C2_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspDeInit 0 */
/* USER CODE END I2C2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C2_CLK_DISABLE();
/**I2C2 GPIO Configuration
PF0 ------> I2C2_SDA
PF1 ------> I2C2_SCL
*/
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0);
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_1);
/* I2C2 DMA DeInit */
HAL_DMA_DeInit(i2cHandle->hdmarx);
HAL_DMA_DeInit(i2cHandle->hdmatx);
/* I2C2 interrupt Deinit */
HAL_NVIC_DisableIRQ(I2C2_EV_IRQn);
HAL_NVIC_DisableIRQ(I2C2_ER_IRQn);
/* USER CODE BEGIN I2C2_MspDeInit 1 */
/* USER CODE END I2C2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
Set DMA interruptions.
dma.c
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
/* DMA1_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream7_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
I use HAL_I2C_Mem_Read_DMA() because i can select the register from acceleremoter it save the accelerations. When I run this code in debug mode, HAL_I2C_Mem_Read_DMA() works fine and I can read 6 bytes of acceleration on rxData1 enter to while(1) and stop in HAL_Delay(50). After that, jump to DMA Interruption on stm32f4xx_it.c specifically on DMA1_Stream2_IRQHandler() function (describes below). Here excecute HAL_DMA_IRQHandler(&hdma_i2c2_rx) and go to HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c2) describe in main.c. After all that the code come back to HAL_Delay(50) from while(1) and never go jump to interrupt for refresh data from accelerometer.
I hope you can help me. I'm not sure if I'm doing it right, if you have a tips it will be hopefull for me or if you need more information feel free to ask me.
main.c
#include "stdio.h"
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#define KX132_ADDRESS 0x1E
#define READ 0x01
#define WRITE 0x00
#define RX_BUFF_LEN 12
uint8_t BUFF_ADDRESS = 0x63;
uint8_t XOUT_L = 0x08;
static uint8_t rxData1[RX_BUFF_LEN];
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#define RX_BUFF_LEN 12
static uint8_t rxData1[RX_BUFF_LEN];
extern DMA_HandleTypeDef hdma_i2c2_rx;
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_DMA_Init();
MX_I2C2_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_I2C_Mem_Read_DMA(&hi2c2, (uint16_t)(KX132_ADDRESS << 1) | READ, XOUT_L, 1, (uint8_t *)rxData1, 6);
while (1)
{
HAL_Delay(50);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c2)
{
/* Toggle LED: Transfer in transmission process is correct */
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
}
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c2)
{
/* Toggle LED: Transfer in transmission process is correct */
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *I2cHandle)
{
/* Turn LED3 on: Transfer error in reception/transmission process */
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
}
/**
* #brief System Clock Configuration
* #retval None
*/
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_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 180;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Activate the Over-Drive mode
*/
if (HAL_PWREx_EnableOverDrive() != 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_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();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #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 */
DMA Interruption
stm32f4xx_it.c
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_i2c2_rx;
extern DMA_HandleTypeDef hdma_i2c2_tx;
extern I2C_HandleTypeDef hi2c2;
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/**
* #brief This function handles DMA1 stream2 global interrupt.
*/
void DMA1_Stream2_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream2_IRQn 0 */
/* USER CODE END DMA1_Stream2_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_i2c2_rx);
/* USER CODE BEGIN DMA1_Stream2_IRQn 1 */
/* USER CODE END DMA1_Stream2_IRQn 1 */
}
/**
* #brief This function handles DMA1 stream7 global interrupt.
*/
void DMA1_Stream7_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream7_IRQn 0 */
/* USER CODE END DMA1_Stream7_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_i2c2_tx);
/* USER CODE BEGIN DMA1_Stream7_IRQn 1 */
/* USER CODE END DMA1_Stream7_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
At the moment I am trying to operate a WS2811 LED strip. The way I see it is to transmit Pulse values through DMA using STM32 MC (rn I have nucleo-f303k8), so timer creates continuous PWM signal on STM pin, WS2811 gets the gata and lights up correct LED with correct color.
However, right now I have a big problem with DMA: using CubeMX and Keil Uvision, I configure DMA on timer on CubeMX's defaults (only configuring prescaler, counter and pulse). Using hal_tim_pwm_start_dma function doesn't give me the result I need: whatever value I type into variable I use in the function, it gives me 3.3V signal for 100% of the cycle. Googling had me find 0 of the same problems.
Here is code from main.c. Everything in other files is unchanged.
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define DATA_LENGTH 6
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;
DMA_HandleTypeDef hdma_tim2_ch2_ch4;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
uint32_t ws2811_data [DATA_LENGTH] = {6, 1, 3, 17, 0, 9};
/* 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_USART2_UART_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
//TIM2->EGR |= TIM_EGR_UG;
//TIM2->CCR2 = ws2811_data[0];
//HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
HAL_TIM_PWM_Start_DMA(&htim2,TIM_CHANNEL_2, ws2811_data, DATA_LENGTH);
/* 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 = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** 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();
}
}
/**
* #brief TIM2 Initialization Function
* #param None
* #retval None
*/
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 79;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 20;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
__HAL_TIM_DISABLE_OCxPRELOAD(&htim2, TIM_CHANNEL_2);
/* USER CODE BEGIN TIM2_Init 2 */
htim2.Init.RepetitionCounter = 1;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim2, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
/**
* #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 = 38400;
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;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
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_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn);
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #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 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
So the problem was with the timer. I was trying to get my program going, using TIM2, and output didn't look like anything I wanted to get. Then I decided to switch to TIM1 and for some magical reason everything started working!
That said, if you encounter same problem, try switching between timers of your STM32.
I'm trying to convert 3 ADC channels using DMA. But the variables don't seem to change when I watch them in the debugger. I know the conversion complete callback is executed because I breakpointed it. So this suggests that the DMA transfer is not executing and the buffer is not being filled. I'm using stm32cube to initialize my project. I've trimmed the generated code. Thanks.
ADC_HandleTypeDef hadc;
DMA_HandleTypeDef hdma_adc;
uint32_t uwADC8ConvertedValue = 0;
uint32_t uwADC10ConvertedValue = 0;
uint32_t uwADC11ConvertedValue = 0;
uint32_t adcBuffer[3];
/* USER CODE BEGIN 0 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle) {
uwADC8ConvertedValue = adcBuffer[0];
uwADC10ConvertedValue = adcBuffer[1];
uwADC11ConvertedValue = adcBuffer[2];
}
/* USER CODE END 0 */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_RTC_Init();
MX_ADC_Init();
MX_USART2_UART_Init();
MX_USART5_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
HAL_ADC_Start_IT(&hadc);
HAL_ADC_Start_DMA(&hadc, adcBuffer, 3);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_UART_Transmit(&huart2, TxBuffer, 15, 5000);
GPIO_PinState userPBstate = OFF;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(MODEM_PW_GPIO_Port, MODEM_PW_Pin);
HAL_GPIO_TogglePin(CAM1_LD_GPIO_Port, CAM1_LD_Pin);
HAL_GPIO_TogglePin(CAM1_PW_GPIO_Port, CAM1_PW_Pin);
HAL_Delay(100);
userPBstate = HAL_GPIO_ReadPin(USER_PB_GPIO_Port, USER_PB_Pin);
if (userPBstate == ON) {
HAL_UART_Transmit(&huart2, (uint8_t *)"User button pressed!\n\r", 22, 5000);
}
else {
HAL_UART_Transmit(&huart2, (uint8_t *)"User button NOT pressed!\n\r", 26, 5000);
}
}
/* USER CODE END 3 */
}
/* ADC init function */
static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**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_160CYCLES_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_10;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_11;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
User custom code:
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
HAL_ADC_Start_IT(&hadc);
HAL_ADC_Start_DMA(&hadc, adcBuffer, 3);
/* USER CODE END 2 */
should be:
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim2);
HAL_ADC_Start_DMA(&hadc, adcBuffer, 3);
/* USER CODE END 2 */
If you want to use DMA mode, then do not use interrupt mode.