cancel
Showing results for 
Search instead for 
Did you mean: 

How to correctly synchronize timer with ADC

BartlomiejAlomiej
Associate

Hello everyone,

I have problem with my univeristy project and I'm trying to find some help.

I'm using Nucleo64 STM32F411RE.

The most important setting in CubeMX:

0690X000006CL5mQAG.png

0690X000006CL5rQAG.png0690X000006CL5wQAG.png

In ADC every rank have 3 cycles, and Rank 1-4 Channel 10, Rank 5-8 Channel 11, Rank 9-12 Channel 12, Rank 13-16 Channel 14

My code:

Global Variables:

#define length 32768
uint16_t reciver[length];
union u_type
{
	uint16_t prepare[(length/4)];
	uint8_t sender[(length/2)];
} temp;
uint16_t where1, where2;
//uint8_t sender[(length/8)];
int taskcounter1 = 0;
int taskcounter2 = 0;
int taskcounter3 = 0;

int main():

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_TIM3_Init();
 
  /* Create the semaphores(s) */
  /* definition and creation of myBinarySem01 */
  osSemaphoreDef(myBinarySem01);
  myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
 
  /* definition and creation of myBinarySem02 */
  osSemaphoreDef(myBinarySem02);
  myBinarySem02Handle = osSemaphoreCreate(osSemaphore(myBinarySem02), 1);
 
  xSemaphoreTake( myBinarySem01Handle, ( TickType_t ) 10 );
  xSemaphoreTake( myBinarySem02Handle, ( TickType_t ) 10 );
 
  /* definition and creation of recivedTask */
  osThreadDef(recivedTask, StartADCTask, osPriorityNormal, 0, 128);
  recivedTaskHandle = osThreadCreate(osThread(recivedTask), NULL);
 
  /* definition and creation of prepareTask */
  osThreadDef(prepareTask, StartPrepareTask, osPriorityNormal, 0, 128);
  prepareTaskHandle = osThreadCreate(osThread(prepareTask), NULL);
 
  /* definition and creation of sendTask */
  osThreadDef(sendTask, StartSendTask, osPriorityNormal, 0, 128);
  sendTaskHandle = osThreadCreate(osThread(sendTask), NULL);
 
  osKernelStart();
 
  while (1) {}
}

My Reciver Task:

void StartADCTask(void const * argument)
{
  for(;;)
  {
	  HAL_ADC_Start_DMA( &hadc1, reciver, length);
	  HAL_TIM_Base_Start_IT( &htim3 );
  }
}

Don't worry about another two Task, they work correctly. Logic is that:

1.

a) Recive first interrupt when signals recived from ADC feel reciver[32768] tab in half

b) When interrupt is recived it should free myBinarySem01Handle, but in the same time reciving data from ADC still works

c) Recive secondinterrupt when signals recived from ADC feel reciver[32768] tab in full

d) When interrupt is recived it should free myBinarySem01Handle, but in the same time reciving data from ADC still works

2. Repeat step 1. 12 times in second

3. This should never stop

I have problem only with that:

  • How to set up prescaler and counter period for Timer corectly for this scenario?
  • How to catch interrupt on half and full tab feel?

Everything else in the project (recalulating recived data, sending it via USB, etc) is done.

I tried to find something in documentation, in The Internet, but without any resoults...

You are my last hope. Can someone help me and explain how it works for future?

Thanks a lot and Best regards,

Bartlomiej

1 REPLY 1

I don't Cube/CubeMX.

You have set the ADC to trigger from TIM3_TRGO and TIM3_TRGO is set to be sourced from Update event, so it's the TIM3 "overflow" rate which triggers the ADC. In other words, the timer input clock (which is the timer-respective APB or APB/2 depending on your APB divider setting) gets divided by (PSC+1)*(ARR+1), so set them so that they produce a complete timer period matching your desired ADC triggering rate.

The half- and full- buffer interrupt is a property of DMA so it's about setting the DMA2Stream0 global interrupt on the ADC tab and then processing appropriately whatever falls out from Cube/HAL machine at the DMA2/Stream0 interrupt callback.

I am not sure it's a good idea to enable ADC interrupts.

JW