[Tiva] GPIOIntTypeSet()

임베디드/TI 2015.07.13 10:55

void GPIOIntTypeSet(uint32_t ui32Port, uint8_t ui8Pins, uint32_t ui32IntType)

설명 : 특정한 핀에 대한 인터럽트 방식을 설정합니다.


uint32_t ui32Port

GPIO의 포트를 설정합니다.


uint8_t ui8Pins

설정하고자 하는 해당 포트의 핀번호를 선택합니다.


uint32_t ui32IntType

자신이 원하는 인터럽트의 신호를 선택합니다.


 여기서 ui32IntType를 통하여 다음과 같은 인터럽트 신호들을 감지할 수 있도록 설정할 수 있습니다.


GPIO_FALLING_EDGE

핀의 입력이 1에서 0으로 내려가는 순간에 인터럽트를 발생시킵니다.


GPIO_RISING_EDGE

핀의 입력이 0에서 1로 올라가는 순간에 인터럽트를 발생시킵니다.


GPIO_BOTH_EDGE

위의 GPIO_FALLING_EDGE와 GPIO_RISING_EDGE가 발생시 인터럽트를 발생시킵니다.


GPIO_LOW_LEVEL

핀의 입력이 0이 되었을 때 인터럽트를 발생시킵니다.


GPIO_HIGH_LEVEL

핀의 입력이 1이 되었을 때 인터럽트를 발생시킵니다.


GPIO_DISCRETE_INT

GPIO 포트에서의 각 핀에 대한 별개의 인터럽트를 설정합니다.



 인터럽트를 설정할 때 의도치 않은 인터럽트 설정을 피하기 위해 위의 함수를 사용할 시에 GPIO의 입력이 안정된 상태어야 합니다. 즉, Floating 현상으로 인해 의도치 않은 인터럽트가 발생할 수 있다는 점을 유의해야 합니다. Floating에 대한 자세한 설명은 아래 포스팅을 참조해 주시기 바랍니다.


http://elecs.tistory.com/15

[Tiva] Tiva 기반 MCU로 블루투스 모듈을 활용하여 UART 통신하기

임베디드/TI 2014.09.13 02:04

 MCU를 활용하여 다른 기기와의 통신으로 UART를 많이 사용할 겁니다. 이러한 MCU에 블루투스 모듈을 사용하면 간단한 설정으로 무선으로 UART를 활용할 수 있다는 점은 상당히 매력적이지요.

 다만 아쉬운 점이라면 블루투스 모듈을 사용시 AT 커맨드 등 기본적인 활용 지식이 없는 상태에서 입문하기에는 공부할 것이 많다는 점이 블루투스에 입문하는데 장벽이 되고 있기도 하지요.


 아래의 코드는 MCU와 블루투스 모듈이 연결되어 있을 때 해당 코드를 활용하면 바로 다른 기기와 연결모드에 진입할 수 있습니다. 이후 다른 기기와 블루투스를 연결하면 UART 통신을 통해 블루투스와 연결된 기기간에 통신을 할 수 있게 됩니다.


 해당 코드는 TI사의 TM4C123GH6PM MCU를 활용하였으며 소스코드는 TI사의 Tivaware 라이브러리 내의 소스코드를 활용하였습니다. 블루투스 모듈은 FirmTech 사의 FB155BC를 사용하였음을 알립니다.


※UART0은 PC와 연결되어 있으며 UART7은 블루투스 모듈과 연결되어 있습니다.

※블루투스 모듈의 모드는 AT COMMAND를 받는 모드로 설정되어 있습니다.

※블루투스 모듈에 UART로 'AT+BTSCAN'을 전송하면 블루투스 모듈이 다른 기기의 연결을 기다리게 됩니다.




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
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/adc.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
 
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
 
void ConfigureUART(void) {
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
 
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART7);
 
    //
    // Configure GPIO Pins for UART mode.
    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    ROM_GPIOPinConfigure(GPIO_PE0_U7RX);
    ROM_GPIOPinConfigure(GPIO_PE1_U7TX);
    ROM_GPIOPinTypeUART(GPIO_PORTE_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 
    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    
    UARTClockSourceSet(UART7_BASE, UART_CLOCK_PIOSC);
 
    //
    // Initialize the UART for console I/O.
    //
    ROM_UARTConfigSetExpClk(UART0_BASE, ROM_SysCtlClockGet(), 115200,
            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
            UART_CONFIG_PAR_NONE));
    ROM_UARTConfigSetExpClk(UART7_BASE, ROM_SysCtlClockGet(), 9600,
            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
            UART_CONFIG_PAR_NONE));
}
 
void findDevice() {
    UARTCharPut(UART7_BASE, 'A');
    UARTCharPut(UART7_BASE, 'T');
    UARTCharPut(UART7_BASE, '+');
    UARTCharPut(UART7_BASE, 'B');
    UARTCharPut(UART7_BASE, 'T');
    UARTCharPut(UART7_BASE, 'S');
    UARTCharPut(UART7_BASE, 'C');
    UARTCharPut(UART7_BASE, 'A');
    UARTCharPut(UART7_BASE, 'N');
    UARTCharPut(UART7_BASE, 0x0D);
}
 
void AT() {
    UARTCharPut(UART7_BASE, 'A');
    UARTCharPut(UART7_BASE, 'T');
    UARTCharPut(UART7_BASE, 0x0D);
    UARTCharPut(UART0_BASE, '0');
}
 
