UART programing in the TI ARM Tiva TM4C123G
The following exercise show you how to make use of an UART port from the ARM Cortex-M4-based microcontroller Tiva TM4C123G LaunchPad. The ASIC character “Yes” will be send to a terminal emulator program on your PC as an example.
The TM4C123G datasheet provide a series of steps under the below sections that will be required for UART set-up:
General-Purpose Input/Outputs (GPIOs) - Initialization and Configuration.
Universal Asynchronous Receivers/Transmitters (UARTs)
I will summarize those steps with a visual representation for better understanding of the procedure and to easily go through the datasheet. Eventually each step will be part of an entire source code for you to use. Complete source code is at the end of this article.
Note: For the purpose of this tutorial we are going to use IAR as our integrated development environment tool (IDE). I’m not affiliated, nor support, or receive any commission by doing so.
Note: Users should have been familiarized previously with the IAR tool.
To begin with...
You need to know that the Tiva ARM TM4C123GH6PM has up to 8 UART ports, designated as UART0 to UART7.
Table 23-5. GPIO Pins and Alternate Functions, page 1351 of the datasheet, shows all of the UARTs ports and correlation with their pins.
For simplicity, and because I don’t have any other cable other than the USB included in the box at the moment, we are going to program UART0. The reason why we choose UART0 is because pins 17 & 18 allow virtual COM connection between our device and the device driver at the host PC. And will work with communication software on the PC such as a terminal emulator.
Page 20 of the User’s Manual.
In the TI LaunchPad, the pins 17 & 18 of the TM4C123GH6PM is connected to the ICDI (In-Circuit Debug Interface), which is connected to a USB connector. Thus, only the USB cable will be needed to communicate with UART0.
From this point on the steps that you will follow represent single lines of code to be compiled later on in your source code. As mentioned before the complete source code can be found at the end.
Part I. GPIOA Initialization and Configuration
General-Purpose Input/Outputs (GPIOs) module, Port A.
DATA SHEET, p.656.
This section describes the steps to follow to access and configure the GPIO pins of a particular block. In our case the block we want to manipulate is block A, as we just see from the previous schematic pins 17 & 18 correspond to GPIOA.
STEP 1. Enable signal clock to the appropriate GPIO module.
Set the appropriate bits in the RCGCGPIO register to enable clock signal to the GPIOA.
Datasheet - General-Purpose Input/Output Run Mode Clock Gating Control (RCGCGPIO), offset 0x608, p.340
It’s telling you that to enable the clock and access to the GPIO Port A module, bit 0 in the RCGCGPIO register must be set to 1.
SYSCTL->RCGCGPIO |= 0x01; //STEP1: enable clock signal to GPIOA
STEP 2. Set the direction of the pins either as input or output.
SKIP STEP 2
STEP 3A. Enable the corresponding GPIO line with an alternate function.
Each GPIO line can be configured as a GPIO or have another alternate function.
Table 23-5 on page 1351 details which functions are muxed on each GPIO pin.
In our case, PA0 and PA1 would be enabled to act as an ALT function in the GPIOAFSEL since both can act as UART or CAN.
Datasheet - GPIO Alternate Function Select (GPIOAFSEL), offset 0x420, p.671
GPIOA->AFSEL = 0x03; /* STEP3A. Use PA0, PA1 alternate function */
Note: We set bits 1-0 because those represent pins 17 & 18. PA0 = 17, PA1 = 18. See the schematic.
STEP 3B. Selects the specific peripheral signal for the corresponding selected GPIO line.
Datasheet - GPIO Port Control (GPIOPCTL), offset 0x52C, p.688
Each PMCn field in the GPIOPCTL register represents a GPIO line. 8 lines in total -> from bit 0 to 31.
For each line you could select a specific peripheral signal to be used on those lines. The specific signal is represented by a value between 1 to 15 in Table 23-5 on page 1351.
Digital Function 1 is the value that should be placed in the PMC1 and PMC1 fields of the GPIOPCTL register to assign the UART ALT function to the GPIO Port A line 0 (Rx) and 1 (Tx) .
GPIOA->PCTL = 0x11; /* STEP3B. Configure PA0 and PA1 for UART */
STEP 4. Set the drive strength for each of the pins through the GPIODR2R, GPIODR4R, and GPIODR8R registers.
Enable GPIODEN register bits 1:0 as digital by setting bits from 0 to 1.
GPIOA->DEN = 0x03; /* STEP6. Enable PORTF2-0 DIGITAL pins */
STEP 7: Enable and configure the GPIO Interrupt options
SKIP STEP 7
Part II. UART Initialization and Configuration
Datasheet - Universal Asynchronous Receiver/Transmitter Run Mode Clock
Gating Control (RCGCUART), offset 0x618, p.344STEP 2. Disable UART0 before making any changes.
Disable the UART by clearing the UARTEN bit in the UARTCTL register.
Datasheet - UART Control (UARTCTL), offset 0x030, p.918
3A. Write the integer portion of the BRD to the UARTIBRD register.
UART0->IBRD = 104; /* STEP3A. 16Mhz/16 = 1MHz, 1Mhz/104 = 9600 baud rate */
3B. Write the fractional portion of the BRD to the UARTFBRD register.
Datasheet - UART Fractional Baud-Rate Divisor (UARTFBRD), offset 0x028, p.915
UART0->FBRD = 11; /* STEP3A. fraction part, see Example 4-4 */
STEP4. Write the desired serial parameters to the UARTLCRH register (in this case, a value of 0x0000.0060).
Desired UART Serial configuration:
¦ 9600 baud rate
¦ Data length of 8 bits
¦ One stop bit
¦ No parity
¦ FIFOs disabled
¦ No interrupts
Datasheet - UART Line Control (UARTLCRH), offset 0x02C, p.916
UART->LCRH = 0x60; /* 8-bit, no parity, 1-stop bit, no FIFO */
STEP6. Optional
Part III. UART Flag Register (Status)
void UART0Tx(char c)
{
/* -------------------------- PART III -------------------------- */
while ((UART0->FR & 0x20) != 0);/* wait until Tx buffer not full */
UART0->DR = c; /* before giving it another byte */
/* ----------------------- PART III (END) ----------------------- */
}
Press the Download & Debug at the top of the IAR tool bar to upload the code to your Tiva LaunchPad.
Then, open your terminal emulator program (PuTTY for example). Serial configuration is as follows: Note: Go to Device Manager and validate which COMX is your Tiva LaunchPad connected to.
- Open a section. You should be able to see the word “Yes” in the terminal emulator screen.
CODE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | /* UART Sending "Yes" to UART0 on TI ARM Launchpad (TM4C123GH6PM) UART0 is on USB/Debug Use PuTTY to see the message "YES" on a PC Desired UART configuration: ¦ 9600 baud rate ¦ Data length of 8 bits ¦ One stop bit ¦ No parity ¦ FIFOs disabled ¦ No interrupts */ #include <stdint.h> #include <TM4C123GH6PM.h> //Tiva C Series TM4C123G “Header File”. void GPIO_init(void); void UART0_init(void); void UART0Tx(char c); void delayMs(int n); int main(void) { GPIO_init(); UART0_init(); delayMs(1); /* wait for output line to stabilize */ for (;;) { UART0Tx('Y'); UART0Tx('E'); UART0Tx('S'); UART0Tx(' '); } } void GPIO_init(void) { /* ---------------------------- PART I ---------------------------- */ /* ------------ GPIOA Initialization and Configuration ------------ */ SYSCTL->RCGCGPIO |= 0x01; /* STEP1. Enable clock signal to the GPIOA */ /*SKIP STEP2*/ GPIOA->AFSEL = 0x03; /* STEP3A. Use PA0, PA1 alternate function */ GPIOA->PCTL = 0x11; /* STEP3B. Configure PA0 and PA1 for UART */ /*SKIP STEP4 - 5*/ GPIOA->DEN = 0x03; /* STEP6. Enable PORTF2-0 DIGITAL pins */ /* ------------------------ PART I (END) -------------------------- */ } void UART0_init(void) { /* --------------------------- PART II -------------------------- */ /* ----------- UART Initialization and Configuration ---------- */ SYSCTL->RCGCUART |= 1; /* STEP1. Enable clock signal to UART0. */ UART0->CTL = 0x00; /* STEP2. Disable UART0 before any changes */ /* desire configuration */ UART0->IBRD = 104; /* STEP3A. 16Mhz/16 = 1MHz, 1Mhz/104 = 9600 baud rate */ UART0->FBRD = 11; /* STEP3B. Fraction part, see Example 4-4 */ UART0->LCRH = 0x60; /* STEP4. 8-bit, no parity, 1-stop bit, no FIFO */ UART0->CC = 0; /* STEP5. Use system clock */ /*SKIP STEP6*/ UART0->CTL = 0x301; /* STEP7. Enable UART0, TXE, RXE */ /* ------------------------ PART II (END) ------------------------ */ } void UART0Tx(char c) { /* --------------------------- PART III -------------------------- */ /* ----------------- UART Flag Register (Status) ----------------- */ while ((UART0->FR & 0x20) != 0); /* wait until Tx buffer not full */ UART0->DR = c; /* before giving it another byte */ /* ------------------------ PART III (END) ----------------------- */ } void delayMs(int n) { int i, j; for(i = 0; i < n; i++) for(j=0; j < 3180; j++) {} // do nothing for 1 ms } |
Comments