Complete DS1621 library (all functions implemented)
Revision 0:096dbb58d60e, committed 2012-07-14
- Comitter:
- bborredon
- Date:
- Sat Jul 14 08:20:05 2012 +0000
- Commit message:
- [mbed] converted /I2c/DS1621
Changed in this revision
ds1621.cpp | Show annotated file Show diff for this revision Revisions of this file |
ds1621.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 096dbb58d60e ds1621.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ds1621.cpp Sat Jul 14 08:20:05 2012 +0000 @@ -0,0 +1,479 @@ +/*********************************************************** +Author: Bernard Borredon +Date: 27 december 2011 +Version: 1.0 +************************************************************/ +#include "ds1621.h" + +#define BIT_SET(x,n) (x=x | (0x01<<n)) +#define BIT_TEST(x,n) (x & (0x01<<n)) +#define BIT_CLEAR(x,n) (x=x & ~(0x01<<n)) + +// Constructor +DS1621::DS1621(PinName sda, PinName scl, uint8_t address) : _i2c(sda, scl) +{ + _errnum = DS1621_NoError; + _config = DS1621_PolHigh; + + // Check address range (0 to 7) + _address = address; + if(address > 7) { + _errnum = DS1621_BadAddress; + } + _address = _address << 1; + + // Set I2C frequency + _i2c.frequency(100000); +} + +// Get temperature with 0.5 degrees resolution +float DS1621::getTemp(void) +{ + char cmd; + int8_t temp8[2]; + float temp; + int ack; + + // Check error + if(_errnum) + return(0.0); + + // No error + _errnum = DS1621_NoError; + + // Start convert + startConvert(true); + if(getError() != 0) + return(0.0); + + cmd = 0xAA; // Read Temperature [AAh] + ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Read value + ack = _i2c.read(DS1621_address | _address,(char *)temp8,sizeof(temp8)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Format temperature + temp8[1] = temp8[1] >> 7; + if(temp8[0] < 0) { // - + temp = -~temp8[0] + 0.5 * temp8[1]; + } + else { // + + temp = temp8[0] - 0.5 * temp8[1]; + } + + return(temp); +} + +// Get temperature with 0.01 degrees resolution +float DS1621::getHrTemp(void) +{ + char cmd; + int8_t temp8[2]; + int ack; + uint8_t count_remain, count_per_c; + uint8_t config,config_mem; + int16_t ifract; + int16_t itemp; + float temp; + + // Check error + if(_errnum) + return(0.0); + + // No error + _errnum = DS1621_NoError; + + // Get config register + config = getConfig(); + if(getError() != 0) + return(0.0); + + // Force 1Shot if needed + config_mem = 0; + if(!BIT_TEST(config,DS1621_CFG_1SHOT)) { + config_mem = config; + BIT_SET(config,DS1621_CFG_1SHOT); + setConfig(config); + if(getError() != 0) + return(0.0); + startConvert(false); + if(getError() != 0) + return(0.0); + } + + // Start conversion + startConvert(true); + if(getError() != 0) + return(0.0); + + // Wait end of conversion + waitEndConvert(); + if(getError() != 0) + return(0.0); + + cmd = 0xAA; // Read Temperature [AAh] + ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Read value + ack = _i2c.read(DS1621_address | _address,(char *)temp8,sizeof(temp8)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + cmd = 0xA8; // Read Counter [A8H] + ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Read value + ack = _i2c.read(DS1621_address | _address,(char *)&count_remain,sizeof(count_remain)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + cmd = 0xA9; // Read Slope [A9H] + ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Read value + ack = _i2c.read(DS1621_address | _address,(char *)&count_per_c,sizeof(count_per_c)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Format temperature + ifract = ((int16_t)(count_per_c - count_remain) * 100) / 25; + if(temp8[0] < 0) { // - + itemp = -~temp8[0] * 100 + ifract; + } + else { // + + itemp = temp8[0] * 100 + ifract; + } + temp = (float)itemp / 100.0; + + // Restore config if needed + if(config_mem) { + setConfig(config_mem); + if(getError() != 0) + return(0.0); + startConvert(true); + if(getError() != 0) + return(0.0); + } + + return(temp); +} + +// Read config register +uint8_t DS1621::getConfig(void) +{ + char cmd; + uint8_t config; + int ack; + + // Check error + if(_errnum) + return(0); + + // No error + _errnum = DS1621_NoError; + + cmd = 0xAC; // Access Config [ACh] + ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0); + } + + // Read value + ack = _i2c.read(DS1621_address | _address,(char *)&config,sizeof(config)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0); + } + + return(config); +} + +// Write config register +void DS1621::setConfig(uint8_t config) +{ + char cmd[2]; + int ack; + + // Check error + if(_errnum) + return; + + // No error + _errnum = DS1621_NoError; + + _config = config; + + cmd[0] = 0xAC; // Access Config [ACh] + cmd[1] = config; + ack = _i2c.write(DS1621_address | _address,cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + } +} + +// Start or stop convert +void DS1621::startConvert(bool flag) +{ + char cmd; + int ack; + + // Check error + if(_errnum) + return; + + // No error + _errnum = DS1621_NoError; + + if(flag) + cmd = 0xEE; // Start Convert [EEh] + else + cmd = 0x22; // Stop Convert [22h] + + ack = _i2c.write(DS1621_address | _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + } +} + +// Wait end of conversion +void DS1621::waitEndConvert(void) +{ + uint8_t cfg; + + // Check error + if(_errnum) + return; + + // No error + _errnum = DS1621_NoError; + + // Wait end of conversion + do { + // Get Config register and test bit DONE + cfg = getConfig(); + if(getError() != 0) + return; + } + while(cfg < DS1621_DONE); +} + +// Read Temperature High Flag +bool DS1621::getTHF(void) +{ + uint8_t cfg; + bool thf; + + // Check error + if(_errnum) + return(0); + + // No error + _errnum = DS1621_NoError; + + // get Config register + cfg = getConfig(); + if(getError() != 0) + return(0); + + // Test THF bit + if(BIT_TEST(cfg,DS1621_CFG_THF)) + thf = true; + else + thf = false; + + return(thf); +} + +// Read Temperature Low Flag +bool DS1621::getTLF() +{ + uint8_t cfg; + bool tlf; + + // Check error + if(_errnum) + return(0); + + // No error + _errnum = DS1621_NoError; + + // get Config register + cfg = getConfig(); + if(getError() != 0) + return(0); + + // Test TLF bit + if(BIT_TEST(cfg,DS1621_CFG_TLF)) + tlf = true; + else + tlf = false; + + return(tlf); +} + +// Read Temperature Low and High Flag +void DS1621::getTF(bool& tlf,bool& thf) +{ + uint8_t cfg; + + // Check error + if(_errnum) + return; + + // No error + _errnum = DS1621_NoError; + + // get Config register + cfg = getConfig(); + if(getError() != 0) + return; + + // Test TLF bit + tlf = false; + if(BIT_TEST(cfg,DS1621_CFG_TLF)) + tlf = true; + + // Test THF bit + thf = false; + if(BIT_TEST(cfg,DS1621_CFG_THF)) + thf = true; +} + +// Read 1Shot bit +bool DS1621::get1Shot(void) +{ + + // Test 1Shot bit + if(BIT_TEST(_config,DS1621_CFG_1SHOT)) + return(true); + else + return(false); +} + +// Write Temperature (High or Low) +void DS1621::setTemperature(float temp,uint8_t trig) +{ + uint8_t temp8[3]; + int ack; + float r; + + // Chack param + if(trig > 1) { + _errnum = DS1621_ParamError; + return; + } + + // Check error + if(_errnum) + return; + + // No error + _errnum = DS1621_NoError; + + // Format temperature + if(temp >= 0.0) { + temp8[1] = (uint8_t)temp; + r = temp - (int)temp; + if(r >= 0.5) + temp8[2] = 0x80; + else + temp8[2] = 0; + } + else { + temp8[1] = ~(-(int8_t)temp); + r = -temp + (int)temp; + if(r >= 0.5) + temp8[2] = 0x80; + else + temp8[2] = 0; + } + + wait_ms(100); + + temp8[0] = 0xA1 + trig; // Access TH or TL [A1h or A2h] + ack = _i2c.write(DS1621_address | _address,(char *)temp8,sizeof(temp8)); + if(ack != 0) { + _errnum = DS1621_I2cError; + } +} + +// Read Temperature (High or Low) +float DS1621::getTemperature(uint8_t trig) +{ + char cmd; + float temp; + int8_t temp8[2]; + int ack; + + // Check param + if(trig > 1) { + _errnum = DS1621_ParamError; + return(0.0); + } + + // Check error + if(_errnum) + return(0.0); + + // No error + _errnum = DS1621_NoError; + + wait_ms(100); + + cmd = 0xA1 + trig; // Access TH or TL [A1h or A2h] + ack = _i2c.write(DS1621_address| _address,&cmd,sizeof(cmd)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + ack = _i2c.read(DS1621_address | _address,(char *)temp8,sizeof(temp8)); + if(ack != 0) { + _errnum = DS1621_I2cError; + return(0.0); + } + + // Format temperature + temp8[1] = temp8[1] >> 7; + if(temp8[0] < 0) { // - + temp = -~temp8[0] + 0.5 * temp8[1]; + } + else { // + + temp = temp8[0] - 0.5 * temp8[1]; + } + + return(temp); +} + +// Get current error number +uint8_t DS1621::getError(void) +{ + return(_errnum); +} \ No newline at end of file
diff -r 000000000000 -r 096dbb58d60e ds1621.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ds1621.h Sat Jul 14 08:20:05 2012 +0000 @@ -0,0 +1,264 @@ +#ifndef DS1621__H_ +#define DS1621__H_ + +// Includes +#include <string> + +#include "mbed.h" + +// Example +/* +#include <string> + +#include "mbed.h" +#include "ds1621.h" +#define DS1621_ADDR 0 // I2c DS1621 address is 0x00 + +static void myerror(std::string msg) +{ + printf("Error %s\n",msg.c_str()); + exit(1); +} + +int main() +{ + DS1621 ds(p9,p10,DS1621_ADDR); // Declare DS1621 i2c with sda = p9 and scl = p10 + bool tlf,thf; + uint8_t i; + uint8_t config; + uint16_t count = 0; + float temp = 0.0; + + printf("Test DS1621 I2C\n\n"); + + // Check error + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + + // Config with OneShot and Pol high and test error + ds.setConfig(DS1621_1Shot | DS1621_PolHigh); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + + // Read Config register + config = ds.getConfig(); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + printf("DS1621 Config : %02X\n",config); + + printf("Test HR Temperature\n"); + + // Test HR temperature + for(i = 0;i < 24;i++) { + temp = ds.getHrTemp(); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + printf("Measurment at start + %d seconds, Temperature HR = %.2f\n",(count*5),temp); + wait(5.0); + count++; + } + + printf("Test Temperature\n"); + + // Test temperature + count = 0; + for(i = 0;i < 12;i++) { + temp = ds.getTemp(); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + printf("Measurment at start + %d seconds, Temperature = %.2f\n",(count*5),temp); + wait(5.0); + count++; + } + + // Config with Continuous and Pol high + ds.setConfig(DS1621_PolHigh); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + + // Read Config register + config = ds.getConfig(); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + printf("DS1621 Config : %02X\n",config); + + // Write trigger temperatures + ds.setTemperature(18.0,DS1621_Access_TL); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + ds.setTemperature(25.5,DS1621_Access_TH); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + + printf("Test temperature and triggers\n"); + while(1) { + temp = ds.getTemp(); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + ds.getTF(tlf,thf); + if(ds.getError() != 0) + myerror(ds.getErrorMessage()); + printf("Temperature=%.2f TLF %d THF %d\n",temp,tlf,thf); + wait(5.0); + } +} +*/ + +// Defines +#define DS1621_address 0x90 + +#define DS1621_PolHigh 0x02 +#define DS1621_1Shot 0x01 +#define DS1621_DONE 0x80 + +#define DS1621_CFG_1SHOT 0 +#define DS1621_CFG_POL 1 +#define DS1621_CFG_TLF 5 +#define DS1621_CFG_THF 6 +#define DS1621_CFG_DONE 7 + +#define DS1621_Access_TH 0 +#define DS1621_Access_TL 1 + +#define DS1621_NoError 0x00 +#define DS1621_BadAddress 0x01 +#define DS1621_I2cError 0x02 +#define DS1621_ParamError 0x03 + +#define DS1621_MaxError 4 + +static std::string _ErrorMessageDS1621[DS1621_MaxError] = { + "", + "Bad chip address", + "I2C error (nack)", + "Invalid parameter", + }; + +// Class +class DS1621 { +public: + /* + * Constructor, initialize the ds1621 on i2c interface. + * @param sda : sda i2c pin (PinName) + * @param scl : scl i2c pin (PinName) + * @param address : ds1621 address between 0 and 7 (uint8_t) + * @return none + */ + DS1621(PinName sda, PinName scl, uint8_t address); + + /* + * Get temperature from the ds1621 with 0.5 degrees resolution + * @param : none + * @return current temperature in degrees Celsius between -55 and +125 (float) + */ + float getTemp(void); + + /* + * Get temperature from the ds1621 with 0.01 degrees resolution + * @param : none + * @return current temperature in degrees Celsius between -55 and +125 (float) + */ + float getHrTemp(void); + + /* + * Read config register + * @param : none + * @return current config register value (uin8_t) + */ + uint8_t getConfig(void); + + /* + * Write config register + * @param config : config value (uint8_t) + * @return none + */ + void setConfig(uint8_t config); + + /* + * Start / stop convert + * @param flag : start convert if true else stop + * @return none + */ + void startConvert(bool flag); + + /* + * Wait end of conversion (Config register bit 7 at 1) + * @param : none + * @return none + */ + void waitEndConvert(void); + + /* + * Get Temperature High Flag + * @param : none + * @return thf flag (bool) + */ + bool getTHF(void); + + /* + * Get Temperature Low Flag + * @param : none + * @return tlf flag (bool) + */ + bool getTLF(void); + + /* + * Get Temperature Low and High Flags + * @param tlf : temperature low flag (uint8_t&) + * @param thf : temperature high flag (uint8_t&) + * @return none + */ + void getTF(bool& tlf,bool& thf); + + /* + *Get 1Shot bit + *@param : none + *@return true if 1Shot (bool) + */ + bool get1Shot(void); + + /* + *Set Temperature (High or Low) + *@param temp : temperature, the fractionnal part is rounded to 0.5 (float) + *@param trig : mode,low or high (uint8_t) [DS1621_Access_TL DS1621_Access_TH] + *@return none + */ + void setTemperature(float temp,uint8_t trig); + + /* + *Get Temperature (High or Low) + *@param trig : mode,low or high (uint8_t) [DS1621_Access_TL DS1621_Access_TH] + *@return temperature, with 0.5 degrees Celsius resolution (float) + */ + float getTemperature(uint8_t trig); + + /* + *Get current error message + *@param : none + *@return current error message(std::string) + */ + std::string getErrorMessage(void) + { + if(_errnum < DS1621_MaxError) + return(_ErrorMessageDS1621[_errnum]); + else + return("errnum out of range"); + } + + /* + * Get the current error number (DS1621_NoError if no error) + * @param : none + * @return current error number (uint8_t) + */ + uint8_t getError(void); + +//---------- local variables ---------- +private: + I2C _i2c; // Local i2c communication interface instance + int _address; // Local ds1621 i2c address + uint8_t _errnum; // Error number + uint8_t _config; // Config register value +//------------------------------------- +}; + +#endif \ No newline at end of file