void UARTIntHandler() {
    unsigned char get;
    get = UARTCharGet(UART7_BASE);
    if (get == '\r') {
        UARTCharPut(UART0_BASE, '\n');
        UARTCharPut(UART0_BASE, '\r');
    } else
        UARTCharPut(UART0_BASE, get);
}
 
void InsertUART2() {
    unsigned char get;
    get = UARTCharGet(UART0_BASE);
    
    if (get == '\r') {
        UARTCharPut(UART7_BASE, '\r');
        UARTCharPut(UART7_BASE, '\n');
    } else
        UARTCharPut(UART7_BASE, get);
}
 
void SendString(char *str) {
    while (*str) {
        UARTCharPut(UART7_BASE, *str);
        SysCtlDelay(SysCtlClockGet() / 100);
        str++;
    }
    
}
 
int main(void) {
    ROM_FPULazyStackingEnable();
 
    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
    SYSCTL_XTAL_16MHZ);
 
    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
 
    //
    // Enable the GPIO pins for the LED (PF2 & PF3).
    //
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
 
    //
    // Initialize the UART.
    //
    ConfigureUART();
 
    IntMasterEnable();
 
    IntEnable(79);
    UARTIntEnable(UART7_BASE, UART_INT_RX | UART_INT_RT);
    UARTIntRegister(UART7_BASE, UARTIntHandler);
 
    IntEnable(21);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    UARTIntRegister(UART0_BASE, InsertUART2);
 
    SysCtlDelay(SysCtlClockGet() / 4);
    findDevice();
 
    while (1) {
    
    UARTCharPut(UART7_BASE, 'H');
    UARTCharPut(UART7_BASE, 'e');
    UARTCharPut(UART7_BASE, 'l');
    UARTCharPut(UART7_BASE, 'l');
    UARTCharPut(UART7_BASE, 'o');
    UARTCharPut(UART7_BASE, ',');
    UARTCharPut(UART7_BASE, 'W');
    UARTCharPut(UART7_BASE, 'o');
    UARTCharPut(UART7_BASE, 'r');
    UARTCharPut(UART7_BASE, 'l');
    UARTCharPut(UART7_BASE, 'd');
    UARTCharPut(UART7_BASE, '!');
    UARTCharPut(UART7_BASE, '\n');
    UARTCharPut(UART7_BASE, '\r');
    SysCtlDelay(SysCtlClockGet());
    
    }
}
 


[Tiva] Tiva C 기반의 MCU로 초음파센서 SRF-10 활용하기

임베디드/TI 2014.09.12 23:51

[SRF-10 source code using tm4c123g]


본 소스코드는 TI 사에서 제공하는 TivaWare 기반으로 작성되었으며

TI 사의 tm4c123gh6pm MCU에서 동작을 확안하였음을 알립니다.


기타 문의사항이 있으시거나 코드에 문제가 있을 경우 알려주시면 감사하겠습니다.



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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "driverlib/i2c.h"
#include "utils/uartstdio.h"
 
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
 
void ConfigureUART(void)
{
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
 
    //
    // Enable UART0
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
 
    //
    // Configure GPIO Pins for UART mode.
    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 
    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
 
    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}
 
void DelaySoft(volatile unsigned long ulDelay) {
    SysCtlDelay((SysCtlClockGet() / 10000) * ulDelay);
}
 
#define    SLAVE_ADDRESS    0xE0 / 2
 
void ChangeAddress(int old, int new) {
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, old, false);
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x00);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0xA0);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    //SysCtlDelay(SysCtlClockGet() / 1000000 * 2);
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x00);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0xAA);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    //SysCtlDelay(SysCtlClockGet() / 1000000 * 2);
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x00);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0xA5);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    //SysCtlDelay(SysCtlClockGet() / 1000000 * 2);
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x00);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterDataPut(I2C1_BASE, new);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
}
 
int getI2CValue(int ADDR) {
    uint32_t rcv1 = 0;
    uint32_t rcv2 = 0;
    uint32_t rcv = 0;
 
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, ADDR, false);
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x00);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x51);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    SysCtlDelay(SysCtlClockGet() / 1000000 * 2);
 
    ROM_I2CMasterDataPut(I2C1_BASE, 0x02);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterDataPut(I2C1_BASE, 93);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    DelaySoft(115);
 
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, ADDR, false);
    ROM_I2CMasterDataPut(I2C1_BASE, 0x02);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, ADDR, true);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    rcv1 = ROM_I2CMasterDataGet(I2C1_BASE);
    rcv = rcv1 << 8;
 
    SysCtlDelay(SysCtlClockGet() / 1000000 * 2);
 
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, ADDR, false);
    ROM_I2CMasterDataPut(I2C1_BASE, 0x03);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_BURST_SEND_START);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, ADDR, true);
    ROM_I2CMasterControl(I2C1_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    rcv2 = ROM_I2CMasterDataGet(I2C1_BASE);
    rcv += rcv2;
 
    //ROM_I2CMasterSlaveAddrSet(I2C0_BASE, SLAVE_ADDRESS, true);
    //ROM_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
    //rcv = ROM_I2CMasterDataGet(I2C0_BASE);
 
    while (ROM_I2CMasterBusy(I2C1_BASE)) {
 
    }
 
    //DelaySoft(500);
    DelaySoft(300);
 
    return rcv;
}
 
