Difference between revisions of "PIC32MX: I2C DAC"
NickMarchuk (talk | contribs) |
|||
(6 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
== Original Assignment == |
|||
'''Do not erase this section!''' |
|||
Your assignment is to interface to the MAX518 I2C digital to analog converter (DAC). |
|||
== Overview == |
== Overview == |
||
Note: PROJECT NOT FULLY FUNCTIONAL! |
|||
On this page we will present code and a wiring schematic that allows for the PIC32MX to speak to an 8-bit Digital to Analog Converter. In particular, our project used the MAX518 DAC. |
On this page we will present code and a wiring schematic that allows for the PIC32MX to speak to an 8-bit Digital to Analog Converter. In particular, our project used the MAX518 DAC. |
||
The MAX518 requires three bytes (note: 1 byte = 8 bits) of information every time it changes its output. The first byte defines the DAC as a slave, and contains the address. This byte WILL NOT change when repeatedly sending data to the DAC. The next byte is the command byte. The bits are, in order of most significant to least significant: R2, R1, R0, RST, PD, X, X, A0. R2 = R1 = R0 =0. This is always true. The next bit, RST, will reset all registers if set to 1. Setting PD to 1 will tell the device to hibernate after it outputs the desired data. The next two bits do not matter (X = don't care). Finally, the address bit, instructing the DAC which output to send the data too. The third byte sent to the MAX518 is the 8 bit value the DAC should output. |
|||
While we were able to send data to the DAC, we were NOT able to elicit output from said DAC. |
|||
== Circuit == |
|||
This particular DAC, the MAX518 requires three bytes (note: 1 byte = 8 bits) of information every time it changes its output. The first byte defines the DAC as a slave, and contains the address. This byte WILL NOT change when repeatedly sending data to the DAC. The next byte is the actual data the IC should convert. |
|||
The DAC used is a MAX518 Digital to Analog Converter Chip. The following circuit was used after consulting the MAX518 data sheet under the practical application wiring diagrams section. The two PIC32 NU32 outputs are shown as Serial Data Clock (A14) and Serial Data Output (A15). |
|||
The third byte is named the command byte. The bits are, in order of most significant to least significant: R2, R1, R0, RST, PD, X, X, A0. R2 = R1 = R0 =0. This is always true. The next bit, RST, will reset all registers if set to 1. Setting PD to 1 will tell the device to hibernate after it outputs the desired data. The next two bits do not matter (X = don't care). Finally, the address bit, instructing the DAC which output to send the data too. |
|||
One thing to keep in mind: the MAX518 is a 5V chip and requires 3.5V to read 'high' at any of its inputs, and the PIC can only put out 3.3V. Pull up resistors R1 and R2, 1 kOhm, allow the MAX518 to receive data from the PIC. The MAX518 can change its outputs (0 and 1) from 0 to 5V with 8 bit resolution. |
|||
== Circuit == |
|||
The circuit was fairly simple after consulting the DAC online data sheets under the practical application wiring diagrams section. The Chip is a MAX 518 Digital to Analog Converter Chip. The two PIC32 NU32 outputs are shown as Serial Data Clock (A14) and Serial Data Output (A15). |
|||
[[Image:I2C Schematic.jpg]] |
[[Image:I2C Schematic.jpg]] |
||
== Code == |
== Code == |
||
This code sets up the I2C to 100kHz and changes output 0 of the MAX518 every 100ms |
|||
Our code is separated into sections, each with sufficient comments to explain all functions |
|||
Our code: |
|||
<pre> |
<pre> |
||
Line 29: | Line 20: | ||
#include <HardwareProfile_NU32.h> |
#include <HardwareProfile_NU32.h> |
||
#include <plib.h> |
#include <plib.h> |
||
// Configuration Bit settings |
// Configuration Bit settings |
||
Line 38: | Line 28: | ||
// Other options are don't care |
// Other options are don't care |
||
// |
// |
||
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF |
//#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF |
||
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2 |
//#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2 |
||
//#define SYSCLK (80000000) // set system clock to 80MHz |
|||
// DEFINES |
|||
//#define PBCLK (SYSCLK/1000) // set PBCLK to 80 KHz |
|||
#define FPB SYS_FREQ // Result of bootloader |
|||
#define |
#define I2CBAUD 100000 // 100 kHz clock |
||
#define BRG_VAL ((SYS_FREQ/2/I2CBAUD)-2) |
|||
#define PBCLK (SYSCLK/1000) // set PBCLK to 80 KHz |
|||
void Delayms( unsigned t) |
|||
#define Fsck 50000 |
|||
// This uses Timer 1, can be changed to another timer. Assumes FPB = SYS_FREQ |
|||
#define BRG_VAL ((PBCLK/2/Fsck)-2) |
|||
{ |
|||
OpenTimer1(T1_ON | T1_PS_1_256, 0xFFFF); |
|||
#define Nop() asm( "nop" ) //allows for a pause command |
|||
while (t--) |
|||
{ // t x 1ms loop |
|||
// a simple puase command |
|||
WriteTimer1(0); |
|||
void i2c_wait(unsigned int cnt) |
|||
while (ReadTimer1() < FPB/256/1000); |
|||
{ |
|||
} |
|||
while(--cnt) |
|||
CloseTimer1(); |
|||
{ |
|||
} // Delayms |
|||
Nop(); |
|||
Nop(); |
|||
} |
|||
} |
|||
///////////////////////////////////////////// |
|||
///////////////////////////////////////////// |
|||
int main(void) |
int main(void) |
||
{ |
|||
ODCA = 0xC000; |
|||
unsigned char SlaveAddress; |
|||
char i2cData[3]; |
|||
//Enable channel using default values |
|||
OpenI2C1( I2C_EN, BRG_VAL ); |
|||
SlaveAddress = 0x58; |
|||
i2cData[0] = ((SlaveAddress )); |
|||
i2cData[1] = 0x05; //command line |
|||
i2cData[2] = 0xFF; //end command |
|||
while(1) // run the code over and over again |
|||
{ |
{ |
||
ODCA = 0xC000; |
|||
unsigned char addr = 0x58; |
|||
//Enable channel using default values |
|||
OpenI2C1( I2C_EN, BRG_VAL ); |
|||
unsigned char cmd = 0; //command line |
|||
unsigned char data = 0; //output data, digital value to be converted |
|||
SYSTEMConfigPerformance(SYS_FREQ); // tell PIC its operating frequency |
|||
mInitAllLEDs(); // initialize LEDs on NU32 board, defined in HardwareProfile_NU32.h |
|||
mInitAllSwitches(); // initialize switches on NU32 board |
|||
while(1) // run the code over and over again |
|||
{ |
|||
StartI2C1(); //Send the Start Bit (begin of data send) |
|||
// start the I2C communication |
|||
IdleI2C1(); //Wait to complete |
|||
StartI2C1(); // Send the Start Bit (begin of data send) |
|||
MasterWriteI2C1 (i2cData[0]); //address |
|||
IdleI2C1(); // Wait to complete |
|||
AckI2C1(); //ask for acknowledge bit before continuing |
|||
// write the address of the chip, defined by pins AD0 and AD1 on the MAX518 |
|||
MasterWriteI2C1 (i2cData[1]); //command line |
|||
MasterWriteI2C1 (addr); // address |
|||
IdleI2C1(); |
|||
IdleI2C1(); |
|||
AckI2C1(); |
|||
while( !I2C1STATbits.ACKSTAT==0 ){} |
|||
MasterWriteI2C1(i2cData[2]); //output |
|||
IdleI2C1(); |
|||
// write the command to tell the MAX518 to change its output on output 0 |
|||
AckI2C1(); |
|||
MasterWriteI2C1 (cmd); // command line |
|||
StopI2C1(); //end of data send |
|||
IdleI2C1(); |
|||
while( !I2C1STATbits.ACKSTAT==0 ){} |
|||
} |
|||
} |
|||
// wite the value to put on the output |
|||
MasterWriteI2C1(data); // output |
|||
IdleI2C1(); |
|||
while( !I2C1STATbits.ACKSTAT==0 ){} |
|||
// end the I2C communication |
|||
StopI2C1(); // end of data send |
|||
IdleI2C1(); // Wait to complete |
|||
// the total write time is ~285us with an I2C clock of 100 kHz |
|||
data++; // increase the data, make a sawtooth wave as an example |
|||
Delayms(100); |
|||
//if(data>255) { // don't have to worry about this, data is 8 bit so it will roll over automatically |
|||
// data=0; |
|||
//} |
|||
} // end while(1) |
|||
} // end main |
|||
</pre> |
</pre> |
Latest revision as of 13:34, 6 March 2010
Overview
On this page we will present code and a wiring schematic that allows for the PIC32MX to speak to an 8-bit Digital to Analog Converter. In particular, our project used the MAX518 DAC.
The MAX518 requires three bytes (note: 1 byte = 8 bits) of information every time it changes its output. The first byte defines the DAC as a slave, and contains the address. This byte WILL NOT change when repeatedly sending data to the DAC. The next byte is the command byte. The bits are, in order of most significant to least significant: R2, R1, R0, RST, PD, X, X, A0. R2 = R1 = R0 =0. This is always true. The next bit, RST, will reset all registers if set to 1. Setting PD to 1 will tell the device to hibernate after it outputs the desired data. The next two bits do not matter (X = don't care). Finally, the address bit, instructing the DAC which output to send the data too. The third byte sent to the MAX518 is the 8 bit value the DAC should output.
Circuit
The DAC used is a MAX518 Digital to Analog Converter Chip. The following circuit was used after consulting the MAX518 data sheet under the practical application wiring diagrams section. The two PIC32 NU32 outputs are shown as Serial Data Clock (A14) and Serial Data Output (A15).
One thing to keep in mind: the MAX518 is a 5V chip and requires 3.5V to read 'high' at any of its inputs, and the PIC can only put out 3.3V. Pull up resistors R1 and R2, 1 kOhm, allow the MAX518 to receive data from the PIC. The MAX518 can change its outputs (0 and 1) from 0 to 5V with 8 bit resolution.
Code
This code sets up the I2C to 100kHz and changes output 0 of the MAX518 every 100ms
#include <HardwareProfile.h> #include <HardwareProfile_NU32.h> #include <plib.h> // Configuration Bit settings // SYSCLK = 80 MHz (8MHz Crystal/ FPLLIDIV * FPLLMUL / FPLLODIV) // PBCLK = 50 KHz // Primary Osc w/PLL (XT+,HS+,EC+PLL) // WDT OFF // Other options are don't care // //#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF //#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_2 //#define SYSCLK (80000000) // set system clock to 80MHz //#define PBCLK (SYSCLK/1000) // set PBCLK to 80 KHz #define FPB SYS_FREQ // Result of bootloader #define I2CBAUD 100000 // 100 kHz clock #define BRG_VAL ((SYS_FREQ/2/I2CBAUD)-2) void Delayms( unsigned t) // This uses Timer 1, can be changed to another timer. Assumes FPB = SYS_FREQ { OpenTimer1(T1_ON | T1_PS_1_256, 0xFFFF); while (t--) { // t x 1ms loop WriteTimer1(0); while (ReadTimer1() < FPB/256/1000); } CloseTimer1(); } // Delayms int main(void) { ODCA = 0xC000; unsigned char addr = 0x58; //Enable channel using default values OpenI2C1( I2C_EN, BRG_VAL ); unsigned char cmd = 0; //command line unsigned char data = 0; //output data, digital value to be converted SYSTEMConfigPerformance(SYS_FREQ); // tell PIC its operating frequency mInitAllLEDs(); // initialize LEDs on NU32 board, defined in HardwareProfile_NU32.h mInitAllSwitches(); // initialize switches on NU32 board while(1) // run the code over and over again { // start the I2C communication StartI2C1(); // Send the Start Bit (begin of data send) IdleI2C1(); // Wait to complete // write the address of the chip, defined by pins AD0 and AD1 on the MAX518 MasterWriteI2C1 (addr); // address IdleI2C1(); while( !I2C1STATbits.ACKSTAT==0 ){} // write the command to tell the MAX518 to change its output on output 0 MasterWriteI2C1 (cmd); // command line IdleI2C1(); while( !I2C1STATbits.ACKSTAT==0 ){} // wite the value to put on the output MasterWriteI2C1(data); // output IdleI2C1(); while( !I2C1STATbits.ACKSTAT==0 ){} // end the I2C communication StopI2C1(); // end of data send IdleI2C1(); // Wait to complete // the total write time is ~285us with an I2C clock of 100 kHz data++; // increase the data, make a sawtooth wave as an example Delayms(100); //if(data>255) { // don't have to worry about this, data is 8 bit so it will roll over automatically // data=0; //} } // end while(1) } // end main