SPI on Pi - Serial Peripheral Interface on Raspberry Pi 2 with bcm2835 library

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone in this video we're going to talk about serial peripheral interface also known as spy and so we're going to spy on pie and what the seral peripheral interface is it's just one way that a microcontroller communicates with other devices and in our particular example today we're going going to be using the raspberry pi and we're going to be interfacing with a device uh that allows us to add some additional gpio that has both analog and digital capability and that would be analog in analog out digital in digital out so it's going to add some capability to the Raspberry Pi and we're going to interface with that device using the serial Prof interface we're also going to be making use of the BCM 2835 Library uh that's a library we used before in our Blinky LED program uh we also used it uh in our example for reading gpio with the push buttons and stuff uh so it's a library we used before but in this case we're going to be using it to implement the serial peripheral interface so before we get going too far let's talk about the physical layer of Serial pereral interface in general um here on the left I'm showing three examples of how a Serial peral interface may be wired uh in the first example up here we have the microcontroller in our case today it will be the Raspberry Pi and we have uh two data lines in a Serial periperal interface we have what's uh often called Master out slave in and master in slave out now one of those uh Master out slave in is sending data from the master or the micro controller to the device also known as the slave uh and we also have uh the slave sending Dei uh data back to the controller or to the master and that's the master enslave out so this is full duplex communication what that means is data can move in both directions simultaneously uh so that makes it really useful uh and allows us to do a lot of things with it uh the next thing we have is we actually have a clock line uh so this is a synchronous bus so what synchronous means is that each bit of data that's moving on these lines corresponds with a clock uh signal and uh we'll get into that a little bit further when we test this and I can show you a scope plot to show you how the clock lines up with the data lines in our particular uh example today uh each falling edge of the clock uh is what signifies the device to read data so uh so every time the clock goes low goes from high to low it looks to see what is on this line and it reads that as a as a logic high or a logic low and it reads it as a bit and so that's what uh what the clock will do for us you'll see that a little bit better when we show it in a scope plot uh the fourth line we have here is called uh many different things depending on which data sheet which device you're looking at uh the Raspberry Pi calls this a chip enable line uh the device we're using today actually calls it a sync line uh the BCM 2835 Library calls it a chip select line and I've also called seen it called a slave select line uh what this does is it's just a high or low signal uh that tells the device that uh it's the one it's talking to now the reason it does that is that we can have multiple devices connecting to each of these other three lines so we could have uh two or three or four different devices all connected to the same Master out slave in the same master in slave out and the same clock and then we use this fourth line uh per device uh to select which device is active and so we would need one of these lines for every device that we have connected to the Spy bus uh on the Raspberry Pi we have two of those available to us uh over here uh this is a schematic of the j8 GPO header on Raspberry Pi uh and you can see we have a c0o and a C1 uh so uh we have in the uh basic configuration of Raspberry Pi this would be on the B+ and on the Raspberry Pi 2 uh you have two uh uh chip enable lines so we could have uh two serial peripheral interface devices uh connected to the same spy bus and uh in the example I'm going to show you uh that's what I've done uh the next example here of a of how this might be connected is uh this is an example where let's just say that we're only ever going to have one device on our spy bus uh if that's the case we don't really have to have the chip select link connected to the the master uh that chip select line can be hardwired to either low or high depending on the device the device we're using today wants to see a low signal there uh to signify that it's selected uh so in that case we would tie it the ground uh another device might want to see that connected to connected to our high signal or whatever our logic high is for the device uh so in that case we'd only need three lines connected uh the fourth or I'm sorry the third example here uh it would help if I could count uh is as a case where we only want to send data one way let's say we have a device maybe a a simple display output uh that doesn't send any data back uh in that case if we only have a single device and it's only receiving data and it's not going to send data back we could get by with just two lines and so in that case we have the same number of pins taken up as we would say for i2c or or uart uh but we have a uh some of the advantages of Serial profile interface and and those two advantages over uh say uart or i2c first of all the advantage over that spy has over Ur is it's a synchronous signal we actually have a clock uh if you've worked with Ur you'll you'll know that you need to have both devices operating at the same speed and there there is a what can be known as a drift in the signal so if this device and this device doesn't have the exact same frequency on its clock uh you're eventually going to get errors uh so since we have a clock line we can avoid that with seral prer interface now i2c has a has a clock line as well but i2c only has a single data line so data can only move in One Direction at a time and the other limitation about that is uh in order to select which device is being addressed in i2c we have to send an address before we can start sending data so we have to use up some of our bandwidth to actually identify which device is being addressed uh and uh and we don't need to do that with spy so if you don't know what I'm talking about yet on that uh don't worry I'm going to do some videos on i2c and uart and you'll see what I mean there uh just just not that some of the advantages of silver purle interface first of all it's a synchronous signal so we have a clock that helps us uh send robust data and it's full duplex and we don't need to use up any bandwidth to send an address so those are some advantages of using spy all right uh one more thing before I move to the next next slide uh just again on the Raspberry Pi header uh there are four pins we're going to be using we have to master out slave in master in slave out the serial clock and the chip enable zero so that's what we're going to be using in this particular tutorial and you can see which pins those are connected to okay uh in the particular example we're using today uh I'm going to be using a prototype of a board that I have have in development uh that I'm designing as an add-on to Raspberry Pi that'll give it analog input and output capability uh also it really expands the general purpose iio um in this particular case the the device I'm using is an ad 5592 uh that's a a chip from Analog Devices it's an 8 channel 12bit analog to digital converter or digital to analog converter and also also allows digital input digital output and a lot of different options it also has an internal temperature that it we can read back and just a lot of capability uh in one chip that's configurable over the serial profer interface now in this example here I'm showing you a one of my prototype boards without any components on it so you can see kind of where all the traces are going uh there is a mistake in this board if you're good with the data sheet maybe you can uh figure it out but um there I have a mistake here and if I show you my circuit you'll see kind of A Rat's Nest of jumper wires to kind of overcome that for testing so that's why we make prototypes that's why we test them before we uh before we build a whole bunch of them so I'll have to fix that before it uh before it's done but uh this is basically what we're going to be using in our example okay so let's talk about what we're actually going to be connecting to here uh first of all we have the sync line and the ad 5592 data sheets calling it The sync line uh the Raspberry Pi calls it the c0 line so c0 be connected to sync and notice how this Sync has a a line over top of it that means it's active low if you ever see that in a data sheet it means that uh this this is enabled when this signal is low uh that's what that line means so we'll we'll need to remember that when we set up our code uh the next thing we have here is the serial clock of course and that's very straightforward and if you look here you can see that I have have this this this pin connected to both of these uh devices here and this this is set up to take two of these devices you see that both of them are connected to the same pin uh next we have uh the master out slave in and on the data sheet for the 5592 it's actually called an SDI um but you can also see here that I have uh both devices connected to the same pin again so there you go that device is connected there and this one's connected here so uh we have two devices connected to the same pin and then we have the master and slave out or on the 5592 it's called sdo and again you can I guess I you can't see it here because it's on the other side of the board but trust me that both of these chips are connected to that pin uh and uh and so just just like I was showing on the on the previous slide that uh you can have multiple devices connected to the the same spy bus but you need to have a chip enable for each device and you can see that uh this this this pin right here uh it has a trace it's going down around here down to this device and then then this is coming down to this device so what we have is uh chip enable Zer is connected to this and Chip enable one is connected to this uh in this example we're just going to be using one uh but you can see that I have two devices connected to the same serial peripheral interface but we just distinguish which ones are active using those uh those two pin uh so now let's move on to uh some the some of the setup of the software now the steps I'm showing here are going to be common uh whether you're using no matter which device you're going to use uh if you're using the raspberry pi and you're using the bcm2835 library uh to set up a spy device you're going to use steps very similar to this some of the details might be different depending on the device but the steps will be basically the same uh the first thing we do of course is we need to import the library and it's a same as we've done for the Blinky LED tutorial that I did a while back and also the gpio input tutorial I did a while back same step uh uh step two is the same as those as well and we're just initializing that Library step three is a little bit different but this will be the same step whether you're using uh the the 5592 device or using some other spy device so this step would be should be exactly the same for your for your case if you're using Raspberry Pi in a Library um next we're going to set up the the bit order and this will be different depending on which device you're going to use uh some devices want to see the least significant bit first and some devices want to see the most significant bit first in the case of the 5592 it wants to see the most significant bit first and so that's what we'll have this set up to now notice um you don't want to copy this code down exactly here uh I'm putting these three dots here just to signify that there's more here uh I just didn't couldn't fit all on the side and make it nice and neat so wait until we get to the actual source code and and you can see what I'm actually putting there uh Next Step though is to set the data mode and what this function is doing is it's actually setting the clock uh polarity and the clock phase so by clock polarity we mean uh when the clock is at an idle state is it higher low so that's that's one piece of it uh and this particular device expects the clock to be high when it's idle and uh and so that's that's something we just need to be aware of and uh the clock phase means are we looking for the rising edge of the clock or the falling edge of the clock and what that means is is it the device is going to read the data line at a particular point in time and do we want that point in time to be the rising edge of the clock or the falling edge of the clock and those two things is what the the data mode is is doing and I'll show you that here in a little bit it's actually really well documented for this library and I'll show you right off the website on on where you can find that um so the next step is to set the clock divider and what the clock divider is actually doing is it setting up the speed of the clock now this will be different for a for your device um it really depends on the data sheet what the capabilities of the device are on this particular device the data sheet says that it's good up to 20 mahz so I'm setting the clock divider to give me about a 15 mahz signal it should be just fine there uh I did test this with a uh with a clock divider of eight and that gives me a clock of of a little over a little over 30 MHz and it worked uh but that wouldn't necessarily work on every single case of this device because uh you know good suppliers will put margin in their data sheets often but uh but it's there can be um there can be variability from component to component and you wouldn't be able to count on that performance all the time so we're going to use 15 MHz just to play it safe there now if you have problems with your device one thing you can do in your troubleshooting is just slow down your clock a little bit and uh that might help you deal with issues that say you've got some some uh noise in the signal or you got maybe some long lines or something slow down the clock a little bit that might that might help um next thing we're going to do is actually set our chip select uh or on Raspberry Pi is called chip enable and that's just setting which which channel we're going to use and then the last step we're actually going to uh tell it that it's active low so we're going to set the the chip select polarity and and in our case it's looking for a low signal to say that the chip is active and so that are those are the steps that we want to take let's go ahead and look at the actual source code and step through that so here we are on the Raspberry Pi and this is the uh the source code for example project and you can see the first lines we're just importing our libraries uh like we've done in a lot of the other uh tutorials next I'm I'm defining some values uh that I'm going to use to configure the device and if you haven't seen this before uh these for if you use a a zero B uh that means that the the digits that follow is a binary number so uh what we're what I'm actually doing here is I'm creating a b binary number that I'm calling gpio fig for example and I I like to use a binary number here when I'm configuring a device like this because I can read uh these values right off the data sheet and I can see uh very easily see what each bit is set at uh a lot of a lot of cases you might see people use heximal here in which case we would use a ZX and then then the hexadecimal number um but uh in this case uh just I'm using binary numbers just to make it a little easier to line up the data sheet I'm not going to go over what each one of these is doing uh because it's going to be different for any device you use you really have to look at the data sheet for the device determine uh What uh what string of values that you need to to put in here uh but but just know that that's what I'm doing there I'm s setting some things that represent commands to the uh spy device the next thing I have here is I created a function uh to break up these commands into uh words that the Raspberry Pi can use uh by by default and really the only option at this time with the BCM 2835 library is to use an 8bit word on your spy uh spy device uh what that means is you can only send eight bits at a time time uh to the the device and uh the device I'm using here uh is looking for a 16bit word uh so the the problem I have to solve is I have to take this 16bit message and send it out in uh two words to the uh to the device and so I've created a function I've just called it make word uh I'm uh I'm passing to it an uh an array I'm calling it The 8 Bits and uh uh and I'm also uh passing in the value that I want to stick into that word so basically I'm creating a two element array uh that uh each element contains eight bits and then I am I am sticking that those 16 bits uh the first eight bits or the most significant eight bits into the the first word or first element and then the uh last eight bits into the second element and so on this line you can see I have my 16 bits data uh that is uh something that would look like this and I'm using the bit shift operator to shift all those bits eight positions to the right and then assign it to this first element here uh so what that does is it takes these uh the most significant eight bits and moves them to the least significant 8 Bits And then it assigns it here um so yeah and then the next element I'm actually just I'm using a bit mask uh so I have my my 16bit thing uh or data and I'm using the uh the bitwise and operator to create a bit mask and so this FF will make the the lower eight bits um the mask and so it'll only read the lower eight bits and assign it to the the second element so what does this will do just creates a two element array that uh it stores my 16bit message that I can then send to the Spy device so that is a if you have a device that is anything other than an 8bit word you'll need to do something like this uh next we just get into Main and I'm creating a uh uh just a an array that is uh that is setting up my device now uh I'm not going to show you the testing of all the stuff but I did have uh I did have this set up so that it's actually going to uh basically create a a binary counter blinking some LEDs uh sending out a a digital uh sign or I'm sorry sending out an analog signal and then reading an anal along signal back uh and all kinds of stuff so this was the array to kind of set up the device okay and these values I am defining up here okay next let me scroll a little bit faster there uh those are these are those two element arrays I was talking about that I'm actually going to be passing to the to this spy module uh to contain my data and uh remember I said that Cal peral interface is a is a full duplex so we'll be sending data out at the same time of bringing data in so you might want to create a different placeholder for the data that's coming in uh otherwise your data going out will be overwritten and I'll I'll go over that in just a minute here uh next thing here uh I'm not using this an example I'm not going to explain it uh here uh this is is a this is the actual data that I'm going to be sending to the digital to analog converter so I'm calling it DAC data it's 36 elements and these are uh uh digital counts for an analog signal so there's 36 elements and what each of those elements is going to represent is it's the uh the decimal value of a voltage signal uh that that represents a basically a sine wave so a sine wave at 10° increments is what what it really is and uh this isn't really a video on digital analog or analog digital uh but a remember I said this is a 12bit ADC or DAC and what that means is it's two to the the power of 12 uh would represent uh the uh the high value and uh so that was 4,95 would represent 3.3 volts in this in this case and then zero would represent zero volts and then the numbers in between represent some uh some uh increment of that and uh so that that's what we have there okay so that up there was actually the the data that we want to put out on the digital analog converter we also need to combine that data with the command to the device to tell it that it's a digital analog conversion and which pin it should go on and that's what this four Loop does here I'm I'm basically I'm iterating through that that array that that I just created at 36 element array uh that's down here and I'm oring that with the command that tells the device that hey this is a digital analog conversion conversion and it should go out on pin six so these three bits it if you just took these three bits on their own it would be a a decimal value of six uh and that represents pin6 of the device and this bit right here tells it hey this is a digital analog conversion command and then uh these values up here are loaded into the lower 12 bits is that 12 12 no that's 12 right there so this data here is already in here and I'm I'm I'm or that that's that's what's stored in here these these lower bits from here and then I'm this is a a bitwise or command and so since we have these in here it's going to uh basically put these load these bits into each element up here and that's what this is doing here so I have a command and a data into the same word so you might need to do something similar with your spy device but uh the actual values will be different and that you can get those from the data sheet uh The Next Step here uh we're coming in and and do doing those same steps I showed in the slides initializing the the library we're beginning the spy and then uh we're setting the bit order and this is the full command to set the bit order for MSB first and it would be very similar except uh I think it would be uh LSB first if it was uh it was the other way around then you you put in the uh set the data mode that's it right there I set the clock divider oops I have this set at eight remember I I said that uh uh we were going to use 16 there and then we uh set the chip select uh chip select polarity so just just like I said right off the slides and there is the the full uh commands and and you could actually go to the header file and find what the values should be here and you could input those uh directly but just using these makes it a little bit easier to read okay okay this next for Loop is just basically setting up the spot by device so I've set got the for Loop to iterate through the config array that I created that just holds all of the commands to set up the device uh and then I'm passing the uh the Spy out uh basically that's a two element array and then the actual data uh that I want to stick into that array so I'm passing that to that make word function and then uh when that comes back the Spy out uh array will hold this this uh this command and so then I'm I'm taking that spy out I'm I'm passing that to the BCM 2835 spy transfer n function and uh this is a function that you can use if you're if you're really just sending data out remember I said that spy is full duplex meaning it's going to send and receive data at the same time what this function will do is uh if the if the device sends any data back it's going to overwrite this uh this array with the data that's sent back that's what this function will do it's going to send this data out and then it's going to read back into uh that element uh the data that's coming back from the device and then over here you put in what what how many bytes is uh that data now could use uh and this might be actually better I could use size of and then put this uh uh in there so I could use size of spy out that might be a better way to go but for right now I just Define this as as two yeah so that's all I'm doing here I I'm creating a couple integers just to uh just to help with the control in my while loop and next I have my infinite while loop while one um I've got some stuff I'm not using in this particular example uh but right here I'm basically I'm creating uh I'm using uh L equal m modulus 36 and what this is going to do is I'm going to be incrementing uh this element L uh from 0 to 35 and so this will only return a 0 to 35 because remember a modulus Returns the remainder so it's it's basically uh M the remainder of M divided by 36 and so it can only be a value between 0 and 35 and so that's what this is going to do so every time this goes through here it's going to increment through 0 to 35 and then then it'll go back to zero um and so that'll that'll allow us to then step through our DAC data array uh which remember is a 36 element array and we start counting at zero so it's 0 to 35 so so this L will now allow us to step through this and then we can create our word Our Two element uh spy out array uh pass that to this time I'm using the transfer NB function so what this does is I'm actually passing to it to arrays and these arrays are basically buffers we have the output buffer and the input buffer or the transmit buffer and the receive buffer and remember I said that serial peripheral interface is dual is a full duplex which means data is going to be coming in at the same time it's going out and by passing two different arrays to this uh the data is going out here and data is coming in here okay so if you don't want to to overwrite your output data you want to use uh this this function so you can read it into here and again just using the word size there and so that's about it I'm I'm incrementing M and M will just uh overflow uh once it once it uh once it reaches the maximum value for integer it will overflow but up here I'm using a modulus so it doesn't really matter and so uh when we go ahead and run this what it should be should output is a sine wave on pin six uh and it's going to basically be doing that at the maximum performance uh of the um of the device at the frequency we've set for the clock so let's go ahead and uh compile and build and uh I get a few things down here that I'm not using some very variables but it does compile successfully it's just because there's some code I'm not using anymore uh no problem it should run just fine uh so I'm going to um go ahead and switch the camera now to take a picture of the scope so you can see what this does when it runs there won't be anything on the screen we'll just be looking on the scope to see what it does okay I decided I'm going to show you this Rat's Nest here uh this this is the the board here that that is has the uh the Spy Dev I you can see that there's a there's a couple chips there right here right here uh I have some wires going here and uh like I said I did have some LEDs here set up for as a kind of a binary counter um I have my scope connected here and you see I have some some long jumper wires going to the Raspberry Pi so remember we're going to be sending 15 megahertz over these wires so the signal is not going to be that good and you'll see that here in a second okay here you can see that I've captured uh just one sequence of the signal uh so I can show it to you on channel one we have the serial clock on channel two we have the master out slave in line and you can see that uh the channel one is measured at uh 16.1 megahertz uh we set our clock at uh at around 15 megahertz so uh pretty close uh and that is uh pretty darn fast you can see period is 62 NS um and you can see the signal looks like well looks like crap um and a lot of that has to do with the length of those wires that over there um if we if we had uh had a direct connection it would it should look a little bit better um um but you can see um remember when we set up the DAC command the first three bits were ones and you can see that uh on each clock you see that the edge is falling here and and and then where this Edge is falling the signal is high on the data line and so that's a one and then on the next s clock signal where it's where we have a falling Edge it's still high so that's another one and then on the third signal where the the lot The Edge is falling it's still high so that's another one so we have one one one and then the next one here it's low so it's a zero then another zero another zero another zero and then a one and so that's our first bite or our first eight bits of data and you can see there is a slight pause and then there then then we get the other eight eight bits of our word and I just change the position here so you can see it um and so here we have those those three bits that say Hey this is a DAC and it should go out on pin6 and then down here uh we have the actual binary message and you can see that we have a 1 0 0 0 1 0 0 1 0 so that's the binary message that went out to the DAC uh so now let me switch my probes around and you can see the signal that's actually going out on the on the pin that the device is creating but this is the Spy signal okay here we have my oscilloscope attached to the output of the uh of the device and you can see I have a real nice sinusal waveform it's coming in at about uh 11 11.14 khz uh I've got a peak voltage of 3.36 volts and just just what I expect and even though that Digital Signal looked you know pretty awful I'm still getting a really nice clean output on the the analog out and uh so that's just one of the things that we can do with a external device over SE peripheral interface uh and that's about it so I hope you like this video hope you learned something please subscribe please leave comments and we will talk again real soon
Info
Channel: SpazzTech
Views: 57,050
Rating: undefined out of 5
Keywords: Tutorial, Raspberry Pi (Computer), Serial Peripheral Interface Bus, Serial Communication, BCM2835, Software (Industry), C Programming, C (Programming Language), SPI, RPi, GPIO, ADC, DAC, I/O, Technology, Data
Id: 0QcteUtzB4o
Channel Id: undefined
Length: 37min 42sec (2262 seconds)
Published: Tue Apr 28 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.