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.

UART connection problems with TM4C123GH6PM

Other Parts Discussed in Thread: MAX232, EK-TM4C123GXL

Hi,

I am a newbie and have a EK-TM4C123GXL. I am trying to transmit 9600 samples per second from ADC, using UART channels to a Bluetooth device. I am using timer triggered interrupts for sampling. However, I still could not get UART working properly. I am using a MAX232 in order to convert from UART to RS232 and see what I receive by a Terminal. I have several problems,

RealTerm gives framing error if I choose 115200, which I think I set. It gives periodic results as expected, when I choose 57600. However, the values do not correspond to what I transmit. I checked MAX232 setup, it is functioning well. What may be causing the problem? For example, for 'A', I get C1(hex), for 'B', C0(hex).

void UART_Init(void){

  SYSCTL_RCGC1_R |= SYSCTL_RCGC1_UART1; 
  SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOC;
  UART1_CTL_R &= ~UART_CTL_UARTEN;      
  UART1_IBRD_R = 43;                    // IBRD = int(80,000,000 / (16 * 115200)) = int(43.402778)
  UART1_FBRD_R = 26;                    // FBRD = round(0.402778 * 64) = 26
                                        // 8 bit word length (no parity bits, one stop bit, FIFOs)
  UART1_LCRH_R = (UART_LCRH_WLEN_8|UART_LCRH_FEN);
  UART1_CTL_R |= UART_CTL_UARTEN;       // enable UART
  GPIO_PORTC_AFSEL_R |= 0x30;          
  GPIO_PORTC_DEN_R |= 0x30;            
                                        
  GPIO_PORTC_PCTL_R = (GPIO_PORTC_PCTL_R&0xFF00FFFF)+0x00220000;
  GPIO_PORTC_AMSEL_R &= ~0x03;          
}


unsigned char UART_InChar(void){
  while((UART1_FR_R&UART_FR_RXFE) != 0);
  return((unsigned char)(UART1_DR_R&0xFF));
}


void UART_OutChar(unsigned char data){
  while((UART1_FR_R&UART_FR_TXFF) != 0);
  UART1_DR_R = data;
}


