Skip to main content
Graduate II
August 28, 2024
Solved

Sine wave generation using DAC

  • August 28, 2024
  • 4 replies
  • 1398 views

Hello everyone, 

I am trying to generate sine wave using DAC and interrupts in my STM32F446 board. I want to do it without using array model. I am getting b infinite_loop when the program is run in debug mode. I have initialised "use float with printf/scanf" settings. The code is as follows:-

#include "stm32f4xx.h"

#include <math.h>

volatile float data;

#include "dac_sine.h"

#define pi 3.14159265359

volatile uint32_t theta = 0;

volatile uint32_t del_theta = 1;

float value;

 

void dac_sine_gpio_init(void)

{

 

RCC->AHB1ENR |= (1U<<0); //enable clock for GPIO Port A

GPIOA->MODER |= (0b11<<10); //setting PA5 in analog mode

GPIOA->MODER |= (0b11<<8); //setting PA4 in analog mode

 

}

void dac_sine_timer_init(void)

{

RCC->APB1ENR |= (1U<<29); //Clock access to DAC Enabled

RCC->APB1ENR |= (1U<<0); //clock access to Timer2 Enabled

TIM2->PSC = 1; //setting pre-scalar value

TIM2->ARR = 999; //setting ARR value

TIM2->CR1 = (1U<<0); //counter enabled

TIM2->DIER |= (1U<<0); //update interrupt enable

DAC->CR |= (1U<<0); //DAC Channel 1 is enable

NVIC_EnableIRQ(TIM2_IRQn);

}

 

void tim_callback(void)

{

theta = theta + del_theta;

if (theta > 999) {theta = 0;}

float sine_value = sin((theta*2*pi)/1000);

uint32_t dac_value = (uint32_t)((sine_value + 1)*999);

 

//if (theta > (2*pi)) {theta = 0;}

//data = sin (theta); //statement for sine waveform

//uint16_t dac_value = (uint16_t)((data+1)*0.5*4095);

DAC->DHR12R1 = theta; //statement to load the data in channel 1 of DAC

}

 

void TIM2_IRQHandler(void)

{

if (TIM2->SR & (1U<<0)) //check if update interrupt flag is raised

{TIM2->SR &=~ (1U<<0);} //clear the flag

tim_callback(); //go to this callback function

}

can someone pls help me getting sine values in live expression windows please.

thanks in advance.

    This topic has been closed for replies.
    Best answer by waclawek.jan

    Use f suffix to the float constants (including pi). Otherwise the calculations are performed as double, which is very slow. 

    Also make sure you have switched on the hardware floating point unit, and also have switched on compiler optimisations. 

    JW

    4 replies

    Technical Moderator
    August 28, 2024

    Hello,

    Please use </> button to paste your code. I'm editing it then ..

    and review our tips on how to post a thread here.

    Graduate II
    August 28, 2024

    Ahhh sir, are you sure sin is calculated quicker as tim period ?

    float sine_value = sin((theta*2*pi)/1000);

     

    Graduate II
    August 29, 2024

    sir, can you please elaborate how to go about this problem?

    Graduate II
    August 29, 2024

    Your question is how live expression. Simply make it global variable not local, but for what?

    And problem .... normal way to work with sine is precalculated tables in RAM. Create array DAC_value[1000] and fill it in main. 

    void tim_callback(void)
    {
    theta = theta + del_theta;
    if (theta > 999) {theta = 0;}
    
    DAC->DHR12R1 = DAC_value[theta]; //statement to load the data in channel 1 of DAC
    }

     

    Super User
    August 29, 2024

    Use f suffix to the float constants (including pi). Otherwise the calculations are performed as double, which is very slow. 

    Also make sure you have switched on the hardware floating point unit, and also have switched on compiler optimisations. 

    JW

    Graduate II
    August 29, 2024

    It would be a LOT faster for you to use a complex phasor instead of a sine wave. sin(x) is one of the most expensive functions you can call. A complex phasor would do the same thing with a fraction of the processing power.