Skip to main content
DYann.1
Senior II
October 30, 2023
Question

TIMER

  • October 30, 2023
  • 40 replies
  • 9791 views

Hello,

I found an example on the internet of a project but I don't understand the usefulness of using a Timer 7. Could you tell me why ? Thanks in advance.

 

__IO uint32_t usTick;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
 /* Prevent unused argument(s) compilation warning */
 if(htim==&htim7){
	usTick++;	
	}
 /* NOTE : This function Should not be modified, when the callback is needed,
 the __HAL_TIM_PeriodElapsedCallback could be implemented in the user file
 */
}

void delay_us(__IO uint32_t Delay){
uint32_t t=usTick;
uint32_t wait = Delay;
while( usTick - t < wait);

}
int main(void)
{

 /* 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_TIM7_Init();
	/*if (HAL_TIM_Base_Start(&htim7) != HAL_OK) {
		 _Error_Handler(__FILE__, __LINE__);
 }*/
	if (HAL_TIM_Base_Start_IT(&htim7) != HAL_OK) {
		 _Error_Handler(__FILE__, __LINE__);
 }

 MX_I2C1_Init();
	 MX_I2S2_Init();

	HAL_Delay(100);

	audio.init();


	bool ptt=HAL_GPIO_ReadPin(GPIOE,PTT_SWITCH);
	bool pttstate=ptt;
	uint16_t index = 0;
	uint16_t buf = 0;
	audio.set_volume(0);
 /* Infinite loop */
 	while (1)//	read power switch
	{
		ptt=HAL_GPIO_ReadPin(GPIO_PINS,PTT_SWITCH);
		if(ptt!=pttstate){
			if(ptt==0){

				audio.start_receive();
				for(buf=0;buf<32;buf++){
					for(index=0;index < AUDIO_BUF_SIZE;index++){
						HAL_I2SEx_TransmitReceive(&hi2s2, &i2s_zero,&i2s_buf[buf][index], 1,0xFF);
					}
				}

				audio.start_play();
				for(buf=0;buf<32;buf++){
					for(index=0;index < AUDIO_BUF_SIZE;index++){
						HAL_I2SEx_TransmitReceive(&hi2s2, &i2s_buf[buf][index],&i2s_zero, 1,0xFF);
					}
				}
			}
			
			pttstate=ptt;
		}
 	}

}

 

 

This topic has been closed for replies.

40 replies

LCE
Principal II
October 31, 2023

Of cours I'm a beginner... So you have a problem with theses people ?

Surely not, but most people here don't have the time to take you by the hand.
That's why I say, read the manual, check some tutorials, example code, etcpp...
It helps if there are at least some basics.
As AC/DC said, it's a long way to the top! ;)

The good thing: trial and error will (probably & hopefully) not kill your hardware.

Pavel A.
October 31, 2023

@DYann.1 Here is the official ST tutorial on the DMA :   https://wiki.st.com/stm32mcu/wiki/Getting_started_with_DMA

And there are so many folks ready to patiently help beginners .... they just expect something in return :) Care and share goes both ways.

 

ST official training on STM32L5: https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-online-training/stm32l5-online-training.html

Enjoy!

DYann.1
DYann.1Author
Senior II
October 31, 2023

Thank you, I'll look at these 2 links.

DYann.1
DYann.1Author
Senior II
November 2, 2023

Hi,

After reading the SAI and DMA documentation, I coded a piece of the program. I think I'm recovering data. Here is the code what do you think ? Thank you for your help.

 

