Getting Started with STM32 and Nucleo Part 5: How to Use SPI | Digi-Key Electronics

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Applause] [Music] [Applause] [Music] after making the stm32 video about how to use i squared c the biggest request i got was to do the same thing but for spy well this is it how to use spy with stm32 once again i'll be sticking to using the hal api along with the stm32 cube ide as both of those together offer a relatively easy way to get spy up and running spy or serial peripheral interface is a synchronous communication protocol developed by motorola in the 1980s it's a de facto standard meaning there's no formal standard for it as a result you'll run into lots of variations in naming and implementations from different companies spy is implemented with one controller or master device that initiates all communication it requires one clock line separate data out and data in lines and a chip select line sometimes you'll see these pins with different names or acronyms such as clock or serial clock data coming out of a device might be labeled with sdo for serial data out which should be connected to the serial data in or sdi pin of other devices for data coming out of the controller you'll also often see master out slave in or controller out peripheral in for data going into the controller you'll see master in slave out or controller in peripheral out finally the chip select or cs pin can sometimes be labeled as ss for slave select note that spy is normally full duplex as it has separate transmit and receive lines which means you can transmit and receive at the same time every now and then you'll come across a device that tries to save on pins so it will implement a half duplex version of spy so you cannot transmit and receive simultaneously in that case you'll need to connect the devices as follows for most stm32 parts the sdo or mosi pin is used as the shared input output pin when spy is configured for half duplex mode we won't go into that here though one of the big advantages of spy is that it is a bus meaning you can have multiple peripherals for each controller device all of the lines are shared except for the chip select line you will need to dedicate one pin on your controller for each peripheral you wish to communicate with notice that the chip select lines are active low so by default all of your chip select lines are high when you want to talk to one of the peripherals you pull the chip select line connected to that peripheral low sometimes you'll come across parts that work in a daisy chain configuration this is popular with things like spy led drivers here the clock and chip select lines are shared among all the peripherals data out from the controller goes to the first peripheral then data out from the first peripheral goes to the data inline on the second peripheral this can continue for any number of peripheral devices on the last peripheral data out is connected back to the data in pin on the controller here is a simple timing diagram of what spy communication looks like to start you pull the chip select line low and then the controller begins to pulse the clock line with data going out and coming in simultaneously on the mosi and miso lines however because spy is not an official standard things start to get a little complicated you sometimes see two versions of the clock one that idles low and another that idles high the clock polarity or c pole parameter determines this the other parameter is the clock phase or cpha when cpha is zero it means that bits on the miso and mosi lines should be sampled on the leading edge of the clock pulse if c pull is zero that means on the rising edge and if c pull is one it's on the falling edge additionally you can have cpha be 1 in which case bits are sampled on the trailing clock edge these two parameters can make spy quite confusing but they do make it more flexible as you're able to choose how the clock line operates and when to sample data bits rather than clock polarity and clock phase parameters you will sometimes just see a mode parameter there are four possible modes and they correspond to the four possible configurations of the polarity and phase parameters in practice you will almost always use mode 0 as this is what most peripheral devices support in this mode clock polarity and phase are both set to zero meaning the clock is default low and you sample on the rising edge here is an actual spy signal that i captured on my logic analyzer in it i'm asking the eeprom chip that we will use in our demo to return the value in its status register the controller begins communication with the peripheral by pulling the chip select line low then on each clock pulse it sends out data on the mosi line because this is mode 0 the clock idle is low and data is sampled on the leading edge as a result we get 5 for the first byte on the mosi line and 0 on the miso line this is the read status register command for our eeprom chip while spy is full duplex and the peripheral could transmit data back to the controller this particular device does not behave like that it wants you to transmit data first and then read second on the next byte we do not send out anything from our controller instead we simply read the miso line here the eeprom is telling us that the value in its status register is 2. when we're done transmitting we pull the cs line connected to our eeprom chip back to high this is a very simple communication example but i hope it gives you an idea of how spy works a question you'll often hear is what's the maximum speed for spy because spy is synchronous which means it has a separate clock line theoretically it can run at any speed however you'll often run into limitations based on the speeds of your individual parts and any signal integrity issues you might have due to line length and their proximity to other signals it's often a good idea to look at all of your data sheets in your project and figure out the maximum spy speeds for them and go with whatever is the lowest for my purposes i usually find that speeds in the range of 1 to 10 megabits per second work fine for most of my needs for this demo i'm going to use this simple 4 kilobit ee prompt from microchip i know that most modern microcontrollers have built-in eeprom but external eeprom chips like this one are cheap and they're good for showing spy operation notice that the maximum clock speed of this chip is 10 megahertz also we'll need to hold the active low right protect and hold pins high we can wire up the rest of the pins as a normal spy point-to-point device with our nucleo board if we look at the timing diagrams we can see that the bits are sampled on the rising clock edge indicating that modes 0 or 3 will work since mode 0 is the most common we'll stick with that scroll down and you'll see the supported instructions while we can use 9 bits to access memory addresses we'll stick to 8 bits for our example to make things easier we'll want to first set the write enable latch then we can perform a page write sequence where we send the right instruction followed by the starting address in memory from there we can write up to 16 bytes in succession which will be stored to the eeprom the write enable latch is automatically reset after our write instruction to read those bytes back we first need to read the status register and see if the write in progress bit is set we keep reading that bit until it clears which means the write operation has completed from there we can perform a read page sequence just like we did with the write operation we'll send out the read instruction followed by the starting address the eeprom chip will send us the values in its memory in successive bytes over its serial outline as long as we keep toggling the clock line all we need to do is read those bytes and compare them to what we wrote if they match we can say that our spy communication and eeprom chip work here is how we'll connect the eeprom chip to our nucleo board the spy pins on the nuclio should be labeled and easy to use note that you can use any gpio pin for your chip select line while you can have the hardware automatically control the chip select line i'm going to show you how to do it manually with a gpio pin which makes it easier to use with multiple peripheral devices i'll be using an stm32 nucleo l476 rg for this demo but almost any nucleo board should work because we're working with the microcontroller directly we need to know the pin names connected to the board headers i find that the embed site for the nucleo boards offer the best pin out diagrams we can see that we should use pa567 and pb6 for our spy pins notice that we need to use the spy-1 peripheral in stm32 cube ide start a new stm32 project select your board which is the nucleo l476 rg for me give your project a memorable name and open the cube mx perspective i told cubemx to initialize all of the peripherals in their default states for the board which means we get access to uart and an led however that led is connected to d13 on the board which is shared with our spy clock line so we need to disable it in connectivity click on spy 1 set the mode as full duplex master we can have the stm32 hardware control the chip select line but we'll leave that feature disabled in configuration leave the format as motorola and change the data size to 8 bits as our eeprom chip communicates in one byte chunks leave the first bit as msb as the eeprom expects the most significant bit to arrive first 40 megabits per second is too fast for our eeprom so let's adjust the prescaler to slow it down i'm going to take it to about 1 megabits per second since i'm working with jumper wires on a breadboard which can make signal integrity very sketchy a clock polarity of low is the same as zero and a phase of one edge refers to the leading edge which is also zero from our table so we'll leave these settings alone i don't think it matters as we're not using a hardware chip select line but i like to disable the nss pulse mode which from what i could gather brings the chip select line back to high between data bursts finally because we plan to adjust the chip select line manually we need to set its mode to gpio output if you remember it's pb6 from our pinout diagram save to generate code and open main.c to begin we need to include the standard input output header file as we need it for s printf then i'll create a number of constants that represent the available instructions we can send to the eeprom chip in main i'll then declare some variables the uart buffer is needed to store strings that we want to print out to our serial terminal we'll also need a spy buffer to send and receive spy data after configuring our peripherals we should make sure that our chip select pin is driven high i'll then print something out to the serial terminal to make sure everything is working to write something to eeprom we first need to send the write enable command to do that i'll pull the chip select line low send out the write enable command and then pull the chip select line back high the house by transmit function requires us to pass it a handle to our spy configuration and cast the data we wish to send to an 8-bit unsigned integer pointer finally we tell it how many bytes we wish to send one in this case and give it a timeout you can use hal max delay but i like to keep the timeout period shorter like 100 milliseconds note that i really should be checking the return status of each spy function as i did in the i squared c episode but that creates more code than i want to show here remember the logic analyzer screen capture we looked at this next command shows how i generated that diagram we pull the chip select line low send out the read status register command and then we call the spy receive function which works like the transmit function the difference here is that we give it a pointer to a buffer which will be filled with the red bytes the third parameter is the number of bytes we wish to read which is only one in this case finally we print the contents of the status register to the serial terminal let's build the project and start debugging i'll use putty to connect to my nucleo board click the play button and you should see some info show up in the serial terminal because we sent the write enable command first the write enable latch bit should be set in the status register giving us a value of 2. i hope this gives you a basic idea of how to use spy with stm32 hal just to show you how you might want to interact with that eeprom chip i wrote some extra code as a demonstration i'll fill the first three bytes of the spy buffer with the data i want to write to the eeprom and set the starting address to 5. next i'll send the write command followed by the starting address and then i'll send over all three data bytes sequentially i'll clear the buffer after that because eeprom can sometimes take a while to write we need to wait for the write in progress bit to be cleared in the status register before doing anything else with it so we read the status register and check the value of the wip bit we loop doing that so long as that bit is 1. in retrospect a do while loop would have made more sense here oh well once we're sure that the ee prom is done writing we can read those three bytes back note that i'm using the receive function here after sending the read command followed by the same starting address after that we print those three bytes out to the serial terminal i'll read the status register again to show how the write enable bit automatically clears itself after a successful write let's debug and bring up the serial terminal again we should see a b c d e f printed to the console notice that the status register in the ee prompt chip starts at 2 when we first send it the write enable command and then clears to 0 when we're done writing because these spy functions are blocking your code will do nothing waiting for everything to finish transmitting or receiving i'm going to show you one way to make it non-blocking if you look at the hal api documentation for the l4 series you can see that there are interrupt-based functions we can use these are the ones that end in underscore it when the transmit underscore it function completes it will call the tx complete callback function which we need to implement in our code the same thing is true for the receive underscore it function and the rx complete callback function you can click on these to jump to the full function description to see what parameters are required rather than go piece by piece i'm going to give you a broad overview of the code a link to all the code in this episode will be provided in the description if you'd like to dig into it to use the interrupt-based spy functions we need to go back into the cubemx software and open our spy configuration in nvic settings enable the global interrupt for your spy controller without this interrupts won't work for spy save and regenerate code in main our includes and ee prom instructions look the same i added a couple of global flags here that we'll use from within the interrupt callbacks note the volatile keyword this is necessary when changing variables in your main thread and in interrupt service routines without it the compiler might think you're not using the variable and optimize it away we're going to use a finite state machine to perform the reading and writing over spy so i need a state variable setup is the same as before we write something to the serial terminal and set our eeprom starting address my state machine starts with case 0. here we fill the buffer with the write command starting address and then 10 bytes of data we wish to store i'll just make it sequentially count from 0 to 9. like before we first send the write enable command using the blocking spywrite as it's only one byte then we do something a little different for the non-blocking write we pull the chip select line low and send out all 12 bytes of data including the command and address using the transmit underscore it command i need to leave the chip select line low until it's done so i just increment the state and leave in the next state i do nothing while waiting for the transmit flag to be set because this is part of a state machine the main while loop will be called over and over which means you can still implement your code after this switch case statement your code will run while waiting for the long spy transmit sequence to complete interrupts will occur in the background to send out spy bytes as needed the transmit flag gets set in the tx complete callback function which i will show you in a minute once we get that flag we immediately clear it and go to the next state here we read the write in progress bit from the status register we continually do that and only go to the next state once it's cleared we then set up to read 10 bytes from the eeprom starting at our given address like before we use the receive underscore it function to read bytes in interrupt mode once again i do not pull the chip select line high in the next state we wait for the receive flag this time once we get it we clear the flag and go to the final state in that we simply print out the bytes that we received followed by a newline character i'll add a delay here to make this happen more slowly yes i know it's bad practice to use a blocking delay in non-blocking code but this is just a demo we'll set the state to 0 and start over don't forget to make a default state just in case something really goes wrong we'll implement our interrupt service routine callbacks at the bottom of our main.c when transmitting is done we pull the chip select line high and set the transmit flag we do the same thing in the receive callback but using the receive flag instead these will get called automatically whenever transmitting or receiving is done let's compile and run our program when we look at the serial terminal we should see our 10 bytes being printed to the console this tells us that we're successfully reading and writing to the eeprom chip i hope this helps you get started using spy in your own projects and gives you some ideas on how to make your code non-blocking please subscribe if you want to see more videos like this one and happy hacking [Music] you
Info
Channel: Digi-Key
Views: 38,556
Rating: 4.9375 out of 5
Keywords: DigiKey, STM32, STM32CubeIDE, SPI, interrupt, microcontroller, embedded, electronics
Id: eFKeNPJq50g
Channel Id: undefined
Length: 19min 30sec (1170 seconds)
Published: Mon Aug 03 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.