int main(void) {
    //volatile uint32_t ui32Loop;
    uint32_t var1, var2;
 
    //
    // Enable lazy stacking for interrupt handlers.  This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPULazyStackingEnable();
 
    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
    SYSCTL_OSC_MAIN);
 
    //
    // Enable the GPIO port that is used for the on-board LED.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1);
 
    ROM_GPIOPinConfigure(GPIO_PA6_I2C1SCL);
    ROM_GPIOPinConfigure(GPIO_PA7_I2C1SDA);
 
    ROM_GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_6);
    ROM_GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_7);
 
    ROM_I2CMasterInitExpClk(I2C1_BASE, SysCtlClockGet(), false);
 
    ROM_I2CMasterSlaveAddrSet(I2C1_BASE, SLAVE_ADDRESS, false);
 
    ROM_I2CMasterEnable(I2C1_BASE);
 
 ConfigureUART();
 
 //I2C Slave의 주소를 바꿀 때 사용합니다.
 //이 때, ChangeAddress의 첫 번째 인자는 원래 주소, 두 번째 인자는 바꾸기를 원하는 주소를 입력합니다.
 //단, 첫 번째 인자의 경우 7비트로 전송해야 하므로 원래 주소 / 2 를 하여 전송하고
 //두 번째 인자의 경우 변경하기 원하는 주소를 그대로 입력해줍니다.
    //ChangeAddress(0xE0 / 2, 0xE2);
 
    //
    // We are finished.  Hang around doing nothing.
    //
    while (1) {
 
        //I2C를 통해 SRF10 초음파 거리측정 센서와 통신하여 거리를 측정합니다.
             //getI2CValue() 함수 사용시 인자는 측정을 원하는 센서의 주소를 입력합니다.
             //단, 7비트로 전송해야 하므로 원래주소 / 2 를 하여 전송합니다.
        var1 = getI2CValue(0xE0 / 2);
        var2 = getI2CValue(0xE2 / 2);
 
        UARTprintf("LEFT : %5d, RIGHT : %5d\r", var1, var2);
    }
}
 


참고 자료 : http://www.robot-electronics.co.uk/htm/srf10tech.htm

[CCS] The program generated is not compatible with any of the CPUs in your target configuration.

임베디드/TI 2014.08.28 14:04

 Code Composer Studio를 활용하여 MCU를 실행하기 위해 프로젝트 파일을 디버그를 시도하려 할 때 이러한 경고 메시지가 뜨면서 작동이 되지 않는 경우기 있습니다.


 The program generated by "프로젝트명" is not compatible with any of the CPUs in your target configuration. The program will not be looaded.





 위의 경우를 해결하는 방법은 다음과 같습니다.



1. 해당 프로젝트에서 오른쪽 버튼을 누른 후 Properties -> General 메뉴로 들어가면 다음과 같은 화면을 보실 수 있습니다.



Main 탭에서 Connection 란이 비어있는 것을 확인하실 수 있습니다.


2. 설정되어 있지 않은 Connection을 클릭하신 후 MCU와 USB 사이에 연결하는 방식을 설정합니다.

Tiva 시리즈의 경우 "Stellaris In-Circuit Debug Interface"를 선택하시면 되겠습니다.



다음과 같이 설정하신 후 디버그를 시도하면 프로그램이 정상적으로 동작됨을 확인하실 수 있습니다.


참고 : http://e2e.ti.com/support/development_tools/code_composer_studio/f/81/t/319982.aspx

[Tiva] TM4C MCU와 ECHO UART 통신

임베디드/TI 2014.08.27 21:30

 Tiva MCU를 활용하여 UART의 RX와 TX의 동작을 간단하게 확인할 수 있는 코드입니다.

 MCU가 키보드로부터 입력받은 값을 다시 TX로 출력하는 코드입니다.



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
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
 
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
void ConfigureUART(void) {
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
 
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
    UARTStdioConfig(0, 115200, 16000000);
}
 
int main(void) {
    unsigned char getChar;
    ROM_FPULazyStackingEnable();
    ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
    SYSCTL_OSC_MAIN);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
 
    ConfigureUART();
    while (1) {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
        SysCtlDelay(SysCtlClockGet() / 10 / 3);
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
        SysCtlDelay(SysCtlClockGet() / 10 / 3);
 
        getChar = UARTCharGet(UART0_BASE);
        if(getChar=='\r'){
            UARTCharPut(UART0_BASE, '\n');
            UARTCharPut(UART0_BASE, '\r');
        }else{
            UARTCharPut(UART0_BASE, getChar);
        }
    }
}



 위의 코드를 적용한 후 Port 통신을 실행하여 키보드로 값을 입력하면 그 값을 그대로 컴퓨터로 다시 전송하여 값을 출력한다.




  • 2016.05.20 11:36 ADDR 수정/삭제 답글

    비밀댓글입니다

    • Justin T. 2016.05.20 20:01 신고 수정/삭제

      죄송합니다. 원칙상 비밀글에는 답변을 해 드리지 않습니다. 그리고 해당 포스팅과 관련되지 않은 글은 방명록을 통해서만 답변드립니다.

[Tiva] I2CMasterDataGet()

임베디드/TI 2014.08.26 00:23

 uint32_t I2CMasterDataGet(uint32_t ui32Base)

 설명 : I2C 통신을 통해 Slave로부터 받아온 값을 return값으로 받습니다.


 uint32_t ui32Base

 Slave와 통신을 했던 I2C의 Base Address를 설정합니다.


 위 함수를 사용하기 위해 I2CMasterControl() 함수를 사용하에 Slave로부터 값을 받아야 합니다.


 다음은 위의 함수를 실행하기 위한 코드와 그 결과입니다.



