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.

TM4C123GH6PM: Read and Writing from Individual Pins

Part Number: TM4C123GH6PM

I am trying to write two programs 1) is going to write 4 bits of a number to 4 pins in one port and the second 4 bits in the second port 2) read these bits. Where I am stuck is how to write and read individual pins, maybe I am missing some documentation but I can't seem to figure this out. 

I have port D and E initialized as follows below: 

If someone could point me in the right direction on where to read up on this or correct my intializations I would appreciate it. Thanks. 

void PortDInit(void) {
volatile unsigned long delay;

SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOF; // 1) D clock
delay = SYSCTL_RCGC2_R; // delay
GPIO_PORTD_LOCK_R = 0x4C4F434B; // 2) unlock PortD
GPIO_PORTD_CR_R |= 0x14; // allow changes to PF4 (SW1) and PF2 (Blue LED)
GPIO_PORTD_AMSEL_R = 0x00; // 3) disable analog function
GPIO_PORTD_PCTL_R = 0x00; // 4) GPIO clear bit PCTL
GPIO_PORTD_DIR_R &=~ 0x07; // 5) PD2, PD1, PD0 for output
// PF2 (Blue LED) is output
GPIO_PORTD_AFSEL_R = 0x00; // 6) no alternate function
GPIO_PORTD_PUR_R |= 0x10; // enable pullup resistor on PF4
GPIO_PORTD_DEN_R |= 0x14; // 7) enable digital pins PF4, PF2
}

//initalizes portE
void PortE_Init(void){
volatile unsigned long delay;
SYSCTL_RCGC2_R |= 0x00000010; // 1) E clock
delay = SYSCTL_RCGC2_R; // delay
GPIO_PORTE_CR_R = 0x2F; // allow changes to PE5,3-0
GPIO_PORTE_AMSEL_R = 0x00; // 3) disable analog function
GPIO_PORTE_PCTL_R = 0x00000000; // 4) GPIO clear bit PCTL
GPIO_PORTE_DIR_R |= 0x08; // 5) PE3 input
GPIO_PORTE_DIR_R &=~ 0x07; // 5) PE2,PE1,PE0 output
GPIO_PORTE_AFSEL_R = 0x00; // 6) no alternate function
GPIO_PORTE_PUR_R = 0x08; // enable pullup resistors on PE3
GPIO_PORTE_DEN_R = 0x0F; // 7) enable digital pins PE3-PE0

  • Justin,

     I don't see you writing to or reading from the data register. You should have a GPIO_PORTD_DATA_R. I don't know how you define it in your header file for your school. You can write to or read from the data register. See below and also from the device datasheet. Normally, we strongly discourage people from using DRM. You will greatly speed up your development using the free TivaWare library.

     

  • Here is where I am getting confused I believe I figured out the write with
    while(1){
    int x = 0;
    int temp = 0;

    PortD = PortD&0x00000000;
    PortE = PortE&0x00000000;

    SW1 = GPIO_PORTF_DATA_R&0x10;

    if (!SW1) {
    while (x != 5) {
    x++; // increment x from 0 to [some number]
    temp = x; // set x to a temporary value for data transfer
    PortD = temp&0x0F; // pass first four bits onto PortD
    temp = temp >> 4; // prepare temp to transfer remaining bits to PortE
    PortE = temp&0x0F;
    Delay100ms(1);
    }
    // Clear bits once desired number is reached
    PortD = PortD&0x00000000;
    PortE = PortE&0x00000000;

    But how would I end up doing the read from the same pins?
    I have been reading around and
    GPIOPinWrite(GPIO_PORTE_BASE,GPIO_PIN_1, Value);
    seems like this would do the right thing or am I in the wrong direction?
  • simple:

    1) write a set of macros that set / clear a pin, or read a pin: IO_SET(port, pin), IO_CLR(port, pin) and IO_GET(port, pin), or whatever names you may wish to have.

    2) write a function that writes to those two ports and another to read it back, like this:

    //write a number
    
    void dat_write(uint8_t dat) {
    
      if (dat & (1<<0)) IO_SET(PORT1, PIN0); else IO_CLR(PORT1, PIN0);
    
      if (dat & (1<<1)) IO_SET(PORT1, PIN1); else IO_CLR(PORT1, PIN1);
      ...
    
      if (dat & (1<<6)) IO_SET(PORT2, PIN6); else IO_CLR(PORT2, PIN6);
    
      if (dat & (1<<7)) IO_SET(PORT2, PIN7); else IO_CLR(PORT2, PIN7);
    
    }
    
    
    
    //read a number
    
    uint8_t dat_read(void) {
    
      uint8_t tmp=0;
    
      if (IO_GET(PORT1, PIN0)) tmp |= (1<<0);
    
      if (IO_GET(PORT1, PIN1)) tmp |= (1<<1);
    
      ...
    
      if (IO_GET(PORT2, PIN6)) tmp |= (1<<6);
    
      if (IO_GET(PORT2, PIN7)) tmp |= (1<<7);
    
      return tmp;
    
    }
    
    

    you can implement IO_SET(), IO_CLR() and IO_GET() macros however you wish, depending on the framework you are coding within.

    the code has two advantages:

    1) it is hardware independent: should you move it to a different platform, simply link in the appropriate IO_SET(), IO_CLR() and IO_GET() macros and you are ready to go;

    2) it is inherently consistent: if you wish to change pin / port assignment, simply modify the definitions of PORT1/2, or PIN0..7, hit recompile and you know that your code will work.

    anything more complicated than that, you are doing something wrong.

  • if I were you, I would actually write the two routines with the potential to use 8 different pins on 8 different ports. To run it on two ports, you can simply make PORT0..7 definitions to be on those two ports.
  • May I generally agree w/poster Danny's guidance - but w/the addition (surely the NEEDED addition) of (both) a, "FULL & PARTIAL PORT:  WRITE, CLEAR & READ!"

    Individual bit control IS required - but so too - Partial & Full Port Control...

    The ability to "extend such capability" to (other) platforms (really devices) may not have sensed the fact that (other) ARM MCUs have long accommodated,  "16-bit WIDE GPIO Ports" - demanding another "hoop" for jumping...