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

임베디드/TI 2014. 9. 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

300x250

숨겨진 Activity 혹은 Fragment의 Thread를 종료시키는 방법

 요즘 나오는 안드로이드 앱의 구성을 보면 여러개의 Fragment를 사용하여 Action Activity나 PagerView Activity를 활용하는 경우가 많습니다. 위의 Activity를 적절히 사용하면 몇 줄 안되는 코드로 화려한 화면 연출을 구성할 수 있기 때문이겠죠.

 그러나 안드로이드 개발 초보자들의 경우 위의 구성을 한 Activity와 Fragment의 동작 원리를 잘 이해하지 못할 경우 앱이 원하는 대로 동작을 하지 않는 경우가 수두룩 합니다. 특히 Fragment 내의 Thread를 활용하던 중 갑자기 앱이 죽어버리는 광경을 많이 보셨을 것이라 생각합니다.


 


 위에 보시는 화면은 Fragment를 활용하여 Tab과  Pager를 적용한 어플리케이션입니다. 보시는 바와 같이 4개의 탭이 존재하고 각 탭마다 고유의 Fragment를 가지고 있습니다.

 위의 화면으로 보기에는 첫 번째 'Simple'의 Fragment만이 동작을 하는 것 처럼 보이지만 사실은 보이는 탭을 중심으로 왼쪽과 오른쪽의 Fragment 또한 동작을 하고 있는 상황입니다. Pager 형식으로 화면으로 오른쪽에서 왼쪽으로 드래그를 하면 Contacts의 Fragment 화면으로 넘어가게 되는데요. 이는 'Simple'의 Fragment가 떠 있는 상황에도 'Contacts'의 Fragment가 미리 로딩이 되어 자신의 Fragment로 넘어가기를 기다리기 때문에 바로 뜰 수 있는 것이지요.


 Fragment의 이러한 점은 상당히 합리적인 듯 하지만 만약 Fragment에서 메인 핸들러를 활용하여 Fragment의 UI를 계속 바꾸어 주고 있는 상황이면 어떻게 될까요? 해당 Fragment가 다른 Fragment로 전환되는 순간 자신의 Fragment에 돌리던 Thread가 종료되지 않고 계속 동작을 하다가 Fragment의 UI를 수정하는 작업에 접근하게 되고 이로인해 숨겨진 Fragment의 UI를 건드릴 경우 앱이 죽어버리는 일이 벌이집니다!


 그렇다면 해당 Thread를 어떻게 처리하면 좋을지의 방안을 생각해보면 다음과 같은 해결책을 세울 수 있습니다.


 1. Fragment 화면이 넘어가게 될 때 Thread에 Interrupt를 걸어준다.

 - 위의 방안대로 수행하게 되면 Fragment가 숨겨짐과 동시에 Thread에 인터럽트가 걸리면서 Thread가 종료됨을 볼 수 있습니다. 코드는 다음과 같이 작성해 주시면 되겠습니다.


1
2
3
4
public void onStop(){
        super.onStop();
        U.interrupt();
    }


 하지만 분명 이렇게 Thread에 Interrupt를 걸어 종료시켰음에도 불구하고 Fragment의 UI를 건드려 앱이 죽어버립니다. 이는 UI 핸들러의 Message가 Queue 방식의 구조로 되어 있어 Queue에 UI와 관련된 작업의 Message가 남아 있을 경우 Thread가 종료되었음에도 UI의 동작에 접근하게 되는 상황이 발생합니다. 이에 대한 대처 방식으로 다음과 같은 방안을 다시 마련할 수 있습니다.


 2. Flag 방식을 사용하여 UI를 건드리는 Handler의 Message를 막는다.

 - 위의 코드에서 Flag만 추가해주시면 됩니다. 