unsigned int rcv = 0;

ROM_I2CMasterSlaveAddrSet(I2C0_BASE, 0xE0 / 2, true);

ROM_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);

rcv = ROM_I2CMasterDataGet(I2C0_BASE);


while (ROM_I2CMasterBusy(I2C0_BASE)) {


}



① : START

② : Slave address
7비트로 전송된 Slave의 address값은 7비트이므로 0xE0 / 2 입니다.

③ : R/S
HIGH 상태이므로 SLAVE로부터 DATA를 전달받게 됩니다.

④ : ACK

⑤ : DATA
Slave로부터 DATA를 전달받습니다. 전달받게된 DATA의 값은 0x00입니다.

⑥ : ACK

⑦ : STOP


[Tiva] I2CMasterControl()

임베디드/TI 2014.08.25 23:58

 void I2CMasterControl(uint32_t ui32Baseuint32_t ui32Cmd)

 설명 : I2C 통신시 Master의 동작을 설정하는 함수입니다.

 

 uint32_t ui32Base

 I2C 통신을 하게 될 Master의 Base Address를 설정합니다.


 uint32_t ui32Cmd

 I2C 통신을 하게 될 Master가 하게 될 동작을 설정합니다. 이 인자의 경우 다음과 같은 값들을 입력하실 수 있습니다.


I2C_MASTER_CMD_SINGLE_SEND

I2C_MASTER_CMD_SINGLE_RECEIVE

I2C_MASTER_CMD_BURST_SEND_START

I2C_MASTER_CMD_BURST_SEND_CONT

I2C_MASTER_CMD_BURST_SEND_FINISH

I2C_MASTER_CMD_BURST_SEND_ERROR_STOP

I2C_MASTER_CMD_BURST_RECEIVE_START

I2C_MASTER_CMD_BURST_RECEIVE_CONT

I2C_MASTER_CMD_BURST_RECEIVE_FINISH

I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP

I2C_MASTER_CMD_QUICK_COMMAND

I2C_MASTER_CMD_HS_MASTER_CODE_SEND


 이들 중 빈번하게 사옹되는 것으로 다음과 같은 값들이 있습니다.


 I2C_MASTER_CMD_SINGLE_SEND

 Master가 Slave에게 명령어를 전달하는 모드입니다.


 I2C_MASTER_CMD_SINGLE_RECEIVE

 Master가 Slave로부터 명령어를 전달받는 모드입니다.


 I2C_MASTER_CMD_BURST_SEND_START

 Master가 Slave에게 명령어를 전달하는 모드입니다. 위의 I2C_MASTER_CMD_SINGLE_SEND와 달리 바로 명령어를 전달하지 않고 일단 Slave에게 명령어를 전달하겠다는 설정만 합니다.


 I2C_MASTER_CMD_BURST_SEND_CONT

 위의 I2C_MASTER_CMD_BURST_SEND_START를 실행한 후 Slave에게 입력할 명령어를 전달합니다.


 I2C_MASTER_CMD_BURST_SEND_FINISH

 Slave에게 마지막 명령어를 전달한 후 I2C 통신을 종료합니다.


 I2C_MASTER_CMD_BURST_RECEIVE_START

 I2C_MASTER_CMD_BURST_RECEIVE_CONT

 I2C_MASTER_CMD_BURST_RECEIVE_FINISH


 Master가 Slave로부터 명령어를 전달받는 모드로 SINGLE모드와 BURST 모드의 차이는 위의 SEND와 유사합니다.


다음은 SINGLE 모드와 BURST 모드로 I2C통신시 파형을 나타냅니다.


SINGLE_SEND


ROM_I2CMasterSlaveAddrSet(I2C0_BASE, 0xE0 / 2, false);

ROM_I2CMasterDataPut(I2C0_BASE, 0x7E);

ROM_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);


while (ROM_I2CMasterBusy(I2C0_BASE)) {


}




BURST_SEND


ROM_I2CMasterSlaveAddrSet(I2C0_BASE, 0xE0 / 2, true);

ROM_I2CMasterDataPut(I2C0_BASE, 0x02);

ROM_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_START);


while (ROM_I2CMasterBusy(I2C0_BASE)) {


}


ROM_I2CMasterDataPut(I2C0_BASE, 0xFF);

ROM_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_BURST_SEND_FINISH);


while (ROM_I2CMasterBusy(I2C0_BASE)) {


}









[Tiva] tm4c 시리즈 MCU로 TextLCD(CLCD) 동작

임베디드/TI 2014.08.21 02:30

 MCU로 프로그램을 실행할 때 자신이 확인하고 싶은 값을 보기 위해서 주로 UART통신 또는 TextLCD에 값을 띄워보는 방법이 있습니다.

 MCU가 컴퓨터와 항상 연결되어 있을 때엔 당연히 UART를 통해 원하는 값을 모니터에 출력하는 것이 가능합니다. 그러나 일반적으로 MCU를 응용하시는 분들께서는 컴퓨터와 연결하여 사용하는 경우는 많지 않으실 겁니다. 이럴 때 가장 좋은 방법이 TextLCD를 활용하는 것이지요.


 자신이 원하는 값이 숫자와 같은 수치라면 FND를 사용하는 방법또한 있습니다만 FND의 경우 원하는 값을 얻기애 연결해야 하는 핀의 수가 TextLCD보다 상대적으로 많이 사용되는 편이기도 합니다. 심지어 TextLCD는 텍스트 값 또한 출력이 가능하기 때문에 간단한 수치를 확인하는 목적 이상을 원한다면 TextLCD를 사용하는 쪽이 바람직할 듯 합니다.


 가장 많이 사용되는 TextLCD는 2 X 16일 겁니다. 인터넷 상에서도 Atmega128을 기반으로 한 소스코드도 쉽게 구할 수 있어 생각보다 번거롭지 않게 TextLCD에 값을 출력하실 수 있을 것입니다.


 아래의 코드는 Atmega128에서 많이 사용되는 코드를 TivaWare를 활용하는 MCU에서 바로 사용할 수 있게 작성되었습니다.



참고로 회로는 다음과 같이 연결하시면 되겠습니다.

RS    = A6,    RW    = GND,    EN    = A7

데이터0~7    = B0 ~ B7


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
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
 
void EnablePulse(void) {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN_7);
    SysCtlDelay(SysCtlClockGet() / 1200);
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0);
}
 
void sendLCDcommand(unsigned char command) {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, 0);
    GPIOPinWrite(GPIO_PORTB_BASE, 0xFF, command);
    EnablePulse();
    SysCtlDelay(SysCtlClockGet() / 1200);
}
 
void InitLcd(void) {
    SysCtlDelay(SysCtlClockGet() / 10);
    sendLCDcommand(0x38);
    sendLCDcommand(0x0C);
    sendLCDcommand(0x01);
    SysCtlDelay(SysCtlClockGet() / 1200);
}
 
void sendLCDdata(unsigned char data) {
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_PIN_6);
    GPIOPinWrite(GPIO_PORTB_BASE, 0xFF, data);
    EnablePulse();
    SysCtlDelay(SysCtlClockGet() / 1200);
 
}
 
void displayStr(char *str){
    while(*str){
        sendLCDdata(*str);
        str++;
    }
}
 
void setLocate(int x, int y){
    unsigned char addr;
    if(x==0)
        addr = 0x80+y;
    else
        addr = 0xC0+y;
    sendLCDcommand(addr);
}
 
void setLcdShift(char a){
    unsigned char shift;
    //0 == Left    1 == Right
    if(a==0)
        shift = 0x18;
    else if(a==1)
        shift = 0x1C;
    sendLCDcommand(shift);
    SysCtlDelay(SysCtlClockGet() / 10);
}
 
int main(void) {
 
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
 
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE,
            GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4
                    | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
 
    GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7, 0x00);
    GPIOPinWrite(GPIO_PORTB_BASE,
            GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4
                    | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7, 0x00);
 
 
    InitLcd();
    setLocate(0,1);
    displayStr("Hello, World!");
    setLocate(1,0);
    displayStr("http://elecs.tistory.com/");
 
    while (1) {
        setLcdShift(0);
    }
}
 


해당 코드를 런치패드에 실행시키면 CLCD에 다음과 같은 값이 출력됨을 확인하실 수 있습니다.



[Tiva]startup_ccs.c 파일에 외부 인터럽트 추가하기

임베디드/TI 2014.08.09 22:33

 Tiva C 기반의 MCU로 외부 인터럽트를 설정할 때 일반적으로 메인함수에서 IntRegister()와 같이 해당 인터럽트가 발생하였을 때 실행할 함수를 직접 설정하는 방법이 있습니다. 이 방법 이외에 인터럽트 함수를 등록할 수 있는 방법이 하나 존재합니다!

 프로젝트 내부에 있는 startup_ccs.c 파일에 인터럽트 함수명을 설정해두면 main() 함수에서 정의를 하지 않아도 해당 함수를 인터럽트로 바로 사용하실 수 있습니다.



프로젝트에서 startup_ccs.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
#include <stdint.h>
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
 
extern void Timer0IntHandler(void);
extern void Timer1IntHandler(void);
 
#pragma DATA_SECTION(g_pfnVectors, ".intvecs")
void (* const g_pfnVectors[])(void) =
{
    (void (*)(void))((uint32_t)&__STACK_TOP),
                                            // The initial stack pointer
    ResetISR,                               // The reset handler
    NmiSR,                                  // The NMI handler
    FaultISR,                               // The hard fault handler
    //--------코드 생략--------//
    Timer0IntHandler,                       // Timer 0 subtimer A
    IntDefaultHandler,                      // Timer 0 subtimer B
    Timer1IntHandler,                       // Timer 1 subtimer A
    IntDefaultHandler,                      // Timer 1 subtimer B
    IntDefaultHandler,                      // Timer 2 subtimer A
    IntDefaultHandler,                      // Timer 2 subtimer B
    //--------코드 생략--------//
    IntDefaultHandler,                      // PWM 1 Generator 0
    IntDefaultHandler,                      // PWM 1 Generator 1
    IntDefaultHandler,                      // PWM 1 Generator 2
    IntDefaultHandler,                      // PWM 1 Generator 3
    IntDefaultHandler                       // PWM 1 Fault
};


위의 함수에서 extern void는 사용하게 될 인터럽트의 명칭들입니다.

그리고 아래는 등록하고자 하는 코드들의 모임입니다.