int main(void)
{
 /* USER CODE BEGIN 1 */
	HAL_StatusTypeDef fresult;
	int32_t playbuf[4096*2] __attribute__ ((aligned (32)));
 /* 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();

/* Configure the peripherals common clocks */
 PeriphCommonClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_SAI1_Init();
 MX_I2C1_Init();
 /* USER CODE BEGIN 2 */
 HAL_SAI_RegisterCallback(&hsai_BlockB1, HAL_SAI_TX_HALFCOMPLETE_CB_ID, HAL_SAI_TxHalfCpltCallback);
 HAL_SAI_RegisterCallback(&hsai_BlockB1, HAL_SAI_TX_COMPLETE_CB_ID, HAL_SAI_TxCpltCallback);
 fresult= HAL_SAI_Init(&hsai_BlockB1);
 if (fresult != HAL_OK)
	{
 	return HAL_ERROR;
	}
 fresult = HAL_SAI_Transmit_DMA(&hsai_BlockB1, (uint8_t *)playbuf , (sizeof(playbuf))/4);
 HAL_Delay(100);
 SGTL5000_init();
 set_volume(0);
 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
	 start_receive();
	 HAL_Delay(100);
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

Here is what I see in the table :

DYann1_0-1698920072462.png

 

Pavel A.
November 2, 2023

The last image "Expressions" is indeed confusing. The values in the rightmost column are not values but addresses of 100-item slices of array playbuf.  If you expand any slice it will show the actual array elements.

This is how the Eclipse debugger behaves ((

LCE
Principal II
November 2, 2023

For simple testing without the Codec, you could directly connect SAI data output to data input, then compare transmit buffer ("playbuf")  with the receive buffer.

Start with a simple signal in playbuf, like playbuf[i] = i; i++;

 

 

DYann.1
DYann.1Author
Senior II
November 2, 2023

Hi,

It's a good idea but after my configuration :

DYann1_0-1698928962986.png

Right for SAI data output to data input but what should I do for the other 3 connections ? Which are :

SAI1_MCLK_B (Master CLK)

SAI1_FS_B (Frame Synchro)

SAI1_SCK_B (Bit Clock).

I still let them connect to the CODEC, it seems to me, right ? In my case I just connect

SAI1_SD_B with SAI1_SD_A. Right ?  

DYann.1
DYann.1Author
Senior II
November 2, 2023

After connecting SAI1_SD_B with SAI1_SD_A and do the for loop.

DYann1_0-1698934602077.png

But now How to check if I have theses values via SAI1_SD_B ?

DYann1_1-1698936733022.png

I wonder what is the meaning of 'Memory To Peripheral'. After me the DMA stores data in a device but what is this device? A user-defined memory area ?

LCE
Principal II
November 2, 2023

The SAI blocks can be synchronized internally.

Connection: I mean a hardware connection from pin to pin, don't know if that is feasible on your board, there might be some soldering involved.

Memory: internal SRAM buffer, those you assign by calling the DMA start function

Peripheral: all that stuff not CPU or memory, like interfaces (in your case the SAI), ADC, DAC, Timers, ...

Data go this way:

  • ext. ADC -> SAI RX -> DMA -> SRAM AD buffers
  • SRAM DA buffers (your "playbuf") -> DMA -> SAI TX -> ext. DAC
DYann.1
DYann.1Author
Senior II
November 2, 2023

Thank you for your helps, this information is very clear (for me) compared to the numerous videos or code examples that I have seen. No problem for the connection, I've the evaluation board STM32L5 and the CODEC so I use this jump between 2 connections  :

  DYann1_0-1698939704259.png

Sorry In my program I did not call the DMA Start function as you say. I configured the DMA in circular mode only :

DYann1_0-1698940013222.png

I don't know if this is the right method but I have no errors when my program runs.

DYann.1
DYann.1Author
Senior II
November 2, 2023

Here is my Main for this moment :

int main(void)
{
 /* USER CODE BEGIN 1 */
	HAL_StatusTypeDef fresult;
	int32_t playbuf[4096*2] __attribute__ ((aligned (32)));
 /* 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();

/* Configure the peripherals common clocks */
 PeriphCommonClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_SAI1_Init();
 MX_I2C1_Init();
 /* USER CODE BEGIN 2 */
 HAL_SAI_RegisterCallback(&hsai_BlockB1, HAL_SAI_TX_HALFCOMPLETE_CB_ID, HAL_SAI_TxHalfCpltCallback);
 HAL_SAI_RegisterCallback(&hsai_BlockB1, HAL_SAI_TX_COMPLETE_CB_ID, HAL_SAI_TxCpltCallback);
 fresult= HAL_SAI_Init(&hsai_BlockB1);
 if (fresult != HAL_OK)
	{
 	return HAL_ERROR;
	}
 fresult = HAL_SAI_Transmit_DMA(&hsai_BlockB1, (uint8_t *)playbuf , (sizeof(playbuf))/4);
 HAL_Delay(100);
 SGTL5000_init();
 set_volume(0);
 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* USER CODE END WHILE */
	 int32_t i;

	 for (i=0;i<100;i++)
	 {playbuf[i]=i;}
	 start_receive();
	 HAL_Delay(100);
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
LCE
Principal II
November 2, 2023

I'd rather fill the buffer once, before the while loop, and fill it completely.

DYann.1
DYann.1Author
Senior II
November 2, 2023

Yes of course, you're right about this buffer. But I would like to have a little precision please. After your explanation

DYann1_0-1698962001575.png

So when I fill the array (playbuf) with the values, I only check the way

SRAM DA buffer -> DMA -> SAI TX -> ext. DAC (not for me). In this case why to connect SAI1_SD_B with SAI1_SD_A ? Is this really necessary ?

I can't verify for the moment the way : ext.ADC -> SAI RX -> DMA -> SRAM AD buffers. Right ? 

LCE
Principal II
November 3, 2023

What kind of of hardware do you actually have?

Is a Codec connected, and if yes, how?

How are the SAI blocks set up? Which is transmitter, which is receiver?

 

DYann.1
DYann.1Author
Senior II
November 3, 2023

"What kind of of hardware do you actually have ?" 

I have a STM32L552E-EV evaluation board with audio board (CODEC SGTL5000, Audio Adaptor Rev D for Teensy 4.0).  

https://www.pjrc.com/store/teensy3_audio.html

DYann1_0-1699019209727.png

"Is a Codec connected, and if yes, how?"

Yes the CODEC is connect to the STM32 and my configuration with the CODEC is :

DYann1_1-1699020940384.png

According to my knowledge via the documentation

FSx - Frame Synchronisation

SCKx - bit Clock

SDx - Serial data line

MCLK - Master Clock

And for I2S LRCLK is equivalent FS for SAI.

"How are the SAI blocks set up?"

I have this configuration but I don't know if I answer your question ?

DYann1_2-1699021664950.png

DYann1_3-1699021699986.png

DYann1_4-1699022034025.png

Which is transmitter, which is receiver?

The transmitter is SAI B and the receiver is SAI A (so CODEC is the slave after me). I hope I answered your questions.