Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Sine Wave Generation with SPI and TIM interrupt in STM32_v2

Status
Not open for further replies.

uranyumx

Advanced Member level 4
Joined
Mar 5, 2011
Messages
102
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,296
Activity points
2,093
Hello,
On my circuit, there is an external 12-bit DAC. I want to modulate the DAC output with a sine wave. So I generate a sine wave with a lookup table. I set maximum value as 1575 (equals to 1.92 V) because the DAC output is amplified 2 times with another circuit. Because of the 5V compliance voltage. I set this value.

Code:
const uint16_t Wave_LUT_100_Per_Modulation[NS] = {788, 826, 865, 904, 942, 980, 1018, 1055, 1091, 1127, 1161, 1195, 1228, 1260, 1290,
1320, 1348, 1374, 1400, 1423, 1446, 1466, 1485, 1502, 1518, 1531, 1543, 1553, 1561, 1568,
1572, 1574, 1575, 1573, 1570, 1565, 1558, 1549, 1538, 1525, 1510, 1494, 1476, 1456, 1435,
1412, 1387, 1361, 1334, 1305, 1275, 1244, 1212, 1178, 1144, 1109, 1073, 1036, 999, 961,
923, 885, 846, 807, 768, 729, 690, 652, 614, 576, 539, 502, 466, 431, 397,
363, 331, 300, 270, 241, 214, 188, 163, 140, 119, 99, 81, 65, 50, 37,
26, 17, 10, 5, 2, 0, 1, 3, 7, 14, 22, 32, 44, 57, 73,
90, 109, 129, 152, 175, 201, 227, 255, 285, 315, 347, 380, 414, 448, 484,
[CODE]520, 557, 595, 633, 671, 710, 749, 787};

I set the external DAC value with this code. But the modulated maximum amplitude of the signals is not matching with non-modulated signal amplitude. The maximum value of the amplitude modulated signal is every time 0.5V. Do you have any suggestion about the problem? The below code is running in the TIM callback function.

Code:
Divison_Table[z] = round((102.4-(102.4*1)) + (1*round((Wave_LUT_100_Per_Modulation[z]/(1575/102.4)))));
                                            HAL_GPIO_WritePin(DAC_CS_GPIO_Port, DAC_CS_Pin, GPIO_PIN_RESET);
                                            DACA_Buf = DAC_A_Write << 12 | Divison_Table[z];
                                            HAL_SPI_Transmit(&hspi2,(uint8_t*)&DACA_Buf,2,100);
                                            HAL_GPIO_WritePin(DAC_CS_GPIO_Port, DAC_CS_Pin, GPIO_PIN_SET);

                                            HAL_GPIO_WritePin(DAC_CS_GPIO_Port, DAC_CS_Pin, GPIO_PIN_RESET);
                                            DACB_Buf = DAC_B_Write << 12 | Divison_Table[z];
                                            HAL_SPI_Transmit(&hspi2,(uint8_t*)&DACB_Buf,2,100);
                                            HAL_GPIO_WritePin(DAC_CS_GPIO_Port, DAC_CS_Pin, GPIO_PIN_SET);

                                            z++;
                                            if (z>=127)z=0;     }
 
Last edited by a moderator:

Hello!

I want to modulate the DAC output with a sine wave.

What do you mean by modulate the DAC output?
Usually you feed the DAC with data, and it spits out an analog value, that's it, there is no modulation.
Now I don't feel like reading all your code, but what do you expect this to do:
Code:
round((102.4-(102.4*1))
This will get to:
round((102.4 - 102.4))
which is 0.
Why bothering adding 0 in your code?

Dora.

Addendum: by the way, what about starting with a plain sine wave to the output.
In this case, do you get a signal at DAC0 or DAC1?
 

Hi,

The values in the table do not give a clean sinewave (just on a quick view)...

I also don't understand the calculation:
* Multiply with 1 ... is useless at all
* If you want a multiply output to be float ... better use 1.0 than 1
* (102.4-(102.4*1)) .... will always be zero, thus it's also useless
* (Wave_LUT_100_Per_Modulation[z]/(1575/102.4)) ... avoid division with (1575/102.4) better multiply with (102.4/1575)
...and even better if you define (102.4/1575) as a const, so you can be sure the calculation is done once by the compiler instead of continously during runtime
... and even more better if you store the lookup table exactly with the values you need. ... no runtime calculations at all


I see no clean timing for the DAC outputs. Thus the samples may not be output at a fix, constant sampling rate, which is urgent when you want a clean sinewave and predictable output frequency. Currently the output frequency depends on processing power and code. Every time you change the code the output frequency will change, too.

Also the output depends on the used DAC and your schematic. --> show these informations.

****
There are probably thousands of examples, tutorials, application notes ... on how to do DAC outputs (and sinewave generation) properly.
Read through them. Learn from them. Adjust existing code for your needs.

Klaus
 

Hello!

I agree. And I would also add that when playing with an ADC, you usually don't need other than integers. If you absolutely need floats, for example to scale up or down, yes, calculating 1/n at start is usually a good solution. Beside this, 102.4 is 1024 / 10. There is certainly a better way to calculate this. 1575 / 102.4 is the same as
1575 * 10 / 1024. The compile will translate the 1024 division to >> 10 (*), and 1575*10 is an integer calculation, therefore very fast.

(*) Never replace a multiplication or division by a shift yourself. Let the compiler do it for you.

Dora.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top