twim.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //***************************************************************************
  2. //
  3. // Author(s)...: Павел Бобков http://ChipEnable.Ru
  4. //
  5. // Target(s)...: mega16
  6. //
  7. // Compiler....: IAR
  8. //
  9. // Description.: Драйвер ведущего TWI устройства.
  10. // Код основан на Atmel`овских доках - AVR315.
  11. //
  12. // Data........: 13.11.13
  13. //
  14. //***************************************************************************
  15. #include "twim.h"
  16. #define TWSR_MASK 0xfc
  17. volatile static uint8_t twiBuf[TWI_BUFFER_SIZE];
  18. volatile static uint8_t twiState = TWI_NO_STATE;
  19. volatile static uint8_t twiMsgSize;
  20. /*предделители для установки скорости обмена twi модуля*/
  21. uint8_t pre[4] = {2, 8, 32, 128};
  22. /****************************************************************************
  23. Инициализация и установка частоты SCL сигнала
  24. ****************************************************************************/
  25. uint8_t TWI_MasterInit(uint16_t fr)
  26. {
  27. uint8_t i;
  28. uint16_t twbrValue;
  29. for(i = 0; i<4; i++){
  30. twbrValue = ((((F_CPU)/1000UL)/fr)-16)/pre[i];
  31. if ((twbrValue > 0)&& (twbrValue < 256)){
  32. TWBR = (uint8_t)twbrValue;
  33. TWSR = i;
  34. TWDR = 0xFF;
  35. TWCR = (1<<TWEN);
  36. return TWI_SUCCESS;
  37. }
  38. }
  39. return 0;
  40. }
  41. /****************************************************************************
  42. Проверка - не занят ли TWI модуль. Используется внутри модуля
  43. ****************************************************************************/
  44. static uint8_t TWI_TransceiverBusy(void)
  45. {
  46. return (TWCR & (1<<TWIE));
  47. }
  48. /****************************************************************************
  49. Взять статус TWI модуля
  50. ****************************************************************************/
  51. uint8_t TWI_GetState(void)
  52. {
  53. while (TWI_TransceiverBusy());
  54. return twiState;
  55. }
  56. /****************************************************************************
  57. Передать сообщение msg из msgSize байтов на TWI шину
  58. ****************************************************************************/
  59. void TWI_SendData(uint8_t *msg, uint8_t msgSize)
  60. {
  61. uint8_t i;
  62. while(TWI_TransceiverBusy()); //ждем, когда TWI модуль освободится
  63. twiMsgSize = msgSize; //сохряняем кол. байт для передачи
  64. twiBuf[0] = msg[0]; //и первый байт сообщения
  65. if (!(msg[0] & (TRUE<<TWI_READ_BIT))){ //если первый байт типа SLA+W
  66. for (i = 1; i < msgSize; i++){ //то сохряняем остальную часть сообщения
  67. twiBuf[i] = msg[i];
  68. }
  69. }
  70. twiState = TWI_NO_STATE ;
  71. TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA); //разрешаем прерывание и формируем состояние старт
  72. }
  73. /****************************************************************************
  74. Переписать полученные данные в буфер msg в количестве msgSize байт.
  75. ****************************************************************************/
  76. uint8_t TWI_GetData(uint8_t *msg, uint8_t msgSize)
  77. {
  78. uint8_t i;
  79. while(TWI_TransceiverBusy()); //ждем, когда TWI модуль освободится
  80. if(twiState == TWI_SUCCESS){ //если сообщение успешно принято,
  81. for(i = 0; i < msgSize; i++){ //то переписываем его из внутреннего буфера в переданный
  82. msg[i] = twiBuf[i];
  83. }
  84. }
  85. return twiState;
  86. }
  87. /****************************************************************************
  88. Обработчик прерывания TWI модуля
  89. ****************************************************************************/
  90. #pragma vector=TWI_vect
  91. __interrupt void TWI_ISR(void)
  92. {
  93. static uint8_t ptr;
  94. uint8_t stat = TWSR & TWSR_MASK;
  95. switch (stat){
  96. case TWI_START: // состояние START сформировано
  97. case TWI_REP_START: // состояние повторный START сформировано
  98. ptr = 0;
  99. case TWI_MTX_ADR_ACK: // был передан пакет SLA+W и получено подтверждение
  100. case TWI_MTX_DATA_ACK: // был передан байт данных и получено подтверждение
  101. if (ptr < twiMsgSize){
  102. TWDR = twiBuf[ptr]; //загружаем в регистр данных следующий байт
  103. TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT); //сбрасываем флаг TWINT
  104. ptr++;
  105. }
  106. else{
  107. twiState = TWI_SUCCESS;
  108. TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO)|(0<<TWIE); //формируем состояние СТОП, сбрасываем флаг, запрещаем прерывания
  109. }
  110. break;
  111. case TWI_MRX_DATA_ACK: //байт данных принят и передано подтверждение
  112. twiBuf[ptr] = TWDR;
  113. ptr++;
  114. case TWI_MRX_ADR_ACK: //был передан пакет SLA+R и получено подтвеждение
  115. if (ptr < (twiMsgSize-1)){
  116. TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA); //если это не предпоследний принятый байт, формируем подтверждение
  117. }
  118. else {
  119. TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT); //если приняли предпоследний байт, подтверждение не формируем
  120. }
  121. break;
  122. case TWI_MRX_DATA_NACK: //был принят байт данных без подтверждения
  123. twiBuf[ptr] = TWDR;
  124. twiState = TWI_SUCCESS;
  125. TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWSTO); //формируем состояние стоп
  126. break;
  127. case TWI_ARB_LOST: //был потерян приоритет
  128. TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA); // сбрасываем флаг TWINT, формируем повторный СТАРТ
  129. break;
  130. case TWI_MTX_ADR_NACK: // был передан пает SLA+W и не получено подтверждение
  131. case TWI_MRX_ADR_NACK: // был передан пакет SLA+R и не получено подтверждение
  132. case TWI_MTX_DATA_NACK: // был передан байт данных и не получено подтверждение
  133. case TWI_BUS_ERROR: // ошибка на шине из-за некоректных состояний СТАРТ или СТОП
  134. default:
  135. twiState = stat;
  136. TWCR = (1<<TWEN)|(0<<TWIE)|(0<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); //запретить прерывание
  137. }
  138. }