PDA

View Full Version : PIC18F4525 to DAC (PCF8591P) I2CWrite too fast?



opticsteam1
- 4th April 2008, 05:40
I have an I2C compatible DAC (PCF8591P (http://www.nxp.com/acrobat/datasheets/PCF8591_6.pdf)) that I've connected to the SCL/SDA of my PIC18F4525 (http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocName=en010298). I'm using the following code to program it, and an external 20MHz oscillator to the PIC. The output of the DAC should simply ramp from 0 to 5V repeatedly, but I'm getting some weird noise from it when I look at it from the oscilloscope. I checked the output of SCL to see what frequency it is and the oscillator says that its around 1MHz! Is that normal? I thought standard I2C is normally run at 100kHz...
It feels like that the communication synchronization would occur if the SCL/SDA was slowed down to 100kHz, but I don't know how to do that in code, or what I should change in the code. I'm pretty inexperienced in PicBasic Pro, so any help you could provide would be appreciated.


DEFINE OSC 20 '20 MHz external oscillator

SDA var PORTC.4 'SDA port
SCL var PORTC.3 'SCL port

Loop VAR Byte

DACAddressByte con %01001000 ' DAC Address byte (7-bit address: 1001 000)
DACControlByte con %01000000 ' DAC control byte (sets DAC to D/A:0100 0000)

start:

For Loop = 0 To 255 'ramp up
I2CWRITE sda,scl,DACAddressByte,DACControlByte,[Loop] 'I2CWrite
Pause 10 'wait for write
Next

GoTo start

mister_e
- 4th April 2008, 06:05
Do you have any Pull-up resistors on SDA & SCL ~4.7K?

What are your configuration fuses settings?

In your code.. what you call 'DACAddressByte' have to be %10010000 instead, and DACControlByte can't be a constant. must be a Byte variable.

Finnally, it's possible that you have a SCL frequency a bit higher than 100kHZ... but 1MHz it's impossible... unless i really missed something ;) one thing is sure, depending of the signal you measure, if it's noise.. frequency measure could be anything that's for sure.

Anyways. Your current device support MAX 100KHz. But @20Mhz, I2CWRITE will produce a higher frequency, you need to add the following line to your code

DEFINE I2C_SLOW 1

Read I2CWRITE section in your manual for more details.

opticsteam1
- 4th April 2008, 07:02
I'm using pull-up resistors on the SDA/SCL lines that are 2.2k (which i think is standard for 100kbps I2C communication).

I'm pretty new to coding in PicBasic Pro, but what is a configuration fuses setting? I'm coding/compiling it in MicroCode Studio using the PicBasic Pro compiler and using the MPLAB PICSTART PLUS programmer to program it to the board. It seems to use MPASM to convert the code from Assembly to Hex.

The period of the SCL signal when it's hooked up to the oscilloscope is a regular square wave (not noisy) with a period of 1us, which was a very clear clock signal showing 1MHz. With the changes applied to the code, the clock signal was still showing a frequency of 1MHz. It doesn't change when adding the I2C_SLOW code.



DEFINE OSC 20 '20 MHz external oscillator
DEFINE I2C_SLOW 1

SDA var PORTC.4 'SDA port
SCL var PORTC.3 'SCL port

Loop VAR Byte

DACAddressByte con %10010000 ' DAC Address byte (7-bit address: 1001 000)
DACControlByte VAR BYTE ' DAC control byte (sets DAC to D/A:0100 0000)
DACControlByte = %01000000

start:

For Loop = 0 To 255 'ramp up
I2CWRITE sda,scl,DACAddressByte,DACControlByte,[Loop] 'I2CWrite
Pause 10 'wait for write
Next

GoTo start

opticsteam1
- 4th April 2008, 07:27
Also, I'm a little confused on my usage of I2CWrite...

According to the DAC's datasheet, the first byte sent needs to be the address byte which is 1001(A2,A1,A0)W which is programmed to 000, so 1001000W. Then the control byte is sent and stored in the control register, which flags the analog output, and sets everything else to 0 (01000000). The I2CWrite definition, however, sends the "Control" first and the optional Address out second, followed by the value. ??

mister_e
- 4th April 2008, 08:16
Hey welcome here :D

Configurations fuses are some of the PIC settings which may screw a design pretty quick. One of the most important is the Oscilattor setting. By default, PBP use XT mode, this is good enough for crystal ~4Mhz, you're using 20MHz so you need to change the OSC mode, in your case you select HS mode. Refer to section 2 of your datasheet.

There's several way to do it, but we suggest you to place the settings in your code, so you don't need to change it all the time before you program your PIC.

Short tutorial about that bellow... post 1-5 cover most thing you have to know.
http://www.picbasic.co.uk/forum/showthread.php?t=543

I'll suggest you to paste the following lines in your code.


asm
__CONFIG _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOREN_ON_2L & _BORV_3_2L
__CONFIG _CONFIG2H, _WDT_OFF_2H
__CONFIG _CONFIG3H, _PBADEN_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_ON_3H & _CCP2MX_PORTC_3H
__CONFIG _CONFIG4L, _DEBUG_OFF_4L & _XINST_OFF_4L & _LVP_OFF_4L & _STVREN_ON_4L
endasm
Definitions of the above are in your datasheet section 23.1

once you have it and change your

DACAddressByte con %01001000
to

DACAddressByte con %10010000

it will produce this SCL signal
<img SRC="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2469&stc=1&d=1207293080">

and
<img SRC="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=2468&stc=1&d=1207293035">

I2CWRITE send the ControlByte first, then the address.. it's the usual naming convention for EEPROM, in your case they named it another way to better fit with their own convention... but the sequence must be the same as in your datasheet...so the way you did.