Skip to content

Instantly share code, notes, and snippets.

@ajarmst
Last active December 13, 2021 15:56
Show Gist options
  • Save ajarmst/bacc3072cddef9edd931e87d5b75dbfc to your computer and use it in GitHub Desktop.
Save ajarmst/bacc3072cddef9edd931e87d5b75dbfc to your computer and use it in GitHub Desktop.
I2C Demo Using a DAC
/////////////////////////////////////////////////////////////////////////////
// HC12 Program: Demo 10 - SPI DAC
// Processor: MC9S12XDP512
// Bus Speed: 20 MHz (Requires Active PLL)
// Author: AJ Armstrong
// Details: Connect and control an MCP4812 DAC via SPI.
// Date: 25 Oct 2021
// Revision History :
/////////////////////////////////////////////////////////////////////////////
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
// other system includes or your includes go here
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "pll.h"
#include "swled.h"
#include "segs.h"
#include "timer.h"
#include "lcd.h"
#include "i2c.h"
/////////////////////////////////////////////////////////////////////////////
// Local Prototypes
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////
// LTC2633 - Dual 12-bit I2C DAC Library
// 7-bit device address 0x10, but 0x20 as command
// this device can go to 400kHz
/////////////////////////////////////////////
// this is a 12-bit, 4.096V (1mV/step), two channel DAC
// write time per value is ~118.5us @ 400KHz bus (measured)
// general form (write only):
// <ADDR><C3:C0,A3:A0><D11:D4[DAC Value]><D3:D0[0]>
// C3 C2 C1 C0
// 0 0 0 0 - write to register n
// 0 0 0 1 - update (power up) DAC, register n
// 0 0 1 0 - write to input register n, update (power up) all
// 0 0 1 1 - write to and update (power up) DAC register n
// 0 1 0 0 - power down n
// 0 1 0 1 - power down chip
// 0 1 1 0 - select (power up) internal reference
// 0 1 1 1 - select external reference
// 1 1 1 1 - no op
// NOTE: left-aligned data
// A3 A2 A1 A0
// 0 0 0 0 - DAC A
// 0 0 0 1 - DAC B
// 1 1 1 1 - all DACs
// command form (8-bit) of address is 0x20 (0x10 << 1)
#define LTC2633ADDR 0x20
// channel decode tags for LTC write function
typedef enum LTC2633_CHAN_SELECT
{
LTC2633_CHAN_A,
LTC2633_CHAN_B,
LTC2633_CHAN_BOTH
} LTC2633_CHAN_SELECT;
// write a channel
int LTC2633_WriteChan (unsigned int Value, LTC2633_CHAN_SELECT chan);
/////////////////////////////////////////////////////////////////////////////
// Global Variables
/////////////////////////////////////////////////////////////////////////////
volatile uint ADCVal[8] = {0};
/////////////////////////////////////////////////////////////////////////////
// Constants
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Main Entry
/////////////////////////////////////////////////////////////////////////////
int main(void)
{
unsigned int DACVal = 0; //12-bit DAC output (0 - 4096)
_DISABLE_COP();
EnableInterrupts; // Ensure our board will respond to interrupt signals.
/////////////////////////////////////////////////////////////////////////////
// One-Time Initializations
/////////////////////////////////////////////////////////////////////////////
PLL_To20MHz(); // Configure the main clock to 20 MHz
SWL_Init(); // Standard initialization for switches and LEDs
SEG_Init(); // Standard initialization for 7-segment displays
LCD_Init_Simon(); // Standard initialization for LCD
// Set up Channel 5 ADC
///////////////////////////;//////////////////////////////////////////////////
// ADC Initializations
/////////////////////////////////////////////////////////////////////////////
DDR1AD0 = 0b00000000; //All channels input
ATD0DIEN = 0b00000000; //All channels analog
ATD0CTL2 = 0b11100010; //Enable intrpt, no ext trigr, on, fast, cont in wai
//Quick 50 mikes busy wait to allow ADC to power up
asm LDX #134;
asm DBNE X,*;
ATD0CTL3 = 0b00000010; //8 conversions per sequence, continue b4 freeze
ATD0CTL4 = 0b00100110; //div. 14 clock -> 7 mikes per sample (56 / set)
ATD0CTL5 = 0b10110000; //fill from bottom, sample all 8, continuous, right just
//Set up I2C
I2C_Init0(I2CMicro20MHz, I2CBus400, 0);
/////////////////////////////////////////////////////////////////////////////
// Main Program Loop
/////////////////////////////////////////////////////////////////////////////
for (;;)
{
//Get ten-bit ADC, convert to 12 bit DAC
DACVal = (unsigned int)((ADCVal[5]/1024.0) * 4096);
(void) LTC2633_WriteChan(DACVal,LTC2633_CHAN_A);
SEG_16H(ADCVal[5],0);
SEG_16H(DACVal,1);
}
}
/////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
int LTC2633_WriteChan (unsigned int Value, LTC2633_CHAN_SELECT chan)
{
// address the device
if (I2C_SendAddressRW(LTC2633ADDR, I2C_WRITE, I2C_WAIT))
return -1;
// send command (write chan, power up all)
if (chan == LTC2633_CHAN_A)
(void)I2C_WriteByte (0b00100000, I2C_NOSTOP); // P18, datasheet
else if (chan == LTC2633_CHAN_B)
(void)I2C_WriteByte (0b00100001, I2C_NOSTOP); // P18, datasheet
else // assume all channels
(void)I2C_WriteByte (0b00101111, I2C_NOSTOP); // P18, datasheet
// send msb data (data is 12 bits, oddly, left aligned, P18, datasheet)
(void)I2C_WriteByte ((unsigned char)(Value >> 4), I2C_NOSTOP); // 0x0123 becomes 0x12
// send lsb data
(void)I2C_WriteByte ((unsigned char)(Value << 4), I2C_STOP); // 0x0123 becomes 0x30
return 0; // good condition
}
/////////////////////////////////////////////////////////////////////////////
// Interrupt Service Routines
/////////////////////////////////////////////////////////////////////////////
/***** ATD0 Event Handler *****/
interrupt VectorNumber_Vatd0 void INT_AD0 (void)
{
ADCVal[0] = ATD0DR0;
ADCVal[5] = ATD0DR5;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment