-
Notifications
You must be signed in to change notification settings - Fork 0
/
uart0.c
235 lines (208 loc) · 7.72 KB
/
uart0.c
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// UART0 Library - Lab5
// Nathan Fusselman
//-----------------------------------------------------------------------------
// Hardware Target
//-----------------------------------------------------------------------------
// Target Platform: EK-TM4C123GXL
// Target uC: TM4C123GH6PM
// System Clock: -
// Hardware configuration:
// UART Interface:
// U0TX (PA1) and U0RX (PA0) are connected to the 2nd controller
// The USB on the 2nd controller enumerates to an ICDI interface and a virtual COM port
//-----------------------------------------------------------------------------
// Device includes, defines, and assembler directives
//-----------------------------------------------------------------------------
#include <stdint.h>
#include <stdbool.h>
#include "tm4c123gh6pm.h"
#include "uart0.h"
// PortA masks
#define UART_TX_MASK 2
#define UART_RX_MASK 1
//-----------------------------------------------------------------------------
// Subroutines
//-----------------------------------------------------------------------------
// Initialize UART0
void initUart0()
{
// Enable clocks
SYSCTL_RCGCUART_R |= SYSCTL_RCGCUART_R0;
SYSCTL_RCGCGPIO_R |= SYSCTL_RCGCGPIO_R0;
_delay_cycles(3);
// Configure UART0 pins
GPIO_PORTA_DIR_R |= UART_TX_MASK; // enable output on UART0 TX pin
GPIO_PORTA_DIR_R &= ~UART_RX_MASK; // enable input on UART0 RX pin
GPIO_PORTA_DR2R_R |= UART_TX_MASK; // set drive strength to 2mA (not needed since default configuration -- for clarity)
GPIO_PORTA_DEN_R |= UART_TX_MASK | UART_RX_MASK; // enable digital on UART0 pins
GPIO_PORTA_AFSEL_R |= UART_TX_MASK | UART_RX_MASK; // use peripheral to drive PA0, PA1
GPIO_PORTA_PCTL_R &= ~(GPIO_PCTL_PA1_M | GPIO_PCTL_PA0_M); // clear bits 0-7
GPIO_PORTA_PCTL_R |= GPIO_PCTL_PA1_U0TX | GPIO_PCTL_PA0_U0RX;
// select UART0 to drive pins PA0 and PA1: default, added for clarity
// Configure UART0 to 115200 baud, 8N1 format
UART0_CTL_R = 0; // turn-off UART0 to allow safe programming
UART0_CC_R = UART_CC_CS_SYSCLK; // use system clock (40 MHz)
UART0_IBRD_R = 21; // r = 40 MHz / (Nx115.2kHz), set floor(r)=21, where N=16
UART0_FBRD_R = 45; // round(fract(r)*64)=45
UART0_LCRH_R = UART_LCRH_WLEN_8 | UART_LCRH_FEN; // configure for 8N1 w/ 16-level FIFO
UART0_CTL_R = UART_CTL_TXE | UART_CTL_RXE | UART_CTL_UARTEN;
// enable TX, RX, and module
}
// Set baud rate as function of instruction cycle frequency
void setUart0BaudRate(uint32_t baudRate, uint32_t fcyc)
{
uint32_t divisorTimes128 = (fcyc * 8) / baudRate; // calculate divisor (r) in units of 1/128,
// where r = fcyc / 16 * baudRate
UART0_IBRD_R = divisorTimes128 >> 7; // set integer value to floor(r)
UART0_FBRD_R = (((divisorTimes128 + 1)) >> 1) & 63; // set fractional value to round(fract(r)*64)
}
// Blocking function that writes a serial character when the UART buffer is not full
void putcUart0(char c)
{
while (UART0_FR_R & UART_FR_TXFF); // wait if uart0 tx fifo full
UART0_DR_R = c; // write character to fifo
}
// Blocking function that writes a serial character when the UART buffer is not full
void putbUart0(bool in)
{
while (UART0_FR_R & UART_FR_TXFF); // wait if uart0 tx fifo full
if (in)
UART0_DR_R = '1'; // write character to fifo
else
UART0_DR_R = '0'; // write character to fifo
}
// Blocking function that writes a serial character when the UART buffer is not full
void putiUart0(uint32_t num) {
uint8_t countValue = num;
uint8_t digits = 0;
while (countValue > 0) {
countValue /= 10;
digits++;
}
if (digits == 0) {
putcUart0('0');
}
else {
char ans[10] = "\0\0\0\0\0\0\0\0\0\0";
for (digits = digits; digits > 0; digits--) {
ans[digits-1] = (num%10) + '0';
num /= 10;
}
putsUart0(ans);
}
}
// Blocking function that writes a string when the UART buffer is not full
void putsUart0(char* str)
{
uint8_t i = 0;
while (str[i] != '\0')
putcUart0(str[i++]);
}
// Blocking function that returns with serial data once the buffer is not empty
char getcUart0()
{
while (UART0_FR_R & UART_FR_RXFE); // wait if uart0 rx fifo empty
return UART0_DR_R & 0xFF; // get character from fifo
}
void getsUart0(USER_DATA* data)
{
uint8_t count = 0;
for (count = 0; true; count++) {
data->buffer[count] = getcUart0();
if (data->buffer[count] == 13 || data->buffer[count] == 10) {
data->buffer[count] = '\0';
return;
}
if (data->buffer[count] < ' ' || data->buffer[count] == 127) {
count -= 2;
}
if (count > MAX_CHARS) {
data->buffer[count+1] = '\0';
return;
}
}
}
void parseFields(USER_DATA* data)
{
uint8_t count = 0;
data->fieldCount = 0;
uint8_t i = 0;
for (i = 0; i < MAX_FIELDS; i++) {
data->fieldPosition[i] = 255;
data->fieldType[i] = '\0';
}
bool delimiter = true;
for (count = 0; data->buffer[count] != '\0'; count++) {
char test = data->buffer[count];
if ((test >= 'A' && test <= 'Z') || (test >= 'a' && test <= 'z')) {
if (delimiter && data->fieldCount < 5) {
delimiter = false;
data->fieldPosition[data->fieldCount] = count;
data->fieldType[data->fieldCount] = 'A';
data->fieldCount++;
}
} else {
if ((test >= '0' && test <= '9')) { //Optionally || test == '-' || test == '.'
if (delimiter&& data->fieldCount < 5) {
delimiter = false;
data->fieldPosition[data->fieldCount] = count;
data->fieldType[data->fieldCount] = 'N';
data->fieldCount++;
}
} else {
delimiter = true;
data->buffer[count] = '\0';
}
}
}
}
char* getFieldString(USER_DATA* data, uint8_t fieldNumber)
{
char out[MAX_CHARS+1];
uint8_t count;
for (count = data->fieldPosition[fieldNumber]; data->buffer[count] != '\0'; count++) {
out[count-data->fieldPosition[fieldNumber]] = data->buffer[count];
}
out[count-data->fieldPosition[fieldNumber]] = '\0';
return out;
}
int32_t getFieldInteger(USER_DATA* data, uint8_t fieldNumber)
{
if (data->fieldType[fieldNumber] == 'N') {
uint8_t count;
int32_t res = 0;
for (count = data->fieldPosition[fieldNumber]; data->buffer[count] != '\0'; count++) {
res = res * 10 + data->buffer[count] - '0';
}
return res;
} else {
return 0;
}
}
bool isCommand(USER_DATA* data, const char strCommand[], uint8_t minArguments)
{
if (data->fieldCount >= minArguments+1) {
if (stringCompare(data->buffer, strCommand)) {
return true;
}
}
return false;
}
bool stringCompare(char* a, char* b)
{
uint8_t count;
for (count = 0; a[count] != '\0'; count++) {
if (a[count] != b[count]) {
return false;
}
}
if (a[count] != b[count]) {
return false;
}
return true;
}
// Returns the status of the receive buffer
bool kbhitUart0()
{
return !(UART0_FR_R & UART_FR_RXFE);
}