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