i2c_master.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* Library made by: g4lvanix
  2. * Github repository: https://github.com/g4lvanix/I2C-master-lib
  3. */
  4. #include <avr/io.h>
  5. #include <util/twi.h>
  6. #include "i2c_master.h"
  7. #define F_SCL 400000UL // SCL frequency
  8. #define Prescaler 1
  9. #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
  10. void i2c_init(void)
  11. {
  12. TWSR = 0; /* no prescaler */
  13. TWBR = (uint8_t)TWBR_val;
  14. //TWBR = 10;
  15. }
  16. uint8_t i2c_start(uint8_t address)
  17. {
  18. // reset TWI control register
  19. TWCR = 0;
  20. // transmit START condition
  21. TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
  22. // wait for end of transmission
  23. while( !(TWCR & (1<<TWINT)) );
  24. // check if the start condition was successfully transmitted
  25. if(((TW_STATUS & 0xF8) != TW_START) && ((TW_STATUS & 0xF8) != TW_REP_START)){ return 1; }
  26. // load slave address into data register
  27. TWDR = address;
  28. // start transmission of address
  29. TWCR = (1<<TWINT) | (1<<TWEN);
  30. // wait for end of transmission
  31. while( !(TWCR & (1<<TWINT)) );
  32. // check if the device has acknowledged the READ / WRITE mode
  33. uint8_t twst = TW_STATUS & 0xF8;
  34. if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
  35. return 0;
  36. }
  37. uint8_t i2c_write(uint8_t data)
  38. {
  39. // load data into data register
  40. TWDR = data;
  41. // start transmission of data
  42. TWCR = (1<<TWINT) | (1<<TWEN);
  43. // wait for end of transmission
  44. while( !(TWCR & (1<<TWINT)) );
  45. if( (TW_STATUS & 0xF8) != TW_MT_DATA_ACK ){ return 1; }
  46. return 0;
  47. }
  48. uint8_t i2c_read_ack(void)
  49. {
  50. // start TWI module and acknowledge data after reception
  51. TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
  52. // wait for end of transmission
  53. while( !(TWCR & (1<<TWINT)) );
  54. // return received data from TWDR
  55. return TWDR;
  56. }
  57. uint8_t i2c_read_nack(void)
  58. {
  59. // start receiving without acknowledging reception
  60. TWCR = (1<<TWINT) | (1<<TWEN);
  61. // wait for end of transmission
  62. while( !(TWCR & (1<<TWINT)) );
  63. // return received data from TWDR
  64. return TWDR;
  65. }
  66. uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length)
  67. {
  68. if (i2c_start(address | I2C_WRITE)) return 1;
  69. for (uint16_t i = 0; i < length; i++)
  70. {
  71. if (i2c_write(data[i])) return 1;
  72. }
  73. i2c_stop();
  74. return 0;
  75. }
  76. uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length)
  77. {
  78. if (i2c_start(address | I2C_READ)) return 1;
  79. for (uint16_t i = 0; i < (length-1); i++)
  80. {
  81. data[i] = i2c_read_ack();
  82. }
  83. data[(length-1)] = i2c_read_nack();
  84. i2c_stop();
  85. return 0;
  86. }
  87. uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length)
  88. {
  89. if (i2c_start(devaddr | 0x00)) return 1;
  90. i2c_write(regaddr);
  91. for (uint16_t i = 0; i < length; i++)
  92. {
  93. if (i2c_write(data[i])) return 1;
  94. }
  95. i2c_stop();
  96. return 0;
  97. }
  98. uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length)
  99. {
  100. if (i2c_start(devaddr)) return 1;
  101. i2c_write(regaddr);
  102. if (i2c_start(devaddr | 0x01)) return 1;
  103. for (uint16_t i = 0; i < (length-1); i++)
  104. {
  105. data[i] = i2c_read_ack();
  106. }
  107. data[(length-1)] = i2c_read_nack();
  108. i2c_stop();
  109. return 0;
  110. }
  111. void i2c_stop(void)
  112. {
  113. // transmit STOP condition
  114. TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
  115. // wait until stop condition is executed and bus released
  116. while(TWCR & (1<<TWSTO));
  117. }