|Digital to Analog Conversion
||[Sep. 25th, 2008|03:39 pm]
As they say, "it's an analog world."
I wrote a short program in Microchip's MPLAB using their C18 compiler to test the free sample 12-bit DAC I received in the mail.
The program takes the SIN of a floating point number, ADdata, and like a typical sin function, gives an output from -1 to +1, depending on the value of ADdata. It then multiplies the result by 32768 (2^15) to give a range from -32768 to +32767. It adds 32768 to that, giving a final range of 0 to 65535. This gives us a number that can be represented as a 16-bit integer. The DAC is only 12 bits, though, so we send the highest 12 bits of the integer and discard the lowest 4 bits (which don't really matter that much anyways). The data is sent to the DAC via the SPI (serial port interface). ADdata is then incremented by a small amount, and we do the whole thing over again.
The PIC is running on it's internal RC 8MHz oscillator, and the instructions are executed at 2MHz. You'd think you could get a pretty decent sinusoidal frequency out of the DAC, but the following image shows that it output a wave at a measly 5Hz.
This is probably due to the fact that I used a high level language (HLL), which adds some extraneous overhead which wouldn't be there if I programmed in assembly. The sin function and floating point routines add a LOT of instructions to the program. Another factor that determines the frequency is how much the variable ADdata is incremented. Here, it is incremented by 0.1. When this number was increased, to say, 1, the resolution of the waveform became quite choppy, like in the figure below, but the frequency increased a bit.
At an increment level of only 0.01, the sin wave was very smooth, but the frequency was only about 2Hz.
The guts of the program are below:
data = (int)((sin(ADdata)*32768.)+32768.); //do math and convert float to int
dataL = (char) (data >> 4); //get the middle 8 bits of the int
dataH = (char) (data >> 12); //get the highest 4 bits of the int
SPI_CS=0; //chip select DAC
WriteSPI(0b00010000 + dataH); //send 1st byte
WriteSPI(dataL); //send 2nd byte
SPI_CS=1; //deselect DAC
ADdata = ADdata+.1; //increment ADdata