Hi, I started using CCS to program Stellaris LM3S3748 two days back. I want to use two GPIO pins as input pins which get binary values to give an output using an IF statement. I built a simple program for the purpose but I am unable to obtain any output. I gave 0V and 5V to the pins to check the code. Even the values that get stored in the variables are junk values. I want you to help me out in finding the error in the program and/or suggest changes. As I am new to CCS/Stellaris, I might have used unnecessary header files. My main program is as follows:
#include "inc/hw_memmap.h"#include "inc/hw_types.h"#include "driverlib/sysctl.h"#include "inc/hw_sysctl.h"#include "driverlib/debug.h"#include "inc/hw_ints.h"#include "driverlib/systick.h"#include "grlib/grlib.h"#include "inc/hw_nvic.h"#include "driverlib/rom.h"#include "inc/hw_adc.h"#include "driverlib/adc.h"#include "driverlib/gpio.h"#include "inc/hw_gpio.h"#include "driverlib/interrupt.h"#include "inc/lm3s3748.h"#include "drivers/formike128x128x16.h"#include "inc/lm3s3748.h"tContext g_sContext; intmain(void){ tRectangle sRect;unsigned long ival1,ival2; ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ); GPIO_PORTD_DIR_R=0x00; GPIO_PORTD_DEN_R=0xff; Formike128x128x16Init(); // // Turn on the backlight. // Formike128x128x16BacklightOn(); // // Initialize the graphics context. // GrContextInit(&g_sContext, &g_sFormike128x128x16); // // Fill the top 15 rows of the screen with blue to create the banner. // sRect.sXMin = 0; sRect.sYMin = 0; sRect.sXMax = GrContextDpyWidthGet(&g_sContext) - 1; sRect.sYMax = 14; GrContextForegroundSet(&g_sContext, ClrDarkBlue); GrRectFill(&g_sContext, &sRect); // // Put a white box around the banner. // GrContextForegroundSet(&g_sContext, ClrWhite); GrRectDraw(&g_sContext, &sRect); // // Put the application name in the middle of the banner. // GrContextFontSet(&g_sContext, &g_sFontFixed6x8);GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); ival1= GPIOPinRead(GPIO_PORTD_BASE,GPIO_PIN_0); ival2=GPIOPinRead(GPIO_PORTD_BASE,GPIO_PIN_1);if(ival1==1 && ival2==0) { GrStringDrawCentered(&g_sContext, "Location1", -1, GrContextDpyWidthGet(&g_sContext) / 2, 7, 0); } if(ival1==1 && ival2==1) { GrStringDrawCentered(&g_sContext, "Location2", -1, GrContextDpyWidthGet(&g_sContext) / 2, 7, 0); } else { GrStringDrawCentered(&g_sContext, "unknkown", -1, GrContextDpyWidthGet(&g_sContext) / 2, 7, 0); } while(1){}}
Please reply ASAP.
ASAP reply - as requested - herein:
Welcome to the Stellaris family of ARM MCUs.
Yours is a classic issue (actually you have three!) - has happened to most of us during our early use phase.
#1 Your code has failed to "enable" the GPIO port housing the 2 pins you wish to read:
GPIO_PORTD_DIR_R=0x00; GPIO_PORTD_DEN_R=0xff; // *** these lines signal your intent to set your pins as input and enable them for their digital function - but PORTD has never been enabled!
Fix: // Enable the GPIO port that is used for digital inputs. Best to restrict these to 3V3 SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOD; // add this "port enable" line atop your "bit config" line pair *** I do not recommend this "method"
#2 Your code "mixes" Programming Modes - first employing "Direct Register" and then switching to StellarisWare functions.
GPIO_PORTD_DIR_R=0x00; // Direct Register GPIO_PORTD_DEN_R=0xff;
GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); // StellarisWare - this method vastly preferred - especially for those early on!
Fix: (by switching to StellarisWare:
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); // Enable your chosen GPIO block/port *** recommended method
SysCtlDelay(10); // "It takes five clock cycles after the write to enable a peripheral before the the peripheral is actually enabled." (this - direct quote from Stellaris DRL_UG_8264)
GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); // Note StellarisWare manages both pin direction and enabling - single instruction...
Such "mixed" programming modes is not strictly an error - in fact has advantages when speed is required - but is likely "too complex" for an early user. Stick with StellarisWare - especially as examples abound w/in StellarisWare - not so much in Direct Register. (blinky.c)
#3 GPIO manipulation (reading/writing) of GPIO (your code will fail when reading GPIO_PIN_1)
ival2=GPIOPinRead(GPIO_PORTD_BASE,GPIO_PIN_1); // you expect that a logic 1 on this pin will place "1" into ival2 - it will not! Two will be placed into ival2.
Everyone misses this - only GPIO_PIN_0 "escapes" this abberation - returning 1 when read. Others return 2,4,8,16 etc - and same holds true when setting or writing these bits. Examples abound w/in StellarisWare - your MCU and others - the Software DRL_UG should be your constant companion - StellarisWare functions are nicely documented - well detailed. The time you spend reading/studying/practicing with small, focused code examples will pay huge dividends as you progress...
Following your lead - kindly "tick" the green "Verified Answer" box - (asap - just as I have responded to you...)
You don't enable clocking to the GPIO Port D peripheral. This must be done before you reference any other registers related to GPIO Port D.
The GPIOPinRead() function doesn't work the way you are expecting it to.
The 2nd argument is a bit mask for which pins to read from the port. The value returned will be the value from the port with the mask applied. More than one pin can be read at the same time.
Bharathram Balasubramanian ival2=GPIOPinRead(GPIO_PORTD_BASE,GPIO_PIN_1);
After the line above, ival2 will either contain 0, or the value GPIO_PIN_1 (which happens to be 2). It will never have the value 1.
@slandrum-
You got two - do you accept new user's "mix" of Direct Register & StellarisWare?
Twice this morning I posted replies to messages to find out that by the time I finished my composition and posted it someone else had just responded as well. Sorry, I wasn't trying to step on your answer.
Yes, I generally agree that if you are using any of the StellarisWare functions, you are better off using them throughout your code for consistency. I've made exceptions when either the StellarisWare functions didn't do exactly what I wanted/needed, or at times I use my own macros to streamline my interrupt code and remove the function calls.
One big advantage of using the StellarisWare functions instead of rolling your own or using direct register writes is that in a debug build, you have all the assertions test the validity of your arguments.
No "sorrow" sought - I've been in exact situation - in no way did I feel "stepped on."
Has to be 20+ times you/I have advised re: GPIO individual pin "weight." My belief is that TI should torpedo "Red Everywhere" - and create a highlighted sticky for this pesky GPIO weight issue. (you did see/comment on the post I originated - with my, gentle/ever polite, "KILL the damn Red" suggestion.)
Surely - such GPIO "weighting" deserves a more prominent alert - repeat answers (6+ years running) do NOT show great corp. insight. (hurray - outsiders)
BTW - thank you for the great assistance/guidance you've provided so many - for such a sustained period.