PDA

View Full Version : PicBasic Pro code to drive MCP4291 DAC?



jellis00
- 8th June 2011, 02:12
Can anyone point me to posts/tutorials for PicBasic Pro code to drive MCP4291 DAC? I did an advanced search of the Forum using keywork DAC and came up empty. Will probably be using a PIC16F676 to control the MCP4291 DAC.

ScaleRobotics
- 8th June 2011, 15:03
Hi jellis00

Here's an example in basic (but the wrong basic) for the MCP4921. It's a little past half way through:

http://www.mikroe.com/eng/chapters/view/46/chapter-13-examples/

aajgss
- 9th June 2011, 07:58
This is what I have used to produce 3 sinewaves out of 3 MCP4921 DACs. Cant find an MCP4291


include "modedefs.bas"
ANSEL = %00000000 'Disable analog inputs Channels 0 to 7
ANSELH = %00000000 'Disable analog inputs Channels 8 to 11
WPUB = %00000000 'Disable weak pull-ups
ADCON0 = %00000000 'A/D Module is OFF
CM1CON0 = %00000000 'Comparator1 Module is OFF
CM2CON0 = %00000000 'Comparator2 Module is OFF
INTCON = %00000000 'INTerrupts CONtrol
TRISA = %00000000 'Set Input/Output (0 to 5)
PORTA = %00000000 'Ports High/Low (0 to 5)
TRISB = %00000000 'Set Input/Output (4 to 7)
PORTB = %00000000 'Ports High/Low (4 to 7)
TRISC = %01000000 'Set Input/Output (0 to 7)
PORTC = %01000000 'Ports High/Low (0 to 7)
addr var word [90]
addr[1]=2139
addr[2]=2278
addr[3]=2415
addr[4]=2551
addr[5]=2684
addr[6]=2813
addr[7]=2938
addr[8]=3059
addr[9]=3175
addr[10]=3285
addr[11]=3389
addr[12]=3486
addr[13]=3576
addr[14]=3658
addr[15]=3732
addr[16]=3797
addr[17]=3854
addr[18]=3902
addr[19]=3940
addr[20]=3969
addr[21]=3989
addr[22]=3998
addr[23]=3998
addr[24]=3989
addr[25]=3969
addr[26]=3940
addr[27]=3902
addr[28]=3854
addr[29]=3797
addr[30]=3732
addr[31]=3658
addr[32]=3576
addr[33]=3486
addr[34]=3389
addr[35]=3285
addr[36]=3175
addr[37]=3059
addr[38]=2938
addr[39]=2813
addr[40]=2684
addr[41]=2551
addr[42]=2415
addr[43]=2278
addr[44]=2139
addr[45]=2002
addr[46]=1861
addr[47]=1722
addr[48]=1585
addr[49]=1449
addr[50]=1316
addr[51]=1187
addr[52]=1062
addr[53]=941
addr[54]=825
addr[55]=715
addr[56]=611
addr[57]=514
addr[58]=424
addr[59]=342
addr[60]=268
addr[61]=203
addr[62]=146
addr[63]=98
addr[64]=60
addr[65]=31
addr[66]=11
addr[67]=2
addr[68]=2
addr[69]=11
addr[70]=31
addr[71]=60
addr[72]=98
addr[73]=146
addr[74]=203
addr[75]=268
addr[76]=342
addr[77]=424
addr[78]=514
addr[79]=611
addr[80]=715
addr[81]=825
addr[82]=941
addr[83]=1062
addr[84]=1187
addr[85]=1316
addr[86]=1449
addr[87]=1585
addr[88]=1722
addr[89]=1861
addr[90]=1996


'-------------------------------------------------------------------------------
' Variables
SCK VAR PORTB.6 'Clock pin
CS1 VAR PORTC.0 'Chip Select Active low
CS2 VAR PORTC.1
CS3 VAR PORTC.2
SDO VAR PORTC.7 'Data Out pin
FREQ VAR BYTE
SWITCH VAR PORTC.6
counter VAR word
highbit var word
lbit var highbit.byte0
hbit var highbit.byte1
'-------------------------------------------------------------------------------
START:
IF SWITCH THEN
FREQ = 35
ELSE
FREQ = 185
ENDIF
for counter = 1 to 90
highbit = addr[counter] +20480

