A collection of Analog Devices drivers for the mbed platform
Embed:
(wiki syntax)
Show/hide line numbers
AD7791.cpp
Go to the documentation of this file.
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