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.
AD7791.cpp
00001 /** 00002 * @file AD7791.cpp 00003 * @brief Source file for AD7791 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/ad7791 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 "AD7791.h" 00051 00052 /** 00053 * @brief AD7791 constructor, sets CS pin and SPI format 00054 * @param reference_voltage - the reference voltage to be used in computation 00055 * @param CS - (optional)chip select of the AD7791 00056 * @param MOSI - (optional)pin of the SPI interface 00057 * @param MISO - (optional)pin of the SPI interface 00058 * @param SCK - (optional)pin of the SPI interface 00059 */ 00060 AD7791::AD7791(float reference_voltage, 00061 PinName CS, 00062 PinName MOSI, 00063 PinName MISO, 00064 PinName SCK) : 00065 miso(MISO), ad7791(MOSI, MISO, SCK), cs(CS), _vref(reference_voltage) 00066 { 00067 cs = true; // cs is active low 00068 ad7791.format(8, _SPI_MODE); 00069 _continous_conversion = true; 00070 _channel = DIFFERENTIAL; 00071 } 00072 00073 /** 00074 * @brief Set AD7791 SPI frequency 00075 * @param hz - SPI bus frequency in hz 00076 * @return none 00077 */ 00078 void AD7791::frequency(int hz) 00079 { 00080 ad7791.frequency(hz); 00081 } 00082 00083 /** 00084 * @brief Resets the AD7791 00085 * @return none 00086 */ 00087 void AD7791::reset() 00088 { 00089 ad7791.format(8, _SPI_MODE); 00090 cs = false; 00091 wait_us(_DELAY_TIMING); 00092 ad7791.write(_RESET); 00093 ad7791.write(_RESET); 00094 ad7791.write(_RESET); 00095 ad7791.write(_RESET); 00096 wait_us(_DELAY_TIMING); 00097 cs = true; 00098 _continous_conversion = true; 00099 } 00100 00101 /** 00102 * Sets the mode register. Also sets continous mode and range based on the value 00103 * written in reg_val 00104 * @param reg_val 00105 */ 00106 void AD7791::write_mode_reg(uint8_t reg_val) 00107 { 00108 write_reg(MODE_REG, reg_val); 00109 uint8_t continous_mode = (reg_val & 0xC0); 00110 if(continous_mode == 0x00) { 00111 _continous_conversion = true; 00112 } else { 00113 _continous_conversion = false; 00114 } 00115 /* uint8_t range = (reg_val & 0x30); 00116 _PGA_gain = 1 << (range >> 4);*/ 00117 00118 } 00119 00120 /** 00121 * Reads the mode register and returns its value 00122 * @return value of the mode register 00123 */ 00124 uint8_t AD7791::read_mode_reg() 00125 { 00126 return read_reg(MODE_REG); 00127 } 00128 00129 /** 00130 * Writes the filter register 00131 * @param regValue value to be written. 00132 */ 00133 void AD7791::write_filter_reg(uint8_t reg_val) 00134 { 00135 write_reg(FILTER_REG, reg_val); 00136 } 00137 00138 /** 00139 * Reads the filter register and returns its value 00140 * @return the value of the filter register 00141 */ 00142 uint8_t AD7791::read_filter_reg() 00143 { 00144 return read_reg(FILTER_REG); 00145 } 00146 00147 /** 00148 * Reads the data register and returns its value 00149 * @return value of the data register 00150 */ 00151 uint32_t AD7791::read_data_reg() 00152 { 00153 uint32_t data_result; 00154 ad7791.format(8, _SPI_MODE); 00155 cs = false; 00156 ad7791.write(_DATA_READ | (static_cast<uint8_t>(_channel))); 00157 data_result = ((ad7791.write(_DUMMY_BYTE)) << 16); 00158 data_result |= ((ad7791.write(_DUMMY_BYTE)) << 8 ); 00159 data_result |= (ad7791.write(_DUMMY_BYTE)); 00160 cs = true; 00161 return data_result; 00162 } 00163 00164 /** 00165 * Reads the status register of the ADC and returns its value 00166 * @return value of the status reg 00167 */ 00168 uint8_t AD7791::read_status_reg() 00169 { 00170 return read_reg(STATUS_REG); 00171 } 00172 00173 00174 /** 00175 * @brief Enables/disables continous_conversion mode 00176 * In Single Conversion mode, read_u16 method will read the MODE register of the ADC, 00177 * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low, 00178 * When the pin is driven low, data register is read back from the ADC. 00179 * 00180 * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low, 00181 * the data register is read back from the ADC. 00182 * 00183 * @param mode 00184 * true - continous conversion mode enabled 00185 * false - single conversion mode enabled 00186 */ 00187 void AD7791::set_conversion_mode(AD7791Mode_t mode) 00188 { 00189 uint8_t mode_reg_val; 00190 mode_reg_val = read_mode_reg() & 0x3F; 00191 mode_reg_val = mode_reg_val | (static_cast<uint8_t>(mode)); 00192 write_mode_reg(mode); 00193 } 00194 00195 /** 00196 * - From mbed AnalogIn API - 00197 * @brief Read the input voltage, represented as an unsigned short in the range [0x0, 0xFFFF] 00198 * Depending on the conversion mode, this method will have different behavior. Conversion mode is set using 00199 * set_continous_conversion_mode(bool). 00200 * 00201 * In Single Conversion mode, read_u16 method will read the MODE register of the ADC, 00202 * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low, 00203 * When the pin is driven low, data register is read back from the ADC. 00204 * 00205 * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low, 00206 * the data register is read back from the ADC. 00207 * 00208 * @return 16-bit unsigned short representing the current input voltage, normalised to a 16-bit value 00209 * returns -1 (0xFFFF) along with a debug message if conversion failed. 00210 */ 00211 uint32_t AD7791::read_u32(void) 00212 { 00213 uint32_t data_result = 0; 00214 ad7791.format(8, _SPI_MODE); 00215 cs = false; 00216 uint16_t timeout_cnt = 0; 00217 if(_continous_conversion == false) { 00218 00219 uint8_t mode_reg = read_mode_reg(); 00220 wait_us(_DELAY_TIMING); 00221 00222 cs = false; 00223 mode_reg = (mode_reg & 0x3F) | MD1; // mask single conversion bits 00224 ad7791.write((MODE_REG << 4) | (static_cast<uint8_t>(_channel))); // start single conversion 00225 ad7791.write(mode_reg); 00226 timeout_cnt = _SINGLE_CONVERSION_TIMEOUT; // starts timeout 00227 } else { 00228 timeout_cnt = _CONTINOUS_CONVERSION_TIMEOUT; // starts timeout 00229 } 00230 wait_us(1); 00231 00232 while(miso) { // wait for the MISO pin to go low. 00233 if(timeout_cnt) { 00234 timeout_cnt--; 00235 } else { 00236 cs = true; 00237 #ifdef AD7791_DEBUG_MODE 00238 printf("timeout occurred reading the AD7791. "); // error, MISO line didn't toggle 00239 #endif 00240 return -1; // ERROR 00241 } 00242 wait_us(10); 00243 } 00244 00245 ad7791.write(_DATA_READ | (static_cast<uint8_t>(_channel))); 00246 data_result = ((ad7791.write(_DUMMY_BYTE)) << 16); 00247 data_result |= ((ad7791.write(_DUMMY_BYTE)) << 8 ); 00248 data_result |= (ad7791.write(_DUMMY_BYTE)); 00249 cs = true; 00250 return data_result; 00251 } 00252 00253 uint16_t AD7791::read_u16(void) 00254 { 00255 uint32_t data = read_u32(); 00256 return static_cast<uint16_t>((data & 0xffff00) >> 8); 00257 } 00258 00259 /** 00260 * @brief Reads a register of the AD7791 00261 * @param address - address of the register 00262 * @return value of the register 00263 */ 00264 uint16_t AD7791::read_reg(AD7791Register_t address) 00265 { 00266 uint16_t data = address << 12; 00267 data |= _DUMMY_BYTE; 00268 data |= _READ_FLAG; 00269 data |= (static_cast<uint8_t>(_channel) << 8); 00270 return write_spi(data); 00271 } 00272 00273 /** 00274 * @brief Writes a register of the AD7791 00275 * @param address - address of the register 00276 * @param reg_val - value to be written 00277 * @return none 00278 * 00279 */ 00280 void AD7791::write_reg(AD7791Register_t address, uint8_t reg_val) 00281 { 00282 uint16_t spi_data = address << 12; 00283 spi_data |= reg_val; 00284 spi_data |= (static_cast<uint8_t>(_channel) << 8); 00285 write_spi(spi_data); 00286 } 00287 00288 /** 00289 * @brief Writes 16bit data to the AD7791 SPI interface 00290 * @param reg_val to be written 00291 * @return data returned by the AD7791 00292 */ 00293 uint16_t AD7791::write_spi(uint16_t reg_val) 00294 { 00295 uint16_t data_result; 00296 uint8_t upper_byte = (reg_val >> 8) & 0xFF; 00297 uint8_t lower_byte = reg_val & 0xFF; 00298 ad7791.format(8, _SPI_MODE); 00299 cs = false; 00300 data_result = (ad7791.write(upper_byte) << 8); 00301 data_result |= ad7791.write(lower_byte); 00302 cs = true; 00303 return data_result; 00304 } 00305 00306 /** 00307 * Sets the reference voltage of the AD7790 00308 * @param ref reference voltage to be set 00309 */ 00310 void AD7791::set_reference_voltage(float ref) 00311 { 00312 _vref = ref; 00313 } 00314 00315 /** 00316 * Gets the reference voltage of the AD7790 00317 * @return reference voltage 00318 */ 00319 float AD7791::get_reference_voltage(void) 00320 { 00321 return _vref; 00322 } 00323 00324 /** 00325 * Reads the data register of the ADC and converts the result to volts 00326 * Gain needs to be correctly set using set_gain in order to get accurate results 00327 * @return voltage of the ADC input 00328 */ 00329 float AD7791::read_voltage(void) 00330 { 00331 return data_to_voltage(read_u32()); 00332 } 00333 00334 /** 00335 * Converts an uint16_t to voltage. 00336 * Gain needs to be correctly set using set_gain in order to get accurate results 00337 * @param data in uint16_t format 00338 * @return float value of voltage (in V) 00339 */ 00340 float AD7791::data_to_voltage(uint32_t data) 00341 { 00342 return ((data / static_cast<float>(_RESOLUTION / 2)) - 1) * (_vref ); 00343 } 00344 00345 /** 00346 * Converts voltage to an uint16_t. 00347 * Gain needs to be correctly set using set_gain in order to get accurate results 00348 * @param voltage to be converted 00349 * @return data in uint16_t format 00350 */ 00351 uint32_t AD7791::voltage_to_data(float voltage) 00352 { 00353 return (((voltage / _vref) + 1) * static_cast<float>(_RESOLUTION / 2)); 00354 } 00355 00356 /** 00357 * Sets the conversion channel. 00358 * @param channel 00359 */ 00360 void AD7791::set_channel(AD7791Channel_t channel) 00361 { 00362 _channel = channel; 00363 } 00364 00365 /** 00366 * - From mbed AnalogIn API - 00367 * Read the input voltage, represented as a float in the range [0.0, 1.0] - uses the read_u16 method 00368 * @returns A floating-point value representing the current input voltage, measured as a percentage 00369 * returns 1.0 along with a debug message if the conversion failed 00370 */ 00371 float AD7791::read(void) 00372 { 00373 float percent; 00374 uint32_t data; 00375 data = read_u32(); 00376 percent = (data / static_cast<float>(_RESOLUTION) ); // translate bipolar conversion to [0.0, 1.0] domain 00377 return percent; 00378 } 00379 00380 #ifdef MBED_OPERATORS 00381 00382 /** 00383 * - From mbed AnalogIn API - 00384 * An operator shorthand for read() 00385 * The float() operator can be used as a shorthand for read() to simplify common code sequences 00386 */ 00387 AD7791::operator float() 00388 { 00389 return read(); 00390 } 00391 00392 #endif 00393 00394 00395
Generated on Tue Jul 12 2022 17:59:52 by
1.7.2
CN0357 - Toxic gas measurement
CN0216 - Weight Scale