int main(void){ 

  PLL_Init();
  UART_Init();
  ADC0_InitTimer0ATriggerSeq3(0, 76, 64934);

  while(1){
    WaitForInterrupt();
    UART_OutChar('f');
    WaitForInterrupt();
    UART_OutChar('g');

  }

}

  • Hello Jacob,

    I checked your code except for the PLL_Init and ADC0_InitTimer0ATriggerSet and the code works fine. I am able to see f and g characters as expected on the TeraTerm at Baud Rate of 115200bps.

    I suspect the PLL_Init to be the issue. Also I would suggest using the TIVAWare API's as it is more readable and functions more easy to use.

    Regards

    Amit

  • Here is my PLL.c

    #define SYSCTL_RIS_R            (*((volatile unsigned long *)0x400FE050))
    #define SYSCTL_RIS_PLLLRIS      0x00000040  // PLL Lock Raw Interrupt Status
    #define SYSCTL_RCC_R            (*((volatile unsigned long *)0x400FE060))
    #define SYSCTL_RCC_XTAL_M       0x000007C0  // Crystal Value
    #define SYSCTL_RCC_XTAL_6MHZ    0x000002C0  // 6 MHz Crystal
    #define SYSCTL_RCC_XTAL_8MHZ    0x00000380  // 8 MHz Crystal
    #define SYSCTL_RCC_XTAL_16MHZ   0x00000540  // 16 MHz Crystal
    #define SYSCTL_RCC2_R           (*((volatile unsigned long *)0x400FE070))
    #define SYSCTL_RCC2_USERCC2     0x80000000  // Use RCC2
    #define SYSCTL_RCC2_DIV400      0x40000000  // Divide PLL as 400 MHz vs. 200
                                                // MHz
    #define SYSCTL_RCC2_SYSDIV2_M   0x1F800000  // System Clock Divisor 2
    #define SYSCTL_RCC2_SYSDIV2LSB  0x00400000  // Additional LSB for SYSDIV2
    #define SYSCTL_RCC2_PWRDN2      0x00002000  // Power-Down PLL 2
    #define SYSCTL_RCC2_BYPASS2     0x00000800  // PLL Bypass 2
    #define SYSCTL_RCC2_OSCSRC2_M   0x00000070  // Oscillator Source 2
    #define SYSCTL_RCC2_OSCSRC2_MO  0x00000000  // MOSC
    
    // configure the system to get its clock from the PLL
    void PLL_Init(void){
      // 0) configure the system to use RCC2 for advanced features
      //    such as 400 MHz PLL and non-integer System Clock Divisor
      SYSCTL_RCC2_R |= SYSCTL_RCC2_USERCC2;
      // 1) bypass PLL while initializing
      SYSCTL_RCC2_R |= SYSCTL_RCC2_BYPASS2;
      // 2) select the crystal value and oscillator source
      SYSCTL_RCC_R &= ~SYSCTL_RCC_XTAL_M;   // clear XTAL field
      SYSCTL_RCC_R += SYSCTL_RCC_XTAL_16MHZ;// configure for 16 MHz crystal
      SYSCTL_RCC2_R &= ~SYSCTL_RCC2_OSCSRC2_M;// clear oscillator source field
      SYSCTL_RCC2_R += SYSCTL_RCC2_OSCSRC2_MO;// configure for main oscillator source
      // 3) activate PLL by clearing PWRDN
      SYSCTL_RCC2_R &= ~SYSCTL_RCC2_PWRDN2;
      // 4) set the desired system divider and the system divider least significant bit
      SYSCTL_RCC2_R |= SYSCTL_RCC2_DIV400;  // use 400 MHz PLL
      SYSCTL_RCC2_R = (SYSCTL_RCC2_R&~ 0x1FC00000)  // clear system clock divider
                      + (SYSDIV2<<22);      // configure for 80 MHz clock
      // 5) wait for the PLL to lock by polling PLLLRIS
      while((SYSCTL_RIS_R&SYSCTL_RIS_PLLLRIS)==0){};
      // 6) enable use of PLL by clearing BYPASS
      SYSCTL_RCC2_R &= ~SYSCTL_RCC2_BYPASS2;
    }

  • Hello Jacob

    The use of the above defines while supported, has scope for more errors. In this case the setting of MOSC requires a stabilization time for the external crystal which is not the case Also the define SYSDIV2 is not in place either. To avoid such code cases and to make development and debug simpler, I would strongly suggest you to use

    SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

    This is bound to give to 80MHz (well tested and used). Also then the chances of running into a configuration issue is far much lesser.

    Regards

    Amit

  • Jacob

    This code will do what you are trying to do

    #define SYSCTL_RCC_R            (*((volatile unsigned long *)0x400FE060))
    #define SYSCTL_RCC2_R           (*((volatile unsigned long *)0x400FE070))
    #define SYSCTL_RIS_R            (*((volatile unsigned long *)0x400FE050))
    #define SYSCTL_PLLSTAT_R            (*((volatile unsigned long *)0x400FE168))
    
    void PLL_Init(void){
      SYSCTL_RCC_R = 0x78E3D40;
      SYSCTL_RCC2_R = 0xC1004800;
      SYSCTL_RCC_R |= (1<<22);
      while (!(SYSCTL_RIS_R & 0x00000040)) {} // Wait for PLL to become ready.
      SYSCTL_RCC2_R &= ~(1<<11);	
      while (!(SYSCTL_PLLSTAT_R)) {} // Ensure PLL is ready
    }

    This will set the EK-TM4C123GXL Tiva C Launchpad to 80MHz

  • Hello Rob

    A word of caution if MOSC or external Crystal is used. After powering it up sufficient delay needs to be given for the cyrstal to start up.

    Regards

    Amit

  • Hello Amit

    How long of a delay would you recommend? I have read it can vary from a few milliseconds to a few seconds.

    Thanks

    Rob

  • Hello Rob,

    For the Oscillator IO Pad it is maximum of 18ms for the Crystal to Power Up.

    Regards

    Amit

  • Hello Amit

    Would this be correct? Am I on the right track?
     Am I right that the board will be running at 16MHz with USESYSDIV cleared and BYPASS set in RCC.

        SYSCTL_RCC_R = 0x78E3D50; // Clear MOSCDIS, set XTAL to 16MHz, set SYSDIV
        
        // With USESYSDIV cleared and BYPASS set the board should be running at 16MHz (internal oscillator)
      for (i = 0; i < 20572; i++)
        { float f = 999.99f / 333.33f; } // floating point divide should take 14 clock cycles ( 875ns@16MHz )
        
        SYSCTL_RCC_R &= ~(1<<4);    // Use Main Oscillator ( it should be stabilized now.)
        SYSCTL_RCC2_R = 0xC1004800;

    This is a snippet and int i is declared earlier.

    Thanks

    Rob

  • Hello Rob,

    Yes that should get you the 18ms of Crystal Startup Time

    Regards

    Amit