i2c_slave.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* Library made by: g4lvanix
  2. * Github repository: https://github.com/g4lvanix/I2C-slave-lib
  3. */
  4. #include <avr/io.h>
  5. #include <util/twi.h>
  6. #include <avr/interrupt.h>
  7. #include "i2c_slave.h"
  8. void i2c_init(uint8_t address){
  9. // load address into TWI address register
  10. TWAR = (address << 1);
  11. // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
  12. TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
  13. }
  14. void i2c_stop(void){
  15. // clear acknowledge and enable bits
  16. TWCR &= ~( (1<<TWEA) | (1<<TWEN) );
  17. }
  18. ISR(TWI_vect){
  19. // temporary stores the received data
  20. uint8_t data;
  21. // own address has been acknowledged
  22. if( (TWSR & 0xF8) == TW_SR_SLA_ACK ){
  23. buffer_address = 0xFF;
  24. // clear TWI interrupt flag, prepare to receive next byte and acknowledge
  25. TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
  26. }
  27. else if( (TWSR & 0xF8) == TW_SR_DATA_ACK ){ // data has been received in slave receiver mode
  28. // save the received byte inside data
  29. data = TWDR;
  30. // check wether an address has already been transmitted or not
  31. if(buffer_address == 0xFF){
  32. buffer_address = data;
  33. // clear TWI interrupt flag, prepare to receive next byte and acknowledge
  34. TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
  35. }
  36. else{ // if a databyte has already been received
  37. // store the data at the current address
  38. rxbuffer[buffer_address] = data;
  39. // increment the buffer address
  40. buffer_address++;
  41. // if there is still enough space inside the buffer
  42. if(buffer_address < 0xFF){
  43. // clear TWI interrupt flag, prepare to receive next byte and acknowledge
  44. TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
  45. }
  46. else{
  47. // Don't acknowledge
  48. TWCR &= ~(1<<TWEA);
  49. // clear TWI interrupt flag, prepare to receive last byte.
  50. TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN);
  51. }
  52. }
  53. }
  54. else if( (TWSR & 0xF8) == TW_ST_DATA_ACK ){ // device has been addressed to be a transmitter
  55. // copy data from TWDR to the temporary memory
  56. data = TWDR;
  57. // if no buffer read address has been sent yet
  58. if( buffer_address == 0xFF ){
  59. buffer_address = data;
  60. }
  61. // copy the specified buffer address into the TWDR register for transmission
  62. TWDR = txbuffer[buffer_address];
  63. // increment buffer read address
  64. buffer_address++;
  65. // if there is another buffer address that can be sent
  66. if(buffer_address < 0xFF){
  67. // clear TWI interrupt flag, prepare to send next byte and receive acknowledge
  68. TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
  69. }
  70. else{
  71. // Don't acknowledge
  72. TWCR &= ~(1<<TWEA);
  73. // clear TWI interrupt flag, prepare to receive last byte.
  74. TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN);
  75. }
  76. }
  77. else{
  78. // if none of the above apply prepare TWI to be addressed again
  79. TWCR |= (1<<TWIE) | (1<<TWEA) | (1<<TWEN);
  80. }
  81. }