1
2
3
4
5
public void onStop(){
        super.onStop();
        state = "DeActive";
        U.interrupt();
    }


 다음은 Fragment의 Thread를 종료시키고 UI와 관련된 작업도 중단시키는 방식에 대해 다룬 코드입니다. 이렇게 설계한다면 숨겨진 Fragment의 UI와 간섭할 일을 최소한으로 줄이실 수 있을 것입니다.



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
public class FragmentTab3 extends Fragment {
    UIThread U;
 UIHandler u;
    String state;
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
 
        u = new UIHandler();
 
        View rootView = inflater.inflate(R.layout.fragmenttab3, container,
                false);
        
        state = "Active";
        U = new UIThread();
        U.start();
 
        return rootView;
    }
    
    private class UIThread extends Thread{
        Message msg;
        boolean loop = true;
 
        public void run() {
            try {
                while (loop) {
                    Thread.sleep(100);
 
                    if(Thread.interrupted()){ //인터럽트가 들어오면 루프를 탈출합니다.
                        loop = false;
                        break;
                    }
                    
                    msg = u.obtainMessage();
                    msg.arg1 = 1;
 
                    u.sendMessage(msg);
                }
 
            } catch (InterruptedException e) {//sleep 상태에서 인터럽트가 들어오면 exception 발생
                // TODO Auto-generated catch block
                loop = false;
            }
 
        }
    }
 
    private class UIHandler extends Handler {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.arg1) {
            case 1:
                if(state.equals("DeActive")) //Fragment가 숨겨진 상태일 때
                    break;
                //Fragment의 UI를 변경하는 작업을 수행합니다.
            }
        }
    }
    
    public void onStop(){
        super.onStop();
        state = "DeActive";
        U.interrupt();
    }
    
    public void onResume(){
        super.onResume();
        state = "Active";
    }


300x250

[JAVA] 간단한 파일 입출력(FILE I/O) 구현

프로그래밍 팁 2014. 9. 10. 01:13

 자바로 프로그래밍을 하시는 분들이라면 가끔 파일 입출력(File I/O)를 써 줘야할 때가 간혹 발생할 겁니다.

평소엔 잘 쓰지도 않던 것인데 갑작스럽게 사용하게 되면 사용법이 헷갈려서 헤매는 경우도 많지요.


 아래는 JAVA 환경에서 간단하게 구현해 본 파일 입출력입니다. 프로그램은 먼저 FileOutputStream을 통해 파일을 기록한 후 해당 파일을 다시 FileInputStream을 통해 읽어 들이는 구조로 되어 있습니다.


※ 파일 입출력을 위해 사용된 PrintStream 클래스와 BufferedReader 클래스의 경우 새로 선언되더라도 가비지 컬렉터로 바로 사라지지 않습니다. 해당 클래스를 모두 사용한 후 반드시 close() 함수를 통해 해당 스트림을 종료하셔야 합니다.


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
public static void main(String[] args) {
        // TODO Auto-generated method stub
        File file;
        
        try {
            file = new File("file.txt");
            
            PrintStream ps = new PrintStream(new FileOutputStream(file));
            PrintStream stdout = System.out;
            System.setOut(ps);
            System.out.print("Hello, World!\n http://elecs.tistory.com/");
            ps.close();
            
            BufferedReader br = new BufferedReader(new FileReader(file));
            System.setOut(stdout);
            String str;
            while(true){
                str = br.readLine();
                if(str==null)
                    break;
                System.out.println(str);
            }
            br.close();
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }




프로그램을 실행하면 다음과 같이 프로젝트 폴더 내에 file.txt 파일이 생성된 것을 확인하실 수 있습니다.



생성된 파일을 다시 읽어 다음과 같이 출력하실 수 있습니다.

300x250

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

임베디드/TI 2014. 8. 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

300x250

[Tiva] TM4C MCU와 ECHO UART 통신

임베디드/TI 2014. 8. 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 통신을 실행하여 키보드로 값을 입력하면 그 값을 그대로 컴퓨터로 다시 전송하여 값을 출력한다.




300x250

[Tiva] I2CMasterDataGet()

임베디드/TI 2014. 8. 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


300x250

[Tiva] I2CMasterControl()

임베디드/TI 2014. 8. 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)) {


}









