diff --git a/code/inc/DS3231.h b/code/inc/DS3231.h index 720bb9e..290c68e 100644 --- a/code/inc/DS3231.h +++ b/code/inc/DS3231.h @@ -1,15 +1,8 @@ -#ifndef _DS3231_h -#define _DS3231_h +#ifndef _DS3231_H +#define _DS3231_H -#define DS3231_ADDRESS 0b1101000 +#include -#define REG_SECONDS 0x00 //Sekunden Register - - - - -void DS3231_init(void); -int DS3231_seconds(void); +uint32_t DS3231_read(void); #endif - diff --git a/code/inc/i2c.h b/code/inc/i2c.h deleted file mode 100644 index fa7ef1d..0000000 --- a/code/inc/i2c.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _I2C_h -#define _I2C_h - -/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ -#define I2C_READ 1 - -/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ -#define I2C_WRITE 0 -#define SCL_CLOCK 96000L //i2c clockspeed - - -void i2c_init(void); -unsigned char i2c_start(unsigned char address); -/* -void i2c_stop(void); -unsigned char i2c_write( unsigned char data ); -unsigned char i2c_readAck(void); -unsigned char i2c_readNak(void); -*/ - - -#endif diff --git a/code/inc/i2cmaster.h b/code/inc/i2cmaster.h new file mode 100644 index 0000000..7c39cef --- /dev/null +++ b/code/inc/i2cmaster.h @@ -0,0 +1,178 @@ +#ifndef _I2CMASTER_H +#define _I2CMASTER_H +/************************************************************************* +* Title: C include file for the I2C master interface +* (i2cmaster.S or twimaster.c) +* Author: Peter Fleury +* File: $Id: i2cmaster.h,v 1.12 2015/09/16 09:27:58 peter Exp $ +* Software: AVR-GCC 4.x +* Target: any AVR device +* Usage: see Doxygen manual +**************************************************************************/ + +/** + @file + @defgroup pfleury_ic2master I2C Master library + @code #include @endcode + + @brief I2C (TWI) Master Software Library + + Basic routines for communicating with I2C slave devices. This single master + implementation is limited to one bus master on the I2C bus. + + This I2c library is implemented as a compact assembler software implementation of the I2C protocol + which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c). + Since the API for these two implementations is exactly the same, an application can be linked either against the + software I2C implementation or the hardware I2C implementation. + + Use 4.7k pull-up resistor on the SDA and SCL pin. + + Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module + i2cmaster.S to your target when using the software I2C implementation ! + + Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion. + + @note + The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted + to GNU assembler and AVR-GCC C call interface. + Replaced the incorrect quarter period delays found in AVR300 with + half period delays. + + @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury + @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 + + @par API Usage Example + The following code shows typical usage of this library, see example test_i2cmaster.c + + @code + + #include + + + #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet + + int main(void) + { + unsigned char ret; + + i2c_init(); // initialize I2C library + + // write 0x75 to EEPROM address 5 (Byte Write) + i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode + i2c_write(0x05); // write address = 5 + i2c_write(0x75); // write value 0x75 to EEPROM + i2c_stop(); // set stop conditon = release bus + + + // read previously written value back from EEPROM address 5 + i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode + + i2c_write(0x05); // write address = 5 + i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode + + ret = i2c_readNak(); // read one byte from EEPROM + i2c_stop(); + + for(;;); + } + @endcode + +*/ + + +/**@{*/ + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 +#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" +#endif + +#include + +/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */ +#define I2C_READ 1 + +/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */ +#define I2C_WRITE 0 + + +/** + @brief initialize the I2C master interace. Need to be called only once + @return none + */ +extern void i2c_init(void); + + +/** + @brief Terminates the data transfer and releases the I2C bus + @return none + */ +extern void i2c_stop(void); + + +/** + @brief Issues a start condition and sends address and transfer direction + + @param addr address and transfer direction of I2C device + @retval 0 device accessible + @retval 1 failed to access device + */ +extern unsigned char i2c_start(unsigned char addr); + + +/** + @brief Issues a repeated start condition and sends address and transfer direction + + @param addr address and transfer direction of I2C device + @retval 0 device accessible + @retval 1 failed to access device + */ +extern unsigned char i2c_rep_start(unsigned char addr); + + +/** + @brief Issues a start condition and sends address and transfer direction + + If device is busy, use ack polling to wait until device ready + @param addr address and transfer direction of I2C device + @return none + */ +extern void i2c_start_wait(unsigned char addr); + + +/** + @brief Send one byte to I2C device + @param data byte to be transfered + @retval 0 write successful + @retval 1 write failed + */ +extern unsigned char i2c_write(unsigned char data); + + +/** + @brief read one byte from the I2C device, request more data from device + @return byte read from I2C device + */ +extern unsigned char i2c_readAck(void); + +/** + @brief read one byte from the I2C device, read is followed by a stop condition + @return byte read from I2C device + */ +extern unsigned char i2c_readNak(void); + +/** + @brief read one byte from the I2C device + + Implemented as a macro, which calls either @ref i2c_readAck or @ref i2c_readNak + + @param ack 1 send ack, request more data from device
+ 0 send nak, read is followed by a stop condition + @return byte read from I2C device + */ +extern unsigned char i2c_read(unsigned char ack); +#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak(); + + + +/**@}*/ +#endif diff --git a/code/src/DS3231.c b/code/src/DS3231.c index 846a650..dae2379 100644 --- a/code/src/DS3231.c +++ b/code/src/DS3231.c @@ -1,41 +1,17 @@ -#include "i2c.h" #include "DS3231.h" #include "pinout.h" #include +#include "i2cmaster.h" +uint32_t DS3231_read(){ + i2c_start_wait(0xD0); + i2c_write(0x00); + i2c_stop(); - -void DS3231_init(void){ - //i2c_start(DS3231_ADDRESS); -} - - - -int DS3231_seconds(void){ - - char ret = i2c_start(DS3231_ADDRESS+I2C_WRITE); - /* - USART_Transmit_String(" Return "); - //putchar(ret); - USART_Transmit_String("\n"); - */ -/* - if(ret){ //failed - PORTB |= STATUS_LED_B; - i2c_stop(); - }else{ - // issuing start condition ok, device accessible - i2c_write(0x05); // write address = 5 - i2c_write(0x75); // ret=0 -> Ok, ret=1 -> no ACK - i2c_stop(); - - i2c_start_wait(DS3231_ADDRESS+I2C_WRITE); // set device address and write mode - i2c_write(REG_SECONDS); // write address = 5 - i2c_rep_start(DS3231_ADDRESS+I2C_READ); // set device address and read mode - ret = i2c_readNak(); // read one byte - i2c_stop(); - } - - return ret; - */ + i2c_start_wait(0xD1); + uint8_t sec = i2c_readAck(); + uint8_t min = i2c_readAck(); + uint8_t std = i2c_readNak(); + i2c_stop(); + return ((uint32_t)std<<16) | ((uint32_t)min<<8) | sec; } diff --git a/code/src/i2c.c b/code/src/i2c.c deleted file mode 100644 index b8115cc..0000000 --- a/code/src/i2c.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "i2c.h" -#include "pinout.h" -#include -#include - - -void i2c_init(void) -{ - /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ - - TWSR = 1; /* no prescaler */ - TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */ - -} - - -unsigned char i2c_start(unsigned char address){ - char DATA = 0b10011000; - //Send START condition - TWCR = (1<> 4; + } print_SR_Buffer(); - */ - //putchar((i2c_start(0x68))+48); - //i2c_write(0b00101010); - } + } } void check_dip_switches() { @@ -198,6 +175,7 @@ void setup(){ (1 << TOIE1); //Timer Overflow Enabled uart_init(); + i2c_init(); sei(); //Enable Interrupts //adc_setup(); diff --git a/code/src/twimaster.c b/code/src/twimaster.c new file mode 100644 index 0000000..3fc2ddd --- /dev/null +++ b/code/src/twimaster.c @@ -0,0 +1,202 @@ +/************************************************************************* +* Title: I2C master library using hardware TWI interface +* Author: Peter Fleury http://jump.to/fleury +* File: $Id: twimaster.c,v 1.4 2015/01/17 12:16:05 peter Exp $ +* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3 +* Target: any AVR device with hardware TWI +* Usage: API compatible with I2C Software Library i2cmaster.h +**************************************************************************/ +#include +#include + +#include + + +/* define CPU frequency in hz here if not defined in Makefile */ +#ifndef F_CPU +#define F_CPU 4000000UL +#endif + +/* I2C clock in Hz */ +#define SCL_CLOCK 100000L + + +/************************************************************************* + Initialization of the I2C bus interface. Need to be called only once +*************************************************************************/ +void i2c_init(void) +{ + /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ + + TWSR = 0; /* no prescaler */ + TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */ + +}/* i2c_init */ + + +/************************************************************************* + Issues a start condition and sends address and transfer direction. + return 0 = device accessible, 1= failed to access device +*************************************************************************/ +unsigned char i2c_start(unsigned char address) +{ + uint8_t twst; + + // send START condition + TWCR = (1<