Posted on Leave a comment

Up Counting Timer using STM32L476

I have created this Upcounting timer using the RTC of STM32L476vgt. In this timer, time will keep on incrementing and it will be displayed using the onboard LCD.

How to Read RTC of STM32L476G-DISCO

Here is the code that I have used to make this.

I have used STM32 CUBE IDE for programming and debugging purposes.

  MX_RTC_Init();				// RTC initalization and configuration created using integrated cube mx
  /* USER CODE BEGIN 2 */
  BSP_LCD_GLASS_Init();
  BSP_LCD_GLASS_Clear();
  BSP_LCD_GLASS_DisplayString((uint8_t *)"HALLO");
  HAL_Delay(1000);
  BSP_LCD_GLASS_DisplayString((uint8_t *)"EXASUB");
  HAL_Delay(2000);


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  RTC_TimeTypeDef readTime;	// RTC Time structure
  RTC_DateTypeDef readDate;	// RTC Date structure
  while (1)
  {
    /* USER CODE END WHILE */
    MX_USB_HOST_Process();

    /* USER CODE BEGIN 3 */

    char bufSec[2];
    char bufMin[2];
    char bufHou[2];
    HAL_RTC_GetTime(&hrtc, &readTime, RTC_FORMAT_BIN);	// function to read time from RTC shadow register
    HAL_RTC_GetDate(&hrtc, &readDate, RTC_FORMAT_BIN);	// function to read date from RTC shadow register
   itoa(readTime.Seconds,bufSec,10);
   itoa(readTime.Minutes,bufMin,10);
   itoa(readTime.Hours,bufHou,10);
   if(readTime.Seconds == 0){
	   BSP_LCD_GLASS_Clear();
   }
   if(readTime.Minutes == 0){
	   BSP_LCD_GLASS_Clear();
   }
   /*
    if(readTime.Hours == 0){
   	   BSP_LCD_GLASS_Clear();
      }
   */
   BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufHou[0], POINT_OFF, DOUBLEPOINT_OFF, 0);
   BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufHou[1], POINT_OFF, DOUBLEPOINT_ON, 1);
   BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufMin[0], POINT_OFF, DOUBLEPOINT_OFF, 2);
   BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufMin[1], POINT_OFF, DOUBLEPOINT_ON, 3);
   BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufSec[0], POINT_OFF, DOUBLEPOINT_OFF, 4);
   BSP_LCD_GLASS_DisplayChar((uint8_t *)&bufSec[1], POINT_OFF, DOUBLEPOINT_OFF, 5);

    HAL_Delay(1000);									// HAL Delay of 1000 millisecond
  }
  /* USER CODE END 3 */
}

Posted on 1 Comment

How to Read RTC of STM32L476G-DISCO

Create a Project in STM32 CUBE IDE for the STM32L476G-DISCO board.

Select LSE as Clock Source for RTC

The default option is LSI which uses an internal RC circuit.

LSE is the external 32KHz crystal that is provided on the board for the RTC.

Activate the Clock source and Calendar

This will enable the RTC clock source and will also enable the calendar for date and timekeeping.

If you want to set some default time and date you can set it in the RTC configuration menu. You can always change them later through your code.

After doing the above-said steps you can now generate code. This will give you an initialization code.

To read the value from the RTC registers. You need to remember the following thing.

From Section 38.3.8 of RM0351 Rev 1 Reference Manual

It says that reading the sub-second register or Time register alone will lock the value. It will remain locked until the Date register is read.

To prevent the lockup from happening. It is suggested to read time and date simultaneously one after the another.

