AGH University of Science and Technology Cracow Department of Electronics Microcontrollers Lab Tutorial 2 GPIO programming Author: Paweł Russek http://www.fpga.agh.edu.pl/upt2 ver. 26.10.16 1/12
1. Objectives In this tutorial, student will extend his/her understanding of General Purpose IO structure and programming in NXP Kinetis L family of microcontrollers. The new features of GPIOs will be presented, including Input functionality. To extend the features of the FRDM-KL25Z board, we will use a kit of basic peripheral devices, such as LEDs, push buttons, keyboard, and 4 7-segment LED display. Afterwards, the switch bouncing problem will be introduced. You will write the debouncing code to mitigate it. Also, debugging, a very important feature of the Keil uvision programming environment, will be demonstrated. 2. Basic Peripherals Board The microcontrollers need the peripheral devices to act. There is a variety of peripheral boards available, but we need a customized that fits the Microprocessors Laboratory course. The schematic of the Basic Peripheral Board is given in the figure. You will find the Connection Headers, LEDs, 4 7-Segment LED display, matrix keyboard, push-buttons, and button-pressed sensing circuit (D21-D24, R2). 2/12 A schematic Basic Peripheral Board for Microcontrollers Laboratory
2.1. Connection headers JP1 JP2 JP3 JP4 JP5 JP6 JP7 The JP1 shunt is used to convert 4x4 matrix keyboard to 4 push button interface. If it is closed, switches S1, S2, S3, S4 can be connected directly to the microcontroller's port pins via the C1, C2, C3, and C4 signals and sensed immediately. When it is open micro swich matrix form a keyboard which requires a special procedure to detect a pressed button (see laboratory tutorials for details). The JP2 pin can be used as a source of logical signal (active low) to detect a button press event on the matrix keyboard. The JP3 header is a LED connector. Apply high voltage signal to light a selected LED. The JP4 header is a 4x4 matrix keyboard connector. The C1, C2, C3, and C4 signals are connected to the matrix columns and R1, R2, R3, and R4 are connected to matrix rows. To detect active column, apply low voltage signal to R(1..4) and pull-up C(1..4) with internal microcontroler's ports resistors. To detect active row, apply low voltage signal to C(1..4) and pull-up R(1..4) with internal microcontroller's ports resistors. When the row and column is detected the button is known. The JP5 header is the 7-segment display cathodes connector. Apply low voltage to light a corresponding segment for an active digit. See also the JP6 description. The JP6 header is the 7-segment display common anodes connector. Apply low voltage to actvate a corresponding digit. See also the JP5 description. The JP7 header is the power supply for the board. You usually connect 'VCC' to the '3.3V' or '5.0V' power pin, and 'GND' to the 'GND' pin of FRDM-K25Z. 2.2. The PCB of the peripheral board It is possible to create a peripheral circuit given in figure above using a breadboard or a universal PCB, however, for the convenience a printed circuit was designed and provided for this tutorial. The picture of the proposed PCB for the peripheral board is given in the figure. The PCB for Basic Peripheral Board 3/12
3. GPIO functionality In this section, we will broaden the information about Kinetis L GPIOs that has already been provided in Tutorial 1: C language for microcontroller of this course. In the previous tutorial the GPIOx_PDDR (Port Data Direction Register) and GPIOx_PDOR (Port Data Output Register) were familiarized. The PDOR register is a basic register that provides a complete functionality for the parallel output peripheral. However, for the programmers convenience, there are also extra registers that control the output. There is the GPIOx_PSOR, GPIOx_PCOR, and GPIOx_PTOR registers for each GPIO port. GPIOx_PSOR (Port Set Output Register) GPIOx_PCOR (Port Clear Output Register) GPIOx_PTOR (Port Toggle Output Register) Writing to this register will update the contents of the corresponding bit in PDOR. '0': Corresponding bit in PDORn does not change. '1': Corresponding bit in PDORn is set to logic 1. Writing to this register will update the contents of the corresponding bit in PDOR. '0': Corresponding bit in PDORn does not change. '1': Corresponding bit in PDORn is cleared to logic 0. Writing to this register will update the contents of the corresponding bit in the PDOR. '0': Corresponding bit in PDORn does not change. '1': Corresponding bit in PDORn is set to the inverse of its existing logic state. The table shows additional the registers associated with GPIOx. After we configure the Direction register for output, we can use Set Out, Clear Out, and Toggle Out registers. Those registers make it easier to turn on or off a single pin or a few pins without affecting the other pins. For example, writing a value 4 (0100 in binary) to PCOR will turn off bit 2 of that port without modifying any other pins. For parallel Input functionality, the Data Input register (GPIOx_PDIR) exists for each port A to E. After Direction register (GPIOx_PDIR) is configured for input, the Data Input register is used to bring data into CPU from the pins. We can connect an external SW to the board and experiment with the concept of inputting data via a port. Depending on how we connect an external SW to a pin, we need to enable the internal pull-up or pull-down resistor for a pin. See figure below for connecting external switches to the microcontroller. 4/12
Connecting push buttons to the microcontroller Using the PORTx_PCRn register, not only we select the alternate I/ O function of a given pin, we can also control its internal Pull-up (or Pull-down) resistor. The PE (pull enable) bit of the PORTx_PCRn is used to enable the internal Pull resistor option. If PE = 1, then we use the PS bit (pull select) to enable the pull-up (or pull-down) option. See the figure below. PS and PE bits of PORTxPCRn 5/12
4. Bit naming convention in the MKL25Z4 header. Microcontrollers programming often requires setting individual register bits. Each bit has own functionality and has to be manipulated independently. Access to single bits requires the knowledge of the bit position within the host register. The bit position can be look up in the data sheet, however, programmers can use names of the bits that are defined in MKL25Z4 header, and that definitions carry a position of the pit in the register. For example: The position of bit PE of PCR register is defined as PORT_PCR_PS_MASK. First the name of the module comes (PORT), then the name of the register (PCR), and finally the name of bit (PS). As the definition is used to modify (mask) registers, there is always MASK suffix to the name. More examples: Bit PE of PCR register is PORT_PCR_PS_MASK Bit PORTA of SCGC5 is defined as SIM_SCGC5_PORTA_MASK The same way, we can use pre-definied values to mask bit fields (like MUX of PCR). Bit field MUX of PCR is PORT_PCR_MUX_MASK Furthermore, the MKL25Z header defines macros that allow programmers to set bits and bit fields conveniently. The macros provide the values that result in setting the corresponding bits. Example: //Set the PORTA bit of SMGC5 SIM->SCGC5 =SIM_SCGC5_PORTA(1); //Set multiplexer of pin 10 in Port A for the third alternate function PORTA->PCR[10] =PORT_PCR_MUX(3); If you have doubts what is the name of the certain bit mask or macro, you can inspect MKL25Z.h file (hoover the mouse cursor over the MKL25Z.h name in the uvision code editor, right click the mouse button, and select Open document... in the pop-up menu). 6/12
Exercise 4.1 Find the names of the macros for the corresponding bits and bit fields. Bit SBNS (Stop Bit Number Select) of the BDH register in the UART0 module. That bit determines whether data characters are one or two stop bits in serial communication. Bit field MODE of the CFG1 register in the ADC module. The bits select the ADC resolution mode (8-bit, 10-bit, 12-bit or 16-bit). 5. Toggling LEDs application Exercise 5.1 1. Connect the FRDM-KL25Z board to the Basic Peripheral Board according the figure given below. Connection of FRDM25Z to the Peripheral Board 2. Create a new uvision project Toggling_LEDs. Remember to keep your projects in a separate directory. Create a new folder Toggling_LEDs for the project. 3. In uvision editor, create a new file main.c in the source file folder and copy the program code that is given below. 7/12
/*----------------------------------------------------------------------------- * Name: main.c * Purpose: Toggling_LEDs application * Author: Student *----------------------------------------------------------------------------*/ #include "MKL25Z4.h" /*Device header*/ #define LED_1 0 #define SW_1 0 int main() { //Enable clock for Port B and Port D SIM->SCGC5 =SIM_SCGC5_PORTB(1) SIM_SCGC5_PORTD(1); //Configure Port B pin 0 as GPIO, Output PORTB->PCR[LED_1] =PORT_PCR_MUX(1); PTB->PDDR =(1<<LED_1); //Configure Port D pin 0 as GPIO, Input, Pull-up resistor PORTD->PCR[SW_1] =PORT_PCR_MUX(1) PORT_PCR_PE(1) PORT_PCR_PS(0); PTD->PDDR&=~(1<<SW_1); while(1){ if( (PTD->PDIR & (1<<SW_1))==0){ if(ptb->pdor & (1<<LED_1)) PTB->PDOR&=~(1<<LED_1); else PTB->PDOR =(1<<LED_1); } } } while((ptd->pdir & (1<<SW_1))==0); //Wait for SW_1 release 4. Compile, Download, and Run Toggling_LEDs application on a FRDM-KL25Z board. The LED D1 should toggle when you press the SW1 button 5. Modify the code of Toggling_LEDs to toggle all four LEDs D1 to D4, while pressing the corresponding switches S1 to S4. Try to optimize your code to use as few C statements as possible. Compare the Code size with the results of your colleagues. Size of the code appears in the Built Output window after code building process. Program Size: Code=... 8/12
6. Keil uvision debugger A debugger is a program that is used to test and debug other programs (the "target" program). The µvision Debugger can be configured as a Simulator or as a Target Debugger. The Simulator is a software-only product that simulates most features of a microcontroller without the need for target hardware. The Target Debugger is a hybrid product that combines µvision with a hardware debugger interfacing to your target system. To debug programs running on target hardware, check Use <Hardware Debugger> on the right side of the Debug dialog. When you start a debug session, µvision loads the application, executes the startup code, and, if configured, stops at the main C function. When program execution stops, µvision opens a Text Editor window, with the current source code line highlighted, and a Disassembly Window, showing the disassembled code. Debug menu Description Use the Start/Stop Debug Session command of the Debug Toolbar to start or stop a debugging session. To Start the program execution select the Run command from the Debug Toolbar or from the Debug Menu To Stop the program select Stop from the Debug Toolbar or from the Debug Menu To Reset the microcontroller Select Reset from the Debug Toolbar or from the Debug Reset CPU Menu To step through the program and into function calls use the Step command from the Debug Toolbar or Debug Menu. To step through the program and over function calls use the Step Over command from the Debug 9/12
Toolbar or Debug Menu To step out of the current function use the Step Out command from the Debug Toolbar or Debug Menu. 6.1. Breakpoints In µvision, you can set breakpoints to stop (break/pause) the program to examine its current state. The break can be ordered at some event or at specified instruction by means of a breakpoint. To set execution breakpoints in the source code or in the Disassembly Window, open the Context Menu and select the Insert/Remove Breakpoint command. You can also double-click the gray sidebar of the Editor Window or Disassembly Window to set a breakpoint, or use the breakpoint buttons of the File Toolbar. Breakpoints are visualized in the Editor and the Disassembly Window, and they are denote by the red dot. 6.2. Watches Press to display Watch windows. By default, Watch Windows consist of four page tabs: the Locals to view variables of the current function, two Watch pages for personalized watchpoints, and the Call Stack showing the program tree. Through the Watch Window, you can view and modify program variables. Nested function calls are listed in this window as well. The content is updated automatically whenever you step through the code in Debug Mode and the option View > Periodic Window Update is set. In contrast to the Locals Window, which displays all local function variables, the Watch Window displays user-specific program variables. 10/12
Define watchpoints to observe variables, objects, and memory areas affected by your target program. Watchpoints can be defined in two Watch pages. The Locals Window contains items of the currently executed function. Items are added automatically to the Locals Window. There are several ways to add a watchpoint: In any Watch Window, use the field <double-click or F2 to add> Double-click an existing watch-point to change the name In Debug Mode, open the Context Menu of a variable and use Add <item name> to Watch Window. µvision automatically selects the variablename beneath the mouse pointer. You can also mark an expression and add it to the Watch Window. Modify local variables and watchpoint values by double-clicking the value you want to change, or click on the value and press F2. Remove a watchpoint by selecting it and press the Del key. Exercise 6.1 Set a breakpoint somewhere in the Toggling_LEDs code. Start debugger and Run the program. When program breaks, step through it. Add some Watch Continue stepping while watching your Watch 7. Switches debouncing When a mechanical switch is closed or opened, the contacts do not make a clean transition instantaneously, rather the contacts open and close several times before they settle. This event is called contact bounce. The bounce of switch contact So it is possible when the program first detects a switch in the keypad is pressed but when interrogating which key is pressed, it would find no key pressed. Contact bounce also occurs when the switch is released. Because the switch contacts open and close several times before they settle, the program may detect a key press when the key is released. For many applications, it is important that each key press is only recognized as one action. A simple software solution is that when a transition of the contact state change is detected such as a key pressed or a key released, the software does a delay for about 10 20 ms to wait out the contact bounce. After the delay, the contacts should be settled and stable. 11/12
Exercise 7.1 Add debounce functionality to the Toggling_LEDs application. 12/12