lab
Dependencies: mbed
Fork of MCP4922_Sinewave01 by
MCP4922.cpp@3:dcb142a7bf10, 2015-11-05 (annotated)
- Committer:
- aimp
- Date:
- Thu Nov 05 07:58:12 2015 +0000
- Revision:
- 3:dcb142a7bf10
- Parent:
- 0:5737b1972549
lab
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jf1vrr | 0:5737b1972549 | 1 | /* |
jf1vrr | 0:5737b1972549 | 2 | * MCP4922 - DAC library. |
aimp | 3:dcb142a7bf10 | 3 | mcp4922 แปลงจาก digital เป็น analog |
jf1vrr | 0:5737b1972549 | 4 | */ |
jf1vrr | 0:5737b1972549 | 5 | |
jf1vrr | 0:5737b1972549 | 6 | #include "mbed.h" |
jf1vrr | 0:5737b1972549 | 7 | #include "MCP4922.h" |
jf1vrr | 0:5737b1972549 | 8 | |
jf1vrr | 0:5737b1972549 | 9 | using namespace mbed; |
jf1vrr | 0:5737b1972549 | 10 | |
jf1vrr | 0:5737b1972549 | 11 | int dac =0; |
jf1vrr | 0:5737b1972549 | 12 | |
jf1vrr | 0:5737b1972549 | 13 | MCP4922::MCP4922(PinName mosi, PinName sclk, PinName cs) : _spi(mosi, NC, sclk) { |
jf1vrr | 0:5737b1972549 | 14 | |
jf1vrr | 0:5737b1972549 | 15 | int i; |
jf1vrr | 0:5737b1972549 | 16 | _ndacs = 1; |
jf1vrr | 0:5737b1972549 | 17 | _ncs_array = new DigitalOut*[ _ndacs ]; |
jf1vrr | 0:5737b1972549 | 18 | for (i=0; i<_ndacs; i++) { |
jf1vrr | 0:5737b1972549 | 19 | _ncs_array[i] = new DigitalOut(cs); |
jf1vrr | 0:5737b1972549 | 20 | } |
jf1vrr | 0:5737b1972549 | 21 | |
jf1vrr | 0:5737b1972549 | 22 | // Initialise the DAC SPI interface. |
jf1vrr | 0:5737b1972549 | 23 | _init(); |
jf1vrr | 0:5737b1972549 | 24 | } |
jf1vrr | 0:5737b1972549 | 25 | |
jf1vrr | 0:5737b1972549 | 26 | // Destructor |
jf1vrr | 0:5737b1972549 | 27 | MCP4922::~MCP4922() { |
jf1vrr | 0:5737b1972549 | 28 | |
jf1vrr | 0:5737b1972549 | 29 | // Before destroying the object, shut down all the chips. |
jf1vrr | 0:5737b1972549 | 30 | //shdn_all(); |
jf1vrr | 0:5737b1972549 | 31 | |
jf1vrr | 0:5737b1972549 | 32 | // Delete all the NCS DigitalOut objects and the array pointing to |
jf1vrr | 0:5737b1972549 | 33 | // them. |
jf1vrr | 0:5737b1972549 | 34 | int i; |
jf1vrr | 0:5737b1972549 | 35 | for (i=0; i<_ndacs; i++) { |
jf1vrr | 0:5737b1972549 | 36 | delete _ncs_array[i]; |
jf1vrr | 0:5737b1972549 | 37 | } |
jf1vrr | 0:5737b1972549 | 38 | delete [] _ncs_array; |
jf1vrr | 0:5737b1972549 | 39 | |
jf1vrr | 0:5737b1972549 | 40 | // Delete the LDAC DigitalOut object if it exists. |
jf1vrr | 0:5737b1972549 | 41 | if (_latched ) delete _nldac; |
jf1vrr | 0:5737b1972549 | 42 | } |
jf1vrr | 0:5737b1972549 | 43 | |
jf1vrr | 0:5737b1972549 | 44 | // Initialise SPI interface. |
jf1vrr | 0:5737b1972549 | 45 | void MCP4922::_init() { |
jf1vrr | 0:5737b1972549 | 46 | |
jf1vrr | 0:5737b1972549 | 47 | // Set up the SPI for 16-bit values (12-bit + 4 command bits) and mode 0. |
jf1vrr | 0:5737b1972549 | 48 | _spi.format(16, 0); |
jf1vrr | 0:5737b1972549 | 49 | |
jf1vrr | 0:5737b1972549 | 50 | // Start with all the CS and LDAC signals high (disabled) |
jf1vrr | 0:5737b1972549 | 51 | int i; |
jf1vrr | 0:5737b1972549 | 52 | for (i=0; i<_ndacs; i++) { |
jf1vrr | 0:5737b1972549 | 53 | _ncs_array[i]->write(1); |
jf1vrr | 0:5737b1972549 | 54 | } |
jf1vrr | 0:5737b1972549 | 55 | |
jf1vrr | 0:5737b1972549 | 56 | if (_latched ) _nldac->write(1); |
jf1vrr | 0:5737b1972549 | 57 | return; |
jf1vrr | 0:5737b1972549 | 58 | } |
jf1vrr | 0:5737b1972549 | 59 | |
jf1vrr | 0:5737b1972549 | 60 | // Set SPI clock frequency. |
jf1vrr | 0:5737b1972549 | 61 | void MCP4922::frequency( int freq ) { |
jf1vrr | 0:5737b1972549 | 62 | |
jf1vrr | 0:5737b1972549 | 63 | // Set the SPI interface clock frequency in Hz. |
jf1vrr | 0:5737b1972549 | 64 | _spi.frequency( freq ); |
jf1vrr | 0:5737b1972549 | 65 | return; |
jf1vrr | 0:5737b1972549 | 66 | } |
jf1vrr | 0:5737b1972549 | 67 | |
jf1vrr | 0:5737b1972549 | 68 | /* |
jf1vrr | 0:5737b1972549 | 69 | * Note: There is a lot of code in common between the following 4 functions. |
jf1vrr | 0:5737b1972549 | 70 | * The code is kept in line to keep it efficient. Could the functions have |
jf1vrr | 0:5737b1972549 | 71 | * been written as templates? |
jf1vrr | 0:5737b1972549 | 72 | */ |
jf1vrr | 0:5737b1972549 | 73 | // Write to DAC channel A with gain 1. |
jf1vrr | 0:5737b1972549 | 74 | void MCP4922::writeA(int value) { |
jf1vrr | 0:5737b1972549 | 75 | |
jf1vrr | 0:5737b1972549 | 76 | // Set up the command register with the appropriate value. |
jf1vrr | 0:5737b1972549 | 77 | // For efficiency, the caller is assumed to have checked dac. |
jf1vrr | 0:5737b1972549 | 78 | int reg; |
jf1vrr | 0:5737b1972549 | 79 | //int dac = 0; |
jf1vrr | 0:5737b1972549 | 80 | reg = (value & 0x0FFF) | MCP4922_REG_A1; |
jf1vrr | 0:5737b1972549 | 81 | |
jf1vrr | 0:5737b1972549 | 82 | // Select the DAC chip, write to its command register and |
jf1vrr | 0:5737b1972549 | 83 | // then unselect the DAC chip. |
jf1vrr | 0:5737b1972549 | 84 | _ncs_array[dac]->write(0); |
jf1vrr | 0:5737b1972549 | 85 | _spi.write(reg); |
jf1vrr | 0:5737b1972549 | 86 | _ncs_array[dac]->write(1); |
jf1vrr | 0:5737b1972549 | 87 | return; |
jf1vrr | 0:5737b1972549 | 88 | } |
jf1vrr | 0:5737b1972549 | 89 | |
jf1vrr | 0:5737b1972549 | 90 | // Write to DAC channel B with gain 1. |
jf1vrr | 0:5737b1972549 | 91 | void MCP4922::writeB(int value) { |
jf1vrr | 0:5737b1972549 | 92 | |
jf1vrr | 0:5737b1972549 | 93 | // Set up the command register with the appropriate value. |
jf1vrr | 0:5737b1972549 | 94 | // For efficiency, the caller is assumed to have checked dac. |
jf1vrr | 0:5737b1972549 | 95 | int reg; |
jf1vrr | 0:5737b1972549 | 96 | reg = (value & 0x0FFF) | MCP4922_REG_B1; |
jf1vrr | 0:5737b1972549 | 97 | |
jf1vrr | 0:5737b1972549 | 98 | // Select the DAC chip, write to its command register and then |
jf1vrr | 0:5737b1972549 | 99 | // unselect the DAC chip. |
jf1vrr | 0:5737b1972549 | 100 | _ncs_array[dac]->write(0); |
jf1vrr | 0:5737b1972549 | 101 | _spi.write(reg); |
jf1vrr | 0:5737b1972549 | 102 | _ncs_array[dac]->write(1); |
jf1vrr | 0:5737b1972549 | 103 | return; |
jf1vrr | 0:5737b1972549 | 104 | } |
jf1vrr | 0:5737b1972549 | 105 | |
jf1vrr | 0:5737b1972549 | 106 | // Write an array of values to the DACs. |
jf1vrr | 0:5737b1972549 | 107 | void MCP4922::write(int nchans, int values[], int gain, int latch) { |
jf1vrr | 0:5737b1972549 | 108 | |
jf1vrr | 0:5737b1972549 | 109 | // nchans must be at least 1 but less than or equal to ndacs x 2. |
jf1vrr | 0:5737b1972549 | 110 | if (nchans < 1) nchans = 1; |
jf1vrr | 0:5737b1972549 | 111 | const int maxchans = _ndacs * 2; |
jf1vrr | 0:5737b1972549 | 112 | if (nchans > maxchans) nchans = maxchans; |
jf1vrr | 0:5737b1972549 | 113 | |
jf1vrr | 0:5737b1972549 | 114 | if (latch && _latched) |
jf1vrr | 0:5737b1972549 | 115 | latch_disable(); |
jf1vrr | 0:5737b1972549 | 116 | |
jf1vrr | 0:5737b1972549 | 117 | int i; |
jf1vrr | 0:5737b1972549 | 118 | |
jf1vrr | 0:5737b1972549 | 119 | for (i=0; i<nchans;) { |
jf1vrr | 0:5737b1972549 | 120 | dac = i/2; |
jf1vrr | 0:5737b1972549 | 121 | writeA(values[i]); |
jf1vrr | 0:5737b1972549 | 122 | i++; |
jf1vrr | 0:5737b1972549 | 123 | if (i < nchans) { |
jf1vrr | 0:5737b1972549 | 124 | writeB(values[i]); |
jf1vrr | 0:5737b1972549 | 125 | i++; |
jf1vrr | 0:5737b1972549 | 126 | } else break; |
jf1vrr | 0:5737b1972549 | 127 | } |
jf1vrr | 0:5737b1972549 | 128 | |
jf1vrr | 0:5737b1972549 | 129 | // Automatically latch the new voltages if the latch flag is 1. |
jf1vrr | 0:5737b1972549 | 130 | if (latch && _latched) |
jf1vrr | 0:5737b1972549 | 131 | latch_enable(); |
jf1vrr | 0:5737b1972549 | 132 | return; |
jf1vrr | 0:5737b1972549 | 133 | } |
jf1vrr | 0:5737b1972549 | 134 | |
jf1vrr | 0:5737b1972549 | 135 | // Set latch signal to "enable". |
jf1vrr | 0:5737b1972549 | 136 | void MCP4922::latch_enable() { |
jf1vrr | 0:5737b1972549 | 137 | |
jf1vrr | 0:5737b1972549 | 138 | // Latch all chips. There should be a delay of at least T_LS=40 |
jf1vrr | 0:5737b1972549 | 139 | // nanoseconds between the last CS rising edge and the LDAC falling |
jf1vrr | 0:5737b1972549 | 140 | // edge. The software function calls seem to be sufficient to |
jf1vrr | 0:5737b1972549 | 141 | // introduce that delay. A delay may be inserted here if this |
jf1vrr | 0:5737b1972549 | 142 | // software is ported to a faster processor. |
jf1vrr | 0:5737b1972549 | 143 | if (_latched) _nldac->write(0); |
jf1vrr | 0:5737b1972549 | 144 | // The LDAC pulse width must be at least T_LD=100 nanoseconds long. |
jf1vrr | 0:5737b1972549 | 145 | // A delay can be inserted here if necessary, but so far this has |
jf1vrr | 0:5737b1972549 | 146 | // not been needed (see above). |
jf1vrr | 0:5737b1972549 | 147 | return; |
jf1vrr | 0:5737b1972549 | 148 | } |
jf1vrr | 0:5737b1972549 | 149 | |
jf1vrr | 0:5737b1972549 | 150 | // Set latch signal to "disable". |
jf1vrr | 0:5737b1972549 | 151 | void MCP4922::latch_disable() { |
jf1vrr | 0:5737b1972549 | 152 | |
jf1vrr | 0:5737b1972549 | 153 | // Disable latch for all chips. |
jf1vrr | 0:5737b1972549 | 154 | if (_latched) _nldac->write(1); |
jf1vrr | 0:5737b1972549 | 155 | return; |
jf1vrr | 0:5737b1972549 | 156 | } |
jf1vrr | 0:5737b1972549 | 157 |