Here I am writing working code

 MX_RTC_Init();				// RTC initalization and configuration created using integrated cube mx 
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

  RTC_TimeTypeDef readTime;	// RTC Time structure 
  RTC_DateTypeDef readDate;	// RTC Date structure
  while (1)
  {
    /* USER CODE END WHILE */
    

    /* USER CODE BEGIN 3 */
/*  function to read time from RTC shadow register */
    HAL_RTC_GetTime(&hrtc, &readTime, RTC_FORMAT_BIN);

/* function to read date from RTC shadow register	*/
    HAL_RTC_GetDate(&hrtc, &readDate, RTC_FORMAT_BIN);

    printf("Minute: %d\t",readTime.Minutes);
    printf("Seconds: %d\n",readTime.Seconds);

    HAL_Delay(1000);	// HAL Delay of 1000 millisecond
  }
  /* USER CODE END 3 */
}

I am using print statements for debugging using stm32cube ide.
How to use printf using serial wire debug on STM32L476 Discovery

Posted on Leave a comment

How to Perform Discrete Fourier Transform on N-Point Sequence using STM32L476G

x(n) = { 0, 1, 0, 1}

Here x(n) is a 4 point sequence

Now to perform Fourier transform on this sequence.

DFT Formula

Here X(k) is the DFT of x(n)

‘k’ is the index representing individual frequency component

‘N’ is the Length of the sample sequence

‘n’ is an index of the element of the sequence in x(n)

For example: if we calculate the value for k =1

This will give us the X(1)

So, if the sequence is sampled at 4Hz and the sampling frequency is equal to two times the max frequency. Then X(1) gives us the 1 Hz frequency component.

To calculate Euler identity

Here is the code:

/*
* Author: ABHAY KANT
* Discrete Fourier Transform using STM32L476vg on STM32L476g-Disco board.
* computes N point DFT
* computes magnitude of N/2 Points of dft
* computes phase of N/2 points of dft
* NOTE: DFT array is named xfft. It DOES NOT Calcultes DFT using FFT algo.
* Limitations: for a 2000 point sequence it takes a lot of time.
               And as the number of points increase the computational time also increases.
a rough estimate of time for a 2000 point dft it takes roughly ~ 60 seconds. 
*/
asm("nop");
//int xn[6] = {1,1,2,2,3,3};

int16_t Len = 1024; 
float xn[Len];

float xfft[Len * 2];

/*
 * calculating phase and mag for only N/2 since the value generated after N/2 are conjugate 
 */
float phase[Len/2], mag[Len/2];
int	k = 1;
int	N = 0;
int	n = 0;
float	real = 0;
float	imag = 0;
float	param = 0;
int	freq = 10;
int i;

/*
 * These two "for loops" are used to initalize the array with zero's
 */
for(n=0;n<=Len;n++){xn[n] = 0;}
for(n=0;n<=Len*2;n++){xfft[n] = 0;}



/*
 * Generating a sine Wave 
 */

	for(i=0; i<Len/2; i++){
		xn[i+512] = sin((2 * 3.1415926 * i * freq)/Len);
	}

N = Len;				
/* Note: if Len/8 then it will only calculate the 1/8 th term from 0 only.*/
/*
 * This loop calculates the x[n].e^(-j2.PI.n.k/N)
 */

	for(k=0 ; k<N ; k++){

		for(n=0 ; n<N; n++){
		param = ((2 * M_PI * n * k)/N);
		real = real + ( xn[n] * cos(param) );
		imag = imag + ((-1) * xn[n] * sin(param) );
		}
		xfft[2 * k] = real;
		xfft[(2 * k) + 1] = imag;
		real = 0;
		imag = 0;
	}



/*
 * Calculate phase angle of each frequency component
 */
float temp;
for(k=0; k<N/2;k++)
{
	temp = xfft[(2 * k ) + 1] / xfft[2 * k];
	phase[k] = atan(temp);
}

/*
 * Calculate Magnitude of each frequency 
 */

for(k=0; k<N/2;k++)
{
	temp = sqrt( (xfft[(2 * k ) + 1] * xfft[(2 * k ) + 1] ) + ( xfft[2 * k] * xfft[2 * k] ) );
	mag[k] = temp;
}
asm("nop");  //added to support for creating breakpoint during debug
Posted on Leave a comment

How to add CMSIS DSP Library to STM32 Cube IDE Project for stm32l476vg

To add CMSIS DSP library in you stm32cube project.

You can follow the steps written on ST’s website

Configuring DSP libraries on STM32CubeIDE

I have also made a video.

In this video. I have shown steps to add the arm_math.h header file. You need to configure the stm32 cube ide.

Posted on Leave a comment

IDE Supporting STM32L476-Discovery

An IDE combines a range of different tools which are essential for the development of software. Different IDE from different vendors is available.

Here are the IDE that I have used.

  1. STM CUBE IDE
    website: https://www.st.com/en/development-tools/stm32cubeide.html
    It is distribuited freely by ST. You can use this and it has a good device support and newer devices are quickly added to it. ST uses the eclipse IDE as the base and then they have customized it heavily for the microcontroller development. It also comes with their ST cube MX integrated in it. Which makes development quicker. From the information i have gathered till now it uses gcc as their compiler. Support is available at the forum hosted by ST on thier website.
    They offer support for freeRTOS out of the box.
  2. Keil MDK
    website: https://www2.keil.com/mdk5
    They have a wide support for ARM based devices. You can download the IDE from thier website. It has two version one is the evaluation which limits your code size to 32 Kilo Bytes; but it is good for begineers. The second is the paid option. In both the version all the tools works fine. It is just the code size that puts a limit.
    Keil also host a huge knowledge base on their website. It also has some sample which can be usefull in getting started.
  3. IAR Embedded Workbench for Arm (EWARM)
    website : https://www.iar.com/products/architectures/arm/iar-embedded-workbench-for-arm/
    They are also used by the electronic industry. They also has their own compiler which is written for the speed. They have a standard layout and option. They are user friendly. From the information gathered by me they have tested functions only. So it is very standardised set of tool. They also have put a limit on their evualtion IDE of 32 Kilo Byte Code size.
Posted on Leave a comment

STM32L476vg Discovery Kit Images

These are two images of the development board.

Almost entirely the board is made using SMD components. There are some through-hole components.

The back of the development board shows us the different fuses and connections.
At the back, there is a battery holder which can be powered using cr2032.

The top half of the board has an st-link debugger.

Posted on Leave a comment

STM32L476vg ARM Cortex M4F Architecture

It uses ARM v7E-M architecture.

It a Harvard based architecture with two distinct buses for data and memory.

It has all the instruction set of M0, M1 and M3 .

It also has an additional feature set to support Floating-point Arithmetic. IEEE754 standard in single precision and double precision.

The following points are from the programming model.

There are three modes of operations:

  1. Thumb State
    1. Thread mode: Privileged
    2. Thread mode: Unprivileged
  2. Debug mode

Two thread mode are given to support a operating system. Kernel software run in priviledged mode and the user application software runs in unprivledged mode.

Unprivileged mode has some restriction on memory access.

Privileged mode has full access to system resources.

If an operating system is running and a user application needs to access the Privileged resources it has to generate an exception/interrupt and then the interrupt will be taken by the handler and put the system in privilege mode.

You can switch from privilege mode to unprivileged mode by setting nPRIV and SPSEL bit in the CONTROL register.

Just like all the other processors ARM Cotex M4 has registers and pointer registers.

The major difference is the use of two different stack pointer registers.

  1. Main Stack Pointer (MSP)
  2. Process Stack Pointer (PSP)

If application is running in privileged mode than main stack pointer will be used. And if the application is working in unprivileged the process stack pointer will be used.

General Purpose Registers:

R0 – R12 – General Purpose Register

R13 – Stack Pointer (SP) {MSP and PSP}

R14 – Link Register (LR)

R15 – program counter (PC)

Special registers:

  • xPSR – {APSR, EPSR, IPSR}
  • FAULTMASK
  • BASEPERI
  • PRIMASK
  • CONTROL
floating point registers of arm cortex m4f

There are 32 FPU registers from s0 to s31.

They group together to form a single 64-bit register. which are from D0 to D15

There is a Floating Point Status and Control Register (FPSCR).