TIMER triggered DMA - AD conversion, STM32F4 works only ones - timer

I am implementing an a/d conversion with DMA transfer fired by a timer on a nucleo-STM32F401RE board.
Both TIMER2, the one used for the time base, and ADC with DMA looking at the debug are fine.
But when I use the timer to start the AD conversion it works only once, and then the timer go on, but don't starts the ADC.
I cannot find if there is some flag to clear or set.
Here the code:
TIMER 2 (changed sMasterConfig.MasterOutputTrigger from TIM_TRGO_RESET to TIM_TRGO_UPDATE, else ADC never starts):
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 100;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 100;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; //TIM_TRGO_RESET
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
sConfigOC.OCMode = TIM_OCMODE_TIMING;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
ADC (if I set DMA continuos request at the end of one burst starts immediatly another and ignore the timer):
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_8B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
}
MAIN and CallBack:
#define DEBUG 1
#define UART_RX_BUF_SIZE 1
#define UART_TIMEOUT 0X00000FFF
#define ADC_BUF_SIZE 10
volatile uint8_t UART_rx_buf[UART_RX_BUF_SIZE] = {0};
volatile uint8_t UART_rx_pending = 0;
const volatile char UART_tx_start[1] = "U";
volatile uint8_t UART_timeout = 0;
volatile uint16_t ADC_buf[ADC_BUF_SIZE] = {0};
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
MX_TIM2_Init();
#ifdef DEBUG
DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_TIM2_STOP;
#endif
/*INITIALIZATION: SEND A CHARACTER AND WAIT FOR A RESPONSE*/
HAL_Delay(10);
UART_timeout = HAL_UART_Transmit(&huart2, (uint8_t*)UART_tx_start, (uint16_t)1, (uint32_t)UART_TIMEOUT);
UART_timeout = HAL_UART_Receive(&huart2, (uint8_t*)UART_rx_buf, (uint16_t)UART_RX_BUF_SIZE, (uint32_t)UART_TIMEOUT);
if(UART_timeout == HAL_TIMEOUT) UART_config_timeout();
/*START CONFIGURATION*/
TIMER_CONFIG(UART_rx_buf[0]); //SET TIMER PRSC AND ARR
HAL_UART_Receive_IT(&huart2, (uint8_t*)UART_rx_buf, (uint16_t)UART_RX_BUF_SIZE); //UART RX INTERUPT ENABLE
TIM2 -> EGR |= 0x00000001; //RESET TIMER
HAL_TIM_Base_Start(&htim2); //START TIMER
HAL_ADC_Start_DMA(&hadc1, (uint32_t*) ADC_buf, ADC_BUF_SIZE); //START ADC-DMA REQUEAST
while (1)
{
if(UART_rx_pending == 1) {
UART_rx_pending = 0;
/*MANAGE RX DATA*/
HAL_UART_Receive_IT(&huart2, (uint8_t*)UART_rx_buf, (uint16_t)UART_RX_BUF_SIZE);
}
}
}
=============================================================================================
void HAL_UART_RxCpltCallback (UART_HandleTypeDef* huart) {UART_rx_pending = 1;}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {}
The first part of the main perform a short data transfer with the pc to set the ARR and PSC of TIMER2, in debug their values are fixed, and EGR is masked in order to reset the timer with the new values of ARR and PSC.
There is something that I miss?

Related

STM32 wakeup from CAN bus

