Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

I2C Sniffer using GPIO pins of ATtiny85 Micro-controller?

Status
Not open for further replies.

xpress_embedo

Advanced Member level 4
Joined
Jul 5, 2011
Messages
1,154
Helped
161
Reputation
396
Reaction score
189
Trophy points
1,353
Location
India
Activity points
10,591
Hello!! Everyone,
I am using ATtiny85 micro-controller and have to Sniff the I2C bus and watch its data on UART.

I found one example on AVR freaks website
https://www.avrfreaks.net/projects/i2c-twi-sniffer

This works perfectly but the problem is that, it uses USI hardware, and i can't use that, in my hardware PB1 and PB4 pins are used to sniff the I2C data.
PB1 will Sniff SCL line and PB4 will Sniff SDA line.

I don't know, why i am not able to detect the start condition, with this code can any one please help me in this.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#define SCL_SNIFF   1
#define SDA_SNIFF   4
 
#define IDLE        0
#define START       1
#define DATA        2
#define STOP        3
#define INVAILD     4
 
#define LOW         0
#define HIGH        (!LOW)
 
char state = IDLE;
char sda_state = LOW, sda_state_prev = HIGH;
char scl_state = LOW, scl_state_prev = HIGH;
 
char readPin(char PinNumber)
{
  char status = LOW;
  if(PINB&(1<<PinNumber))
  {
    status = HIGH;
  }
  return status;
}
int main( void )
{
  // Enable Internal Pull-Ups
  PORTB |= (1<<SCL_SNIFF);
  PORTB |= (1<<SDA_SNIFF);
  // Make Pins as Input Output Pins
  DDRB &= ~(1<<SCL_SNIFF);
  DDRB &= ~(1<<SDA_SNIFF);
  init_uart0();
  sei();
  uputs0( "I2C-Sniffer:\n");
  while(1)
  {
    scl_state = readPin(SCL_SNIFF);
    sda_state = readPin(SDA_SNIFF);
    if(scl_state != scl_state_prev)
    {
      scl_state_prev = scl_state;
    }
    if(sda_state != sda_state_prev)
    {
      sda_state_prev = sda_state;
    }
    switch(state)
    {
      case IDLE:
        if(scl_state == HIGH)
        {
          if((sda_state_prev == HIGH) & (sda_state == LOW))
          {
            state = START;
          }
          if((sda_state_prev == LOW) & (sda_state == HIGH))
          {
            state = STOP;
          }
        }
      break;
      case START:
        uputs0( "Start");
        state = IDLE;        
      break;
      case DATA:
      break;
      case STOP:
        uputs0( "Stop\n");
        state = IDLE;
      break;
      case INVAILD:
      default:
        state = IDLE;
      break;
    }
  }
}



I am using PIC16F877A and DS1307 both communication with each other, and using ATtiny85 to sniff its data.

Hardware

Hardware.PNG

Simulation

Simulation.png


Please suggest me what i am doing wrong.
 

Please review your code, or trace it's execution with Proteus source level debugger.

You'll notice that none of the expected events like
Code:
if((sda_state_prev == HIGH) & (sda_state == LOW))
will ever happen because sda_state_prev is set equal to sda_state before. Obviously previous state must be set after checking for input state changes not before.
 
Thanks for Pointing that mistake.

In Proteus Debugger, i am not able to get Source Level Debugging, can anyone help me why it is so, i loaded the *.elf, but no code appears.
:-(

Simulation.png

How I write code, to sniff data, i am not getting how to proceed and what algo should i use to do it correctly.
 
Last edited:

I send 0xD0 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 from PIC16F877A to DS1307 and tried to capture the packet using ATtiny85.
And i got the result, in my buffer i am getting all values correctly, but only in one cycle.
How to detect the stop condition and restart again. (I haven't taken care of NACK, please help if there is any way)
Please let me know what i am doing wrong.

WorkingOneTime.png

Here is my Code:-

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "main.h"
#include "uart0.h"
 
#define SCL_SNIFF   1
#define SDA_SNIFF   4
 
#define IDLE        0
#define START       1
#define DATA        2
#define STOP        3
#define INVAILD     4
 
#define LOW         0
#define HIGH        (!LOW)
 
char state = IDLE;
char sda_state = LOW, sda_state_prev = HIGH;
char scl_state = LOW, scl_state_prev = HIGH;
char buffer[10] = { 0 };
uint8_t buffer_index = 0;
char I2Cbuffer[40] = { 0 };
uint8_t I2Cbuffer_index = 0;
 
char readPin(char PinNumber)
{
  char status = LOW;
  if(PINB&(1<<PinNumber))
  {
    status = HIGH;
  }
  return status;
}
 
int main( void )
{
  uint8_t i = 0;
  // Enable Internal Pull-Ups
  PORTB |= (1<<SCL_SNIFF);
  PORTB |= (1<<SDA_SNIFF);
  // Make Pins as Input Output Pins
  DDRB &= ~(1<<SCL_SNIFF);
  DDRB &= ~(1<<SDA_SNIFF);
  init_uart0();
  sei();
  uputs0( "I2C-Sniffer:\r\n");
  while(1)
  {
    scl_state = readPin(SCL_SNIFF);
    sda_state = readPin(SDA_SNIFF);     
    switch(state)
    {
      case IDLE:
        if(scl_state == HIGH)
        {          
          if((sda_state_prev == HIGH) && (sda_state == LOW))
          {
            state = START;
          }          
        }
      break;
      case START:
        if((scl_state_prev == HIGH) && (scl_state == LOW))
        {
          if(buffer_index >= 8)
          {
            buffer_index = 0;
            for(i=0;i<8;i++)
            {
              I2Cbuffer[I2Cbuffer_index] |= buffer[i]<<(7-i);
            }
            I2Cbuffer_index++;
            if(I2Cbuffer_index >= 9)
            {
              uputs0("Finished");
              while(1);     // Stop when received first byte
            }
          }
          // Read Data
          buffer[buffer_index] = sda_state;
          buffer_index++;
        }
        if(scl_state == HIGH)
        {
          if((sda_state_prev == LOW) && (sda_state == HIGH))
          {
            state = STOP;
          }
        }
      break;
      case DATA:
      break;
      case STOP:
        state = IDLE;
      break;
      case INVAILD:
      default:
        state = IDLE;
      break;
    }
    // Update States
    if(scl_state != scl_state_prev)
    {
      scl_state_prev = scl_state;
    }
    if(sda_state != sda_state_prev)
    {
      sda_state_prev = sda_state;
    }
  }
}

 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top