low cs1
SHIFTOUT SDO,SCK,msbfirst,[hbit]
SHIFTOUT SDO,SCK,msbfirst,[lbit]
high cs1
PAUSEUS FREQ
low cs2
SHIFTOUT SDO,SCK,msbfirst,[hbit]
SHIFTOUT SDO,SCK,msbfirst,[lbit]
high cs2
PAUSEUS FREQ
low cs3
SHIFTOUT SDO,SCK,msbfirst,[hbit]
SHIFTOUT SDO,SCK,msbfirst,[lbit]
high cs3
PAUSEUS FREQ
next counter
counter=1
GOTO START:
END


regards
aajgss

mark_s
- 9th June 2011, 16:04
Here's another example like aajgss's for the MCP4921. It generates a sine or cosine wave.
Would like to try speeding it up, using the MSSI or MSSp modules. If anyone has an idea for this
please post.



'************************************************* ***************
'* Name : DAC_MCP4921_WAVE.PBP *
'* Author : MARK S *
'* Date : 4/30/2011 *
'* Version : 1.0 *
'* Notes : DEMO 12BIT DAC MCP4921 - OUTPUTS SINE OR COSINE WAVE *
'* : FIXED FREQUENCY SHIFTOUT VERY SLOW, TRY MSSP MODULE *
'************************************************* ***************
'PIC18F4680 PBP2.6, MPASM
DEFINE OSC 20
'REGISTERS
INTCON = %00000000
INTCON2.7 = 0 'weak pullups portB
'ADCON0 = %00000001 'A/D module enabled, channel 0
ADCON1 =%00001111 'ALL DIGITAL
'ADCON2 = %10101011 'Right justified, 12 Tad, Frc clock
CMCON =%00000111 'COMP OFF
T3CON = 0
CCP1CON = 0 'ECCP OFF
ECCP1AS = 0
ECCP1DEL = 0
'PORTS
TRISA = %00000000 ' PORTA ALL OUTPUT
TRISB = %00000000 ' PORTB
TRISC = %00000000 ' PortC TMR1 RC0 = INPUT
TRISD = %00000000
TRISE = %00000111
'VARIABLES & DAC CONNECTIONS VREF PIN6 4921 TIED TO +5V
SCLK VAR PORTD.0 'SPI CLOCK PIN3 4921
SDAT VAR PORTD.1 'SPI DATA PIN4 4921
CS_DAC VAR PORTD.2 'Chip select PIN2 4921
LOAD_DAC VAR PORTD.3 'PIN5 4921
WAVE_INDEX VAR WORD 'TABLE POINTER
DAC_OUT VAR WORD '0-4095 OUTPUT 0 TO 5V, value returned from table

MAIN:
HIGH LOAD_DAC
HIGH CS_DAC
FOR WAVE_INDEX = 0 TO 255
'GOSUB COS_TABLE
GOSUB SINE_TABLE
'PAUSEUS 500 'LOWER OUTPUT FREQ
'----------------------
LOW CS_DAC
SHIFTOUT SDAT,SCLK,1,[%0011,DAC_OUT\12] 'Set DAC out
HIGH CS_DAC
LOW LOAD_DAC
@ NOP
HIGH LOAD_DAC
'----------------------
NEXT WAVE_INDEX
GOTO MAIN
SINE_TABLE:

lookup2 WAVE_INDEX, [0,1,2,6,10,15,22,30,39,50,61,74,88,103,120,137,156 ,_
176, 197,219,242,266,291,318,345,374,403,433,465,497,_
531,565,600,636,673,710,749,788,828,869,910,952,99 5,_
1039,1083,1127,1172,1218,1264,1311,1358,1406,1453, 1502,1550,1599,_
1648,1698,1747,1797,1847,1897,1948,1998,2048,2098, 2148,2199,2249,_
2299,2349,2398,2448,2497,2546,2594,2643,2690,2738, 2785,2832,2878,_
2924,2969,3013,3057,3101,3144,3186,3227,3268,3308, 3347,3386,3423,_
3460,3496,3531,3565,3599,3631,3663,3693,3722,3751, 3778,3805,3830,_
3854,3877,3899,3920,3940,3959,3976,3993,4008,4022, 4035,4046,4057,_
4066,4074,4081,4086,4090,4094,4095,4095,4095,4094, 4090,4086,4081,_
4074,4066,4057,4046,4035,4022,4008,3993,3976,3959, 3940,3920,3899,_
3877,3854,3830,3805,3778,3751,3722,3693,3663,3631, 3599,3565,3531,_
3496,3460,3423,3386,3347,3308,3268,3227,3186,3144, 3101,3057,3013,_
2969,2924,2878,2832,2785,2738,2690,2643,2594,2546, 2497,2448,2398,_
2349,2299,2249,2199,2148,2098,2048,1998,1948,1897, 1847,1797,1747,_
1698,1648,1599,1550,1502,1453,1406,1358,1311,1264, 1218,1172,1127,_
1083,1039,995,952,910,869,828,788,749,710,673,636, 600,_
565,531,497,465,433,403,374,345,318,291,266,242,21 9,_
197,176,156,137,120,103,88,74,61,50,39,30,22,15,10 ,6,_
2,1],DAC_OUT

