Microchip MCP342x ADC library

Committer:
SomeRandomBloke
Date:
Mon Sep 10 17:02:22 2018 +0000
Revision:
4:9480edf3926d
Parent:
3:03911aa07029
Child:
5:0ca445d2d2bc
Updates to add end of conversion checking

Who changed what in which revision?

UserRevisionLine numberNew contents of line
antoniogonzalez 0:7dbf7356da6b 1 #include "mcp342x.h"
antoniogonzalez 0:7dbf7356da6b 2
antoniogonzalez 0:7dbf7356da6b 3 #define LEN_ONE_BYTE 1
SomeRandomBloke 4:9480edf3926d 4 extern Serial pc;
antoniogonzalez 0:7dbf7356da6b 5
antoniogonzalez 0:7dbf7356da6b 6 MCP342x::MCP342x(I2C *i2c, uint8_t device_address)
antoniogonzalez 0:7dbf7356da6b 7 {
antoniogonzalez 1:c4da9889ff85 8 _i2c = i2c;
antoniogonzalez 1:c4da9889ff85 9
antoniogonzalez 0:7dbf7356da6b 10 // The address byte is the device code (4 bits, hardcoded in
antoniogonzalez 0:7dbf7356da6b 11 // factory) and the device address (3 bits). These are shifted one
antoniogonzalez 0:7dbf7356da6b 12 // bit to the left because mbed uses 8-bit addresses.
antoniogonzalez 0:7dbf7356da6b 13 _address = (_device_code << 4) | (device_address << 1);
antoniogonzalez 1:c4da9889ff85 14
antoniogonzalez 1:c4da9889ff85 15 // Initialise to default settings: channel 1, gain 1x, 12 bits.
antoniogonzalez 1:c4da9889ff85 16 // It is necessary to do this to ensure that the variables
antoniogonzalez 1:c4da9889ff85 17 // _resolution and _pga are properly set.
SomeRandomBloke 4:9480edf3926d 18 _configuration = 0x10; // Continuous mode
antoniogonzalez 0:7dbf7356da6b 19 set_channel(CHANNEL_1);
antoniogonzalez 0:7dbf7356da6b 20 set_resolution(RESOLUTION_12);
antoniogonzalez 0:7dbf7356da6b 21 set_pga(PGA_1);
antoniogonzalez 0:7dbf7356da6b 22 }
antoniogonzalez 0:7dbf7356da6b 23
antoniogonzalez 0:7dbf7356da6b 24 void MCP342x::set_channel(mcp342x_channel_t channel)
antoniogonzalez 0:7dbf7356da6b 25 {
antoniogonzalez 1:c4da9889ff85 26 _configuration &= REG_CHANNEL_Clear;
antoniogonzalez 1:c4da9889ff85 27 _configuration |= channel << REG_CHANNEL_Pos;
antoniogonzalez 0:7dbf7356da6b 28 _write_configuration();
antoniogonzalez 0:7dbf7356da6b 29 }
antoniogonzalez 0:7dbf7356da6b 30
antoniogonzalez 0:7dbf7356da6b 31 void MCP342x::set_conversion_mode(mcp342x_conversion_mode_t mode)
antoniogonzalez 0:7dbf7356da6b 32 {
antoniogonzalez 1:c4da9889ff85 33 _configuration &= REG_MODE_Clear;
antoniogonzalez 1:c4da9889ff85 34 _configuration |= mode << REG_MODE_Pos;
antoniogonzalez 0:7dbf7356da6b 35 _write_configuration();
antoniogonzalez 0:7dbf7356da6b 36 }
antoniogonzalez 0:7dbf7356da6b 37
antoniogonzalez 0:7dbf7356da6b 38 void MCP342x::set_resolution(mcp342x_resolution_t resolution)
antoniogonzalez 0:7dbf7356da6b 39 {
antoniogonzalez 1:c4da9889ff85 40 _resolution = resolution;
antoniogonzalez 1:c4da9889ff85 41
antoniogonzalez 1:c4da9889ff85 42 // _lsb and _max_code are variables required for converting the ADC
antoniogonzalez 1:c4da9889ff85 43 // data into volts; see Section 4.9 of the MCP342x datasheet. Their
antoniogonzalez 1:c4da9889ff85 44 // value depends on the resolution chosen, so it is useful to
antoniogonzalez 1:c4da9889ff85 45 // calculate these values here, whenever the resolution setting is
antoniogonzalez 1:c4da9889ff85 46 // changed.
antoniogonzalez 1:c4da9889ff85 47 //
antoniogonzalez 1:c4da9889ff85 48 // _lsb is the magnitude (in volts) of the last significant byte,
antoniogonzalez 1:c4da9889ff85 49 // and it is calculated as 2 * 2.048 / (2^N), where N is the
antoniogonzalez 1:c4da9889ff85 50 // resolution (datasheet Eq. 4-3).
antoniogonzalez 1:c4da9889ff85 51 //
antoniogonzalez 1:c4da9889ff85 52 // _max_code is the maximum output code, and it is equal to
antoniogonzalez 1:c4da9889ff85 53 // 2^(N-1) - 1 (datasheet Table 4-3).
SomeRandomBloke 4:9480edf3926d 54 switch(_resolution) {
antoniogonzalez 0:7dbf7356da6b 55 case RESOLUTION_12:
antoniogonzalez 1:c4da9889ff85 56 _lsb = 2 * 2.048 / 4096;
antoniogonzalez 1:c4da9889ff85 57 _max_code = 2047;
antoniogonzalez 0:7dbf7356da6b 58 break;
antoniogonzalez 0:7dbf7356da6b 59 case RESOLUTION_14:
antoniogonzalez 1:c4da9889ff85 60 _lsb = 2 * 2.048 / 16384;
antoniogonzalez 1:c4da9889ff85 61 _max_code = 8191;
antoniogonzalez 0:7dbf7356da6b 62 break;
antoniogonzalez 0:7dbf7356da6b 63 case RESOLUTION_16:
antoniogonzalez 1:c4da9889ff85 64 _lsb = 2 * 2.048 / 65536;
antoniogonzalez 1:c4da9889ff85 65 _max_code = 32767;
antoniogonzalez 0:7dbf7356da6b 66 break;
antoniogonzalez 0:7dbf7356da6b 67 case RESOLUTION_18:
antoniogonzalez 1:c4da9889ff85 68 _lsb = 2 * 2.048 / 262144;
antoniogonzalez 1:c4da9889ff85 69 _max_code = 131071;
antoniogonzalez 0:7dbf7356da6b 70 break;
antoniogonzalez 1:c4da9889ff85 71 }
antoniogonzalez 1:c4da9889ff85 72
antoniogonzalez 1:c4da9889ff85 73 _configuration &= REG_RESOLUTION_Clear;
antoniogonzalez 1:c4da9889ff85 74 _configuration |= _resolution << REG_RESOLUTION_Pos;
antoniogonzalez 0:7dbf7356da6b 75 _write_configuration();
antoniogonzalez 0:7dbf7356da6b 76 }
antoniogonzalez 0:7dbf7356da6b 77
antoniogonzalez 0:7dbf7356da6b 78 void MCP342x::set_pga(mcp342x_pga_t pga)
antoniogonzalez 0:7dbf7356da6b 79 {
antoniogonzalez 1:c4da9889ff85 80 // The gain value (1, 2, 4 or 8) is required for converting digital
antoniogonzalez 1:c4da9889ff85 81 // output codes to voltage. For this purpose the actual PGA value is
antoniogonzalez 1:c4da9889ff85 82 // kept in the variable _pga, instead of keeping the *position* in
antoniogonzalez 1:c4da9889ff85 83 // the register of PGA, which is what the variable type
antoniogonzalez 1:c4da9889ff85 84 // mcp342x_pga_t represents.
antoniogonzalez 1:c4da9889ff85 85 switch (pga) {
antoniogonzalez 0:7dbf7356da6b 86 case PGA_1:
antoniogonzalez 0:7dbf7356da6b 87 _pga = 1;
antoniogonzalez 0:7dbf7356da6b 88 break;
antoniogonzalez 0:7dbf7356da6b 89 case PGA_2:
antoniogonzalez 0:7dbf7356da6b 90 _pga = 2;
antoniogonzalez 0:7dbf7356da6b 91 break;
antoniogonzalez 0:7dbf7356da6b 92 case PGA_4:
antoniogonzalez 0:7dbf7356da6b 93 _pga = 4;
antoniogonzalez 0:7dbf7356da6b 94 break;
antoniogonzalez 0:7dbf7356da6b 95 case PGA_8:
antoniogonzalez 0:7dbf7356da6b 96 _pga = 8;
antoniogonzalez 0:7dbf7356da6b 97 break;
antoniogonzalez 1:c4da9889ff85 98 }
antoniogonzalez 1:c4da9889ff85 99
antoniogonzalez 1:c4da9889ff85 100 _configuration &= REG_PGA_Clear;
antoniogonzalez 1:c4da9889ff85 101 _configuration |= pga << REG_PGA_Pos;
antoniogonzalez 0:7dbf7356da6b 102 _write_configuration();
antoniogonzalez 0:7dbf7356da6b 103 }
antoniogonzalez 0:7dbf7356da6b 104
antoniogonzalez 0:7dbf7356da6b 105 void MCP342x::_write_configuration()
antoniogonzalez 0:7dbf7356da6b 106 {
SomeRandomBloke 4:9480edf3926d 107 // pc.printf("MCP3424 config %0X\r\n", _configuration );
antoniogonzalez 1:c4da9889ff85 108 _i2c_command[0] = _configuration;
antoniogonzalez 1:c4da9889ff85 109 _i2c->write(_address, _i2c_command, LEN_ONE_BYTE);
antoniogonzalez 0:7dbf7356da6b 110 }
antoniogonzalez 0:7dbf7356da6b 111
SomeRandomBloke 4:9480edf3926d 112 uint8_t MCP342x::read_configuration()
SomeRandomBloke 4:9480edf3926d 113 {
SomeRandomBloke 4:9480edf3926d 114 // pc.printf("MCP3424 config %0X\r\n", _configuration );
SomeRandomBloke 4:9480edf3926d 115 _i2c_command[0] = _configuration;
SomeRandomBloke 4:9480edf3926d 116 _i2c->read(_address, _i2c_command, LEN_ONE_BYTE);
SomeRandomBloke 4:9480edf3926d 117 return _i2c_command[0];
SomeRandomBloke 4:9480edf3926d 118 }
SomeRandomBloke 4:9480edf3926d 119
SomeRandomBloke 4:9480edf3926d 120 void MCP342x::_startRead()
SomeRandomBloke 4:9480edf3926d 121 {
SomeRandomBloke 4:9480edf3926d 122 _i2c_command[0] = _configuration | 0x80;
SomeRandomBloke 4:9480edf3926d 123 _i2c->write(_address, _i2c_command, LEN_ONE_BYTE);
SomeRandomBloke 4:9480edf3926d 124 }
SomeRandomBloke 4:9480edf3926d 125
antoniogonzalez 1:c4da9889ff85 126 uint32_t MCP342x::read()
antoniogonzalez 0:7dbf7356da6b 127 {
antoniogonzalez 1:c4da9889ff85 128 uint32_t adc_value = 0;
SomeRandomBloke 4:9480edf3926d 129 uint8_t readConfig = 0;
SomeRandomBloke 4:9480edf3926d 130 int byteNum = 3;
SomeRandomBloke 4:9480edf3926d 131
SomeRandomBloke 4:9480edf3926d 132 if( (_configuration & 0x10) == 0 )
SomeRandomBloke 4:9480edf3926d 133 _startRead();
SomeRandomBloke 4:9480edf3926d 134
SomeRandomBloke 4:9480edf3926d 135 // Read config register
SomeRandomBloke 4:9480edf3926d 136 if (_resolution == RESOLUTION_18 ) {
SomeRandomBloke 4:9480edf3926d 137 byteNum = 4;
SomeRandomBloke 4:9480edf3926d 138 }
SomeRandomBloke 4:9480edf3926d 139
SomeRandomBloke 4:9480edf3926d 140 _i2c->read(_address, _i2c_command, byteNum);
SomeRandomBloke 4:9480edf3926d 141
SomeRandomBloke 4:9480edf3926d 142 while( (_i2c_command[byteNum-1] & 0x80) == 0x80 ) {
SomeRandomBloke 4:9480edf3926d 143 wait_ms(10);
SomeRandomBloke 4:9480edf3926d 144 // pc.printf("MCP3424 config %0X %0X %0X %0X\r\n", _i2c_command[0],_i2c_command[1],_i2c_command[2],_i2c_command[3] );
SomeRandomBloke 4:9480edf3926d 145 _i2c->read(_address, _i2c_command, byteNum);
SomeRandomBloke 4:9480edf3926d 146 }
SomeRandomBloke 4:9480edf3926d 147
antoniogonzalez 0:7dbf7356da6b 148
antoniogonzalez 0:7dbf7356da6b 149 switch (_resolution) {
antoniogonzalez 1:c4da9889ff85 150 case RESOLUTION_12:
antoniogonzalez 1:c4da9889ff85 151 adc_value = (_i2c_command[0] << 8) | _i2c_command[1];
antoniogonzalez 0:7dbf7356da6b 152 adc_value &= 0xfff;
antoniogonzalez 0:7dbf7356da6b 153 break;
antoniogonzalez 0:7dbf7356da6b 154
antoniogonzalez 1:c4da9889ff85 155 case RESOLUTION_14:
antoniogonzalez 1:c4da9889ff85 156 adc_value = (_i2c_command[0] << 8) | _i2c_command[1];
antoniogonzalez 0:7dbf7356da6b 157 adc_value &= 0x3fff;
antoniogonzalez 0:7dbf7356da6b 158 break;
antoniogonzalez 0:7dbf7356da6b 159
antoniogonzalez 1:c4da9889ff85 160 case RESOLUTION_16:
antoniogonzalez 1:c4da9889ff85 161 adc_value = (_i2c_command[0] << 8) | _i2c_command[1];
antoniogonzalez 0:7dbf7356da6b 162 adc_value &= 0xffff;
antoniogonzalez 0:7dbf7356da6b 163 break;
antoniogonzalez 0:7dbf7356da6b 164
antoniogonzalez 1:c4da9889ff85 165 case RESOLUTION_18:
antoniogonzalez 1:c4da9889ff85 166 adc_value = (_i2c_command[0] << 16) |
SomeRandomBloke 4:9480edf3926d 167 (_i2c_command[1] << 8) | _i2c_command[2];
antoniogonzalez 0:7dbf7356da6b 168 adc_value &= 0x3ffff;
antoniogonzalez 0:7dbf7356da6b 169 break;
antoniogonzalez 0:7dbf7356da6b 170 }
antoniogonzalez 0:7dbf7356da6b 171 return adc_value;
antoniogonzalez 0:7dbf7356da6b 172 }
antoniogonzalez 1:c4da9889ff85 173
SomeRandomBloke 4:9480edf3926d 174 float MCP342x::read_volts()
SomeRandomBloke 4:9480edf3926d 175 {
antoniogonzalez 1:c4da9889ff85 176 float volts = 0.0;
antoniogonzalez 1:c4da9889ff85 177 uint32_t adc_value = read();
antoniogonzalez 1:c4da9889ff85 178
antoniogonzalez 1:c4da9889ff85 179 // The digital output of the MCP342x is in two's complement format;
antoniogonzalez 1:c4da9889ff85 180 // see datasheet Section 4.9. This 'if... else' construction
antoniogonzalez 1:c4da9889ff85 181 // determines whether the digital code is negative or positive; if
antoniogonzalez 3:03911aa07029 182 // it is the former, its two's complement is calculated.
antoniogonzalez 1:c4da9889ff85 183 if (adc_value > _max_code) {
antoniogonzalez 1:c4da9889ff85 184 // if the output code is negative...
antoniogonzalez 1:c4da9889ff85 185 volts = (~adc_value & _max_code) + 1;
antoniogonzalez 1:c4da9889ff85 186 volts *= -1;
antoniogonzalez 1:c4da9889ff85 187 } else {
antoniogonzalez 1:c4da9889ff85 188 // if the output code is positive...
antoniogonzalez 1:c4da9889ff85 189 volts = (float)adc_value;
antoniogonzalez 1:c4da9889ff85 190 }
antoniogonzalez 1:c4da9889ff85 191
antoniogonzalez 1:c4da9889ff85 192 // The actual voltage is proportional to the resolution and PGA
antoniogonzalez 1:c4da9889ff85 193 // settings. This equation corresponds to Equation 4-4 in the
antoniogonzalez 1:c4da9889ff85 194 // datasheet. The variables _lsb and _pga are calculated whenever
antoniogonzalez 1:c4da9889ff85 195 // the user changes the resolution or PGA parameters.
antoniogonzalez 1:c4da9889ff85 196 return volts * _lsb / _pga;
antoniogonzalez 1:c4da9889ff85 197 }