Bit-Banging an I²C port with David.
Git link: https://gitlab.com/Sepps/generic-bitbang-library-v1
EEVblog Main Web Site: http://www.eevblog.com
The 2nd EEVblog Channel: http://www.youtube.com/EEVblog2
Support the EEVblog through Patreon!
http://www.patreon.com/eevblog
EEVblog Amazon Store (Dave gets a cut):
http://astore.amazon.com/eevblogstore-20
T-Shirts: http://teespring.com/stores/eevblog
💗 Likecoin – Coins for Likes: https://likecoin.pro/ @eevblog/dil9/hcq3
Git link: https://gitlab.com/Sepps/generic-bitbang-library-v1
EEVblog Main Web Site: http://www.eevblog.com
The 2nd EEVblog Channel: http://www.youtube.com/EEVblog2
Support the EEVblog through Patreon!
http://www.patreon.com/eevblog
EEVblog Amazon Store (Dave gets a cut):
http://astore.amazon.com/eevblogstore-20
T-Shirts: http://teespring.com/stores/eevblog
💗 Likecoin – Coins for Likes: https://likecoin.pro/ @eevblog/dil9/hcq3
I2c and the very similar SMBus are in almost everything. You'll even find it as a major part of computer motherboards.. The Interface allows communication with up to 127 devices with only two wires. For Many sensors.
I2C is the standard way to get data. So Here we have two wires, and you've got the S clock and the S data, that's SCL and SDA. The Reason that the bus can communicate with 127 devices on only two wires is because those wires are open drain.. Open Drain means that the driving side only drives low.
Each of the wires have to have a pull up, which means that when the line isn't being driven low, it gets pulled high. Now If you see a schematic one day and you see two resistors pulling up to the power rail, you'll know why that is. The Value of these resistors can vary quite a lot and that depends on the speed grade of the interface. The smaller the resistance, the faster the response.
***OHM*** I2C is a really slow interface and a comparable one would be dial-up Internet. Dial-up Internet was like 56 kilobits per second. I2C's lowest standard speed is 100 kilobits per second. so it's standard speed is double the speed of dial-up Internet.
Now A gigabit Internet connection, for example,, is over ten thousand times that speed. I2C Until recently only had four speed grades, but in 2012 a fifth one was introduced. These Speed grades might not be good enough for things like Internet or displays, but they are ample for most sensors and data acquisition applications.. The Sample rate of common sensors, especially mechanical ones, is mostly quite slow.
Strain Gauges, which are on bridges, only require a few hertz for the sample rate. Even Accelerometers rarely go above tens of Kilohertz and the I2C bus in the megabit range easily accommodates the data requirements for those sensors.. Now If we have an accelerometer that samples at 32 Kilohertz, which is unrealistic,, we only need 256 kilobits per second for an 8-bit accelerometer.. Every Sample of an 8-bit accelerometer requires 8 bits of data to communicate.
so multiplying the speed, the sample rate of the Excel Model with the bits, you get 256 kilobits per second.. Let's assume that half a frame is our data and the other half is the address and so for this case, it would be 512 kilobits per second, which is far below the 1 megabit per second mode.. Now Even with our unrealistic accelerometer, we're still Ok with 1 megabit per second. So Every transaction begins with a start condition.
The Start condition is when the data line gets pulled low and then the clock line gets pulled low. After The start condition data is sent. The Data that is sent is usually in 8-bit blocks. Each of the eight bits is sent with a rising and falling edge of the clock.
This is called clocking out data. In The case that it's a read transaction, you would be clocking in data. The Master still drives the clock, but it doesn't drive the data line. After The block is complete. There are two different things that can happen.. If The Slave Device is okay with the data that was sent. Then it will acknowledge the transaction and it will pull the line low. If It's not okay.
It will allow the line to float high, which indicates that there's a problem with the transaction. The First block of data that is transmitted is the address of the slave,. The address is between 0 and 127 and this is a 7 bit address.. There are another type of addresses.
This is 10 bit addresses, but we're not going to talk about them here.. If A device exists on the I2C bus with the address that was sent. Then an acknowledgment will be received. That's when the line is pulled low.
If There isn't a device with the address that was sent. Then the acknowledge line will stay high. Now There are some devices that claim to have 8-bit addresses, but this is usually a device that says it has two different addresses where the read address is this and the write address is that. Notice That the least significant bit is the only thing that changes in these addresses.
This effectively means that even though they say it's an 8-bit address, it's actually a 7-bit address. You Can take version of the 8-bit address and say it is the 7-bit address. After The address is sent, depending on what the read and write bit was, data is either received or it is sent from the micro-controller. If The read-write bit was one.
Then the master is receiving data. If it was zero. Then the master is sending data. When The master is receiving data.
It just leaves the data line alone and allows the slave device to set the data bits. If The data block is not acknowledged by the slave. Then it's probably the slave saying "stop reading, there's no more data". If The master is writing data and the slave didn't acknowledge.
Then there's a problem. If All went well. The master will probably then follow through with a stop condition. The Stop condition is when the clock line is released, or allowed to go high, and then the data line does the same, it is allowed to go high.
Between Blocks of data, for example. between the address and the data blocks,, the clock line is held low, but the data line is allowed to go high. If You were bit banging this, for example,. This makes things quite simple because your function that writes data only needs to clock out eight bits of data.
and before and after the transaction have a start and stop condition.. At The end of data sending. It's always required that the data line is released for acknowledgement,, so the state between data blocks is always going to be okay. I've always found it very useful to learn how to bit bang an algorithm, so that you fully understand it.
So we're going to do that right now. We're going to Bit Bang the algorithm. So Here we go. Okay, so we're just going to put it in C++. The Code I'm working on here is based on the example for Bit Banging SPI I Use some structures which help in developing these Bit Banging libraries. I'm just going to work on the Bit Banging Library now.. This is a simple implementation and a lot of it is based on the previous SPI Bit Banging Tutorial. So the first thing I'm going to do is write this Send function.
The Send function is a basic for loop which sends eight bits and this is going to be the fundamental thing that sent the address and the data and all that kind of thing. So The Send function is basically just a loop and it does a few different things and it accesses you know GPIO through functions instead of actual pin set and clear calls. The Reason that we're doing functions instead of direct pin set and clears is because the functions kind of isolate the platform-agnostic-ism so that if I were to change platform from this Visual studio environment to for example an MSP430 I would only have to change the code inside those functions so I can have those functions. in their own file and that file just includes everything that is platform dependent.
So I'm just modifying the SPI code just to you know, make the names and logging system make any sense. The way I actually do. This is by having before and after any change of a pin. I Basically just record the state of all the pins, and that's all I'm doing here.
That allows me to plot the data and see, kind of like the relative change between each of the pins, assuming that there's no noticeable overhead from program execution.. Okay In the send function, we're just going to store a temporary, we're going to, we're going to mask out that top bit and we're going to store the temporary and probably like clock it out. Clocking out is the rising and falling edge, so let's write that. Okay., So You know a rising edge is setting it high, then a falling edge is setting it low again.
Okay, so we need a start and a stop function and those just assert the start and the stop conditions we talked about before. Those are going to be used in the I2C write and the first thing we're going to do in that function is assert the start condition, then we're going to send the address of course, and you know then the data and then then we're going to assert the stop condition in between each of the the blocks of data we send. We're going to look for an acknowledgment. So We need a function that converts and 7-bit address to the 8-bit Data address and that function is going to take whether it's a read or a write address and that read and write is the lowest bit of a byte.
So All we're going to do is mask the address to make sure it really is seven bits. Then we're going to shift it across so we have room for that read or write bit and then we're going to OR in that bit. We Also need a function to get an acknowledgment.. An Acknowledgement is basically allowing the data line to go high and then clocking and reading the data from the slave, and that's what we have here. Now If we don't receive an acknowledgement, we do want to abort the write routine. So let's check if we received an acknowledgement and then figure out what we're going to do with that. I Think I'll probably just return true if it's successful and false if it's not. Okay, So I'm going to make sure that I'm actually setting the output that's the SDA So let's call the function that gets that bit out temporary and sets the pin.
Okay, So we're going to write to device 0x10 and we're going to write the data 81 in HEX so we should see that in the spreadsheet we're going to generate. I Need to make sure that the default states of all the pins are correct, so they've got to be all default high because by default the bus is open, it's open drain. Just Going to update the write routine so that it does indeed stop. If it receives the acknowledgement,, it sends the stop condition.
I Mean,, it should probably do that anyway,, but it doesn't matter. Okay, So okay, now it,. now it's fixed. So What I'm doing here is just setting the default state of the pins in the variable so that it's also defaulted to zero on the actual variables.
And Then what I'm doing here is just copying the values from the terminal that it output to, The print the I2C print command did that. Okay, So I've got a scatter plot in Libre Calc here and let's just check it.. Here's the start condition and here we have the address, there are seven bits there, And here's the acknowledgment here, which we haven't received because we're not actually talking to a device. And The condition before the data byte is correct, so it seems like our formation of the frame is correct.
Hope You learned a little bit about I2C. See you next time!.
Thanks for your explanation.
Could you make something similar to read 9 bits serial data in arduino mega 2560 ?
I am trying to read 9 bits serial data, but in the uart ports for arduino mega 2560, I have understood that we only can read 8 bits serial data.
I will appreciate your example and explanation.
Thanks in advance.
Regards
Thanks for this example. Could please make a video for one wire bus- bit-banging ? Basically, I am looking for examples to read data from DS18B20 using BG22 in simplicity.
Awesome! Could you please tell me which books deal with this topic? I happen to need to do a development with ESP8266 and I2C acting as multi-master
If somebody can follow whats going on here, they do not need to watch this video. It is too fast for learning or following the subject.
check how other people make videos
This is not targeted at the complete fresh meat, like everyone complaining expects..
If youre watching this you are expected to have tried and failed in some way.
perfect video!
Thank youuu!!
BITBANGING is the best banging
please don't show this my girlfriend
C++ in a mcu lol
IIC = I²C ! I2C = I*(C+C) ! U NOOB!
Hello David. Thank you for sharing your knowledge. We need more people like you on the internet. I arrived here looking to clear up some doubts and your video sort of helped me. Since I am a newbie I got lost on all the C code which is what I was more interested in, but I appreciate your effort. Hopefully you will continue to provide more content for all of us who need to know more about electronics and programming. Best regards.
I wrote my I2C routines in Z80 assembler. There's no minimum speed it will run at as I was able to single step through my code to check everything was working correctly.
I wonder if there are other protocols that send the address, send how many sets of 8 bits to expect, and then send the data.
When your bit bashing this shit how do you get the timings right?
The code section goes really fast and you move around really fast. If it were slower it would be easier to follow.
Yeah… that was a great explanation until you started coding, you should have slowed down a little bit but you know that.
The only thing that is really unforgivable was…saying I TWO C instead of I SQUARE C ^^
I2c Is CAN?
hey! that's my motherboard! but i have the micro atx version. 785g chipset
Hey there, David! Could one use a constant current source as the pullup? Thanks.
I liked the Dave's approach better with the white board and always learned a lot even if the subject is new to me. But I cannot say the same for this one. The introduction of subject was too general and insufficient. There was no way of fallowing the code because everything happens too fast. The only thing I got from the video is, there are two pins, there are start and stop bits, and MC waits for the response of the other device…
You don't have to mask the address before shifting it left. Maybe assert that the address is within the range but the mask is a no-op.
Good pace. Love the format.
Great videos. Really nice to see the theory and then the actual code in practice. Love to see some more of these.
The Bit Bang Theory !
Informative and enjoyable, plus that photo at the end concreted the passion you put forth.
Very nicely done, David.
The presentation is way too fast for COMPREHENSION. It reminds me of lightning in a bowl of glitter. We have some engineers at work who behave this way. (Millenial types, usually.) I often wonder if they have a firm grasp of the subject matter, or if they are just pressing buttons until something works? Tell you what, let me do a video in this style/format on something potentially foreign to you, like say.. "reconstructing brightness temperature in the presence of sun-glint angles requiring fringe washing in Base-6 math for two-dimensional aperture synthesis space-based microwave radiometers" and we'll see how much you truly absorbed. Sorry, but just watching code snippits fly by on the screen is so Matrix and Keanu Reeves. And I am rather well-versed in I2C bit-banging (Thank you very much.) It once wasn't as common on microcontrollers as it is these days…
Nice tutorial, more of that please 🙂