A collection of Analog Devices drivers for the mbed platform
Embed:
(wiki syntax)
Show/hide line numbers
AD7790.cpp
Go to the documentation of this file.
00001 /** 00002 * @file AD7790.cpp 00003 * @brief Source file for AD7790 ADC 00004 * @author Analog Devices Inc. 00005 * 00006 * For support please go to: 00007 * Github: https://github.com/analogdevicesinc/mbed-adi 00008 * Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers 00009 * Product: http://www.analog.com/ad7790 00010 * More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all 00011 00012 ******************************************************************************** 00013 * Copyright 2016(c) Analog Devices, Inc. 00014 * 00015 * All rights reserved. 00016 * 00017 * Redistribution and use in source and binary forms, with or without 00018 * modification, are permitted provided that the following conditions are met: 00019 * - Redistributions of source code must retain the above copyright 00020 * notice, this list of conditions and the following disclaimer. 00021 * - Redistributions in binary form must reproduce the above copyright 00022 * notice, this list of conditions and the following disclaimer in 00023 * the documentation and/or other materials provided with the 00024 * distribution. 00025 * - Neither the name of Analog Devices, Inc. nor the names of its 00026 * contributors may be used to endorse or promote products derived 00027 * from this software without specific prior written permission. 00028 * - The use of this software may or may not infringe the patent rights 00029 * of one or more patent holders. This license does not release you 00030 * from the requirement that you obtain separate licenses from these 00031 * patent holders to use this software. 00032 * - Use of the software either in source or binary form, must be run 00033 * on or directly connected to an Analog Devices Inc. component. 00034 * 00035 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR 00036 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, 00037 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00038 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, 00039 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00040 * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR 00041 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00042 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00043 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00044 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00045 * 00046 ********************************************************************************/ 00047 00048 #include <stdint.h> 00049 #include "mbed.h" 00050 #include "AD7790.h" 00051 00052 /** 00053 * @brief AD7790 constructor, sets CS pin and SPI format 00054 * @param CS - (optional)chip select of the AD7790 00055 * @param MOSI - (optional)pin of the SPI interface 00056 * @param MISO - (optional)pin of the SPI interface 00057 * @param SCK - (optional)pin of the SPI interface 00058 */ 00059 AD7790::AD7790(float reference_voltage, 00060 PinName CS, 00061 PinName MOSI, 00062 PinName MISO, 00063 PinName SCK) : 00064 miso(MISO), ad7790(MOSI, MISO, SCK), cs(CS), _vref(reference_voltage), _PGA_gain(1) 00065 { 00066 cs = true; // cs is active low 00067 ad7790.format(8, _SPI_MODE); 00068 _continous_conversion = true; 00069 _channel = DIFFERENTIAL; 00070 } 00071 00072 /** 00073 * @brief Set AD7790 SPI frequency 00074 * @param hz - SPI bus frequency in hz 00075 * @return none 00076 */ 00077 void AD7790::frequency(int hz) 00078 { 00079 ad7790.frequency(hz); 00080 } 00081 00082 /** 00083 * @brief Resets the AD7790 00084 * @return none 00085 */ 00086 void AD7790::reset() 00087 { 00088 ad7790.format(8, _SPI_MODE); 00089 cs = false; 00090 wait_us(_DELAY_TIMING); 00091 ad7790.write(_RESET); 00092 ad7790.write(_RESET); 00093 ad7790.write(_RESET); 00094 ad7790.write(_RESET); 00095 wait_us(_DELAY_TIMING); 00096 cs = true; 00097 _continous_conversion = true; 00098 } 00099 00100 /** 00101 * Sets the mode register. Also sets continous mode and range based on the value 00102 * written in reg_val 00103 * @param reg_val 00104 */ 00105 void AD7790::write_mode_reg(uint8_t reg_val) 00106 { 00107 write_reg(MODE_REG, reg_val); 00108 uint8_t continous_mode = (reg_val & 0xC0); 00109 if(continous_mode == 0x00) { 00110 _continous_conversion = true; 00111 } else { 00112 _continous_conversion = false; 00113 } 00114 uint8_t range = (reg_val & 0x30); 00115 _PGA_gain = 1 << (range >> 4); 00116 } 00117 00118 /** 00119 * Reads the mode register and returns its value 00120 * @return value of the mode register 00121 */ 00122 uint8_t AD7790::read_mode_reg() 00123 { 00124 return read_reg(MODE_REG); 00125 } 00126 00127 /** 00128 * Writes the filter register 00129 * @param regValue value to be written. 00130 */ 00131 void AD7790::write_filter_reg(uint8_t reg_val) 00132 { 00133 write_reg(FILTER_REG, reg_val); 00134 } 00135 00136 /** 00137 * Reads the filter register and returns its value 00138 * @return the value of the filter register 00139 */ 00140 uint8_t AD7790::read_filter_reg() 00141 { 00142 return read_reg(FILTER_REG); 00143 } 00144 00145 /** 00146 * Reads the data register and returns its value 00147 * @return value of the data register 00148 */ 00149 uint16_t AD7790::read_data_reg() 00150 { 00151 uint16_t data_result; 00152 ad7790.format(8, _SPI_MODE); 00153 cs = false; 00154 ad7790.write(_DATA_READ | (static_cast<uint8_t>(_channel))); 00155 data_result = ((ad7790.write(_DUMMY_BYTE)) << 8); 00156 data_result |= (ad7790.write(_DUMMY_BYTE)); 00157 cs = true; 00158 return data_result; 00159 } 00160 00161 /** 00162 * Reads the status register of the ADC and returns its value 00163 * @return value of the status reg 00164 */ 00165 uint8_t AD7790::read_status_reg() 00166 { 00167 return read_reg(STATUS_REG); 00168 } 00169 00170 00171 /** 00172 * @brief Enables/disables continous_conversion mode 00173 * In Single Conversion mode, read_u16 method will read the MODE register of the ADC, 00174 * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low, 00175 * When the pin is driven low, data register is read back from the ADC. 00176 * 00177 * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low, 00178 * the data register is read back from the ADC. 00179 * 00180 * @param mode 00181 * true - continous conversion mode enabled 00182 * false - single conversion mode enabled 00183 */ 00184 void AD7790::set_conversion_mode(AD7790Mode_t mode) 00185 { 00186 uint8_t mode_reg_val; 00187 mode_reg_val = read_mode_reg() & 0x3F; 00188 mode_reg_val = mode_reg_val | (static_cast<uint8_t>(mode)); 00189 write_mode_reg(mode); 00190 } 00191 00192 /** 00193 * - From mbed AnalogIn API - 00194 * @brief Read the input voltage, represented as an unsigned short in the range [0x0, 0xFFFF] 00195 * Depending on the conversion mode, this method will have different behavior. Conversion mode is set using 00196 * set_continous_conversion_mode(bool). 00197 * 00198 * In Single Conversion mode, read_u16 method will read the MODE register of the ADC, 00199 * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low, 00200 * When the pin is driven low, data register is read back from the ADC. 00201 * 00202 * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low, 00203 * the data register is read back from the ADC. 00204 * 00205 * @return 16-bit unsigned short representing the current input voltage, normalised to a 16-bit value 00206 * returns -1 (0xFFFF) along with a debug message if conversion failed. 00207 */ 00208 uint16_t AD7790::read_u16(void) 00209 { 00210 uint16_t data_result = 0; 00211 ad7790.format(8, _SPI_MODE); 00212 cs = false; 00213 uint16_t timeout_cnt = 0; 00214 if(_continous_conversion == false) { 00215 00216 uint8_t mode_reg = read_mode_reg(); 00217 wait_us(_DELAY_TIMING); 00218 00219 cs = false; 00220 mode_reg = (mode_reg & 0x3F) | MD1; // mask single conversion bits 00221 ad7790.write((MODE_REG << 4) | (static_cast<uint8_t>(_channel))); // start single conversion 00222 ad7790.write(mode_reg); 00223 timeout_cnt = _SINGLE_CONVERSION_TIMEOUT; // starts timeout 00224 } else { 00225 timeout_cnt = _CONTINOUS_CONVERSION_TIMEOUT; // starts timeout 00226 } 00227 wait_us(1); 00228 00229 while(miso) { // wait for the MISO pin to go low. 00230 if(timeout_cnt) { 00231 timeout_cnt--; 00232 } else { 00233 cs = true; 00234 #ifdef AD7790_DEBUG_MODE 00235 printf("timeout occurred reading the AD7790. "); // error, MISO line didn't toggle 00236 #endif 00237 return -1; // ERROR 00238 } 00239 wait_us(10); 00240 } 00241 00242 ad7790.write(_DATA_READ | (static_cast<uint8_t>(_channel))); 00243 data_result = ((ad7790.write(_DUMMY_BYTE)) << 8); 00244 data_result |= (ad7790.write(_DUMMY_BYTE)); 00245 cs = true; 00246 return data_result; 00247 } 00248 00249 /** 00250 * @brief Reads a register of the AD7790 00251 * @param address - address of the register 00252 * @return value of the register 00253 */ 00254 uint16_t AD7790::read_reg(AD7790Register_t address) 00255 { 00256 uint16_t data = address << 12; 00257 data |= _DUMMY_BYTE; 00258 data |= _READ_FLAG; 00259 data |= (static_cast<uint8_t>(_channel) << 8); 00260 return write_spi(data); 00261 } 00262 00263 /** 00264 * @brief Writes a register of the AD7790 00265 * @param address - address of the register 00266 * @param reg_val - value to be written 00267 * @return none 00268 * 00269 */ 00270 void AD7790::write_reg(AD7790Register_t address, uint8_t reg_val) 00271 { 00272 uint16_t spi_data = address << 12; 00273 spi_data |= reg_val; 00274 spi_data |= (static_cast<uint8_t>(_channel) << 8); 00275 write_spi(spi_data); 00276 } 00277 00278 /** 00279 * @brief Writes 16bit data to the AD7790 SPI interface 00280 * @param reg_val to be written 00281 * @return data returned by the AD7790 00282 */ 00283 uint16_t AD7790::write_spi(uint16_t reg_val) 00284 { 00285 uint16_t data_result; 00286 uint8_t upper_byte = (reg_val >> 8) & 0xFF; 00287 uint8_t lower_byte = reg_val & 0xFF; 00288 ad7790.format(8, _SPI_MODE); 00289 cs = false; 00290 data_result = (ad7790.write(upper_byte) << 8); 00291 data_result |= ad7790.write(lower_byte); 00292 cs = true; 00293 return data_result; 00294 } 00295 00296 00297 /** 00298 * Sets the AnalogInputRange to be used by the AD7790 00299 * @param range AnalogInputRange_t to be used in voltage computations 00300 */ 00301 void AD7790::set_range(AnalogInputRange_t range) 00302 { 00303 00304 uint8_t mode_reg_val; 00305 mode_reg_val = read_mode_reg() & 0xCF; 00306 mode_reg_val = mode_reg_val | (range << 4); 00307 write_mode_reg(mode_reg_val); 00308 } 00309 00310 /** 00311 * Sets the reference voltage of the AD7790 00312 * @param ref reference voltage to be set 00313 */ 00314 void AD7790::set_reference_voltage(float ref) 00315 { 00316 _vref = ref; 00317 } 00318 00319 /** 00320 * Gets the reference voltage of the AD7790 00321 * @return reference voltage 00322 */ 00323 float AD7790::get_reference_voltage(void) 00324 { 00325 return _vref; 00326 } 00327 00328 /** 00329 * Reads the data register of the ADC and converts the result to volts 00330 * Gain needs to be correctly set using set_gain in order to get accurate results 00331 * @return voltage of the ADC input 00332 */ 00333 float AD7790::read_voltage(void) 00334 { 00335 return data_to_voltage(read_u16()); 00336 } 00337 00338 /** 00339 * Converts an uint16_t to voltage. 00340 * Gain needs to be correctly set using set_gain in order to get accurate results 00341 * @param data in uint16_t format 00342 * @return float value of voltage (in V) 00343 */ 00344 float AD7790::data_to_voltage(uint16_t data) 00345 { 00346 return ((data / static_cast<float>(_RESOLUTION / 2)) - 1) * (_vref / _PGA_gain); 00347 } 00348 00349 /** 00350 * Converts voltage to an uint16_t. 00351 * Gain needs to be correctly set using set_gain in order to get accurate results 00352 * @param voltage to be converted 00353 * @return data in uint16_t format 00354 */ 00355 uint16_t AD7790::voltage_to_data(float voltage) 00356 { 00357 return (((voltage * _PGA_gain / _vref) + 1) * static_cast<float>(_RESOLUTION / 2)); 00358 } 00359 00360 /** 00361 * Sets the conversion channel. 00362 * @param channel 00363 */ 00364 void AD7790::set_channel(AD7790Channel_t channel) 00365 { 00366 _channel = channel; 00367 } 00368 00369 /** 00370 * - From mbed AnalogIn API - 00371 * Read the input voltage, represented as a float in the range [0.0, 1.0] - uses the read_u16 method 00372 * @returns A floating-point value representing the current input voltage, measured as a percentage 00373 * returns 1.0 along with a debug message if the conversion failed 00374 */ 00375 float AD7790::read(void) 00376 { 00377 float percent; 00378 uint16_t data; 00379 data = read_u16(); 00380 percent = (data / static_cast<float>(_RESOLUTION) ); // translate bipolar conversion to [0.0, 1.0] domain 00381 return percent; 00382 } 00383 00384 #ifdef MBED_OPERATORS 00385 00386 /** 00387 * - From mbed AnalogIn API - 00388 * An operator shorthand for read() 00389 * The float() operator can be used as a shorthand for read() to simplify common code sequences 00390 */ 00391 AD7790::operator float() 00392 { 00393 return read(); 00394 } 00395 00396 #endif 00397 00398 00399
Generated on Tue Jul 12 2022 17:59:52 by 1.7.2