123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /****************************************************
- Low Level I2C Data Transreceiveing APIs
- PLEASE SEE WWW.EXTREMEELECTRONICS.CO.IN FOR DETAILED
- SCHEMATICS,USER GUIDE AND VIDOES.
- COPYRIGHT (C) 2008-2009 EXTREME ELECTRONICS INDIA
- ****************************************************/
- #include <avr/io.h>
- #include "i2c.h"
- /* Private defines */
- // twi_br must be 3
- #define TWI_SPEED 400000UL
- #define TWI_PRESCALER 4
- #define TWI_BR ((F_CPU / TWI_SPEED) - 16) / (2 * TWI_PRESCALER)
- #define TWPS_1 ((0<<TWPS1) | (0<<TWPS0))
- #define TWPS_4 ((0<<TWPS1) | (1<<TWPS0))
- #define TWPS_16 ((1<<TWPS1) | (0<<TWPS0))
- #define TWPS_64 ((1<<TWPS1) | (1<<TWPS0))
- #define TWI_PS TWPS_4
- #define TWI_WDT_TIMEOUT 10
- /* Private variables */
- uint8_t TWI_WDT;
- /**
- * @brief Initialize TWI
- * @param None
- * @return None
- */
- void I2C_Init(void) {
- //Set up TWI Module
- TWSR = TWI_PS;
- TWBR = TWI_BR;
- //Enable the TWI Module
- TWCR |= 1<<TWEN;
- }
- /**
- * @brief Disable TWI
- * @param None
- * @return None
- */
- void I2C_Close(void)
- {
- //Disable the module
- TWCR &= ~(1<<TWEN);
- }
- /**
- * @brief TWI Start condition
- * @param None
- * @return Operation status
- */
- twi_stats_t I2C_Start(void) {
- //Put Start Condition on Bus
- TWCR= (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
- //Poll Till Done
- TWI_WDT = TWI_WDT_TIMEOUT;
- while (!(TWCR & (1<<TWINT))) {
- if (TWI_WDT == 0) {
- return TWI_TIMEOUT;
- }
- }
- if ((TWSR & 0xF8) == 0x08 || (TWSR & 0xF8) == 0x10) {
- //start condition sent from master
- //or
- //repeat start condition sent from master
- return TWI_SUCCESS;
- } else {
- return TWI_ERROR;
- }
- }
- /**
- * @brief TWI Stop condition
- * @param None
- * @return Operation status
- */
- twi_stats_t I2C_Stop(void) {
- //Put Stop Condition on bus
- TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
- //Wait for STOP to finish
- // зачем это ждать тут? проверять перед стартом и всё!
- TWI_WDT = TWI_WDT_TIMEOUT;
- while (TWCR & (1<<TWSTO)) {
- if (TWI_WDT == 0) {
- return TWI_TIMEOUT;
- }
- }
- return TWI_SUCCESS;
- }
- /**
- * @brief TWI Send Byte
- * @param None
- * @return Operation status
- */
- twi_stats_t I2C_WriteByte(uint8_t data) {
- TWDR = data;
- //Initiate Transfer
- TWCR = (1<<TWEN) | (1<<TWINT);
- //Poll Till Done
- TWI_WDT = TWI_WDT_TIMEOUT;
- while (!(TWCR & (1<<TWINT))) {
- if (TWI_WDT == 0) {
- return TWI_TIMEOUT;
- }
- }
- //Check Status
- if ((TWSR & 0xF8) == 0x18 || (TWSR & 0xF8) == 0x28 || (TWSR & 0xF8) == 0x40) {
- //SLA+W Transmitted and ACK received
- //or
- //SLA+R Transmitted and ACK received
- //or
- //DATA Transmitted and ACK recived
- return TWI_SUCCESS;
- } else {
- return TWI_ERROR; //Error
- }
- }
- /**
- * @brief TWI Receive Byte
- * @param None
- * @return Operation status
- */
- twi_stats_t I2C_ReadByte(uint8_t *data, twi_ask_t ack) {
- //Set up ACK
- if (ack == TWI_ACK) {
- //return ACK after reception
- TWCR |= (1<<TWEA);
- } else {
- //return NACK after reception
- //Signals slave to stop giving more data
- //usually used for last byte read.
- TWCR &= ~(1<<TWEA);
- }
- //Now enable Reception of data by clearing TWINT
- TWCR |= (1<<TWINT);
- //Wait till done
- TWI_WDT = TWI_WDT_TIMEOUT;
- while(!(TWCR & (1<<TWINT))) {
- if (TWI_WDT == 0) {
- return TWI_TIMEOUT;
- }
- }
- //Check status
- if ((TWSR & 0xF8) == 0x58 || (TWSR & 0xF8) == 0x50) {
- //Data received and ACK returned
- // or
- //Data received and NACK returned
- //Read the data
- *data = TWDR;
- return TWI_SUCCESS;
- } else {
- return TWI_ERROR; //Error
- }
- }
|