RETURN

COS_TABLE:
lookup2 WAVE_INDEX, [4095,4095,4094,4090,4086,4081,_
4074,4066,4057,4046,4035,4022,4008,3993,3976,3959, 3940,3920,3899,_
3877,3854,3830,3805,3778,3751,3722,3693,3663,3631, 3599,3565,3531,_
3496,3460,3423,3386,3347,3308,3268,3227,3186,3144, 3101,3057,3013,_
2969,2924,2878,2832,2785,2738,2690,2643,2594,2546, 2497,2448,2398,_
2349,2299,2249,2199,2148,2098,2048,1998,1948,1897, 1847,1797,1747,_
1698,1648,1599,1550,1502,1453,1406,1358,1311,1264, 1218,1172,1127,_
1083,1039,995,952,910,869,828,788,749,710,673,636, 600,_
565,531,497,465,433,403,374,345,318,291,266,242,21 9,_
197,176,156,137,120,103,88,74,61,50,39,30,22,15,10 ,6,_
2,1,0,1,2,6,10,15,22,30,39,50,61,74,88,103,120,137 ,156,_
176, 197,219,242,266,291,318,345,374,403,433,465,497,_
531,565,600,636,673,710,749,788,828,869,910,952,99 5,_
1039,1083,1127,1172,1218,1264,1311,1358,1406,1453, 1502,1550,1599,_
1648,1698,1747,1797,1847,1897,1948,1998,2048,2098, 2148,2199,2249,_
2299,2349,2398,2448,2497,2546,2594,2643,2690,2738, 2785,2832,2878,_
2924,2969,3013,3057,3101,3144,3186,3227,3268,3308, 3347,3386,3423,_
3460,3496,3531,3565,3599,3631,3663,3693,3722,3751, 3778,3805,3830,_
3854,3877,3899,3920,3940,3959,3976,3993,4008,4022, 4035,4046,4057,_
4066,4074,4081,4086,4090,4094,4095],DAC_OUT

RETURN
END

aajgss
- 9th June 2011, 19:07
Mark_s

What speed are you looking for?
Mine was running at about 9 Hz on an 18F14K50. By setting Config1 to $F100 I now get around 70hZ which is what I was after.

aajgss

mark_s
- 9th June 2011, 21:09
aajgss,
I was getting similar frequencies as you, at 20mhz and 40mhz clock settings. My lookup table has 256
values, so it takes long time to cycle. I going to try the MSSP tonight and see what is gained. I know a dspic running at 80mhz can output about 4khz with the same dac and MSSP. So I am trying for 1 to 2khz. Maybe a pipe dream? I'll post the code if it works.

regards

aajgss
- 9th June 2011, 22:57
Mark_s

I'll be interested in how you go. I did try the MSSP and actually got slower. I know it was the code I had written, because its just logical it should be faster and was going to continue with it to see if I could find my error(s), but the change to the CONFIG1 gave me the frequency I wanted. If I could get it faster and use 2 degree steps instead of 4 degree steps it would be better.

regards
aajgss

mark_s
- 10th June 2011, 15:25
Okay I hammered out a routine to use the MSSP module. It gave me
a 6x speed increase over shiftout. I'm just a hack so there maybe a
better way to do it.
Results:
Shiftout MSSP
10mhz 10hz 66hz
20mhz 21hz 117hz
40mhz 42hz 2 63hz
80mhz 83hz 526hz
The 80mhz is 20mhz crystal 4xpll, overclocking probably not reliable? but worked!