300x250

Didn't find class "android.support.v4.view.ViewPager"

 넷상에 업로드된 안드로이드 패키지를 다운받아 빌드를 한 후 안드로이드에 실행하였을 경우 다음과 같은 오류가 발생하는 경우가 있습니다.


Didn't find class "android.support.v4.view.ViewPager"


 android.support.v4 패키지는 안드로이드가 새로운 버전에 추가된 기능(클래스)들을 이전 버전에서도 사용할 수 있도록 해주는 패키지입니다. 최근에는 안드로이드 프로젝트를 새로 만들 때 해당 프로젝트에 자동으로 로딩이 될 수 있게 해주기 때문에 따로 추가하는 등의 번거로운 과정을 덜 수 있었습니다.

 그렇다면 android.support.v4를 적용하는 방법을 알아보도록 하겠습니다.


 1. Android SDK Manager를 실행하여 Extra(가장 아랫쪽 목록)에서 Android Support Library를 설치합니다. 




2. 이클립스를 실행한 후 android.support.v4 패키지를 추가할 프로젝트를 클릭한 후 Project->Properties-> Java build Path->Libraries 를 선택합니다.



3. 위와 같은 화면이 나올 경우 오른쪽 메뉴에서 Add External JARs를 선택하여  android.support.v4 패키지를 추가합니다.

  android.support.v4 패키지는 Android SDK Tool을 설치한 폴더에 있으며 Windows 기준으로 다음 경로에서 확인하실 수 있습니다.

 C:\Program Files\Android\android-sdk\extras\android\support\v4



4.android.support.v4 패키지를 추가한 후 Order and Export 탭으로 들어간 후  android-support-v4.jar를 체크한 후 맨 위로 옮겨놓습니다.




 다음과 같이 설정하시면  android.support.v4 패키지가 적용된 프로그램이 정상적으로 동작하는 것을 확인하실 수 있습니다.

300x250

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

임베디드/TI 2014. 8. 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에 다음과 같은 값이 출력됨을 확인하실 수 있습니다.



300x250

URL을 통해 안드로이드로 xml 파일 다운로드

 안드로이드 프로그램에서 필요한 자료를 받기 위해서는 URL을 통해 해당 주소에 있는 원하는 자료를 다운로드 받아 사용할 수 있습니다.

 특히 RSS와 같이 지속적으로 갱신되는 파일의 경우 실시간으로 새로운 정보를 수신해야 하기 때문에 이를 활용해 xml 파서를 이용하기도 하지요.


 만약 용량이 큰 파일을 다운로드할 경우 프로그램이 다운로드를 완전히 마치지 않고 바로 다음 단계로 넘어가는 경우가 있습니다. 다운로드를 완전히 끝내기 위해서 자바의 Thread를 사용하였습니다. Thread의 join() 함수는 Thread가 종료될 때 까지 함수가 선언한 단계에서 다음 단계로 넘어가지 않고 기다립니다.


 아래는 rss를 다운로드 하여 String으로 객체화 시킨 예제입니다.


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
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
 
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
 
public class MainActivity extends ActionBarActivity {
    TextView textview1;
    String xml;
    URL url;
    HttpURLConnection conn;
    InputStreamReader isr;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textview1 = (TextView) findViewById(R.id.textview1);
 
        try {
            rcvXml RX = new rcvXml();
            RX.start();
            RX.join();
            textview1.setText(xml);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    class rcvXml extends Thread {
        public void run() {
            try {
                url = new URL("http://www.kma.go.kr/wid/queryDFS.jsp?gridx=60&gridy=126");
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        url.openStream(), "UTF-8"));
                xml = in.readLine();
                while(true){
                    String temp;
                    temp = in.readLine();
                    if(temp==null)
                        break;
                    xml += temp;
                }
            } catch (Exception e) {
 
            }
        }
    }
}
 
 
 


300x250