extern void로 Timer0IntHandler()와 Time1IntHandler() 함수를 다음과 같이 입력한 후

아래 주석 부분에 자신이 해당 코드를 실행하고자 하는 인터럽트 부분에 함수명을 적어주면 됩니다.


이 과정을 거치신 후 프로그램을 실행하시면 인터럽트가 원활하게 동작되는 것을 확인하실 수 있습니다.

[Tiva] I2CMasterSlaveAddrSet()

임베디드/TI 2014.08.01 21:02

I2CMasterSlaveAddrSet(uint32_t ui32Base, uint8_t ui8SlaveAddr, bool bReceive)


 이 함수는 MCU가 I2C 통신을 개시하기 전에 통신할 Slave의 주소값을 설정한 후 통신을 개시할 때 쓰는 함수이다.


uint32_t ui32Base

첫 번째 인자는 I2C 통신을 하게 될 Master 의 Base Address이다.


uint8_t ui8SlaveAddr

두 번째 인자는 I2C 통신시 전달할 Slave의 Address이다. 이 때 Slave의 Address값은 7bit값이어야 한다.

시중에 있는 I2C 통신의 DataSheet에서 설정되어 있는 주소는 일반적으로 8비트로 구성되어있는데

이는 해당 8비트 주소의 오른쪽 끝부분이 R/S를 설정하는 부분이기 때문이다.

DataSheet에 설정된 Address를 사용할 경우 실제 Slave의 Address를 오른쪽으로 비트이동을 하면 된다. 간단하게 ui8SlaveAddr / 2를 하면 쉽게 적용할 수 있다.


bool bReceive

세 번째 인자는 I2C 통신시 Slave에게 하고자 하는 R/S를 설정합니다.

true - R(Slave로부터 데이터를 읽어옵니다.)

false - S(Slave에 값을 저장합니다.)



다음은 해당 함수를 적용한 소스코드와 결과이다.


ROM_I2CMasterSlaveAddrSet(I2C0_BASE, 0xE0 / 2, false);

ROM_I2CMasterDataPut(I2C0_BASE, 0x7E);

ROM_I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);


while (ROM_I2CMasterBusy(I2C0_BASE)) {


}




① : SLAVE의 ADDRESS 주소

② : R/S

③ : SLAVE의 ACK

④ : R의 경우 = Master가 Slave로부터 전달되는 값을 읽음

S의 경우 = Master가 Slave에게 값을 전달함

⑤ : Master의 ACK


[Tiva] TM4C의 I2C 통신 파형 보는 방법

임베디드/TI 2014.07.28 21:50

 I2C 통신을 처음 입문하는 분들은 종종 파형의 원리를 깨닫지 못해 많이 해메는 경우가 많습니다. 코드 상으로는 감이 오지 않는 I2C 통신을 오실로스코프를 통해 파형을 확인해보면 그 원리를 쉽게 알 수 있습니다.




 위 사진은 오실로스코프에 찍은 I2C 통신중인 파형이고 노란색은 SDA, 파란색은 SCL입니다. 아래는 I2C 회로를 설계하는데 참고할 수 있는 데이터시트의 파형입니다.


 위 사진의 파형을 쉽게 구분할 수 있게 7단계로 나누었고 그에 대한 각각의 부분은 다음과 같이 설명할 수 있습니다.


① : START

SCL이 HIGH 상태일 때 SDA가 HIGH에서  LOW로 변하는 것으로 I2C 통신을 개시합니다.


② : Slave address

Master가 통신하기 원하는 Salve address 주소를 전송합니다. 1번째부터 7번째 SCL의 edge 클록에서의 7비트가 Slave Address 주소입니다.


③ : R/S

Master가 Salve 에서 할 동작을 설정합니다. HIGH일 때는 Slave로부터 데이터를 전달받고 LOW일 때는 Slave에 데이터를 전송합니다.


④ : ACK

Slave가 Master에게 데이터를 제대로 전송하였음을 확인하는 신호입니다. Slave가 데이터를 완벽히 수신하였을 때 SDA의 값을 LOW로 끌어내려 SCL에 edge 클록이 들어올 때 까지 고정시키다가 값이 제대로 전달되면 SDA를 놓아줍니다다.


⑤ : DATA

R/S에서 설정 대로 데이터를 보내거나 받는다. 데이터 값은 8비트입니다.


⑥ : ACK

Master가 Slave에게 보내는 ACK 신호입니다.


⑦ : STOP