I am trying to wake up the CPU from the CAN bus but it fails. Data from the bus processor receive but does not wake it up, for example, an interrupt from GPIO wakes it up and then it responds to the last 3 data from CAN Bus
CPU STM32F103C6
HAL_SuspendTick();
HAL_TIM_Base_Stop(&htim1);
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
HAL_TIM_Base_Start(&htim1);
HAL_ResumeTick();
tick_sleep = HAL_GetTick();
HAL Config interrupt
CAN Bus config
void MX_CAN_Init(void)
{
/* USER CODE BEGIN CAN_Init 0 */
/* USER CODE END CAN_Init 0 */
/* USER CODE BEGIN CAN_Init 1 */
/* USER CODE END CAN_Init 1 */
hcan.Instance = CAN1;
hcan.Init.Prescaler = 6;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_2TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = ENABLE;
hcan.Init.AutoWakeUp = ENABLE;
hcan.Init.AutoRetransmission = ENABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CAN_Init 2 */
HAL_CAN_Start(&hcan);
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterIdHigh = 0xFFFF;
sFilterConfig.FilterIdLow = 0xFFFF;
sFilterConfig.FilterMaskIdHigh = 0;
sFilterConfig.FilterMaskIdLow = 0;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan,&sFilterConfig);
/* USER CODE END CAN_Init 2 */
}
I forgot to run interrupts from CAN
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN_Init();
MX_I2C1_Init();
MX_TIM3_Init();
MX_USART2_UART_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
HAL_TIM_Base_Start_IT(&htim1);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // CAN interrupts start

ADC in low power run mode measure same numbers

I have stm32L053R8 nucleo64 board. I'm trying to get adc measure in low power run mode. It's not working correctly in Lprun mode but when I try in run mode it's working. In Lprun mode I only get 2 values. Half of the resolution and full of the resolution(12bit -> 2047 & 4095). Can you guys help me to figure out where am I doing wrong?
I tried to figure out why this happens and configured LFMEN, VREFEN, ULP bits but didn't worked.
ADC_HandleTypeDef hadc;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC_Init(void);
uint16_t adcVal = 0;
int main(void) {
HAL_Init();
MX_GPIO_Init();
MX_ADC_Init();
/*
// Bit 25 LFMEN: Low Frequency Mode enabled
ADC->CCR |= (1UL << 25);
// Bit 22 VREFEN: VREFINT enable
ADC->CCR |= (1UL << 22);
// Bit 9 ULP: Vrefint is ON in low power mode
PWR->CR &= ~(1UL << 9U);
*/
HAL_PWREx_EnableLowPowerRunMode();
while (1) {
HAL_Delay(500);
HAL_ADC_Start(&hadc);
HAL_ADC_PollForConversion(&hadc, 100);
adcVal = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop(&hadc);
}
}
/* #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_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_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_2;
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_MSI;
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 ADC Initialization Function
* #param None
* #retval None
*/
static 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_1;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) {
Error_Handler();
}
}

I can't see any signal on the CAN_TX line