(JSON) 기상청으로부터 지역코드 받아오기

 날씨과 관련된 프로그램을 제작하는 분들이라면 기상청에서 제공하는 api가 거의 반드시 필요하실 것이라 생각합니다.

 기상청으로부터 자신이 원하는 지역의 날씨를 받아오기 위해서는 기상청에서 제공하는 RSS를 수신하여 이를 가지고 날씨를 알아낼 수 있습니다. 이를 위해서는 기상청에서 제공하는 지역코드를 통해 해당 지역의 날씨를 받아와야 하지요.

 기상청에서는 해당 지역코드를 알아내기 위해 다음과 같은 JSON파일을 제공합니다.


각 지역 시,도의 코드를 제공합니다.

http://www.kma.go.kr/DFSROOT/POINT/DATA/mdl.11.json.txt
mdl.11.json에서 11은 위에서 알아댄 시,도 코드입니다. 해당 코드를 입력하면 해당 시,도의 시군구 목록이 나타납니다.

leaf.11545,json에서 11545는 위의 과정에서 알아낸 시군구 코드입니다. 이 코드를 통해 자신이 원하는 자료를 알아내실 수 있습니다.

위의 주소로 접속할 경우 다음과 같이 알 수 없는 메시지가 나오는 경우가 있습니다.


이는 JSON파일을 읽어들이는데 인코딩 문제로 인해 나타는 경우입니다. 이를 제대로 보기 위해서 오른쪽 버튼을 클릭한 후 인코딩 → UTF-8 로 변경하시면 됩니다.





그럼 이 JSON파일을 사용하여 지역코드를 받아오는 코드를 간단하게 짜보도록 하겠습니다.


※안드로이드에서는 기본적으로 JSON을 활용하는 클래스가 설정되어 있어 간단하게 사용이 가능합니다. 순수 자바로 구현할 경우 별도의 과정이 추가로 필요합니다.

import org.json.JSONArray;

import org.json.JSONObject;



1. 먼저 JSON을 통해 인터넷에 접속하기 위해서는 안드로이드에 인터넷 접속을 허용하는 permission을 다음과 같이 추가합니다.


AndroidMenifest.xml

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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.framework.json" >
 
    <uses-permission android:name="android.permission.INTERNET" />
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>
cs


2. 다음으로 아래의 코드를 삽입해줍니다.


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
public class MainActivity extends AppCompatActivity {
    URL RSSurl = null;
    rcvJson RJ;
    URLConnection connect;
    JSONObject JStoken;
    String getJSON;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        ....
 
 
        TextView textview = (TextView) findViewById(R.id.textView);
 
        try {
            String Local1 = "서울특별시";
            String Local2 = "용산구";
            String Local3 = "서빙고동";
            String temp;
            String x="0",y="0";
            JSONArray JSA;
 
            RSSurl = new URL("http://www.kma.go.kr/DFSROOT/POINT/DATA/top.json.txt");
            RJ = new rcvJson();
            RJ.start();
            RJ.join();
            JSA = new JSONArray(getJSON);
 
            temp="";
 
            for(int i=0; i < JSA.length(); i++){
                JStoken = JSA.getJSONObject(i);
                if(JStoken.get(JStoken.names().getString(0)).equals(Local1)){
                    temp += JStoken.get(JStoken.names().getString(1));
                    break;
                }
            }
 
            RSSurl = new URL("http://www.kma.go.kr/DFSROOT/POINT/DATA/mdl."+temp+".json.txt");
            RJ = new rcvJson();
            RJ.start();
            RJ.join();
            JSA = new JSONArray(getJSON);
 
            temp="";
 
            for(int i=0; i < JSA.length(); i++){
                JStoken = JSA.getJSONObject(i);
                if(JStoken.get(JStoken.names().getString(0)).equals(Local2)){
                    temp += JStoken.get(JStoken.names().getString(1));
                    break;
                }
            }
 
            RSSurl = new URL("http://www.kma.go.kr/DFSROOT/POINT/DATA/leaf."+temp+".json.txt");
            RJ = new rcvJson();
            RJ.start();
            RJ.join();
            JSA = new JSONArray(getJSON);
 
            temp="";
 
            for(int i=0; i < JSA.length(); i++){
                JStoken = JSA.getJSONObject(i);
                x = JStoken.get(JStoken.names().getString(2)).toString();
                y = JStoken.get(JStoken.names().getString(1)).toString();
                if(JStoken.get(JStoken.names().getString(0)).equals(Local3))
                    break;
            }
 
            textview.setText(x + ","+ y);
 
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
 
 
    }
 
}
cs