SCL이 HIGH 상태일 때 SDA가 LOW에서 HIGH로 변하는 것으로 I2C 통신을 종료합니다.


  • 임베어려워 2017.06.05 10:52 ADDR 수정/삭제 답글

    안녕하세요? 혹시 2개의 TM4C 보드를 이용해서 I2C 통신으로 한쪽은 마스터 한쪽은 슬레이브로 해서
    회로 구성하려고 하는데 각 보드에 소스 하나씩 올려놔야 되는건 알겠는데...
    어떻게 I2C 구성을 해야할 지 감이 안와 도움이 필요합니다 ㅜㅜ
    혹시 관련 프로젝트 경험해 본적이 있으신가요?

    • Justin T. 2017.06.05 12:40 신고 수정/삭제

      각 mcu별로 slave와 master 설정 해주시고 소스코드로 둘을 구분하여 구현하셔야 할겁니다.
      저의 경우 mcu가 마스터이고 제어 대상인 센서들이 slave인 구성의 프로젝트를 진행한 바 있습니다.
      i2c의 경우 관련 데이터시트를 보시면 설명이 자세히 되있을 것입니다.

    • 임베어려워 2017.06.14 12:29 수정/삭제

      답변감사합니다. 늦게 확인했네요 제가 ㅠ
      혹시 두 보드간 회로 구성은 완료한거(?) 같고 각 보드에 맞게 코드를 구성해서 보드에 올려놓고 실행했는데 (pc 2대로...각각의 tera term에서) 마스터에선 계속 데이터를 보내는데 슬레이브에서 못받는 느낌이라...혹시 봐주실수 있을까요??(메일 주소라도 알려주시면 너무너무나도 감사하겠습니다 ㅜㅜ)

    • Justin T. 2017.06.14 13:01 신고 수정/삭제

      전문가 분들께 도움을 받으시면 더 쉽게 해결하실 수 있을겁니다.
      http://e2e.ti.com/
      영어 좀 되신다면 큰 도움 되실겁니다!

[Tiva] TM4C 시리즈에서 외부인터럽트 구현

임베디드/TI 2014.07.26 22:09

 MCU를 활용하는 사람이면 거의 대다수가 맨 처음 프로그램을 구동할 때GPIO(General Purpose Input Output)를 구현하여 동작을 확인하는 경험을 해보셨을 것이라 생각합니다. TI에서 제공하는 Tiva C 시리즈인 TM4C MCU 시리즈 또한 이를 잘 구현해 놓았지요.


 ATmega시리즈로 순식간에 인터럽트를 설정하시던 분들도 Tiva 시리즈를 다룰 때 다소 해메시는 분들도 계실것이라 생각합니다. 하지만 그렇다고 처음부터 겁을 먹을 필요는 없습니다. 코드로 표현하는 방식이 다를 뿐 다른 MCU들 처럼 구현할 수 있는 기능은 똑같으니 말이지요.


 이번에는 MCU 프로그램의 필수 요소라 할 수 있는 Interrupt를 구현해보도록 하겠습니다. 인터럽트와 관련이 있는 부분은 직접 주석으로 적어두었으므로 하나씩 읽으면서 익혀두셨으면 합니다.

 

 단, 처음에 Input으로 설정한 핀을 그대로 입력하고자 하는 곳에 꽃게 되면 플로팅 상태가 되기 때문에 입력값이 들쭉날쭉 하는 현상이 벌어집니다. 플로팅 상태의 입력을 안정하게 하는 방법은 다음 포스트를 참고해주시길 바랍니다.

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
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
 
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
 
    //자신이 설정하고자 하는 인터럽트 핸들러를 설정한다.
void INT_IntHandler(void) {
    ROM_IntDisable(INT_GPIOA);
    GPIOIntClear(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_6);
 
    UARTprintf("Hello, Interrput!\n");
    ROM_IntEnable(INT_GPIOA);
}
 
 
void ConfigureUART(void) {
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
 
    //
    // Enable UART0
    //
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
 
    //
    // Configure GPIO Pins for UART mode.
    //
    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
 
    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
 
    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, 16000000);
}
 
int main(void) {
 
    //
    // Enable lazy stacking for interrupt handlers. This allows floating-point
    // instructions to be used within interrupt handlers, but at the expense of
    // extra stack usage.
    //
    ROM_FPULazyStackingEnable();
 
    //
    // Set the clocking to run directly from the crystal.
    //
    ROM_SysCtlClockSet(    SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
 
    //INTERRUPT를 사용할 GPIO핀을 활성화 시킨다.
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
 
    // Initialize the UART.
    ConfigureUART();
 
    //인터럽트를 받아들일 핀을 Input으로 설정한다.
    ROM_GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_6);
 
    //인터럽트되는 핀의 입력 형태를 선택한다. LOW에서 HIGH 상태로 넘어갈 때 인터럽트를 발생시키고자 하면
    //GPIO_RISING_EDGE를 선택한다.
    ROM_GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_6, GPIO_RISING_EDGE);
 
    //PORTA의 GPIO 인터럽트를 허용한다.
    GPIOIntEnable(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_6);
 
    //PORTA에서 인터럽트가 발생하였을 때 실행할 함수를 설정한다.
    GPIOIntRegister(GPIO_PORTA_BASE, INT_IntHandler);
 
    //인터럽트가 시작되기 전 Clear 시켜준다.(인터럽트 관련 레지스터를 0으로 만든다.)
    GPIOIntClear(GPIO_PORTA_BASE, GPIO_PIN_4 | GPIO_PIN_6);
 
    ROM_IntEnable(INT_GPIOA);
 
    while (1) {
    }
}