I try to use the CAN bus on an STM32F303 discovery board, and I am using the PD0→RX and PD1→TX pins.
I want to try to send a message and analyse on the oscilloscope. So my configuration is seen below in the code blocks.
When I analyse with the oscilloscope which pins are PD0 and PD1, I can't see anything on the oscilloscope.
Where is my fault?
This is my code:
#include <stm32f30x.h>
#include <stm32f30x_i2c.h>
#include <stm32f30x_rcc.h>
#include <stm32f30x_syscfg.h>
#include <stm32f30x_exti.h>
// #include <stm32f30x_misc.h>
#include "main.h"
#include <stdio.h>
#include "common.h"
#include "io_periph_defs.h"
#include "stm32f30x.h"
#include <stdio.h>
#include "conf.h"
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CanTxMsg TxMessage;
CanRxMsg RxMessage;
void Init_TxMes(CanTxMsg *TxMessage)
{
/* Transmit INITIALIZATION*/
TxMessage->IDE = CAN_ID_STD;
TxMessage->DLC = 2;
TxMessage->StdId = 0x321;
TxMessage->RTR = CAN_RTR_DATA;
}
void Init_RxMes(CanRxMsg *RxMessage)
{
uint8_t i = 0;
RxMessage->StdId = 0;
RxMessage->IDE = CAN_ID_STD;
RxMessage->DLC = 0;
RxMessage->FMI = 0;
for (i = 0; i < 8; i++)
{
RxMessage->Data[i] = 0;
}
}
void CAN_setup(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //Enable the clock for CAN
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
/* Configure CAN1 RX pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Configure CAN1 TX pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_9);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_9);
/* Enable the CAN global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
NVIC_Init(&NVIC_InitStructure);
CAN_DeInit(CAN1);
/* Configure CAN1 **************************************************/
/* Struct init*/
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
/* CAN Baudrate = 125kbps (CAN clocked at 36 MHz) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_9tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_Prescaler = 16;
CAN_Init(CAN1, &CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
int main(void)
{
int i;
uint8_t TransmitMailbox = 0;
CAN_setup(); // Set up CAN interface
Init_TxMes(&TxMessage);
init_pin(GPIOA, GPIO_Pin_8, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP);
while (1)
{
TxMessage.Data[0] = 0xAA;
GPIO_SetBits(GPIOA, GPIO_Pin_8); // Transmit data
TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);
i = 0;
while ((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK))
; // I put a breakpoint here to check
// and found the message is pending.
GPIO_ResetBits(GPIOA, GPIO_Pin_8); // Transmit data
//i++;
}
}
I think there is the problem, but how can I solve it?
Stacking in loop.
while ((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK)

Configuring ADC with DMA on Nucleo-F401RE gives erratic values

I want to configure ADC with DMA on STM32(Nucleo-F401RE) and transmit the values through SPI to Basys 3 FPGA. Before transmission through SPI, when i read the values in memory realtime using STMSTudio, it is erratic.
In the past,I have tried increasing the sampling cycles, the issue persists.
Configured ADC without DMA with HAL_ADC_Start function and transferred the values to PC through UART, unable to retrieve the original signal. I'm unable to isolate where the problem lies.
uint32_t ADC1ConvertedValues[100];
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_SPI1_Init();
while (1) {
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC1ConvertedValues, 100) == HAL_OK) {
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1,(uint8_t*)(ADC1ConvertedValues),4,1);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET);
}
}
}
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_SCALE2);
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 = 16;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) {
Error_Handler();
}
}
static void MX_ADC1_Init(void) {
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_8B;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
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 = 1;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
Error_Handler();
}
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Error_Handler();
}
}
static void MX_SPI1_Init(void) {
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
}
static void MX_DMA_Init(void) {
__HAL_RCC_DMA2_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Error_Handler(void) {
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line) {
#endif /* USE_FULL_ASSERT */
EDIT 1: I used the arduino IDE to program NUCLEO-f401 RE and below is the code used :
#include <f401reMap.h>
float analogPin = pinMap(31); //PA0
float val = 0; // variable to store the value read
void setup() {
Serial.begin(115200); // setup serial
analogReadResolution(12);
}
void loop() {
val = analogRead(analogPin); // read the input pin
Serial.println(val); // debug value
}
It works for input signal frequency below 100Hz. How do I increase the throughput rate? My project requires conversion of analog signal between 500KHz to 900Khz.
Tried changing the DMA buffer size/speed uint32_t ADC1ConvertedValues[100]; reading about the DMA for this chip for my project I found that this sets the size of memory direct memory access allocated samples per clock? If it was I2C or if you would like to read about the timing concepts keep reading You need to find the ADC registers that set the spi baud rate and account for the setup requirements or re-initialization.
hadc1.Instance = ADC1;// this selects analog to digital circuit one
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //"skip" 3 out of 4 clock steps in sync with time scale read on...
hadc1.Init.Resolution = ADC_RESOLUTION_8B; //use 8 bits to pack the numbers to send to the intergrated CPU of the f401
Background on the math
ADC and DMA are often classifyed in read rate at the spi level not at the analog level. So if the chip can do 8khz spi using 8 bits then we can calculate in bigO (8n+n) time that we should get just under 1khz read speed. HOWEVER you need to write 8 bits to receive 8bits so bigO time is now bigO(n16+n) . But because of continuous register I believe it could be as low as bigO (8n+n+8) or (8n+n+8setupbits). So using that we know the time consumed by the intermediate operations in terms of clock cycles note that the term n alone is to account for assumptions of unknown internal clock trigger conditions and should have a scalar that relative to theta if scale resolution is a absolute requirement. Also keep in mind that these frequencies you may be experiencing noise from impedance resistance and capacitance.

STM32F4Discovery: Receiving CAN message

I am lost on how to receive CAN message on STM32F4Discovery. I have it in Silent_Loopback mode, meaning all sent messages should arrive in CAN controller itself. I get Transmit_OK status when I send the message, however, nothing appears in the FIFO mailbox. I have skipped CAN filter configuration in order to receive all messages and not to filter any of them out. What am I doing wrong?
/* Includes */
#include "stm32f4xx.h"
#include "stm32f4_discovery.h"
void Delay(__IO uint32_t nCount) {
while(nCount--) {
}
}
void RCC_Configuration(void) {
/* ENABLE CLOCKS */
/* GPIOB clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* USART3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* CAN1 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* CAN2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
}
void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructureUSART;
GPIO_InitTypeDef GPIO_InitStructureCAN_RX;
GPIO_InitTypeDef GPIO_InitStructureCAN_TX;
/* GPIO USART Configuration */
GPIO_InitStructureUSART.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructureUSART.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureUSART.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureUSART.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructureUSART.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructureUSART);
/* Connect USART to AF */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); //USART_TX = PB10
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); //USART_RX = PB11
/* GPIO CAN_RX Configuration */
GPIO_InitStructureCAN_RX.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructureCAN_RX.GPIO_Mode = GPIO_Mode_AF;
//GPIO_InitStructureCAN_TX.GPIO_OType = GPIO_OType_PP;
//GPIO_InitStructureCAN_TX.GPIO_PuPd = GPIO_PuPd_NOPULL;
//GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructureCAN_RX);
/* GPIO CAN_TX Configuration */
GPIO_InitStructureCAN_TX.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructureCAN_TX.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructureCAN_TX.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructureCAN_TX.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructureCAN_TX);
/* Connect CAN_RX & CAN_TX to AF9 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2); //CAN_RX = PB12
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); //CAN_TX = PB13
}
void USART_Configuration(void) {
USART_InitTypeDef USART_InitStructure;
/* USART3 configuration */
/* 256000 baud, window 8 data bits, one stop bit, no parity, no hardware flow control, rx/tx enabled */
USART_InitStructure.USART_BaudRate = 256000;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure);
USART_Cmd(USART3, ENABLE);
}
void CAN_Configuration(void) {
CAN_InitTypeDef CAN_InitStructure;
/* CAN2 reset */
CAN_DeInit(CAN2);
/* CAN2 configuration */
CAN_InitStructure.CAN_TTCM = DISABLE; // Time-triggered communication mode = DISABLED
CAN_InitStructure.CAN_ABOM = DISABLE; // Automatic bus-off management mode = DISABLED
CAN_InitStructure.CAN_AWUM = DISABLE; // Automatic wake-up mode = DISABLED
CAN_InitStructure.CAN_NART = DISABLE; // Non-automatic retransmission mode = DISABLED
CAN_InitStructure.CAN_RFLM = DISABLE; // Receive FIFO locked mode = DISABLED
CAN_InitStructure.CAN_TXFP = DISABLE; // Transmit FIFO priority = DISABLED
CAN_InitStructure.CAN_Mode = CAN_Mode_Silent_LoopBack; // Normal CAN mode
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; // Synchronization jump width = 1
CAN_InitStructure.CAN_BS1 = CAN_BS1_14tq; //14
CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq; //6
CAN_InitStructure.CAN_Prescaler = 4; // Baudrate 500 kbps
//CAN_InitStructure.CAN_Prescaler = 16; // Baudrate 125 kbps
if (CAN_Init(CAN2, &CAN_InitStructure)) { // Initialize CAN
STM_EVAL_LEDInit(LED6); // Initialize and
STM_EVAL_LEDOn(LED6); // Turn ON blue LED if CAN initialization is successful
}
}
void CAN_FilterConfiguration(void) {
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN2 filter configuration */
CAN_FilterInitStructure.CAN_FilterNumber = 0; // Filter number = 0 (0<=x<=13)
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; // Filter mode = identifier mask based filtering
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0300 << 5; //0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x03FF << 5;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0; // FIFO = 0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
void CAN_TxMessage(void) {
CanTxMsg TxMessage;
/* CAN message to send */
TxMessage.StdId = 0x321;
TxMessage.ExtId = 0x01;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = 0x04;
TxMessage.Data[1] = 0x01;
TxMessage.Data[2] = 0x00;
TxMessage.Data[3] = 0x00;
TxMessage.Data[4] = 0x00;
TxMessage.Data[5] = 0x00;
TxMessage.Data[6] = 0x00;
TxMessage.Data[7] = 0x00;
//while (1) {
CAN_TransmitStatus(CAN2, 0);
CAN_Transmit(CAN2, &TxMessage);
if(CAN_TransmitStatus(CAN2, 0)){
STM_EVAL_LEDInit(LED4); // Initialize and
STM_EVAL_LEDOn(LED4); // turn ON green LED if transmit was successful
}
//}
}
void CAN_OBDII_RequestCurrentData(int PIDNumber) {
CanTxMsg TxMessage;
TxMessage.StdId = 0x7DF; // PID request identifier
TxMessage.ExtId = 0x7DF;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 8;
TxMessage.Data[0] = 0x02; // Number of additional bytes = 2
TxMessage.Data[1] = 0x01; // Show current data = 1
TxMessage.Data[2] = PIDNumber; // PID code number
TxMessage.Data[3] = 0x00;
TxMessage.Data[4] = 0x00;
TxMessage.Data[5] = 0x00;
TxMessage.Data[6] = 0x00;
TxMessage.Data[7] = 0x00;
CAN_Transmit(CAN2, &TxMessage); // Transmit OBDII PID request via CAN2/mailbox0
}
void CAN_RxMessage(void) {
CanRxMsg RxMessage;
int d0=0;
while(1) {
CAN_Receive(CAN2,CAN_FIFO0,&RxMessage);
d0 = RxMessage.Data[0];
d0 = RxMessage.Data[1];
d0 = RxMessage.Data[2];
d0 = RxMessage.Data[3];
d0 = RxMessage.Data[4];
d0 = RxMessage.Data[5];
d0 = RxMessage.Data[6];
d0 = RxMessage.Data[7];
}
}
int main(void)
{
/* Initialize Clocks */
RCC_Configuration();
/* Initialize GPIO */
GPIO_Configuration();
/* Initialize USART */
USART_Configuration();
/* Initialize CAN */
CAN_Configuration();
/* Initialize CAN Reception Filter */
//CAN_FilterConfiguration();
/* Transfer CAN message */
CAN_TxMessage();
/* Receive CAN message */
CAN_RxMessage();
You have to configure filter to accept all messages (if you don't have any filter, no message will be accepted). But in your example you use CAN2, so FilterNumber must be 14 or higher.
#define CAN_FIFO_ID 0
#define CAN_FIFO CAN_FIFO0
#define CAN_FIFO_IN CAN_IT_FMP0
/**
* #brief Default filter - accept all to CAN_FIFO
*/
void CAN_SetFilter()
{
/* Default filter - accept all to CAN_FIFO*/
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber = 14; // 0..13 for CAN1, 14..27 for CAN2
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO_ID;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
}
The number of filters assigned to CAN1 and CAN2 is defined in the CAN_FMR register which by default is set to 14 which is the start of the CAN2 filters.
This can be set to 28 which would mean no filters to CAN2 and all 28 to CAN1 or if set to 0 all 28 filters are assigned to CAN2.
Normally (if you have a valid Filter Number) in mask mode any mask = zero will let everything through.

Resources