1
2
3
4
5
6
7
8
9
10
11
12
class rcvJson extends Thread {
        public void run() {
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(
                        RSSurl.openStream(), "UTF-8"));
                getJSON = in.readLine();
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }


위의 소스코드를 실행하면 아래와 같은 결과를 확인하실 수 있습니다.



300x250

좌표값 위도와 경도로 위치주소 구하기

 지도 기반의 프로그램을 개발하시는 분들이라면 GPS와 같은 기능을 통해 원하는 위치의 좌표값을 구하실 수 있습니다. 안드로이드에서는 이를 활용하여 해당위치의 주소를 불러올 수 있는데요 이는 Geocoder 클래스를 사용하여 만들 수 있습니다.

 Geocoder를 활용하여 간단한 프로그램을 만들어보았습니다. 동작환경은 2.3.3 진저브레드입니다.

MainActivity.java
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
import java.io.IOException;
import java.util.List;
import java.util.Locale;
 
import android.support.v7.app.ActionBarActivity;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
 
public class MainActivity extends ActionBarActivity {
 
    TextView textview1;
    EditText edittext1, edittext2;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textview1 = (TextView) findViewById(R.id.textView1);
        edittext1 = (EditText) findViewById(R.id.editText1);
        edittext2 = (EditText) findViewById(R.id.editText2);
 
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    public void OnClick(View v){
        double lat, lng;
        String getDouble;
        switch(v.getId()){
        case R.id.button1:
            getDouble = edittext1.getText().toString();
            if(getDouble.equalsIgnoreCase("")){
                Toast.makeText(MainActivity.this"위도값을 입력하세요.", Toast.LENGTH_LONG).show();
                break;
            }else{
                lat = Double.parseDouble(getDouble);
            }
            getDouble = edittext2.getText().toString();
            if(getDouble.equalsIgnoreCase("")){
                Toast.makeText(MainActivity.this"경도값을 입력하세요.", Toast.LENGTH_LONG).show();
                break;
            }else{
                lng = Double.parseDouble(getDouble);
            }
            getLocation(lat, lng);
        }
    }
    
    public void getLocation(double lat, double lng){
        String str = null;
        Geocoder geocoder = new Geocoder(this, Locale.KOREA);
        
        List<Address> address;
        try {
            if (geocoder != null) {
                address = geocoder.getFromLocation(lat, lng, 1);
                if (address != null && address.size() > 0) {
                    str = address.get(0).getAddressLine(0).toString();
                }
            }
        } catch (IOException e) {
            Log.e("MainActivity""주소를 찾지 못하였습니다.");
            e.printStackTrace();
        }
        
        textview1.setText(str);
        
    }
    
}


activity_main.xml

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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="주소 출력" />
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
 
        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="위도" />
 
        <EditText
            android:id="@+id/editText1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="numberDecimal" >
 
            <requestFocus />
        </EditText>
 
    </LinearLayout>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
 
        <TextView
            android:id="@+id/textView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="경도" />
 
        <EditText
            android:id="@+id/editText2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="numberDecimal" />
 
    </LinearLayout>
 
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="주소확인"
        android:onClick="OnClick" />
 
</LinearLayout>


Manifest.xml에는 다음과 같이 퍼미션을 설정시켜 줍니다.

1
2
3
4
5
6
7
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <library android:name="com.google.android.maps"/>


프로그램을 실행하면 다음과 같은 결과를 얻으실 수 있습니다.


300x250