'************************************************* ***************
'* Name : DAC_12BIT_MSSP *
'* Author : MARK S *
'* Date : 6/9/2011
'* SINE WAVE GENERATOR USING MCP4921 12BIT DAC *
'* USES MSSP MODULE vs SHIFTOUT *
'* PIC18F4680, PBP2.6 MPASM *
'* *
'************************************************* ***************
DEFINE OSC 20
'REGISTER SET
INTCON = %00000000
INTCON2.7 = 0 'weak pullups portB
ADCON1 =%00001111 'ALL DIGITAL
CMCON =%00000111 'COMP OFF
T3CON = 0
CCP1CON = 0 'ECCP OFF
ECCP1AS = 0
ECCP1DEL = 0
SSPSTAT = %00000000 'TX IDLE LOW,SAMPLE MIDDLE
SSPCON1 = %00100000 ' ENABLE MSSP,CLK IDLE LOW,FOSC/4
'-----------------------------------------------------
'PORTS
TRISA = %00000000 ' PORTA ALL OUTPUT '
TRISB = %00000000 ' PORTB
PORTB = %00000000 ' CLEAR PORTB
TRISC = %00000000 ' PortC
TRISD = %00000000
TRISE = %00000000
'----------------------------------------------------
'DAC CONNECTIONS
'VREF PIN6 MCP4921 TIED TO +5V
'CLOCK PIN3 MCP4921 TO PORTC.3 "SCK"
'DATA PIN4 MCP4921 TO PORTC.5 "SDO"
'CS PIN2 MCP4921 TO PORTD.2
'LOAD PIN5 MCP4921 TO PORTD.3 CONNECT THIS TO GROUND TO SAVE A PORT PIN
'--------------------------------------------------
'VARIABLES
CS_DAC VAR PORTD.2
LOAD_DAC VAR PORTD.3 'KEEP LOW
WAVE_INDEX VAR WORD
DAC_OUT VAR WORD
DAC_OUT1 VAR WORD
SSPIF VAR PIR1.3 ' SPI interrupt flag
'----------------------------------------------------
'START
SSPBUF = 0 ' CLEAR SPI BUFFER
SSPIF = 0 ' CLEAR SPI INTERUPT FLAG.
LOW LOAD_DAC
'================================================= ==================
MAIN:
HIGH CS_DAC
FOR WAVE_INDEX = 0 TO 255

GOSUB SINE_TABLE
LOW CS_DAC
DAC_OUT1 =$3000 | DAC_OUT ' Combine table value with dac reg control
SSPBUF = DAC_OUT1.HIGHBYTE 'SEND HIGH
While SSPIF = 0 ' WAIT FOR TX TO COMPLETE
Wend
SSPIF = 0 'RESET INT FLAG
SSPBUF = DAC_OUT1.LOWBYTE 'SEND LOW
While SSPIF = 0 ' WAIT FOR TX TO COMPLETE
Wend
SSPIF = 0 'RESET INT FLAG
HIGH CS_DAC
NEXT WAVE_INDEX
GOTO MAIN

SINE_TABLE:

lookup2 WAVE_INDEX, [0,1,2,6,10,15,22,30,39,50,61,74,88,103,120,137,156 ,_
176, 197,219,242,266,291,318,345,374,403,433,465,497,_
531,565,600,636,673,710,749,788,828,869,910,952,99 5,_
1039,1083,1127,1172,1218,1264,1311,1358,1406,1453, 1502,1550,1599,_
1648,1698,1747,1797,1847,1897,1948,1998,2048,2098, 2148,2199,2249,_
2299,2349,2398,2448,2497,2546,2594,2643,2690,2738, 2785,2832,2878,_
2924,2969,3013,3057,3101,3144,3186,3227,3268,3308, 3347,3386,3423,_
3460,3496,3531,3565,3599,3631,3663,3693,3722,3751, 3778,3805,3830,_
3854,3877,3899,3920,3940,3959,3976,3993,4008,4022, 4035,4046,4057,_
4066,4074,4081,4086,4090,4094,4095,4095,4095,4094, 4090,4086,4081,_
4074,4066,4057,4046,4035,4022,4008,3993,3976,3959, 3940,3920,3899,_
3877,3854,3830,3805,3778,3751,3722,3693,3663,3631, 3599,3565,3531,_
3496,3460,3423,3386,3347,3308,3268,3227,3186,3144, 3101,3057,3013,_
2969,2924,2878,2832,2785,2738,2690,2643,2594,2546, 2497,2448,2398,_
2349,2299,2249,2199,2148,2098,2048,1998,1948,1897, 1847,1797,1747,_
1698,1648,1599,1550,1502,1453,1406,1358,1311,1264, 1218,1172,1127,_
1083,1039,995,952,910,869,828,788,749,710,673,636, 600,_
565,531,497,465,433,403,374,345,318,291,266,242,21 9,_
197,176,156,137,120,103,88,74,61,50,39,30,22,15,10 ,6,_
2,1],DAC_OUT

