This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

GPIO Register Configuration in TivaC Series Microcontrollers

ARM Architecture provides various GPIO Configurations. To perform any operation with GPIOs the following four register configurations are provided. 

IODIR, IOSET, IOCLR, IOPIN

The usual instruction format are similar as follows for LPC2129.

IODIRx |= (1<<LED1PIN)|(1<<LED2PIN); // define LED-Pins as outputs

IOSETx = (1<<LED1PIN)|(1<<LED2PIN); // set Bits = LEDs off (active low)

IODIRx &= ~((1<<BUT1PIN)|(1<<BUT2PIN));// define Button-Pins as inputs

What are the instruction set available in TivaWare for the similar tasks in Tiva Platofrm?

 

  • Hello Vikram,

    The equivalient for

    IODIR is GPIODIR

    IOSET or IOCLR is GPIODATA bit banded to the pattern. E,g, for writting 1 to Pin-2 a write of 0x4 has to be done to address offset (0x4 << 2)

    Regards

    Amit

  • I still haven't added much but here is some explanation on GPIO registers 

    https://sites.google.com/site/luiselectronicprojects/tutorials/tiva-tutorials/direct-register-access-notes

  • Hi Amit,

    You are life saver. Always there for the help. Heartiest Thanks. :) <3

    Okay what will be the exact instruction as I'm getting error maybe because I'm not including required headers.

    Means in my example

    IODIRx |= (1<<LED1PIN)|(1<<LED2PIN); // define LED-Pins as outputs

    'x' stands for port base and pin number is defined by LED1PIN and LED2PIN

    So exact exemplary instruction will be much helpful.

    Also please put some example for bit banding also using GPIODATA. Thanks

    Thanks.

  • For GPIODATA you have a 256 locations to operate.

    check out 10.2.1.2 Data Register Operation.

    Each one of the locations are for the different number of pins you want to configure, just 1 and 2, just 3 and 6, just 1 2 5. In the blinky example it's used the one where you can configure the whole 8 pins, it's in 0x3FC if i am not mistaken, it's 0xFF << 2 because of what's explained in 10.2.1.2.

    For operating like how you described to set PF3 to 1, for example, in TivaWare i would do:

    HWREG(GPIO_PORTF_BASE+0x3FC) |= GPIO_PIN_3;


    Personally i don't like the method used in "blinky" example which includes the MCU header file, it gives to many conflicting declarations with TIvaWare driverlib and other files i usually use.

  • I'm working on the following code:

    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "inc/tm4c123gh6pm.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"
    
    #define RED_LED   GPIO_PIN_1
    #define BLUE_LED  GPIO_PIN_2
    #define GREEN_LED GPIO_PIN_3
    
    // Control Ports used.
    #define	cPort	 	GPIO_PORTE_BASE
    
    
    // Data Ports used.
    #define	dPort	GPIO_PORTD_BASE
    
    #define	lcdrs	GPIO_PIN_0 					// RS ALSO CALLED D/I --- pin4 ----- Pin0 
    #define	lcdrw	GPIO_PIN_1 					// R/W ------------------ pin5 ----- Pin1 
    #define	lcde	GPIO_PIN_2       		// e -------------------- pin6 ----- Pin2 
    #define	lcdcs1	GPIO_PIN_5       	// CS1 ------------------ pin15 ---- Pin5 
    #define	lcdcs2	GPIO_PIN_4       	// CS2 ------------------ pin16 ---- Pin4 
    #define	lcdrst	GPIO_PIN_3 
    
    // LCD Commands.
    #define START_LINE		0xc0
    #define SET_ADDRESS		0x40
    #define SET_PAGE		0xb8
    #define DISP_ON			0x3f
    #define DISP_OFF		0x3e
    
    // Global variables.
    unsigned char column = 0;
    unsigned char page = 0;
    // Fuction prototypes.
    void cSelect(uint8_t col);				// Select the controller chip depending on column number.
    
    // Command pair.
    void CommandMode (void);				// This sets the Data bus to accept commands.
    void WriteCommand(uint8_t cmd);			// This sends the command to the controllers.
    
    // Data pair.
    void DataMode (void);					// This sets the bus to accept data.
    void LocknLoad (void);					// Load the Data Buffer and latch for the next byte.
    
    
    void lcdInit (void);					// Initialise the LCD.
    void clearl (void);						// Clear the LCD.						
    
    // Page change.
    void setNewPage (unsigned char data);	
    
    // Set cursor position.
    void setXY(uint8_t x, uint8_t y);
    
    
    // Draw Bar.
    void Bar(uint8_t height, uint8_t width, uint8_t xpos, uint8_t row);
    
    // Clear Bar.
    void BarC(uint8_t height, uint8_t width, uint8_t xpos, uint8_t row);
    
    // Draw Bar.
    void Bar(uint8_t height, uint8_t width, uint8_t xpos, uint8_t row) {
    	
    	int dP;
    	uint8_t c;
    	uint8_t j;
    	uint8_t fbytes=0;					// Full bytes contain all ones, all pixels.
    	uint8_t pbytes=0;					// Partial bytes contain some ones, some pixels.
    	uint8_t cmd; 						// This is the Command holder.
    	
    	page = row; 						// The bar starts from this specified row.
    	
    	if(height > 64){					// Limit for the height.
    	height=64;
    	}
    	
    	if(width > 128){					// Limit for the width.
    	width=128;
    	}
    	
    	
    	
    	while(height > 8) {	
    		height = height - 8;		
    		fbytes = fbytes + 1;		
    	}		
    	pbytes = height;
    	
    	
    	for(j = 0; j <= fbytes; j++){
    	
    				cmd = SET_PAGE | page;
    				WriteCommand(cmd);	
    				page = page - 1;
    				
    				
    				cmd = SET_ADDRESS | xpos;		
    				WriteCommand(cmd);
    				
    		cSelect(xpos);								// Select which half of the
    													// screen to use.						
    		for(c = 1; c <= width ;c++){ 	
    								
    								
    					if (xpos+c > 64){
    					cSelect(xpos+c);				
    					}
    					
    					DataMode();
    					//dPort = 0b11111111; 
    					//GPIO_PORTB_DATA_R = 0b11111111;
    					GPIO_PORTB_DATA_R = 0xff;
    					LocknLoad();							
    		}
    
    	}
    	
    	
    	
    		cmd = SET_ADDRESS | xpos;		
    		WriteCommand(cmd);
    				
    	
    		if (pbytes ==1){					// The are bits filled from the MSB side first
     		//dP = 0b10000000;					// because the bar is drawn from the
    			dP = 0x80;					// because the bar is drawn from the
    		}									// lower end of the LCD to top.
    
    		if (pbytes ==2){
     		//dP = 0b11000000;
    			dP = 0xc0;
    		}
    
    		if (pbytes ==3){
     		//dP = 0b11100000;
    			dP = 0xe0;
    
    		}
    
    		if (pbytes ==4){
     		//dP = 0b11110000;
    			dP = 0xf0;
    		}
    
    		if (pbytes ==5){
     		//dP = 0b11111000;
    			dP = 0xf8;
    			
    		}
    
    		if (pbytes ==6){
     		//dP = 0b11111100;
    			dP = 0xfc;
    		}
    
    		if (pbytes ==7){
     		//dP = 0b11111110;
    			dP = 0xfe;
    		}
    
    		if (pbytes ==8){
     		//dP = 0b11111111;
    			dP = 0xff;
    		}
    
    		cSelect(xpos);									// Select which half of the screen to use.
    		for(c = 1; c <= width ;c++){ 
    							
    					if (xpos+c > 64){
    					cSelect(xpos+c);		
    					}
    					
    
    
    					DataMode();
    					//dPort = dP; 
    					GPIO_PORTB_DATA_R = dP;
    					LocknLoad();
    		}
    
    		
    	
    }
    
    
    
    
    /* to clear the bar*/
    
    // Clear Bar.
    void BarC(uint8_t height, uint8_t width, uint8_t xpos, uint8_t row) {
    	
    
    	uint8_t c;
    	uint8_t j;
    	uint8_t fbytes=0;
    	uint8_t pbytes=0;	
    	uint8_t cmd; 
    	
    	page = row; 
    	
    	if(height > 64){
    	height=64;
    	}
    	
    	if(width > 128){
    	width=128;
    	}
    
    	
    	while(height > 8) {	
    		height = height - 8;		
    		fbytes = fbytes + 1;		
    	}		
    	pbytes = height;
    	
    	if (height > 0){
    	 fbytes = fbytes + 1;
    	}
    	
    	for(j = 1; j <= fbytes; j++){
    	
    				cmd = SET_PAGE | page;
    				WriteCommand(cmd);	
    				page = page - 1;
    				
    				
    													// Set the x position of the bar.
    				cmd = SET_ADDRESS | xpos;		
    				WriteCommand(cmd);
    				
    		cSelect(xpos);								
    		for(c = 1; c <= width ;c++){ 				// Width of the bar.
    							
    					if (xpos+c > 64){
    					cSelect(xpos+c);				
    					}
    					
    					DataMode();					
    					//dPort = 0b00000000; 
    					GPIO_PORTB_DATA_R = 0x00;
    					LocknLoad();							
    		}
    
    	}
    	
    	
    		
    	
    }
    
    
    
    /* ---------------------------------------------------------------
    	Initialise the LCD according to the Data sheet. I prefer to 
    	go through a reset procedures.
    	
    	Function clearl() will clear all the 128x64 dots, and reset the
    	column and page address to 0. In noisy environments, this 
    	function provides a further insurance of starting with a clean 
    	screen.
     -----------------------------------------------------------------*/
    void lcdInit (void)
    {  
    	
    	GPIO_PORTE_DIR_R = 0xff;
            GPIO_PORTE_DEN_R = 0xff;
    	GPIO_PORTE_DATA_R = 0x00;
    
    	
    	GPIO_PORTB_DIR_R = 0xff;
    	GPIO_PORTB_DEN_R = 0xff;
    	GPIO_PORTB_DATA_R = 0x00;
    
    	// Reset the LCD using reset pin 17.
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdrst, lcdrst);
      
    	WriteCommand(DISP_OFF);	  // According to the data sheet this is needed.
    	WriteCommand(START_LINE);	
    	WriteCommand(DISP_ON);  
      
    	// Clear every pixel and reset the column and page to 0.
    	clearl(); 
    }
    
    /* ---------------------------------------------------------------
    	This function is to clear the LCD screen, and also resets the 
    	column and page registers.
    	
    	Use this function when the whole screen needs clearing to 
    	display another text / graphic.
     -----------------------------------------------------------------*/
    void clearl (void){
     
     unsigned int i;
     
     // Reset global variables.
     column = 0;
     page = 0;
     
     // Reset LCD registers.  
     WriteCommand(SET_ADDRESS);
     WriteCommand(SET_PAGE);
     
     
     for(i = 0; i < 1024 ;i++)
     {
      
      if (column == 128)
      {
       column = 0;
       page++;
       setNewPage(page);
      }
    
      cSelect(column);						
    										
    	DataMode(); 						
    	GPIO_PORTB_DATA_R = 0x00;
    	LocknLoad();						
    
      column++;
     }
     
     // Reset global variables.
     column = 0;
     page = 0;
     
     // Reset LCD registers.
     WriteCommand(SET_ADDRESS);
     WriteCommand(SET_PAGE);
     
    }
    
     
     /* ---------------------------------------------------------------
    	set LCD to data mode. The data sent to the data bus will now
    	be plotted.
     -----------------------------------------------------------------*/
    void DataMode (void)
    {   
      // Set hardware pins for data mode
    
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdrs, lcdrs);
     
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdrw, 0);
    }
    
    /* ---------------------------------------------------------------
    	To send commands to the LCD controllers through the data port.
    	
    	Use this BEFORE using the cSelect() function.
     -----------------------------------------------------------------*/
    void WriteCommand(uint8_t cmd) {
    
    		
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdcs1, lcdcs1);
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdcs2, lcdcs2);
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdrw, 0);
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdrs, 0);	 				
    	GPIO_PORTB_DATA_R = cmd;            // Send the command.
        LocknLoad();
    }
    
    /* ---------------------------------------------------------------
    	This selects the controller chip CS1 or CS2 based on the 
    	column number.
     -----------------------------------------------------------------*/
    void cSelect(uint8_t col)
    {
    
    if (col <= 63){
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdcs1, lcdcs1);
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdcs2, 0);
    	}
    	
    	if (col >= 64){
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdcs2, lcdcs2);
    	GPIOPinWrite(GPIO_PORTE_BASE, lcdcs1, 0);
    		
    	}
    
    }
    
    
    void setNewPage (unsigned char PageData)
    {		
    		PageData = PageData + SET_PAGE;
            WriteCommand(PageData);	
    		
    		WriteCommand(SET_ADDRESS); 		// This line resets the column address to the
    }								   		// first column again.
    
    
    void LocknLoad (void)
    {
    		GPIOPinWrite(GPIO_PORTE_BASE, lcde, lcde);
    	
                    SysCtlDelay(100);
       
    		GPIOPinWrite(GPIO_PORTE_BASE, lcde, 0);
       
    	        SysCtlDelay(100);
    }
    
    /* ---------------------------------------------------------------
    	This function sets the page and column registers of the LCD 
    	based on the column and row values given.
    	
    	Use this prior to printing text on the LCD. This is used when 
    	the text is required at a particular point (x,y) on the screen.
    	
    	The page and column variables are global.
     -----------------------------------------------------------------*/
    void setXY(uint8_t x, uint8_t y) {
    
    	uint8_t cmd;
    	
    	if(x > 127) x = 0;				// Validate the x and y values.
    	if(y > 63)  y = 0;								
    	
    	page = y/8;
    	column = x;
    	cSelect(column); 				// Select the chip based on the column number.
    									// The column variable is global and also used
    									// by the ASCII driver function lcd_putch().
    	
    	
    	cmd = SET_ADDRESS | x;	
    	WriteCommand(cmd);
    	
    	cmd = SET_PAGE | page;			// Set the Page (y address) on the selected chip.
    	WriteCommand(cmd);
    
    }
    
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    int main(void)
    {
        SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    		SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    		SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    		
        GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED);
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, GREEN_LED);	
    		SysCtlDelay(2000000);
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, 0);
    		SysCtlDelay(2000000);
    		lcdInit();
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, RED_LED);
    		
    		Bar(5,5,0,7);
    		SysCtlDelay(100000000);
    		Bar(10,5,10,7);
    		SysCtlDelay(100000000);
    		GPIOPinWrite(GPIO_PORTF_BASE, RED_LED|BLUE_LED|GREEN_LED, 0x00);
        while(1)
        {
          
        }
    }
    

    It seems the code is not working. 

    Can anybody identify the problem

  • Hi Vikram,

     

    Well, without knowing what the code is supposed to do i can't analyze what's wrong. If it's supposed to make pancakes, i assure you it won't work (get the idea?).

    I can analyze the code and from that it seems to be to control a LCD, am i right? Still please provide a explanation before so i don't have to deduce the objective from the code, when asking for help you must make it easy and clear for the people reading to assist you.

    By not providing a explanation and just putting up a long code, just asking for help to get it working, without guidance on what it's supposed to do and what's happening right now, people reading will probably run away from helping you even if it turns out to be a simple fix.

     

    Please answer this:


    What does you want to do with your code?

    How is it not working? What is it doing right now, the image is wrong, no image at all? Have you checked if any fault ISR is happening?

     

    Please answer this questions, it makes analyzing the problem much easier-

  • Hello Vikram,

    I would support Luis here. What is not working? is the code stuck in a fault or not executing beyond a specific point or is the external HW not responding. If it is the latter did you try scoping the pins between the TM4C and LCD to see if the protocol requirements are being met...

    Regards

    Amit

  • Hi Amit, Luis,

    I was in a hurry so couldn't explain the code after pasting here. 

    To avoid dependencies I have kept all the configuration and initialization in the same file. 

    Now the code is a simple test program to display a signal bar using the following functions in a JHD12864E LCD working around KS0108 family controller.

    // Draw Bar.
    void Bar(uint8_t height, uint8_t width, uint8_t xpos, uint8_t row);
    
    // Clear Bar.
    void BarC(uint8_t height, uint8_t width, uint8_t xpos, uint8_t row);

    To get the function working we need to make sure the LCD Initialization functions are working fine.

    void lcdInit (void);                    // Initialize the LCD.
    void clearl (void);                     // Clear the LCD.       

    I have taken reference from various datasheets for initialization sequence, data and control functions.

    The LCD is not initializing. 

    First task is to examine all the instructions like pin mapping/ configuration etc. are correct.
    (specially to make sure lcdInit() runs smoothly)

    Then to figure out why LCD is not responding.

    Thanks in advance.

  • Hello Vikram,

    Another thing is that make sure that the AFSEL is clear and so is ODEN for the GPIO Ports as part of the LCD Initialization funciton

    Regards

    Amit

  • Hi Luis, 

    Recently I was just wandering in your blog post. It always helps me whenever I'm in some doubt. 

    I have a question for you. 

    As you mentioned GPIO_PORTx_DATA_R register to write data to any port.

    What is the equivalent of it to read data from any GPIO Port?

    Thanks