84 lines
3.2 KiB
C
84 lines
3.2 KiB
C
|
|
/*
|
|
* I2C_Slave_C_File.c
|
|
*
|
|
*/
|
|
#include "i2c.h"
|
|
|
|
void I2C_Slave_Init(uint8_t slave_address) {
|
|
TWAR = slave_address << 1; /* Assign address in TWI address register (shifted left by 1) */
|
|
TWCR = (1<<TWEN) | (1<<TWEA) | (1<<TWIE) | (1<<TWINT); /* Enable TWI, Enable ack generation, enable interrupt, clear interrupt flag */
|
|
}
|
|
|
|
int8_t I2C_Slave_Listen() {
|
|
while(1) {
|
|
uint8_t status; /* Declare variable */
|
|
while (!(TWCR & (1<<TWINT))); /* Wait to be addressed */
|
|
status = TWSR & 0xF8; /* Read TWI status register with masking lower three bits */
|
|
|
|
if (status == 0x60 || status == 0x68) /* Check weather own SLA+W received & ack returned (TWEA = 1) */
|
|
return 0; /* If yes then return 0 to indicate ack returned */
|
|
|
|
if (status == 0xA8 || status == 0xB0) /* Check weather own SLA+R received & ack returned (TWEA = 1) */
|
|
return 1; /* If yes then return 1 to indicate ack returned */
|
|
|
|
if (status == 0x70 || status == 0x78) /* Check weather general call received & ack returned (TWEA = 1) */
|
|
return 2; /* If yes then return 2 to indicate ack returned */
|
|
|
|
else
|
|
continue; /* Else continue */
|
|
}
|
|
}
|
|
|
|
int8_t I2C_Slave_Transmit(char data) {
|
|
uint8_t status;
|
|
TWDR = data; /* Write data to TWDR to be transmitted */
|
|
TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWEA); /* Enable TWI and clear interrupt flag */
|
|
|
|
while (!(TWCR & (1<<TWINT))); /* Wait until TWI finish its current job (Write operation) */
|
|
status = TWSR & 0xF8; /* Read TWI status register with masking lower three bits */
|
|
|
|
if (status == 0xA0) /* Check weather STOP/REPEATED START received */
|
|
{
|
|
TWCR |= (1<<TWINT); /* If yes then clear interrupt flag & return -1 */
|
|
return -1;
|
|
}
|
|
|
|
if (status == 0xB8) /* Check weather data transmitted & ack received */
|
|
return 0; /* If yes then return 0 */
|
|
|
|
if (status == 0xC0) /* Check weather data transmitted & nack received */
|
|
{
|
|
TWCR |= (1<<TWINT); /* If yes then clear interrupt flag & return -2 */
|
|
return -2;
|
|
}
|
|
|
|
if (status == 0xC8) /* If last data byte transmitted with ack received TWEA = 0 */
|
|
return -3; /* If yes then return -3 */
|
|
|
|
else /* else return -4 */
|
|
return -4;
|
|
}
|
|
|
|
char I2C_Slave_Receive() {
|
|
uint8_t status; /* Declare variable */
|
|
TWCR = (1<<TWEN) | (1<<TWEA) | (1<<TWINT); /* Enable TWI, generation of ack and clear interrupt flag */
|
|
|
|
while (!(TWCR & (1<<TWINT))); /* Wait until TWI finish its current job (read operation) */
|
|
status = TWSR & 0xF8; /* Read TWI status register with masking lower three bits */
|
|
|
|
if (status == 0x80 || status == 0x90) /* Check weather data received & ack returned (TWEA = 1) */
|
|
return TWDR; /* If yes then return received data */
|
|
|
|
if (status == 0x88 || status == 0x98) /* Check weather data received, nack returned and switched to not addressed slave mode */
|
|
return TWDR; /* If yes then return received data */
|
|
|
|
if (status == 0xA0) /* Check weather STOP/REPEATED START received */
|
|
{
|
|
TWCR |= (1<<TWINT); /* If yes then clear interrupt flag & return -1 */
|
|
return -1;
|
|
}
|
|
|
|
else
|
|
return -2; /* Else return -2 */
|
|
} |