Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
AD7790.cpp
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
CN0357 - Toxic gas measurement
CN0216 - Weight Scale