 Now it's time for the second hands-on. What we're going to do in this hands-on is we're now going to write an application using the C language, and it's going to use direct register access approach. So the goals for this session are to become more familiar with the STM32 as a device, have a bit more of a play around with the ecosystem, so the Kyle Microvision Environment, and we're now actually going to do more of a proper application. So we're going to look at a temperature regulator-based application. The methodology we're going to use on this one, we're going to use direct register access. So we're not using any extra libraries in this one, we're just going to actually write directly to the core registers, which is what predominantly most 8-bit applications used to do. And the technique we're going to use for this is the polling technique. So based on the design flows that we looked at in the previous section. As before, we're going to create a project from scratch using the Kyle environment. We're going to paste in our template again as we did before to generate the majority of our source code. There will still be some lines to edit. And then we'll compile the application, program the target board, and debug the application as we did in the first hands-on. But we'll go into a bit more detail now on play with a few more features of the Kyle Microvision Environment. So what we're going to do, we're going to access the registers directly by bitwise manipulation. All this needs is one extra header file adding to our environment. This file is called stm32f072xb.h. And this will contain the definitions for all the registers inside the stm32f072. The bit definitions for each of those registers and the memory map. So the compiler knows exactly where everything is located within the device. Advantages of direct register access means that you have direct control over exactly what you want to do in your application. And it also means that you are going to get potentially the most optimized speed execution, because you're only accessing what you need to access. And you're potentially going to get the smallest code size footprint because there are no extra libraries getting added to your code from other sources. Disadvantages, again this is a questionable one. Longer time to market, there are the five documents that we highlighted at the start of the day that you need to study in quite a bit of detail. Compared to an 8-bit device project, the 32-bit architecture has a lot more details, a lot more features, so there's a bit more reading. So yes, there will be a longer time to market. Implementation of a single function requires potentially more registers in a 32-bit architecture than it did in an 8-bit architecture. But it is questionable this longer time to market. It depends on how you're used to doing your normal design procedures. Second disadvantage is low portability. Because you're writing the software directly to the registers of one single device, then if you chose to do a high-end product of what we're doing here using a different SDM32, then because we've optimized it directly for the registers, porting that to a different SDM32 might take some time. So portability is not something that is easily done with direct register access. Code is not easy to understand. Yes, you would need to know exactly what each of those registers are doing to understand what the code is doing. Again, this is a questionable one. If you're used to writing comments at the end of each of your lines, potentially then this might not be an issue or a disadvantage. If we look at the format of the SDM32F072XB.h, everything is based on pointers and structures. So what you can see there for UART number two is the structure which contains all the different registers. So all those different offsets that we were looking at in the first hand zone, they are now all defined in this structure. Bit definitions are just macro definitions with a defined statement to show you all the different individual bits on what they do. And then down at the bottom we have got the defines for the base addresses and the UART two is just a pointer to the structure of where all the addresses are located of the different base parts. With direct register access, if you want to write an entire register, then you will use the format shown here at the bottom of the screen. So you've got the pointer to the base address structure which is UART two where our base address was. Then we have the pointer to the offset inside that structure which is the board rate register. And then we can just load a value directly into that register because this is only a single use register, you can just load one value in there directly. If you have a register where you want to manipulate single bits like the control registers, then you start your statements off the same. You have your base address and the pointer to the individual register or the offset inside that base address. Then you just altogether the different bit definitions of the items that you want to enable inside that particular register. So the application we're going to develop now in this hands-on is a Fermo regulator. So we're going to use the microcontroller. We're going to have two different input sources. One of them is the temperature sensor. The second is a push button. And then we're going to drive two outputs. One of them potentially are switch relay to control our heater. For our example, this is going to be our LED. The second output we're going to drive is the communications to an external system, which will be the virtual comport back to our PC. So all these features are available on our nuclear board, so nothing needs to be added to our nuclear board. So here's the features that we're going to use. PA5, which is our green LED. We've already had a play with this in the first hands-on. So we're going to use that as our potential switch relay to our heater. Internal to the SDM32 on one of the ADC channels, we have a temperature sensor. So we're going to use that value from that temperature sensor, and we're going to have that as our controller for our LED switching on and off. Then we're going to use the push button, or the blue push button, which is connected to PC13. So this is going to be our control signal, and that is going to trigger our communications to the PC, which will be using one of the UARTs, which is PA2 and PA3. And on the PCB, they're connected to the microcontroller on the top part of the board, which is circled in the purple, and that will provide the USB virtual comport back to the PC, where we'll use a terminal program to view what is going on on our target board. Schematics, so you've already seen the section of the schematic for the LED at the top. Here we have the schematic for our push button, which is connected to PC13 on our microcontroller, which is pin number two on the micro, and down at the bottom we have our UART connections, which are PA2, PA3, or pins 16 and 17, which are then connected directly to the top half of the board, where we get our virtual comport from. So this is the flow diagram for our application. So we're using polling, so we are going to be going round in our loop here. We're not having any interrupts, or we're not putting the device to sleep at any point in this application. So we will start our application and configure our peripherals. Then we will start the ADC and wait for a conversion of a result. So this is our loop. Is the ADC above the threshold? If yes, we switch our LED on. If no, we switch our LED off. Then we come round, read the state of the push button. Has the button been pressed? No. Then we loop back round and do the ADC question again. If the button has been pressed, then we will transmit our information over the UART and then loop back round and ask our ADC question again. For this particular hands-on, we're going to ignore the push button and the UART. We'll save that for the last hands-on of the day. We're now just going to implement our control using the ADC peripheral and the LED. So we're going to now play with two peripherals instead of just standard GPIOs as we did in our first hands-on. So now we need to go back to our Kile environment and start a new project. The first thing we need to do is terminate our previous hands-on. So we need to close our debug session we had running earlier, and we now need to close the project that we had open. So that gets our Kile back to our entry point where we can start our new project. So we want to go project, new microvision project. I'm going to store this in the same folder as I did for the first hands-on, which is root-c-drive-hands-on-underscore-8-32-bit. I'm going to create a new folder just as I did last time. I'll call this one Lab2 and I'll give my file a name and I'll call that Lab2Save. So we've now got our new project ready to go. Just as we did in the first hands-on, we need to select a sales type for our project. So that was stm32f072rb. And it was the rbtx variant we need. So we select that and click OK. Now we're going to actually use some of these runtime libraries that are provided inside the Kile environment because we have to do the start-up files, the cmsys parts, and we need to pull in the map file for our particular stm32 we are using in this project. So the first items we need to add are the cmsys items, which will be our start-up parts. And we need to expand cmsys and we need to tick that we are using the core functions. Then we need to expand our device and we need to tick that we want to use the start-up file. Now you may have noticed that this has now gone yellow whereas the core part went green. And there is a little warning being shown at the bottom here that we will need some additional components. At the moment the device is set by default to be wanting to receive the information from the Cubamex. We don't want to use Cubamex, we'll do that in the final hands-on. So on this particular one we need to change it to stand alone. And now, hopefully, the device should now have gone green as well and the warning that was in the bottom part of the screen should have disappeared. So we can now select OK for our runtime language. If we now expand our target one, you can see that the cmsys and the device have now been added to our project workspace. So these are extra libraries which the C environment needs to actually run the application. As we did with the assembly file, we need to add a new file to our source group number one. So we want to add new item and this time we want to add a C file, not an ASM file. So the C file we need to add and I will call that main and then add that file. So now you can see I have a main.C included inside my project. Before we go and paste the coding, we've still got to do our configuration as we did with the first hands-on and that is we need to select the correct debug tool. So you can either right-click on target one and go options for target or you can click the magic one there to bring up the options box. And we need to go into the debug tab and by default again Kyle has automatically selected the U-link which is the Kyle tool. So we need to change that to the ST-link debugger. Then we need to click on the settings button and we need to go and make sure that the flash loader has been automatically selected. And again we can tick our reset and run button and we can click OK to that. For those of you who have problems with the linker on the first hands-on you can go and check for this project to make sure the tick box is already selected. So if we click on the linker tab and you need to make sure that the use memory layout from target dialog tick box is selected. Then we can say OK to our configuration settings. Now we need to go and bring in our template for our main application code. So as we did with the first hands-on we need to go and find the files that you extracted from the user disk. So I've gone back to my C drive hands underscore on underscore 8 to 32. I've already extracted chapter number five which is hands on number two. And then I want to go into the template. And then I want to open the main template underscore registers. And as we did before we need to copy all of the code. So ctrl A, ctrl C for copy. Then we go back to our kyle environment. So let's line one and ctrl V to paste our code in there. So you should have pasted 38 with the carriage return 39 lines of code. Hopefully have gone into your application. You might already notice on the left hand side that we have two red crosses. This is the pre-processing that goes on inside the kyle environment. And it's already flagging that there are some errors. These are the lines of code that we need to edit as part of the hands-on. So if I talk you through the code we have got the include of our stm32f072xb.h. So that's pulling in our library definition files for our registers, bits and our base addresses. Then we have some variable declarations that we're going to use during our application. Then as we come down into the main routine we have the configuration of our peripherals. So you can see that we enabled the clock for our ADC. Then set some parameters for our ADC. Then we enable the clock for our GPIO port A as we did in the assembly example this morning. And then we set our mode register to be output. So that's the configuration of our GPIO exactly the same as we did in assembly. Then we go into our while one loop where we start the ADC, wait for a conversion flag, read the value and then make a decision based on that value either switch the LED on or switch the LED off. So it's the same two lines as we had from our assembly which was our toggle example. We're doing exactly the same here, we're toggling the LED but we're doing it based on the ADC value that we have from the temperature sensor. So what we now need to do is fill in the four sections where you have question marks. So that is lines 13, 14, 22 and 24. So these are the bits of information that we need to find. And to find this information we will need to go into the reference manual. So we need to go and have a look at the reference manual to see what values need to be inside these lines of code. So if we start by looking at line 13 we want to enable the ADC. So we've done some configuration above and we're up to the point of we need the command that enables the ADC. So if we look at our reference manual we can see that highlighted in the purple box at the bottom here on my slide, which is the reference manual chapter 13 section 4.2. The procedure to enable the ADC is clear the ready flag, set ADEN to 1 in the control register and then wait for ADREADY to equal 1 in the ISR register. So that is the procedure to enable the ADC. So if we go back to our code you can see that we clear the ready flag in the ISR register at line 12. Then line 13 is the line that we want to put our enable ADC. So we need to look at that which I believe was ADEN was the variable that we need looking at that. And then we need to wait for the ADC ready flag in line 14. So we're actually going to be able to do two of them from that one statement from the reference manual. So if we think back to the manual it was ADEN and Kyle has a nice feature called auto complete which is opened on my screen. If it doesn't open on your laptop then try pressing control and space should open the auto complete. So I can see there that there is a nice option there for ADC control register ADEN. So that looks like the parameter that I need so that's the bit declaration. So I will double click on that it will automatically place it into my code and if you now notice the red X has gone. So that is now a valid line of code and that should have now enabled my ADC bit in the ADC1 control register. So the next part of the procedure was to wait until the ADRDY equals 1 and that bit is in the ADC underscore ISR register. So the format should be the same as we see above which is the ADRDY in the ISR register. And there you can see the auto complete I double clicked on again and the second red X has disappeared. So I'll now give you a few seconds to complete the two remaining missing elements which are the start ADC conversion and the read the conversion result. So for the start ADC conversion it's still in chapter 13 which is the ADC chapter of the reference manual. But you're now down in 4.7 so section 4.7 and setting the ADC start bit in the ADC control register is what you need to do to start the ADC. So there's the ADC start in the ADC control register. So therefore we are only missing at this point the definition of control register. And finally we now need to read the contents of the data register and store them in the ADC value variable we have declared. Now some of you might be thinking that it is the ADC underscore DR data. This is incorrect. Remember you want the contents of the data register not a bit definition. So to get the contents you've got to provide the base address which is ADC one and then you need to point it to the data register. So you need to have ADC one dash greater than DR as your missing line of code. So now we should hopefully have no more red X's available and we can now build the code from project build target or you can press the build icon or F7. And there we have zero errors and zero warnings hopefully. We can now enter debug so we can program our target board and enter debug so you can have to do that from the debug menu and start debug. Or you can press the debug icon there and the compiler will now go off and program our target board. And it stops us at the entry point of our main routine which is at line number eight at the default point. And now you can go and run the code by pressing F5 or the run icon. You will probably find that your green LED has just lit up on your board. That is because our threshold was default to zero. So we now need to go and find out what the threshold of our ADC value is and we need to set that threshold. So to do that we need to go and put a watch on our ADC value variable. So to do that we stop the execution of our code so you hit the stop button up here. Double click on ADC value so it is highlighted in blue as my screen is showing. Then you right click and add ADC value to watch number one. So that has now put ADC value down here in the bottom right which is our watch one window. And to make life easier for myself I will view the value as a decimal rather than a hexadecimal your personal preference. So I will remove that value and I can see when my ADC value is at ambient temperature I am getting a reading of 1,656. If I now restart the code by pressing F5 or the run icon you will see that the ADC value every now will get a blue background. That signifying that the live update is providing information to the screen. If I now place my finger on the STM32 chip on the nuclear board you will see that my ADC value will decrease. So as the device gets hotter the value read by the ADC will decrease. So the hottest I can get it just with my finger attached to the top of the chip is 1,636. So I have got a change of about 20 decimal in my value. So therefore I will need to set a threshold of about 1,646 for my device so that I get a plus and minus 10 swing on my ADC value. There are two ways you can do this. You can terminate the debug session, go back to the software and edit threshold. Or we can now put a watch on threshold just as we did with the ADC value and change it directly in the debug environment. So if I stop my code double click on the variable threshold, right click and add threshold to watch 1. So it now appears directly below my ADC value in the bottom right hand corner. Again I will switch it to a decimal value and I will put my value in as 1,646 and then hit enter. So now when I resume my code by pressing run or F5 I now have my threshold saved. My ADC value has gone back to 1,652. If I now warm my chip up my ADC value will drop below the threshold and my LED on my target board will switch off. Then if I release my finger from on top of the SDM32 chip on the nuclear board the ADC value will go up and the LED value will come back on. So we now have completed our control loop in our software for our example. To complete the software then I will now need to put that value of 1,646 actually into the code. So I will now need to stop my execution of program, stop the debug session, scroll up the software to line number 2 and edit that value to be 1,646. Then I need to rebuild the code which is F7, re-enter the debug mode and now I can run my code. You can already see that threshold is set to 1,646. So now when you press your finger on top of your chip your LED should go off and as you release your finger the LED should come back on. So what have you learnt in this section or this hands on? So you've had a play around now with direct register access. So you've seen a standard C flow with accesses directly to the registers using the definitions in the .h file. You've seen again how to start a development using the Kyle Microvision and the STM32 and which parts of the Kyle Microvision library structure you need to include into your project. And you've now had a bit more playing around and hands on with running a proper application inside the debug part of the Kyle Suite using the STM32.