<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>AVR로 시작하는 임베디드</title>
    <link>https://embed-avr.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 13 Aug 2026 02:02:51 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor> Just4Fun</managingEditor>
    <image>
      <title>AVR로 시작하는 임베디드</title>
      <url>https://t1.daumcdn.net/cfile/tistory/2568CB3F56C3226715</url>
      <link>https://embed-avr.tistory.com</link>
    </image>
    <item>
      <title>템플릿 코드 생성 프로그램</title>
      <link>https://embed-avr.tistory.com/193</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;제법 규모가 있는 프로젝트의 경우 수많은 소스코드로 이루어져 있다.&amp;nbsp; 비단 큰 프로젝트가 아니더라도 새로운 코드를 작성할 때 완전히 빈 화면에서부터 시작하여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경우 그냥 빈화면 보다는 뭔가 미리 필요한 내용이 기본으로 들어가 있으면 전체적인 코드의 모양도 일관성 있게되고 여러명의 개발자가 공동으로 작업하게 되더라도 이질감 없이 코드를 공유하기가 쉬워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 코드 확장자에 맞는 기본 템플릿 코드를 만드는 방법을 공유하고자 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;code_gen.png&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CJ1zT/btsHSxOs1o3/ZLJh6O1IKg6tEEWsTePIO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CJ1zT/btsHSxOs1o3/ZLJh6O1IKg6tEEWsTePIO0/img.png&quot; data-alt=&quot;code generator&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CJ1zT/btsHSxOs1o3/ZLJh6O1IKg6tEEWsTePIO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCJ1zT%2FbtsHSxOs1o3%2FZLJh6O1IKg6tEEWsTePIO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;466&quot; height=&quot;273&quot; data-filename=&quot;code_gen.png&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;code generator&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림은 d:\work\c\tmp 디렉토리에 hello.h hello.cpp 파일을 생성해주는 경우이다.&amp;nbsp; cpp의 경우 class까지 같이 생성해 주려면 class name도 입력해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 선택한 다음 Create 버튼을 눌러주면 다음과 같은 파일이 생성된다.&lt;/p&gt;
&lt;pre id=&quot;code_1717752983895&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*==============================================================================
Copyright (c) 2024, Just4Fun

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
   this list of conditions and the following disclaimer in the documentation 
   and/or other materials provided with the distribution.

3. Neither the name of the Just4Fun nor the names of its contributors may be 
   used to endorse or promote products derived from this software without 
   specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

$Id: $
==============================================================================*/

#ifndef _HELLO_H_
#define _HELLO_H_

class Helloclass
{
public:
    Helloclass();
    ~Helloclass();
};

#endif /* _HELLO_H_ */

// vim:ts=8:sts=4:sw=4:et:&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hello.h&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717753034026&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* HELLO.CPP */
/*==============================================================================
Copyright (c) 2024, Just4Fun

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this 
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, 
   this list of conditions and the following disclaimer in the documentation 
   and/or other materials provided with the distribution.

3. Neither the name of the Just4Fun nor the names of its contributors may be 
   used to endorse or promote products derived from this software without 
   specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

$Id: $
==============================================================================*/

/*------------------------------------------------------------------------------
    HEADER FILE INCLUDE
------------------------------------------------------------------------------*/
#include &amp;lt;&amp;gt;

#include &quot;hello.h&quot;

/*------------------------------------------------------------------------------
    TYPEDEF &amp;amp; MACROS
------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    FUNCTION PROTOTYPES
------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    EXTERNAL VARIABLES
------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    LOCAL VARIABLES
------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    LOCAL FUNCTIONS
------------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
    EXTERNAL FUNCTIONS
------------------------------------------------------------------------------*/

Helloclass::Helloclass()
{
}

Helloclass::~Helloclass()
{
}


// vim:ts=8:sts=4:sw=4:et:&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;hello.cpp&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헤더파일에는 HelloClass라는 class의 원형이 선언되어 있고, cpp 파일에는 실제 class의 생성자와 소멸자가 기본으로 들어가 있는것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;code generator는 python으로 간단하게 만들었는데 필요한 경우 java나 python 코드 생성 기능을 추가하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cX0gYA/btsHSBpPoeK/ldBDpke3CrpQhKUMaOZUPK/code_gen.py?attach=1&amp;amp;knm=tfile.py&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;code_gen.py&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>실전</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/193</guid>
      <comments>https://embed-avr.tistory.com/193#entry193comment</comments>
      <pubDate>Fri, 7 Jun 2024 18:41:35 +0900</pubDate>
    </item>
    <item>
      <title>빌드 버전과 시간 정보 추가</title>
      <link>https://embed-avr.tistory.com/192</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;임베디드 시스템 프로그램을 개발하다 보면 실제로 임베디드용 프로그램을 개발하는 머신과 빌드된 결과물이 동작되는 머신이 다름으로 인해서 생기는 문제가 가끔씩 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 기능을 추가하거나 발견된 오류를 수정해서 타겟 보드에 실행시켰는데 예상대로 동작하지 않는 경우가 있다.&amp;nbsp; 그럴때에 코딩이 잘못되었다고 판단해서 아무리 이리저리 수정해도 전혀 개선되지 않아서 고생하는 경우가 있는데 결국 그 원인이 수정된 결과물 파일과 보드에 내린 파일이 달라서 그랬던걸 한참 뒤에서야 발견하게 되는 경우이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 이런 문제를 조금이라도 줄여 볼 수 있는 방법에 대해서 알아본다.&lt;/p&gt;
&lt;pre id=&quot;code_1717499398081&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;time.h&amp;gt;