4번 핀과 6번 핀에 HIGH_EDGE 입력이 들어오면 mcu에서 인터럽트가 발생하여 설정된 함수를 실행한다.



  • 유수민 2015.07.12 20:39 ADDR 수정/삭제 답글

    안녕하세요 글 잘보고있습니다. 다름이 아니라 같은 gpio에 rising edge와 falling edge 일 때 타이머카운트 값을 읽고 싶습니다.
    그럴땐 어떻게 해야하나요? 우선 초기화 부분에서
    ROM_GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_RISING_EDGE);
    ROM_GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_FALLING_EDGE);
    이런식으로 falling엣지 모드를 추가 해주었구요
    if(mode==0)
    {
    now_count = gCount;
    mode=1;
    }
    else
    {
    pre_count=gCount;
    mode=0;
    }
    duty_count = now_count - pre_count;
    이런 식으로 라이징 엣지 걸렷을때랑 폴링엣지 걸렸을 때를 mode로 나눠주어 그 때의 타이머 카운트 값을 서로 빼준식으로 둘의 차이를 구하려고 하는데
    값이 잘 안나오네요 이렇게 하는거 맞나요?

  • 유수민 2015.07.12 22:44 ADDR 수정/삭제 답글

    질문하나더요! tm4c123 쓰는데요 타이머 카운터수 말고 내부타이머카운터수를 이용해서 pwm 간격을 측정하고 싶은데 어떤 레지스터를 사용해야 하나요?

  • Justin T. 2015.07.13 01:01 신고 ADDR 수정/삭제 답글

    다음과 같이 초기화를 해주시면 원하시는 방식대로 동작될 것으로 보입니다.
    ROM_GPIOIntTypeSet(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_BOTH_EDGE);

    그리고 레지스터와 관련된 부분은 해당 마이크로컨트롤러의 DataSheet를 직접 찾아서 보시는 것을 권장드립니다.
    http://pdf1.alldatasheet.com/datasheet-pdf/view/543230/TI/TM4C123GH6PM.html

  • 유수민 2015.07.13 17:18 ADDR 수정/삭제 답글

    답변감사드립니다. 내부카운터 쓰는것은 레지스터 찾아서 했는데요.SysClock1 = TimerValueGet64(TIMER1_BASE); 이런식으로 카운터 수를 얻었습니다.
    문제가 오버플로우가 생겨서 원하는 값이 일정시간에 얻을 수없었습니다. 그래서 내부카운터수를 리셋시켜주고싶은데 아무리찾아봐도 그런기능은 없는거 같아서요
    어떻게 해결해야할지 알려주실수있나요?

  • Justin T. 2015.07.13 20:13 신고 ADDR 수정/삭제 답글

    설계를 바꾸는 것이 좀 더 쉬운 접근이 될 거 같습니다.
    아무래도 PWM의 rising edge와 falling edge 간의 간격을 측정하시는 것을 원하시는 것으로 보이는데
    rising edge의 순간에서의 timer 값과 falling edge의 순간에서의 timer 값을 따로 받으신 후 그 차이를 계산하는 쪽을 해보셨는지요?
    Tivaware의 API를 보시면 레지스터를 reset 하는 기능이 있을 수 있으니 자세히 읽어보셨으면 합니다.

  • 유수민 2015.07.13 22:24 ADDR 수정/삭제 답글

    네 따로 받아서 차이를 계산했습니다. 리셋기능을 모두 사용해보았지만 되질않아서요 .. ㅠㅠ

  • Justin T. 2015.07.13 22:31 신고 ADDR 수정/삭제 답글

    흠.. 혹시 영어가 되신다면 TI e2e나 stackoverflow에 문의해보셨으면 합니다.
    지금 당장은 Debug 모드로 한 줄씩 검토하며 안되는 부분을 직접 찾아보셨으면 합니다.

  • 유수민 2015.07.13 23:06 ADDR 수정/삭제 답글

    예 알겠습니다. 귀찮으셧을텐데 친절히 답변해주셔서 감사합니다.

  • 유수민 2015.07.15 01:06 ADDR 수정/삭제 답글

    죄송한데 질문하나만 더 해도 될까요? gpio외부인터럽트와 uart인터럽트가 서로 충돌을 합니다. 인터럽트 우선순위도 정해주었습니다. 하지만 작동이 되질 않네요ㅜㅜ
    혹시 이럴때는 어떻게 해주어야 하는지 아시면 자문을 여쭤봐도 될까요? 물어볼데가 없어서 이렇게 매번 귀찮게 해드려서 죄송합니다. ㅠㅠ

  • Justin T. 2015.07.15 01:16 신고 ADDR 수정/삭제 답글

    질문이 구체적이지 않아 상황이 어떠한지 잘 파악이 되지 않는군요..
    GPIO와 UART 포트가 MCU나 LaunchPad상의 설계구조 때문으로 추측됩니다.
    아마도 LaunchPad의 DataSheet를 참조하시면 회로도를 보실 수 있는데 여기서 힌트를 얻으실 수 있을 것으로 보입니다.
    그리고 왠만한 해결방법은 해당 기기에 첨부된 DataSheet를 꼼꼼히 읽어보시면 자신이 어느 부분에서 잘못되었는지를 찾으실 수 있습니다. 위에서 말씀드렸듯이 TI e2e 쪽의 전문가들의 자문이 좀 더 도움이 되실것이라고 생각합니다.
    https://e2e.ti.com/support/microcontrollers/tiva_arm/

  • JG 2016.05.18 21:18 ADDR 수정/삭제 답글

    안녕하세요 외부 인터럽트 관련 질문이있습니다.
    센서들을 외부 인터럽트로 설정한 후 그 센서 값들을 텍스트 혹은 dat 파일로 설정해서 받는 방법이 있을까요?

    • Justin T. 2016.05.19 00:34 신고 수정/삭제

      저장되는 매체가 무엇이냐에 따라 방벙은 다양합니다.
      만약 pc에 저장되는 것이라면 uart를 통해 피씨에 전송한 후 이를 피씨에서 수신하여 파일로 저장해주는 프로그램을 따로 만들어주셔야 할 듯 합니다.