RETURN
END

rmteo
- 10th June 2011, 16:58
I don't know what the OP's application is but using a PIC and a serial DAC (MCP4921) to generate sine waves is extremely inefficient. It consumes a tremendous amount of CPU resources and gives very poor performance - limited frequency range and resolution. Using a DDS chip such as the AD8937 (which incidentally costs about the same as then MCP4921) allows you to generate sine (and triangle and square) waveforms from 0-16MHz with 0.06Hz (28-bit) resolution. For low frequency applications (such as VFDs) you can use a lower speed clock - with a 1MHz clock you get 0-1MHz and 0.004Hz resolution. It uses the same SPI interface as the MCP4921 and the slowest 4MHz PIC will still be able to generate up to a 16MHz sine wave.

gadelhas
- 10th June 2011, 19:20
I don't know what the OP's application is but using a PIC and a serial DAC (MCP4921) to generate sine waves is extremely inefficient. It consumes a tremendous amount of CPU resources and gives very poor performance - limited frequency range and resolution. Using a DDS chip such as the AD8937 (which incidentally costs about the same as then MCP4921) allows you to generate sine (and triangle and square) waveforms from 0-16MHz with 0.06Hz (28-bit) resolution. For low frequency applications (such as VFDs) you can use a lower speed clock - with a 1MHz clock you get 0-1MHz and 0.004Hz resolution. It uses the same SPI interface as the MCP4921 and the slowest 4MHz PIC will still be able to generate up to a 16MHz sine wave.

rmteo, isn't AD9837?

rmteo
- 10th June 2011, 22:33
Yes, it is AD9837. Sorry for the typo.

gadelhas
- 10th June 2011, 22:46
Very interesting chip....

mark_s
- 10th June 2011, 23:30
rmteo,
You are correct an spi dac is not suited for generating sine waves. My goal was to
learn how to use this dac, which I did. I have used the AD9835 and AD9850 which are lower
resolution versions of the AD9837, which you mentioned. The 28 bits of resolution is fantastic and
I may request a sample since Digikey and Mouser don't stock the AD9837 yet.

Regards

jellis00
- 11th June 2011, 01:46
Here's another example like aajgss's for the MCP4921. It generates a sine or cosine wave.
Would like to try speeding it up, using the MSSI or MSSp modules. If anyone has an idea for this
please post.


Thank you aajgss and mark_s. I should have been more specific in my original post, but I am not using the DAC to generate sinusoidal, triangular or square waveforms. All I am doing is outputing an analog voltage value that equates to a calculation performed by the MCU. So I don't think I need the complexity of a look-up table for generating an output analog waveform. Instead, I am just looking for example code to output an analog voltage by the DAC that will change in value relatively slowly every 20 to 100 msecs. Anyone have suggestion as to how to do this, or better yet example PICBASIC Pro code? Oh, and BTW, the DAC I am using is an MCP4921 not a MCP4291 (typo on my part).

aajgss
- 12th June 2011, 13:48
Good stuff Mark_s

I tried your code and got a slightly faster speed than before. The difference being I was doing 360 Degrees in 90 steps where yours is 360 degrees in 510 steps so you code has sped it up by neary 6 times.

Thanks
aajgss

kmsharaf
- 28th May 2013, 12:26
Has Anyone used AD9837 and got programmable pure sine wave above 10MHz?

Normnet
- 29th May 2013, 02:11
Would the PIC16F178X (http://www.microchip.com/pagehandler/en-us/press-release/microchip-expands-8-bit-pic-mi.html) with 16 bit PWM (http://ww1.microchip.com/downloads/en/DeviceDoc/41675A.pdf) be of any help with this application?


Norm

ascpicforum
- 14th July 2015, 03:28
jellis00, i am trying to get the same code for the mcp4921 to output 0-5v. Did you ever find the sample code to do this?