int main(int argc, char** argv) 
{
    if (argc &amp;lt; 2)
    {
        printf(&quot;Usage: build_date &amp;lt;ver_file.c&amp;gt; [z]\n&quot;);
        printf(&quot;    z : Reset build count to zero of ver_file.c\n&quot;);
        return -1;
    }

    time_t cur_time = time(NULL);
    char build_time[128];
    strcpy(build_time, asctime(localtime(&amp;amp;cur_time)));

    // remove new line character at the end of string
    build_time[strlen(build_time)-1] = 0;

    int build_count = 0;
    char    build_str[64];

    FILE    *fp = fopen(argv[1], &quot;rt&quot;);
    if (fp)
    {
        fgets(build_str, 64, fp);
        fclose(fp);

        sscanf(build_str, &quot;/* Build [ %d ] */&quot;, &amp;amp;build_count);

        if (argc == 3 &amp;amp;&amp;amp; argv[2][0] == 'z')
            build_count = 0;
        else
            ++build_count;
    }

    if (!(fp = fopen(argv[1], &quot;wt&quot;)))
    {
        printf(&quot;Couldn't write '%s'\n&quot;, argv[1]);
        return -1;
    }

    fprintf(fp, &quot;/* Build [ %d ] */\n&quot;, build_count);
    fprintf(fp, &quot;/* Do not modify this file. */\n\n&quot;);
    fprintf(fp, &quot;int  build_count_g = %d;\n&quot;, build_count);
    fprintf(fp, &quot;char build_time_g[]  = \&quot;%s\&quot;;\n&quot;, build_time);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 위의 코드를 이용해서 실행파일을 만든다.&amp;nbsp; 여기에서는 build_date.exe 파일로 만들었다고 가정한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;build_date.png&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0f2PJ/btsHNwjj20c/cKnOn7cXxEkmFUePNYYb1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0f2PJ/btsHNwjj20c/cKnOn7cXxEkmFUePNYYb1K/img.png&quot; data-alt=&quot;build_date 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0f2PJ/btsHNwjj20c/cKnOn7cXxEkmFUePNYYb1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0f2PJ%2FbtsHNwjj20c%2FcKnOn7cXxEkmFUePNYYb1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;611&quot; height=&quot;499&quot; data-filename=&quot;build_date.png&quot; data-origin-width=&quot;611&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;build_date 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림처럼 build_date를 실행할 때마다 version.c 파일의 build_count_g의 값이 1씩 증가되고 build_time_g의 내용은 build_date를 실행하는 순간의 날짜와 시간으로 업데이트 되는것을 볼 수 있다.&amp;nbsp; 이 방법을 이용하면 타겟 보드용 프로젝트를 빌드할때마다 그 순간으로 업데이트 된 정보를 이용할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 동작되는지 간단한 윈도우 콘솔 프로그램 프로젝트를 이용해서 확인해 보도록 하겠다.&lt;/p&gt;
&lt;pre id=&quot;code_1717500695609&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BUILD_DIR := build

all: ${BUILD_DIR}

${BUILD_DIR}: cmake
	@build_date version.c
	cmake --build ${BUILD_DIR}
	@head -n 1 version.c

cmake: ${BUILD_DIR}/Makefile

${BUILD_DIR}/Makefile:
	@cmake -B${BUILD_DIR}

clean:
	@rm -rf ${BUILD_DIR}
	@echo &quot;Delete ${BUILD_DIR} directory&quot;


.PHONY: all ${BUILD_DIR} cmake clean&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 Makefile을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세히 보면 cmake --build ${BUILD_DIR} 전후로 build_date를 실행하고 새로 업데이트된 내용을 출력하는것을 볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1717501020759&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

#define MAJOR_VER   3
#define MINOR_VER   15

extern int  build_count_g;
extern char build_time_g[];

int main() 
{
  printf(&quot;Hello Program: [ %d.%d.%d ] - %s\n&quot;, 
          MAJOR_VER, MINOR_VER, build_count_g, build_time_g);

  return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 build_date에 만들어진 변수를 extern으로 불러 들여 출력하도록 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;build_date_ex.png&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oMyeo/btsHPzkUYB8/MZNzbWFdPYhnYnBUWLrccK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oMyeo/btsHPzkUYB8/MZNzbWFdPYhnYnBUWLrccK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oMyeo/btsHPzkUYB8/MZNzbWFdPYhnYnBUWLrccK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoMyeo%2FbtsHPzkUYB8%2FMZNzbWFdPYhnYnBUWLrccK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;979&quot; height=&quot;690&quot; data-filename=&quot;build_date_ex.png&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;make 명령으로 프로젝트를 빌드한 다음 만들어진 파일을 실행했을때 자동으로 빌드 정보가 업데이트가 되는것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>실전</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/192</guid>
      <comments>https://embed-avr.tistory.com/192#entry192comment</comments>
      <pubDate>Sat, 1 Jun 2024 17:12:01 +0900</pubDate>
    </item>
    <item>
      <title>cmake를 이용한 AVR 개발 환경</title>
      <link>https://embed-avr.tistory.com/191</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;주요 칩제조사들은 개발자들이 해당 칩에서 동작되는 프로그램을 쉽게 개발하도록 통합개발환경(IDE)을 무료로 혹은 일부 비용을 받고 전용 도구를 제공한다.&amp;nbsp; 그러나 칩제조사에서 만드는 대부분의 칩을 지원하도록 하기위해서 개발도구의 프로그램도 커지고 컴퓨터의 자원도 많이 필요로한다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무료로 제공되는 개발환경에 포함되는 컴파일러는 대부분 GCC 기반인 경우가 많기 때문에 전용도구 없이도 칩에서 동작되는 프로그램을 개발할수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 윈도우 OS에서 cmake를 사용해서 AVR 칩용 프로그램을 개발하는 환경을 구성하는 방법에 대해서 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 파일은 AVR용 GCC toolchain과 make, cmake, git이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 gcc를 다운받아서 설치한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;avr_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvCiK6/btsHEXnomj0/w1YESEqv20BoiFkELkk2Z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvCiK6/btsHEXnomj0/w1YESEqv20BoiFkELkk2Z0/img.png&quot; data-alt=&quot;AVR gcc download&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvCiK6/btsHEXnomj0/w1YESEqv20BoiFkELkk2Z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvCiK6%2FbtsHEXnomj0%2Fw1YESEqv20BoiFkELkk2Z0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;779&quot; data-filename=&quot;avr_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;AVR gcc download&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치하는 위치는 c:\tools 에 하는걸로 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 make 프로그램을 다운로드한 후 설치한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;make_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5SnjX/btsHGiqnhQn/tHxhzAU9YTCtm3HkTJumRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5SnjX/btsHGiqnhQn/tHxhzAU9YTCtm3HkTJumRk/img.png&quot; data-alt=&quot;make download&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5SnjX/btsHGiqnhQn/tHxhzAU9YTCtm3HkTJumRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5SnjX%2FbtsHGiqnhQn%2FtHxhzAU9YTCtm3HkTJumRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;779&quot; data-filename=&quot;make_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;make download&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림에서 binaries와 dependencies모두 다운로드해서 같은 폴더에서 압축을 풀어주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 cmake 프로그램을 설치한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cmake_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDjqhf/btsHFKOydq9/c2zCWkAby5vLzxcYJ0iA00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDjqhf/btsHFKOydq9/c2zCWkAby5vLzxcYJ0iA00/img.png&quot; data-alt=&quot;cmake download&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDjqhf/btsHFKOydq9/c2zCWkAby5vLzxcYJ0iA00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDjqhf%2FbtsHFKOydq9%2Fc2zCWkAby5vLzxcYJ0iA00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;779&quot; data-filename=&quot;cmake_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;cmake download&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 세개의 프로그램만 설치해도 되지만 윈도우에서 리눅스 명령어를 사용하기 위해서 git을 설치해 주도록 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;git_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IYD4h/btsHGvQDGLo/XYltemqIE9JOFTbh2bJzN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IYD4h/btsHGvQDGLo/XYltemqIE9JOFTbh2bJzN0/img.png&quot; data-alt=&quot;git download&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IYD4h/btsHGvQDGLo/XYltemqIE9JOFTbh2bJzN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIYD4h%2FbtsHGvQDGLo%2FXYltemqIE9JOFTbh2bJzN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;779&quot; data-filename=&quot;git_download.png&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;779&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;git download&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료된 폴더는 다음과 같은 모습이 될것이다.&amp;nbsp; 폴더명은 가급적 간편하게 수정하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;tools.png&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pgdi0/btsHEZyKMqm/c2Kb9Zco5CYdQfkNqM2Ktk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pgdi0/btsHEZyKMqm/c2Kb9Zco5CYdQfkNqM2Ktk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pgdi0/btsHEZyKMqm/c2Kb9Zco5CYdQfkNqM2Ktk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpgdi0%2FbtsHEZyKMqm%2Fc2Kb9Zco5CYdQfkNqM2Ktk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1125&quot; height=&quot;634&quot; data-filename=&quot;tools.png&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 tool의 설치가 완료되면 각각의 tool을 바로 실행될수 있도록 환경변수설정을 해주어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;env.png&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCnihr/btsHGePaau9/d2I6eGx2Lzw5VXHk6GY9Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCnihr/btsHGePaau9/d2I6eGx2Lzw5VXHk6GY9Q0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCnihr/btsHGePaau9/d2I6eGx2Lzw5VXHk6GY9Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCnihr%2FbtsHGePaau9%2Fd2I6eGx2Lzw5VXHk6GY9Q0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;475&quot; height=&quot;529&quot; data-filename=&quot;env.png&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;529&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;env_edit.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JkKPT/btsHGlm7yPS/m1VjodAakXEaulpBzBpgB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JkKPT/btsHGlm7yPS/m1VjodAakXEaulpBzBpgB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JkKPT/btsHGlm7yPS/m1VjodAakXEaulpBzBpgB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJkKPT%2FbtsHGlm7yPS%2Fm1VjodAakXEaulpBzBpgB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;614&quot; height=&quot;585&quot; data-filename=&quot;env_edit.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;path.png&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/840zD/btsHFqiu283/d6amvnryWGaB3VGR33yZK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/840zD/btsHFqiu283/d6amvnryWGaB3VGR33yZK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/840zD/btsHFqiu283/d6amvnryWGaB3VGR33yZK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F840zD%2FbtsHFqiu283%2Fd6amvnryWGaB3VGR33yZK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;524&quot; height=&quot;501&quot; data-filename=&quot;path.png&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;501&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 tool이 제대로 동작되는지 확인해 본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;check_version.png&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFqsfd/btsHESGr2Vp/sDbKLp2vK3QFYbkPp8O3Xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFqsfd/btsHESGr2Vp/sDbKLp2vK3QFYbkPp8O3Xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFqsfd/btsHESGr2Vp/sDbKLp2vK3QFYbkPp8O3Xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFqsfd%2FbtsHESGr2Vp%2FsDbKLp2vK3QFYbkPp8O3Xk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;919&quot; height=&quot;739&quot; data-filename=&quot;check_version.png&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; avr-gcc --version&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; make --version&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; cmake --version&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령을 차례대로 입력하여 각 tool의 버전이 제대로 출력되는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 tool이 제대로 설치되었으면 본격적으로 빌드 환경을 만들어 보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cmake가 동작되기 위해서는 CMakeLists.txt 파일이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 AVR 컴파일러에 대한 설정을 위한 파일이 하나 더 필요하다.&amp;nbsp; 그리고 좀더 간단한 명령으로 빌드되기 위해서 Makefile도 만들어 준다.&lt;/p&gt;
&lt;pre id=&quot;code_1716899688396&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cmake_minimum_required(VERSION 3.28)

project(sample CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

file(GLOB_RECURSE PROJECT_SRC 
    src/*.cpp)

add_executable(${PROJECT_NAME} ${PROJECT_SRC})

target_include_directories(${PROJECT_NAME} PRIVATE
    ./inc)

target_compile_definitions(${PROJECT_NAME} PRIVATE
    F_CPU=1000000)

set(CPU_PARAM 
    -mmcu=attiny85)

target_compile_options(${PROJECT_NAME} PRIVATE
    ${CPU_PARAM}
    -funsigned-char
    -ffunction-sections
    -fdata-sections
    -Og -g2
    -Wall)

target_link_options(${PROJECT_NAME} PRIVATE
    ${CPU_PARAM}
    -Wl,-Map=${PROJECT_NAME}.map
    -Wl,--start-group
    -Wl,-lm
    -Wl,--end-group
    -Wl,--gc-sections)
    
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_SIZE} $&amp;lt;TARGET_FILE:${PROJECT_NAME}&amp;gt;
    COMMAND ${CMAKE_OBJDUMP} -h -S ${PROJECT_NAME} &amp;gt; ${PROJECT_NAME}.lss
    COMMAND ${CMAKE_OBJCOPY} -O ihex $&amp;lt;TARGET_FILE:${PROJECT_NAME}&amp;gt; ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary $&amp;lt;TARGET_FILE:${PROJECT_NAME}&amp;gt; ${PROJECT_NAME}.bin)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CMakeLists.txt&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716899764736&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR avr)

set(TOOLCHAIN_PREFIX avr-)

set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}c++)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_SIZE ${TOOLCHAIN_PREFIX}size)
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump)

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;avr-gcc.make&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716899825310&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BUILD_DIR := build

all: ${BUILD_DIR}

${BUILD_DIR}: cmake
	$(MAKE) -C ${BUILD_DIR} --no-print-directory

cmake: ${BUILD_DIR}/Makefile

${BUILD_DIR}/Makefile:
	cmake \
		-G &quot;Unix Makefiles&quot; \
		-B${BUILD_DIR} \
		-DCMAKE_TOOLCHAIN_FILE=avr-gcc.cmake

clean:
	@rm -rf ${BUILD_DIR}
	@echo &quot;Delete ${BUILD_DIR} directory&quot;


.PHONY: all ${BUILD_DIR} cmake clean&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Makefile&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;AtTiny85 I2C&quot; href=&quot;https://embed-avr.tistory.com/182&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;AtTiny85 I2C&lt;/a&gt;에서 사용한 코드를 이용해서 빌드하면 다음과 같은 결과를 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;test.png&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UfBiX/btsHE92gmOQ/vcQE8YhSWSF2WGAcNaKB81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UfBiX/btsHE92gmOQ/vcQE8YhSWSF2WGAcNaKB81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UfBiX/btsHE92gmOQ/vcQE8YhSWSF2WGAcNaKB81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUfBiX%2FbtsHE92gmOQ%2FvcQE8YhSWSF2WGAcNaKB81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;919&quot; height=&quot;739&quot; data-filename=&quot;test.png&quot; data-origin-width=&quot;919&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/qSXGF/btsHEYmc07t/mpEMU52KNfKcKDSf1QUfvK/usi_cmake.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;usi_cmake.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.01MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>실전</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/191</guid>
      <comments>https://embed-avr.tistory.com/191#entry191comment</comments>
      <pubDate>Tue, 28 May 2024 21:50:14 +0900</pubDate>
    </item>
    <item>
      <title>GPS - 응용</title>
      <link>https://embed-avr.tistory.com/190</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 알아 본 TIMEUTC와 POSLLH 메시지를 분석하여 현재 시간과 위치를 출력해서 제대로 동작되는 프로그램을 만들어 볼 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;loc_tim.jpg&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXRavQ/btrX2qHnuYk/8DAfJApZvQU1JXB32oL4k0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXRavQ/btrX2qHnuYk/8DAfJApZvQU1JXB32oL4k0/img.jpg&quot; data-alt=&quot;시간, 위치 출력 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXRavQ/btrX2qHnuYk/8DAfJApZvQU1JXB32oL4k0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXRavQ%2FbtrX2qHnuYk%2F8DAfJApZvQU1JXB32oL4k0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;539&quot; height=&quot;374&quot; data-filename=&quot;loc_tim.jpg&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;시간, 위치 출력 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 보이는 그림처럼 일정한 주기로 보내주는 시간과 위치 정보를 분석하여 콘솔화면에 출력해 보는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1675426513676&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void setup()
{
    uart0.init();
    uart1.init();

    stdout = std_inout;

    _delay_ms(500);

    printf(&quot;\x1B[2J\x1B[H GPS Test Program\n&quot;);

    send_cfg_prt();
    _delay_ms(100);
    gps.cfg_msg_utc();
    _delay_ms(100);
    gps.cfg_msg_loc();

    sei();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두개의 UART를 초기화 한다음 UART0로 디버깅 메시지를 출력해주기 위해서 stdout에 대한 설정을 해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1675426643642&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static int uart_put(char c, FILE* stream)
{
    if (c == '\n')
        uart0.put_char('\r');

    uart0.put_char(c);

    return 0;
}

extern &quot;C&quot;
{
static FILE* std_inout = fdevopen(uart_put, NULL);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART 설정이 완료 되면 '$' 글자가 들어올 때까지 계속 모니터링 하다가 $가 수신되면 GPS모듈이 정상 동작 되고 있다고 판단해서 CFG-PRT 메시지를 송신한다.&lt;/p&gt;
&lt;pre id=&quot;code_1675426771238&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static void send_cfg_prt()
{
    uint8_t ch;
    while (1)
    {
        if (uart1.get_char(ch))
        {
            if (ch == '$')
                break;
        }
    }

    gps.cfg_prt();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤 이어 TIMEUTC와 POSLLH 패킷을 주기적으로 보내줄 수 있도록 CFG-MSG 패킷을 연속으로 보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPS 모듈이 이 두 메시지를 정상적으로 수신하게 되면 매초 두 메시지를 계속 보내주게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1675426953123&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void Gps::cfg_msg_utc()
{
    struct cfg_msg_msg*  msg = (struct cfg_msg_msg*)&amp;amp;gps_data[6];
    uint32_t pkt_size = sizeof(struct cfg_msg_msg);

    make_header(CLASS_CFG, CFG_MSG, pkt_size);

    msg-&amp;gt;cls_id = CLASS_NAV;
    msg-&amp;gt;msg_id = NAV_TIMEUTC;
    msg-&amp;gt;rate = 1;

    chksum(pkt_size);

    uart1.send_data(gps_data, pkt_size + 8);
}

void Gps::cfg_msg_loc()
{
    struct cfg_msg_msg*  msg = (struct cfg_msg_msg*)&amp;amp;gps_data[6];
    uint32_t pkt_size = sizeof(struct cfg_msg_msg);

    make_header(CLASS_CFG, CFG_MSG, pkt_size);

    msg-&amp;gt;cls_id = CLASS_NAV;
    msg-&amp;gt;msg_id = NAV_POSLLH;
    msg-&amp;gt;rate = 1;

    chksum(pkt_size);

    uart1.send_data(gps_data, pkt_size + 8);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPS로 부터 들어오는 데이터를 수신하기 위해서 인터럽트를 이용하도록 하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1675427013437&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ISR(_VECTOR(30))
{
    gps.rx_data(uart1.get_char());
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART1으로 들어오는 데이터를 처리하는 코드는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1675427143507&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void Gps::rx_data(uint8_t data)
{
    if (prev_data == SYNC1 &amp;amp;&amp;amp; data == SYNC2)
    {
        data_index = 0;
        remain_data = 64;   // set maximum value
    }
    else
    {
        gps_rx_data[data_index++] = data;
        if (data_index == 4) // just received payload length
        {
            remain_data = (gps_rx_data[3] &amp;lt;&amp;lt; 8) | gps_rx_data[2];
        }

        if (remain_data-- == 0)
        {
            parse_msg();
        }
    }

    prev_data = data;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 직전에 들어온 데이터가 SYNC1(0xB5)이고 지금 수신된 데이터가 SYNC2(0x62)라면 패킷의 시작이라고 판단하여 data index값을 0으로 초기화 하고 앞으로 수신될 데이터의 크기를 최대값으로 설정해 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SYNC 데이터 이후에 수신된 데이터는 gps_rx_data 배열에 차례로 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수신된 데이터가 4바이트가 되었다면 패킷의 크기까지 수신되었으므로 앞으로 수신될 패킷의 크기를 알수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 데이터까지 수신이 완료되었으면 어떤 데이터인지 분석한다.&lt;/p&gt;
&lt;pre id=&quot;code_1675427499642&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void Gps::parse_msg()
{
    if (gps_rx_data[0] == CLASS_NAV)
    {
        if (gps_rx_data[1] == NAV_POSLLH)
        {
            struct nav_posllh* msg = (struct nav_posllh*)&amp;amp;gps_rx_data[4];

            longitude = msg-&amp;gt;longitude;
            latitude  = msg-&amp;gt;latitude;

            loc_updated = true;
        }
        else if (gps_rx_data[1] == NAV_TIMEUTC)
        {
            struct nav_timeutc* msg = (struct nav_timeutc*)&amp;amp;gps_rx_data[4];

            year = msg-&amp;gt;year;
            month = msg-&amp;gt;month;
            day = msg-&amp;gt;day;
            hour = msg-&amp;gt;hour;
            min = msg-&amp;gt;min;
            sec = msg-&amp;gt;sec;

            time_updated = true;
        }
        else
        {
            printf(&quot;Not supported NAV MSG : %02X\n&quot;, gps_rx_data[1]);
        }
    }
    else if (gps_rx_data[0] == CLASS_ACK)
    {
        printf(&quot;ACK : %u\n&quot;, gps_rx_data[1]);
    }
    else
        printf(&quot;Not supported class ID : %02X\n&quot;, gps_rx_data[0]);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수신된 데이터의 첫번째와 두번째 데이터를 분석하여 어떤 데이터인지를 알아내어 필요한 데이터를 별도의 변수에 저장한다.&lt;/p&gt;
&lt;pre id=&quot;code_1675427607833&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void loop()
{
    gps.update();
}

int main(void)
{
    setup();

    while (1) 
        loop();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기화가 실행된 이후에는 계속 새로운 데이터가 수신되었는지 확인하여 데이터가 업데이트 되었으면 화면에 출력하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1675427685778&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void Gps::update()
{
    if (time_updated)
    {
        printf(&quot;\x1B[5;H\x1B[2K%4d-%2d-%2d %2d:%2d:%2d&quot;,
                year, month, day, hour, min, sec);
        time_updated = false;
    }

    if (loc_updated)
    {
        if (longitude &amp;amp;&amp;amp; latitude)
        {
            int32_t tmp = longitude / 10000000;
            printf(&quot;\x1B[6;H\x1B[2K%3ld&quot;, tmp);
            tmp *= 10000000;
            tmp = longitude - tmp;
            printf(&quot;.%ld&quot;, tmp / 100000);

            tmp = latitude / 10000000;
            printf(&quot;\x1B[7;H\x1B[2K%3ld&quot;, tmp);
            tmp *= 10000000;
            tmp = latitude - tmp;
            printf(&quot;.%ld&quot;, tmp / 100000);
        }
        loc_updated = false;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 정보 데이터가 업데이트 된경우 5번째 줄에 연월일, 시분초 순서로 출력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위치정보가 수신된 경우 유효한 데이터인지 확인한 후 경도와 위도를 각각 출력한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/3H6ge/btrX40HrIyu/TTCCYoxnDVrCjFI7H70G20/gps.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;gps.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/190</guid>
      <comments>https://embed-avr.tistory.com/190#entry190comment</comments>
      <pubDate>Fri, 3 Feb 2023 21:37:45 +0900</pubDate>
    </item>
    <item>
      <title>GPS - CFG:MSG</title>
      <link>https://embed-avr.tistory.com/189</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;이전의 두개의 글에서 현재 시간을 가지고 오거나 현재 위치 정보를 가지고 오기 위해서는 매번 필요한 키를 입력해 주었다. GPS 모듈에 처음 전원이 들어왔을때 NMEA 메시지를 주기적으로 보내주는 것처럼 UBX 메시지도 주기적으로 보내주면 좋을것 같다.&lt;br&gt;이를 위해서 CFG-MSG 패킷을 이용하면 된다.&lt;br&gt;CFG-MSG 패킷에 원하는 메시지에 해당하는 class ID와 message ID를 넣어주면 된다.&lt;/p&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;c++&quot; data-ke-language=&quot;c++&quot;&gt;&lt;code&gt;void loop()
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uint8_t ch;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (uart0.getchar(ch))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ch == 'p')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gps.cfg_prt();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ch == 'm')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gps.cfg_msg();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ch == 'u')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gps.nav_utc();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (ch == 'l')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gps.nav_loc();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (uart1.getchar(ch))
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uart0.puthex(ch);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

void Gps::cfg_msg()
{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct cfg_msg_msg*&amp;nbsp;&amp;nbsp;msg = (struct cfg_msg_msg*)&amp;amp;gps_data[6];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uint32_t pkt_size = sizeof(struct cfg_msg_msg);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;make_header(CLASS_CFG, CFG_MSG, pkt_size);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg-&amp;gt;cls_id = CLASS_NAV;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg-&amp;gt;msg_id = NAV_TIMEUTC;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;msg-&amp;gt;rate = 1;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;chksum(pkt_size);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uart1.send_data(gps_data, pkt_size + 8);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;'m' 키를 누르면 CFG-MSG 패킷을 내 보내도록 되어 있다. 이번 예제에서는 현재 시간을 주기적으로 받을수 있도록 NAV-TIMEUTC 메시지를 선택하도록 되어 있다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3sFti/btrXnK0MjmC/h7CjMjfe1PfV4jfCqY1SGk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3sFti/btrXnK0MjmC/h7CjMjfe1PfV4jfCqY1SGk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3sFti/btrXnK0MjmC/h7CjMjfe1PfV4jfCqY1SGk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3sFti%2FbtrXnK0MjmC%2Fh7CjMjfe1PfV4jfCqY1SGk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;979&quot; height=&quot;358&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;위에 초록색으로 표시되어 있는 부분이 NAV-TIMEUTC 패킷이다. 동일한 구조의 메시지가 매초마다 한 번씩 들어오는 것을 볼수 있다. 만약 다른 메시지도 주기적으로 받기를 원하면 원하는 message ID를 알려주면 된다.&lt;br&gt; &lt;/p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/u6fCA/btrXmJVOYKk/jSaAbcXV6PIqVq4gyIPWwK/gps.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;gps.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/189</guid>
      <comments>https://embed-avr.tistory.com/189#entry189comment</comments>
      <pubDate>Sat, 28 Jan 2023 19:22:52 +0900</pubDate>
    </item>
    <item>
      <title>GPS - NAV:POSLLH</title>
      <link>https://embed-avr.tistory.com/188</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;현재 위치 정보를 가지고 오기 위한 UBX 메시지는 NAV-POSLLH 이다&lt;/p&gt;
&lt;pre id=&quot;code_1674900047844&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void loop()
{
    uint8_t ch;

    if (uart0.getchar(ch))
    {
        if (ch == 'p')
            gps.cfg_prt();

        if (ch == 'u')
            gps.nav_utc();

        if (ch == 'l')
            gps.nav_loc();
    }

    if (uart1.getchar(ch))
    {
        uart0.puthex(ch);
    }
}

void Gps::nav_loc()
{
    make_header(CLASS_NAV, NAV_POSLLH, 0);

    chksum(0);

    uart1.send_data(gps_data, 8);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'l' 키를 누르면 NAV-POSLLH request 메시지를 내 보낸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nav_posllh.jpg&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/berd44/btrXnKNe7Aq/L7lZGpNv9Eij4kM89IORpK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/berd44/btrXnKNe7Aq/L7lZGpNv9Eij4kM89IORpK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/berd44/btrXnKNe7Aq/L7lZGpNv9Eij4kM89IORpK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fberd44%2FbtrXnKNe7Aq%2FL7lZGpNv9Eij4kM89IORpK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;979&quot; height=&quot;358&quot; data-filename=&quot;nav_posllh.jpg&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오렌지 색으로 보이는 영역이 경도 데이터이고 초록색 부분이 위도 데이터이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/blETGk/btrXooJHpgn/7hFwVK3wz0CaiBNTaK1dBK/gps.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;gps.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/188</guid>
      <comments>https://embed-avr.tistory.com/188#entry188comment</comments>
      <pubDate>Sat, 28 Jan 2023 19:05:30 +0900</pubDate>
    </item>
    <item>
      <title>GPS - NAV:TIMEUTC</title>
      <link>https://embed-avr.tistory.com/187</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;현재 시간을 알려주는 UBX 패킷은 NAV-TIMEUTC이다.&lt;/p&gt;
&lt;pre id=&quot;code_1674899286580&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void loop()
{
    uint8_t ch;

    if (uart0.getchar(ch))
    {
        if (ch == 'p')
            gps.cfg_prt();

        if (ch == 'u')
            gps.nav_utc();
    }

    if (uart1.getchar(ch))
    {
        uart0.puthex(ch);
    }
}

void Gps::nav_utc()
{
    make_header(CLASS_NAV, NAV_TIMEUTC, 0);

    chksum(0);

    uart1.send_data(gps_data, 8);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'u' 키를 누르면 UTC time을 가지고 오는 패킷을 내보낸다.&amp;nbsp; &amp;nbsp;request 메시지는 payload없이 class ID와 message ID만 보내주면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nav_utc.jpg&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buKS5d/btrXqrMGfKi/yEprFuIlc5NyEQaPoFKKg1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buKS5d/btrXqrMGfKi/yEprFuIlc5NyEQaPoFKKg1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buKS5d/btrXqrMGfKi/yEprFuIlc5NyEQaPoFKKg1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuKS5d%2FbtrXqrMGfKi%2FyEprFuIlc5NyEQaPoFKKg1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;979&quot; height=&quot;358&quot; data-filename=&quot;nav_utc.jpg&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨간색으로 표시된 부분이 연,월,일에 해당되는 부분이고 초록색 부분이 시,분,초에 해당되는 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고, 오렌지색 부분이 데이터의 유효성을 알려주는 플래그 바이트이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/CWZF6/btrXo6ourUO/1VSyjHCuAhypfasLOazRUK/gps.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;gps.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/187</guid>
      <comments>https://embed-avr.tistory.com/187#entry187comment</comments>
      <pubDate>Sat, 28 Jan 2023 18:52:17 +0900</pubDate>
    </item>
    <item>
      <title>GPS - CFG:PRT</title>
      <link>https://embed-avr.tistory.com/186</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째로 구현할 UBX 패킷은 CFG-PRT이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPS 모듈은 전원이 인가되면 기본적으로 몇개의 NMEA 메시지를 자동으로 송신하도록 되어 있다는 것은 앞에서 몇차례에 걸쳐서 얘기하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UBX 패킷을 이용하기 위해서는 자동으로 송신되는 NMEA메시지를 보내지 않도록 해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해서 CFG-PRT 패킷을 사용하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cfg_prt_msg1.jpg&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpugJW/btrXqsENu4n/8rf9D0GGp51NQ3CEYGXzBk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpugJW/btrXqsENu4n/8rf9D0GGp51NQ3CEYGXzBk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpugJW/btrXqsENu4n/8rf9D0GGp51NQ3CEYGXzBk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpugJW%2FbtrXqsENu4n%2F8rf9D0GGp51NQ3CEYGXzBk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1264&quot; height=&quot;745&quot; data-filename=&quot;cfg_prt_msg1.jpg&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cfg_prt_msg2.jpg&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dM1ZCr/btrXn79gFJv/PUWTsFZDF0vtrHkgZlYlAK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dM1ZCr/btrXn79gFJv/PUWTsFZDF0vtrHkgZlYlAK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dM1ZCr/btrXn79gFJv/PUWTsFZDF0vtrHkgZlYlAK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdM1ZCr%2FbtrXn79gFJv%2FPUWTsFZDF0vtrHkgZlYlAK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1252&quot; height=&quot;630&quot; data-filename=&quot;cfg_prt_msg2.jpg&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cfg_prt_msg3.jpg&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lDg4e/btrXrT90o3N/1qLDxCLAKKbgtv4TXuKeHk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lDg4e/btrXrT90o3N/1qLDxCLAKKbgtv4TXuKeHk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lDg4e/btrXrT90o3N/1qLDxCLAKKbgtv4TXuKeHk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlDg4e%2FbtrXrT90o3N%2F1qLDxCLAKKbgtv4TXuKeHk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;576&quot; data-filename=&quot;cfg_prt_msg3.jpg&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림은 CFG-PRT 패킷의 구조를 설명하고 있는데 여기에서 중요한 부분은 Proto Mask 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림에 표시되어 있는것처럼 NMEA 메시지와 UBX 메시지를 enable/disable 할수 있다.&amp;nbsp; CFG-PRT메시지를 보낼때 UBX 메시지만 송수신 할수 있도록 해주면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1674897670651&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void loop()
{
    uint8_t ch;

    if (uart0.getchar(ch))
    {
        if (ch == 'p')
            gps.cfg_prt();
    }

    if (uart1.getchar(ch))
    {
        uart0.puthex(ch);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART0에서 p키를 누르면 CFG-PRT 메시지를 내 보내도록 되어 있다.&amp;nbsp; GPS 모듈에서 들어오는 모든 데이터를 헥사값으로 출력하도록 하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1674897832889&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void Gps::cfg_prt()
{
    clear();

    struct cfg_prt_msg*  msg = (struct cfg_prt_msg*)&amp;amp;gps_data[6];
    uint32_t pkt_size = sizeof(struct cfg_prt_msg);

    make_header(CLASS_CFG, CFG_PRT, pkt_size);

    msg-&amp;gt;port = UART_1;
    msg-&amp;gt;mode = 0x08D0;
    msg-&amp;gt;baud = 9600;
    msg-&amp;gt;in_mask = PROTO_UBX;
    msg-&amp;gt;out_mask = PROTO_UBX;

    chksum(pkt_size);

    uart1.send_data(gps_data, pkt_size + 8);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cfg_prt.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U74PF/btrXm6b8K17/lIBFb2k7GGLus9lVCoMrG1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U74PF/btrXm6b8K17/lIBFb2k7GGLus9lVCoMrG1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U74PF/btrXm6b8K17/lIBFb2k7GGLus9lVCoMrG1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU74PF%2FbtrXm6b8K17%2FlIBFb2k7GGLus9lVCoMrG1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;779&quot; height=&quot;534&quot; data-filename=&quot;cfg_prt.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화면에 보이는 데이터들은 NMEA 메시지를 헥사값으로 출력한 것이다. ' p' 키를 누르면 CFG-PRT 패킷이 GPS로 송신되고 GPS는 CFG 패킷에 대한 ACK를 보내주도록 되어 있다.&amp;nbsp; 위의 그림에 빨간색 박스가 ACK-ACK 패킷이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 CFG 패킷을 보냈을때 문제가 있거나 제대로 처리할 수 없는 상황이라면 ACK-NACK를 보내주게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서는 정상적으로 CFG-PRT가 처리되었음을 알려주고, 더이상 NMEA 메시지가 나오지 않게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cH1LYE/btrXrT90Uuk/m7YYr4ByN3mMWBmvdR8Hyk/gps.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;gps.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/186</guid>
      <comments>https://embed-avr.tistory.com/186#entry186comment</comments>
      <pubDate>Sat, 28 Jan 2023 18:29:05 +0900</pubDate>
    </item>
    <item>
      <title>GPS - UBX</title>
      <link>https://embed-avr.tistory.com/185</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 글에서 본 것처럼 GPS에서 보내는 데이터는 모두 $로 시작되는 문자열로 되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔창에 보이는 데이터는 NMEA protocol로 정해진 표준에따라 정의되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nmea.jpg&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfdw5F/btrXm64f5j7/zvgcKnpp4Hpf8TVh8Mn33K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfdw5F/btrXm64f5j7/zvgcKnpp4Hpf8TVh8Mn33K/img.jpg&quot; data-alt=&quot;NMEA protocal&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfdw5F/btrXm64f5j7/zvgcKnpp4Hpf8TVh8Mn33K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbfdw5F%2FbtrXm64f5j7%2FzvgcKnpp4Hpf8TVh8Mn33K%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1173&quot; height=&quot;722&quot; data-filename=&quot;nmea.jpg&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NMEA protocal&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림처럼 $로 하나의 프레임이 시작되고, 뒤이어 GP문자열이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메세지 종류에 따라 세글자로 구분되어 진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 위치정보에 해당되는 메세지 코드는 GLL이며 다음과 같이 정의 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;gll.jpg&quot; data-origin-width=&quot;1263&quot; data-origin-height=&quot;581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLPmW4/btrXqsSi9at/Qjwh3C0oZm5KSAVhd5iNeK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLPmW4/btrXqsSi9at/Qjwh3C0oZm5KSAVhd5iNeK/img.jpg&quot; data-alt=&quot;GLL 메세지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLPmW4/btrXqsSi9at/Qjwh3C0oZm5KSAVhd5iNeK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLPmW4%2FbtrXqsSi9at%2FQjwh3C0oZm5KSAVhd5iNeK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1263&quot; height=&quot;581&quot; data-filename=&quot;gll.jpg&quot; data-origin-width=&quot;1263&quot; data-origin-height=&quot;581&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GLL 메세지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$GPGLL,다음에 위도에 해당되는 값이 나오고, 북위 혹은 남위를 나타내는 글자가 나온다. 다음으로는 경도값이 나오고 동경, 서경을 구분하기 위한 글자가 뒤따른다. 그 다음에는 시간정보도 같이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 위와 같이 4717.11364N, 00833.91565E와 같은 데이터가 들어 왔다면 아래와 같은 방법으로 변환 하면된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;longlat.jpg&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpROxl/btrXrTa3fWv/AkhShHtQ3GkztbjtuHzUak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpROxl/btrXrTa3fWv/AkhShHtQ3GkztbjtuHzUak/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpROxl/btrXrTa3fWv/AkhShHtQ3GkztbjtuHzUak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpROxl%2FbtrXrTa3fWv%2FAkhShHtQ3GkztbjtuHzUak%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1166&quot; height=&quot;388&quot; data-filename=&quot;longlat.jpg&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 모든 데이터가 문자열로 이루어져 있으면 사람이 육안으로 직접 읽을때는 편하겠지만, 프로그램으로 읽어 들인 데이터를 가공하거나 다른 용도로 사용하기 위해서 메모리에 저장하려면 일일이 한글자씩 분석하여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문자열 분석은 생각보다 더 까다롭고 오류가 날 가능성도 높아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램으로 처리하기 위한 데이터는 문자열 보다는 바이너리 형태의 패킷 송수신이 훨씬 편하고 효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;u-blox에서는 이러한 요구 조건을 충족하기 위하여 자체적으로 ubx라는 패킷 전송용 프로토콜을 제공한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ubx_pkt.jpg&quot; data-origin-width=&quot;1243&quot; data-origin-height=&quot;836&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cut81i/btrXrUA1IFu/pY0b7KMosPlN9Vm5Fp0gE0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cut81i/btrXrUA1IFu/pY0b7KMosPlN9Vm5Fp0gE0/img.jpg&quot; data-alt=&quot;UBX Packet structure&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cut81i/btrXrUA1IFu/pY0b7KMosPlN9Vm5Fp0gE0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcut81i%2FbtrXrUA1IFu%2FpY0b7KMosPlN9Vm5Fp0gE0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1243&quot; height=&quot;836&quot; data-filename=&quot;ubx_pkt.jpg&quot; data-origin-width=&quot;1243&quot; data-origin-height=&quot;836&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;UBX Packet structure&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UBX 패킷은 2개의 연속된 sync 데이터(0xB5,0x62)로 시작되고 1바이트의 Class ID, 1바이트의 Message ID가 이어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음에는 2바이트의 payload 크기에 해당되는 값이 들어가고, 뒤이어 가변 크기의 payload data가 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 2바이트의 check sum 값으로 패킷을 끝내게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Class ID와 Message ID를 보면 payload가 어떻게 생겼는지 알수 있으므로 프로그램으로 GPS 데이터를 처리하는게 상당히 간편해 지게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/185</guid>
      <comments>https://embed-avr.tistory.com/185#entry185comment</comments>
      <pubDate>Sat, 28 Jan 2023 16:41:31 +0900</pubDate>
    </item>
    <item>
      <title>GPS - UART</title>
      <link>https://embed-avr.tistory.com/184</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 사용하는 GPS 모듈은 UART 통신을 사용하므로 UART 블럭이 2개 이상 지원되는 마이크로컨트롤러를 사용하는것이 프로그램 디버깅에 편리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이번 프로젝트에서는 UART가 2개 들어있는 Atmega128A를 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;f_cpu.jpg&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wAaqv/btrXrNV8GYb/TKmh5zSYXDATmf7fc0hXq0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wAaqv/btrXrNV8GYb/TKmh5zSYXDATmf7fc0hXq0/img.jpg&quot; data-alt=&quot;Toolchain 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wAaqv/btrXrNV8GYb/TKmh5zSYXDATmf7fc0hXq0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwAaqv%2FbtrXrNV8GYb%2FTKmh5zSYXDATmf7fc0hXq0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;621&quot; height=&quot;519&quot; data-filename=&quot;f_cpu.jpg&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;519&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Toolchain 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Atmega128A 프로젝트를 생성하고 CPU 클럭을 위 그림처럼 보드에 맞게 설정해 준다.&amp;nbsp; 참고로 C++ 프로젝트로 진행할것이기 때문에 AVR/GNU C++ Compiler에서 Symbols를 선택하였지만, 만약 C 프로젝트라면 AVR/GNU C Compiler에 있는 Symbols를 선택한 후 F_CPU값을 입력해 주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 생성이 끝나면 UART0는 디버깅을 위하여 baudrate 값을 115200로 설정하고, UART1은 GPS와 연결하기 위하여 9600으로 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 설정이 끝났으면, 각각 수신된 데이터를 바로 되돌려주어 UART0과 UART1이 제대로 동작되는지 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674884478071&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &quot;uart.h&quot;

Uart    uart0(UART0, 115200);
Uart    uart1(UART1, 9600);

void setup()
{
}

void loop()
{
    uart0.putchar(uart0.getchar());
}

int main(void)
{
    setup();

    while (1) 
        loop();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 코딩한 다음 실행 시켜 UART0의 정상동작 여부를 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;uart0.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vevES/btrXn9slXDA/YHE1z9FdiESyKu2b5Rq0yK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vevES/btrXn9slXDA/YHE1z9FdiESyKu2b5Rq0yK/img.jpg&quot; data-alt=&quot;UART0 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vevES/btrXn9slXDA/YHE1z9FdiESyKu2b5Rq0yK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvevES%2FbtrXn9slXDA%2FYHE1z9FdiESyKu2b5Rq0yK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;779&quot; height=&quot;534&quot; data-filename=&quot;uart0.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;UART0 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키보드의 아무키나 눌러 누른키값이 화면에 제대로 출력 되는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART0이 문제 없는지 확인한 다음 UART1에 대해서도 같은 방법으로 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1674884636283&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void loop()
{
    uart1.putchar(uart1.getchar());
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔창의 baudrate를 9600으로 변경한 후 같은 방법으로 UART1의 동작을 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;uart1.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u0dzd/btrXooCRxeT/Z8UFPRBRzGrsQb3q4bUMN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u0dzd/btrXooCRxeT/Z8UFPRBRzGrsQb3q4bUMN1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u0dzd/btrXooCRxeT/Z8UFPRBRzGrsQb3q4bUMN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu0dzd%2FbtrXooCRxeT%2FZ8UFPRBRzGrsQb3q4bUMN1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;779&quot; height=&quot;534&quot; data-filename=&quot;uart1.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART0과 UART1의 정상 동작을 확인하였다면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART1에 GPS 모듈을 연결하고 코드를 아래와 같이 만든다.&lt;/p&gt;
&lt;pre id=&quot;code_1674885323582&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void loop()
{
    uart0.putchar(uart1.getchar());
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 콘솔프로그램의 baudrate를 115200으로 변경한 후 UART0에 연결한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;gps_raw.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMOoLS/btrXmQ1CKcA/z8KGtWKFsOhqxMQCYmG5oK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMOoLS/btrXmQ1CKcA/z8KGtWKFsOhqxMQCYmG5oK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMOoLS/btrXmQ1CKcA/z8KGtWKFsOhqxMQCYmG5oK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMOoLS%2FbtrXmQ1CKcA%2Fz8KGtWKFsOhqxMQCYmG5oK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;779&quot; height=&quot;534&quot; data-filename=&quot;gps_raw.jpg&quot; data-origin-width=&quot;779&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GPS모듈에서 송신하는 데이터가 콘솔창에 바로 출력되는것을 볼수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로써 기본적인 GPS 디버깅 환경이 갖추어졌으므로 다음 단계로 넘어갈 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bkyALs/btrXnKM7tCW/JUJY90LiVBGuaGpmhnyq51/gps.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;gps.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.00MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>프로젝트/GPS</category>
      <author>Just4Fun</author>
      <guid isPermaLink="true">https://embed-avr.tistory.com/184</guid>
      <comments>https://embed-avr.tistory.com/184#entry184comment</comments>
      <pubDate>Sat, 28 Jan 2023 14:08:24 +0900</pubDate>
    </item>
  </channel>
</rss>