Difference between revisions of "PIC18F4520: Serial Digital-to-Analog Conversion"

From Mech
Jump to navigationJump to search
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
Since PIC microcontrollers do not offer analog outputs, a Digital-to-Analog converter (DAC) must be used to obtain an analog signal. An eight bit digital number can be converted to analog by using eight of the output pins from the PIC MCU to a separate DAC chip, however if more than one conversion is neccessary, this will quickly use up many of the available output pins from the PIC microcontroller, and require extensive wiring. Luckily, there is an easier and more effective way of doing this using <math>I^2C</math> communication. <math>I^2C</math> utilizes two lines to communicate, usually called ''SCL'' and ''SDA'' (a clock line and a data line). A "master" produces an <math>I^2C</math> signal which is sent to the "slave" to work with. Many slaves can be controlled by one master, as long as no slave addresses are used more than once (the number of possible slave addresses is limited by the specific chip being used as a slave). Communication begins with a start condition (the clock line being held high while the data line is dropped low) and ends with a stop condition (clock line held high while the data line is brought from low to high).
Since PIC microcontrollers do not offer analog outputs, a Digital-to-Analog converter (DAC) must be used to output an analog signal. An eight bit digital number can be converted to analog by using eight of the output pins from the PIC MCU to a separate DAC chip, however if more than one conversion is neccessary, this will quickly use up many of the available output pins from the PIC microcontroller, and require extensive wiring. Luckily, there is an easier and more effective way of doing this using <math>I^2C</math> communication. <math>I^2C</math> utilizes two lines to communicate, usually called ''SCL'' and ''SDA'' (a clock line and a data line). A "master" produces an <math>I^2C</math> signal which is sent to the "slave" to work with. Many slaves can be controlled by one master, as long as no slave addresses are used more than once (the number of possible slave addresses is limited by the specific chip being used as a slave). If the slave chip has two programmable address bits, then four slaves can be controlled by one master. If there are three address bits, then eight slaves can be controlled by one master. Communication begins with a start condition (the clock line being held high while the data line is dropped low) and ends with a stop condition (clock line held high while the data line is brought from low to high).
<br><br>
<br><br>
[[Image:startstopcond.jpg|center]]
[[Image:startstopcond.jpg|center]]
Line 6: Line 6:
==C Programming==
==C Programming==
The basic building blocks of programming for <math>I^2C</math> communication are shown below.
The basic building blocks of programming for <math>I^2C</math> communication are shown below.
<br><br>
{| border="1" cellspacing="2" cellpadding="3" align="center"
|-
!Function!! Description
|-
|i2c_start()|| Sends a start condition
|-
|i2c_write()|| Writes a data byte to the slave
|-
|i2c_stop()||Sends a stop condition
|-
|}
<br>
Using these three functions, one can program whatever information is required to the slave device.
==Example of <math>I^2C</math> Communication==
This example shows how to use <math>I^2C</math> to communicate with a DAC. The PIC MCU will take an analog input (0-5V), and through <math>I^2C</math> communication it will utilize an external DAC to display the input voltage. Obviously this is of no practical use, but is meant as an excercise with <math>I^2C</math> and digital-to-analog conversion.
===Sample Code===
Program to output analog voltage via an external DAC

First include header file with definitions for specific PIC.
Set fuses. HS is type of external clock, low voltage programming
(LVP) is off, and the watchdog timer (WDT) is off.
External clock frequency of 20 MHz is specified.

#include <18f4520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)

Setup I2C with the PIC MCU as the master, pin B0 as the clock line, and
pin B1 as the data line.

#use I2C(master,SCL=PIN_B0,SDA=PIN_B1)

Begin main body of program.

void main(){

Introduce the variable "read" as an 8-bit number (same as int8)

int read;

Setup analog inputs. AN0 can be replaced by ALL_ANALOG, AN0_TO_AN1, AN0_TO_AN8,
etc.

setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);

Set the active analog channel.

set_adc_channel(0);

Use while to set up an infinite loop.

while(TRUE){

Read the analog input from the potentiometer.

read = read_adc();

Begin the I2C communication, then write the slave address, then
write the command byte, then write the value "read" from the analog
input. Values for the address and command byte are determined by
inspecting the device's datasheet.

i2c_start();
i2c_write(0x58);
i2c_write(0x00);
i2c_write(read);
i2c_stop();}
}

===Circuit Diagram===
[[Image:DACckt2.jpg]]

Latest revision as of 09:26, 5 July 2007

Since PIC microcontrollers do not offer analog outputs, a Digital-to-Analog converter (DAC) must be used to output an analog signal. An eight bit digital number can be converted to analog by using eight of the output pins from the PIC MCU to a separate DAC chip, however if more than one conversion is neccessary, this will quickly use up many of the available output pins from the PIC microcontroller, and require extensive wiring. Luckily, there is an easier and more effective way of doing this using communication. utilizes two lines to communicate, usually called SCL and SDA (a clock line and a data line). A "master" produces an signal which is sent to the "slave" to work with. Many slaves can be controlled by one master, as long as no slave addresses are used more than once (the number of possible slave addresses is limited by the specific chip being used as a slave). If the slave chip has two programmable address bits, then four slaves can be controlled by one master. If there are three address bits, then eight slaves can be controlled by one master. Communication begins with a start condition (the clock line being held high while the data line is dropped low) and ends with a stop condition (clock line held high while the data line is brought from low to high).

Startstopcond.jpg



Between the start and stop conditions are different bytes of information. These will differ with each application and each device you are communicating with, although many will have some sort of addressing byte, a command byte, and then information bytes. After every byte sent, the slave will send back an acknowledge bit, prompting the master to send the next byte of information.

C Programming

The basic building blocks of programming for communication are shown below.

Function Description
i2c_start() Sends a start condition
i2c_write() Writes a data byte to the slave
i2c_stop() Sends a stop condition


Using these three functions, one can program whatever information is required to the slave device.

Example of Communication

This example shows how to use to communicate with a DAC. The PIC MCU will take an analog input (0-5V), and through communication it will utilize an external DAC to display the input voltage. Obviously this is of no practical use, but is meant as an excercise with and digital-to-analog conversion.

Sample Code

Program to output analog voltage via an external DAC

First include header file with definitions for specific PIC. Set fuses. HS is type of external clock, low voltage programming (LVP) is off, and the watchdog timer (WDT) is off. External clock frequency of 20 MHz is specified.

  #include <18f4520.h>
  #fuses HS,NOWDT,NOPROTECT,NOLVP
  #use delay(clock=20000000)

Setup I2C with the PIC MCU as the master, pin B0 as the clock line, and pin B1 as the data line.

  #use I2C(master,SCL=PIN_B0,SDA=PIN_B1)

Begin main body of program.

  void main(){

Introduce the variable "read" as an 8-bit number (same as int8)

     int read;

Setup analog inputs. AN0 can be replaced by ALL_ANALOG, AN0_TO_AN1, AN0_TO_AN8, etc.

     setup_adc_ports(AN0);
     setup_adc(ADC_CLOCK_INTERNAL);

Set the active analog channel.

     set_adc_channel(0);

Use while to set up an infinite loop.

     while(TRUE){

Read the analog input from the potentiometer.

        read = read_adc();

Begin the I2C communication, then write the slave address, then write the command byte, then write the value "read" from the analog input. Values for the address and command byte are determined by inspecting the device's datasheet.

        i2c_start();
        i2c_write(0x58);
        i2c_write(0x00);
        i2c_write(read);
        i2c_stop();}
  }

Circuit Diagram

DACckt2.jpg