1. 구조체 2

#include <stdio.h>

typedef int INT;
typedef int * PTR_INT;
typedef unsigned int UINT;
typedef unsigned int * PTR_UINT;
typedef unsigned char UCHAR;
typedef unsigned char * PTR_UCHAR;

int main()
{
	INT num1 = 120;
	PTR_INT pnum1 = &num1;
	UINT num2 = 190;
	PTR_UINT pnum2 = &num2;
	UCHAR ch = 'z';
	PTR_UCHAR pch = &ch;
	printf("%d, %u, %c\n", *pnum1, *pnum2, *pch);
}

#include <stdio.h>

struct point
{
	int xpos;
	int ypos;
};

typedef struct point Point;

typedef struct person
{
	char name[20];
	char phoneNum[20];
	int age;
} Person;

int main(){
	Point pos = {10, 20};
	Person man = {"이승기", "010-1211-1111", 11};
	printf("%d %d \n", pos.xpos, pos.ypos);
	printf("%s %s %d \n", man.name, man.phoneNum, man.age);
}

#include <stdio.h>

typedef struct point
{
	int xpos;
	int ypos;
} Point;

void ShowPosition(Point pos)
{
	printf("[%d, %d] \n", pos.xpos, pos.ypos);
}

Point GetCurrentPosition(void)
{
	Point cen;
	printf("Input current pos : ");
	scanf("%d %d", &cen.xpos, &cen.ypos);
	return cen;
}

int main()
{
	Point curPos = GetCurrentPosition();
	ShowPosition(curPos);
	return 0;
}

#include <stdio.h>
// struct   function call by ref

typedef struct point{
	int xpos;
	int ypos;
} Point;

void OrgSymTrans(Point * ptr)
{
	ptr->xpos = (ptr->xpos) *-1;
	ptr->ypos = (ptr->ypos) *-1;
}

void ShowPosition(Point pos)
{
	printf("[%d %d] \n", pos.xpos, pos.ypos);
}

int main()
{
	Point pos = {7, -5};
	OrgSymTrans(&pos);
	ShowPosition(pos);
	OrgSymTrans(&pos);
	ShowPosition(pos);
}

#include <stdio.h>

typedef struct point{
	int xpos;
	int ypos;
}Point;

Point AddPoint(Point pos1, Point pos2)
{
	Point pos = {pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos};
	return pos;
}

Point MinPoint(Point pos1, Point pos2)
{
	Point pos = {pos1.xpos - pos2.xpos, pos1.ypos -pos2.ypos};
	return pos;
}


int main()
{
	Point pos1= {5, 6};
	Point pos2 = {2, 9};
	Point result; 
	
	result = AddPoint(pos1, pos2);
	printf("[%d, %d] \n", result.xpos, result.ypos);
	result = MinPoint(pos1, pos2);
	printf("[%d, %d] \n", result.xpos, result.ypos);
}

#include <stdio.h>

typedef enum syllabel
{
	Do = 1, Re = 2, Mi = 3, Fa = 4, So = 5, La = 6, Ti =7
} Syllabel;

void Sound(Syllabel sy)
{
	switch(sy)
	{
		case Do:
			puts("도는 하얀 도라지");
			return ;
		case Re:
			puts("레는 둥근 레코드");
			return ;
		case Mi:
			puts("미는 파란 미나리");
			return ;
		case Fa:
			puts("파는 예쁜 파랑새");
			return ;
		case So:
			puts("솔은 작은솔방울");
			return ;
		case La:
			puts("라는 라디오고요");
			return ;
		case Ti:
			puts("시는 졸졸시냇물");
	}
	puts("다함께 부르세~");
}

int main()
{
	Syllabel tone;
	
	for(tone=1; tone <=Ti; tone+=1)
		Sound(tone);
}

 

 

2. 메모리 동적 할당

#include <stdio.h>
#include <stdlib.h>

int main()
{
	int *ptr1 = (int *)malloc(sizeof(int));
	int *ptr2 = (int *)malloc(sizeof(int)*7);
	int i;

	*ptr1 = 20;
	for(i=0; i< 7; i++)
		ptr2[i] = i + 1;
	
	printf("%d \n", *ptr1);
	for(i=0; i <7; i++)
		printf("%d ", ptr2[i]);
	
	free(ptr1);
	free(ptr2);
}

#include <stdio.h>
#include <stdlib.h>

char * ReadUserName()
{
	char * name = (char *)malloc(sizeof(char) * 30);
	printf("what's your name? ");
	gets(name);
	return name;
}


int main()
{
	char *name1;
	char *name2;
	name1 = ReadUserName();
	printf("name1 : %s \n ", name1);
	name2 = ReadUserName();
	printf("name2 : %s \n\n", name2);
	
	printf("again name1 : %s \n", name1);
	printf("again name2 : %s \n", name2);
	free(name1);
	free(name2);
}

 

 

 

3. 전처리

#include <stdio.h>
#define SQUARE(X) X*X

int main(){
	int num = 20;
	printf("sq of num : %d \n", SQUARE(num));
	printf("sq of -5 : %d \n", SQUARE(-5));
	printf("sq of 2.5 : %g \n", SQUARE(2.5));
}

#include <stdio.h>
#define PI 3.14
#define PRODUCT(X,Y) ((X) * (Y))
#define CIRCLE_AREA(R) (PRODUCT(R, R) * PI)

int main()
{
	double rad = 2.1;
	printf("반지름이 %g인 원의 넓이 : %g \n", rad, CIRCLE_AREA(rad));
}

 

#include <stdio.h>
#define ADD 1
#define MIN 0

int main()
{
	int num1, num2;
	printf("두 개의 정수 입력 :");
	scanf("%d %d", &num1, &num2);
	
#if ADD
	printf("%d + %d = %d \n", num1, num2, num1+num2);
#endif

#if MIN
	printf("%d - %d = %d \n", num1, num2, num1 - num2);
#endif	
}

#include <stdio.h>
//#define ADD 1
#define MIN 0

int main()
{
	int num1, num2;
	printf("두 정수 입력 : ");
	scanf("%d %d", &num1, &num2);
	
#ifdef ADD
	printf("%d + %d = %d \n", num1, num2, num1 + num2);
#endif

#ifdef MIN
	printf("%d - %d = %d \n", num1, num2, num1 - num2);
#endif
}

 

4. 파일 분할

4.1 산술 연산 예제

- main.c

- basicArith.h, basicArith.c

- areaArith.h, areaArith.c

- roundArith.h, roundArith.c

#include <stdio.h>
#include "areaArith.h"
#include "roundArith.h"

int main()
{
	printf("삼각형 넓이 (밑변 10, 높이 5) : %g \n"
			, TriangleArea(10, 5));
	printf("원 넓이 (반지름 : 10) : %g \n"
			, CircleArea(5));
	printf("직사각형 둘레(밑변 2.6, 높이 : 5.5) : %g \n"
			, RectangleRound(2.6, 5.5));
	printf("정사각형 둘레(변 길이 : 7) : %g \n"
			, SquareRound(3));
}
#define PI 3.1415
double Add(double num1, double num2);
double Min(double num1, double num2);
double Mul(double num1, double num2);
double Div(double num1, double num2);
double Add(double num1, double num2)
{
	return num1 + num2;
}

double Min(double num1, double num2)
{
	return num1 - num2;	
}

double Mul(double num1, double num2)
{
	return num1 * num2;
}

double Div(double num1, double num2)
{
	return num1 / num2;
}
double TriangleArea(double base, double height);
double CircleArea(double rad);
#include "basicArith.h"

double TriangleArea(double base, double height)
{
	return Div(Mul(base, height), 2);
}

double CircleArea(double rad)
{
	return Mul(Mul(rad, rad), PI);
}
double RectangleRound(double base, double height);
double SquareRound(double side);
#include "basicArith.h"

double RectangleRound(double base, double height)
{
	return Mul(Add(base, height), 2);
}

double SquareRound(double side)
{
	return Mul(side, 4);
}

4.2 몫, 나머지 연산(조건부 컴파일 이용 - 중복 인클루드 방지)

- main.c

- stdiv2.h

- intdiv4.h

- intdiv4.c

#include <stdio.h>
#include "stdiv2.h"
#include "intdiv4.h"

int main()
{
	Div val = IntDiv(5, 2);
	printf("몫 : %d \n", val.quotient);
	printf("나머지 : %d \n", val.remainder);
}
#ifndef __STDIV2_H__
#define __STDIV2_H__

typedef struct div
{
	int quotient;
	int remainder;
} Div;

#endif
#ifndef __INTDIV4_H__
#define __INTDIV4_H__

#include "stdiv2.h"

Div IntDiv(int num1, int num2);

#endif
#include "stdiv2.h"

Div IntDiv(int num1, int num2)
{
	Div dval;
	dval.quotient = num1/num2;
	dval.remainder= num1%num2;
	return dval;
}

1. 함수 포인터

 

#include <stdio.h>


void SimpleAdder(int n1, int n2)
{
	printf("%d + %d = %d \n", n1, n2, n1+n2);
}

void ShowString( char *str)
{
	printf("%s \n", str);
}

int main()
{
	char *str = "Function ptr";
	int num1=10, num2=20;
	
	void (*fptr1)(int, int) = SimpleAdder;
	void (*fptr2)(char *) = ShowString;
	
	fptr1(num1, num2);
	fptr2(str);
}

 

#include <stdio.h>

int WhoIsFirst(int age1, int age2, int (*cmp)(int n1, int n2))
{
	return cmp(age1, age2);
}

int OlderFirst(int age1, int age2)
{
	if (age1>age2)
		return age1;
	else if (age1 < age2)
		return age2;
	else
		return 0;		
}

int YoungerFirst(int age1, int age2)
{
	if (age1< age2)
		return age1;
	else if (age1 > age2)
		return age2;
	else
		return 0;	
}

int main()
{
	int age1=20;
	int age2=30;
	int first;
	
	printf("입장순서 1 \n");
	first = WhoIsFirst(age1, age2, OlderFirst);
	printf("%d세와 %d세 중 %d세가 먼저 입장!! \n\n", age1, age2, first);
	
	printf("입장순서 2 \n");
	first = WhoIsFirst(age1, age2, YoungerFirst);
	printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first);
}

 

 

#include <stdio.h>

void SoSimpleFunc(void)
{
	printf("I'm so simple");
}

int main()
{
	int num=20;
	void *ptr; // void* 포인터 변수 함수  담을 수 있따. 
	
	ptr = &num;
	printf("%p \n", ptr);
	ptr = SoSimpleFunc;
	printf("%p \n", ptr);
	return 0;
}

 

#include <stdio.h>

int main(int argc, char *argv[])
{
	int i = 0;
	printf("전달된 문자열 수 : %d\n", argc);
	for(i=0; i<argc; i++)
		printf("%d 번째 문자열 : %s \n", i + 1, argv[i]);
}

 

 

 

2. 문자 스트림

#include <stdio.h>

int main()
{
	int ch;
	
	while(1)
	{
		ch = getchar();
		if ( ch ==EOF)
			break;
		putchar(ch);
	}
}
#include <stdio.h>

int main()
{
	char *str = "simple string";
	
	printf("1. puts test ----\n");
	puts(str);
	puts("so simple string");
	
	printf("2. fputs test ----\n");
	fputs(str, stdout);
	printf("\n");
	printf("so simple string", stdout);
	printf("\n");
	printf("3. end of main ----\n");
}
#include <stdio.h>

int main()
{
	char perID[7];
	char name[10];
	
	fputs("주민번호 앞 6자리 입력 : ", stdout);
	fgets(perID, sizeof(perID), stdin);
	
	//6자리 입력시 fgets는 \n까지 읽고, \n이 남음
	// -> 나머지 fgets에서도 버퍼에 남은 \n에 바로 종료되어 입력 못함 
	fputs("이름 입력 : ", stdout);
	fgets(name, sizeof(name), stdin);
	
	printf("주민번호 : %s \n", perID);
	printf("이름 : %s \n", name);
}
#include <stdio.h>

void ClearLineFromReadBuffer()
{
	while(getchar() != '\n');	
} 

int main()
{
	char perID[7];
	char name[10];
	
	fputs("주민번호 앞 6자리 입력 : ", stdout);
	fgets(perID, sizeof(perID), stdin);
	//getchar()로 버퍼내 \n를 읽으면 무한루프 탈출!, 버퍼가 비워짐. 
	ClearLineFromReadBuffer();
	
	fputs("이름 입력 : ", stdout);
	fgets(name, sizeof(name), stdin);
	
	printf("주민번호 : %s \n", perID);
	printf("이름 : %s \n", name);
}

 

 

 

 

3. 구조체 1

#include <stdio.h>
#include <math.h>

struct point
{
	int xpos;
	int ypos;
};

int main()
{
	struct point pos1, pos2;
	double distance;
	
	fputs("point1 pos : ", stdout);
	scanf("%d %d", &pos1.xpos, &pos2.ypos);
	
	fputs("point2 pos : ", stdout);
	scanf("%d %d", &pos2.xpos, &pos2.ypos);
	
	distance = sqrt((double)((pos1.xpos - pos2.xpos) *
		(pos1.xpos - pos2.xpos) + (pos1.ypos-pos2.ypos) * (pos1.ypos-pos2.ypos)));
	
	printf("두 점의 거리는 %g 입니다~\n", distance);	
}

#include <stdio.h>
#include <string.h>

struct person
{
	char name[20];
	char phoneNum[20];
	int age;
};

int main()
{
	struct person man1, man2;
	strcpy(man1.name, "무야호");
	strcpy(man1.phoneNum, "010-1544-7676");
	man1.age = 23;
	
	printf("이름 입력 : ");
	scanf("%s", man2.name);
	printf("번호 입력 : ");
	scanf("%s", man2.phoneNum);
	printf("나이 입력 : ");
	scanf("%d", &(man2.age));
	
	printf("이름 : %s \n", man1.name);
	printf("번호 : %s \n", man1.phoneNum);
	printf("나이 : %d \n", man1.age);
	
	printf("이름 : %s \n", man2.name);
	printf("번호 : %s \n", man2.phoneNum);
	printf("나이 : %d \n", man2.age);
}

#include <stdio.h>

struct point
{
	int xpos;
	int ypos;
};

struct person
{
	char name[20];
	char phoneNum[20];
	int age;
};

int main(void)
{
	struct point pos = {10, 20};
	struct person man = {"이승기", "010-1234-5678", 21};
	printf("%d %d \n", pos.xpos, pos.ypos);
	printf("%s %s %d \n", man.name, man.phoneNum, man.age);	
}

#include <stdio.h>
//struct arr

struct point
{
	int xpos;
	int ypos;
};

int main()
{
	struct point arr[3];
	int i;
	
	for(i = 0; i < 3; i++)
	{
		printf("점의 좌표 입력 : ");
		scanf("%d %d", &arr[i].xpos, &arr[i].ypos);
	}
	
	for(i = 0; i < 3; i++)
		printf("[%d %d] ", arr[i].xpos, arr[i].ypos);
}

#include <stdio.h>
//init struct array

struct person
{
	char name[20];
	char phoneNum[20];
	int age;
};

int main()
{
	struct person arr[3] = {
		{"이승기", "010-1111-2222", 21},
		{"홍길동", "010-2222-3333",22},
		{"김길동", "010-3333-4444",33}
	};
	
	int i;
	for(i=0;i<3; i++)
		printf("%s %s %d \n", arr[i].name, arr[i].phoneNum, arr[i].age);
}

#include <stdio.h>

struct point
{
	int xpos;
	int ypos;
};

struct circle
{
	double radius;
	struct point * center;
};

int main(){
	struct point cen = {2, 7};
	double rad = 5.5;
	struct circle ring = {rad, &cen};
	printf("원의 반지름 : %g \n", ring.radius);
	printf("원의 중심 [%d, %d] \n", (ring.center) -> xpos, (ring.center) ->ypos);
}

#include <stdio.h>

struct point
{
	int xpos;
	int ypos;
	struct point *ptr;
};

int main(void)
{
	struct point pos1 = {1, 1};
	struct point pos2 = {2, 2};
	struct point pos3 = {3, 3};
	
	pos1.ptr = &pos2;
	pos2.ptr = &pos3;
	pos3.ptr = &pos1;
	
	printf("점의 연결 관계.. \n");
	printf("[%d, %d]와 [%d, %d] 연결 \n",
		pos1.xpos, pos1.ypos, pos1.ptr->xpos, pos1.ptr->ypos);
	printf("[%d, %d]와 [%d, %d] 연결 \n",
		pos2.xpos, pos2.ypos, pos2.ptr->xpos, pos2.ptr->ypos);
	printf("[%d, %d]와 [%d, %d] 연결 \n",
		pos3.xpos, pos3.ypos, pos3.ptr->xpos, pos3.ptr->ypos);
	
}

 

 

 

 

원래 학교에 있는 한백 전자 .. 가 아니고

 

하이버스 임베디드 키트가지고 놀려고 했는데

 

지도 교수님이 보관소 키를 가지고 계신다.

 

그런데 지도 교수님은 내가 전자 회로는 등한시 하는걸로 보셔서 별로 안좋아 하시는데

미뤄둔 진도 다 나가지 않은이상 빌려달라고 해도 안될거 같더라.

 

그렇다보니 학교에서는 시간 날때 전자 회로 만들기만 했는데

기숙사에서는 기구 설계 준비해볼까 싶기도하고

전자회로 만드는거 공부할까 싶기도 하고 고민하다가

 

 

 

사이먼 몽크란 분이 쓴 전자공학 만능 레시피가 괜찮아 보여서 주문했다.

전자 회로, 디지털 논리회로 같은데서 나오는 트랜지스터 원리니 그런것 보다는

필터는 어떻게 만들고, 베터리는 어떻게 골라서 쓰고 그런게 궁금했는데 마침 내가 찾던 내용들이 이 책에 다 있더라

http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788966262229&orderClick=JAj

 

우리나라 서적에는 전자 회로라하면 바이브레이터니 ADC 같은거 만드는게 대다수지

실제 제품 까지는 아니더라도 동작하는 프로토타이핑에 쓸만한 서적이 잘 보이지 않았다.

 

이 책 지르고, 일단 ROS 공부하면서 가제보 모델링하는거나 좀 공부해야겠다.

 

 

이건 오늘 3d 프린터로 출력한 2d 도트 마리오

나중에 채색 도구 사서 채색해볼까 싶다.

얼마전에 대강 이 책을 보면서

제대로 안본 부분도 많긴 한데

 

너무 불친절한 부분이 많았다.

특히 LCD 파트 볼떄

4비트 모드로 동작시키는데 

 

LCD 4비트 모드 초기화라면서 값이 4비트가 아니라 여러개 있지 않나

선은 7개인데 어떻게 4비트로 값을 보내는지 등등등

뭔가 설명이 빠진 부분이 많았다.

 

 

책 제목은 알기 쉽다면서

왜 이렇게 재미없고, 불친절하고, 빠진 부분이 많나 싶었는데

 

 

 

발행 년도가 2006년 2월이었다..

 

2022년에도 우리나라에서는 AVR에 관해서 유용한 자료가 (다른거에 비해서) 그렇게 많지 않은데

 

아 2006년에 나온 책이면 그 때 기준으로는

진짜 알기쉽게 배울수 있게 썼구나 싶은 생각이들었다.

주변장치 

1. UART와 USART

2. GPIO

3. JTAG, SWD

4. I2C(TWI)

5. PWM

6. SPI

7. Flash Memory

8. Ehternet

9. USB

10. CAN

11. 무선 장치

 

 

 

1. UART Universal Asynchronous Receiver/Transmitter

- 범용으로 병렬 데이터를 직렬화 하여 비동기적으로 송수신하는 규격(인터페이스) (* 병렬 통신 : 버스)

- USB2Serial 디버그, 블루투스, Rs-232/422 등 용도로 사용

- RS-232, RS-422와 같이 사용됨(*UART는 직렬 통신 규칙, RS-232는 하드웨어 규칙)

ref : https://treeroad.tistory.com/entry/RS232%EC%99%80-UART

- 위 링크보다는 이게 더 정확한 설명인거 같다.

ref : https://ko.serial-cable.com/info/difference-of-uart-serial-and-rs232-serial-30244548.html

- USART의 경우 동기 직렬 통신도 지원

- 시작비트, 데이터 비트(5 ~ 8비트), 패리티비트(필수 x), 종료 비트로 구성

 

 

** TTL 레벨과 RS-232C 레벨

- TTL 레벨은 0v, 5v로 0,1 표현 <-> RS-232C 레벨은 +-5V 양, 음전압으로 표현하여 노이즈에 강인

ref : https://treeroad.tistory.com/entry/%EC%99%9C-TTL-%ED%86%B5%EC%8B%A0%EC%9D%B8%EA%B0%80

 

 

2. GPIO General Perpose Input Output 

- 범용으로 사용 가능한 입출력 포트

- 디스플레이, 센서, LCD, USB Host, CAN 등 통신 인터페이스로도 사용

- 아래의 링크는 UART GPIO로 시리얼 통신 예시

ref : https://codedosa.com/470

 

 

 

3. 디버그 인터페이스

- JTAG Joint Test Action Group : 플레시 메모리에 소스코드를 다운로드/업로드하는 경우, 디버깅 용도로 사용

  * TDI 테스트 데이터 입력, TDO 테스트 데이터 출력, TCK 테스트 클럭, TMS 테스트 모드, TRST 테스트리셋

- SWD Serial Wired Debug : 직렬 통신이다보니 클럭 SWCLK와 데이터 SWDIO 핀 2개 사용

 

 

 

 

4. I2C Inter Integrated Circuit(TWI Two Wire Interface라고도 함)

- 마이크로 프로세서와 저속 주변장치 간 통신을 위한 규격

- 양방향 선 2개 SCL Serial Clock과 SDA Serial Data 이용. 마스터-슬레이브 구성으로 동작

-> 하드웨어적으로 간단, 수 많은(최대 127개) 노드(슬레이브) 연결, UART와 달리 클럭을 사용해서 속도 안정해도됨

5. PWM 

- 한 주기당 펄스의 폭, 듀티비를 조절하여 만들어 낸 신호

- DC 모터 제어 뿐만 아니라 LED 밝기, 밸브, 유압, 기계 장치 등 많은 분야에서 사용

6. SPI Serial Peripheral Interface

- 모토로라에서 개발한 전이중 동기 통신 규격

- I2C 방식과 비슷하게 마스터-슬레이브 방식 다만 전이중 통신

- SCLK : 시리얼 클럭

- MOSI : 마스터 출력 슬레이브 입력

- MISO : 마스터 인풋, 슬레이브 아웃풋

- SS : 슬레이브 셀렉트

SPI 인터페이스와 데이터 포멧

 

 

 

 

5. 프로세서 아키텍처로 분류

- 프로세서 제조사 or IP 회사로 분류

- x86 : 인텔의 32비트 아키텍처 PC에서 많이 쓰임. 레지스터가 8개로 부족

- amd64 : amd에서 만든 x86을 확장한 64비트 아키텍처. 레지스터를 16개로 늘어남. 가상 메모리, 물리메모리 크게늘어남

- arm : 초기 저전력 soc를 만들다가 고성능 저전력 프로세서 설계   ex) cortex-A(응용어플)/R(rtos 최적)/M(mcu 최적)

   + ARM 설계를 따르는 프로세서 : 퀄컴 스냅드래곤, NVIDA 테그라, 삼성 엑시노스

- mips : 스탠포드에서 RISC로 개발. 비디오 콘솔, 멀티미디어 같이 높은 연산 처리가 필요한 곳에 사용.

 

 

ARM RISC

- 초기 ARM7/9/11 같은 저전력 프로세서 위주였으나 스마트폰 대중화후 고성능 Cortex 아키텍처 시리즈

- RISC 특징 : load-store 구조, 고정 길이 32비트 명령어, 주소 명령어 구조(1개 명령어는 2개 소스 주소 + 1개 목적지)

* 로드-저장 구조 : CISC에서 memory to memory(메모리서 레지스터로 가져와 메모리로 저장) 연산을 하는것과 달리 레지스터에 로드 저장, 메모리 사용 x

- ARM RISC

  - 32비트 프로세서여도 16비트 명령어 사용가능(Thumb 모드) -> 코드 크기 축소

  - 조건부 명령어 구조 : 모든 명령어에 조건부 추가 가능

  - 최적화된 레지스터 갯수: 일반 RISC CPU가 많은 레지스터를 사용해 공간 낭비, ARM RISC는 필요한 레지스터만 사용

 

 

어플리케이션 프로세서 AP

-  모바일 기기에 사용되는 프로세서로 PC에 사용되는것과는 다름. 스마트폰이 나오면서 OS, 게임, 멀티미디어가 중요해져 어플리케이션에 특화하는 쪽으로 설계되 AP라 부름.

- ex : 퀄컴 스냅 드래곤, 삼성 엑시노스, 엔디비아 테그라

퀄컴 스냅드래곤

 

 

ARM Cortex

- 초기 저전력 위주 ARM7/9/11 설계에서 용도별로 구분한 시리즈

- ARM Cortex-A : Non-RTOS와 어플리케이션에 특화된 프로세서

- ARM Cortex-R : RTOS와 실시간 시스템에 특화됨

- ARM Cortex-M : 저가, 저전력에 특화된 MCU

 

 

 

 

ARM 아키텍처

- 다시 정리하면 초기에는 저전력 프로세서 위주였으나 용도 별로 특화된 coretex 시리즈가 나옴

- ARM RISC : 32비트 프로세서에서도 16비트 명령어 지원(thumb 모드), 조건부 명령어, 최적 레지스터 수

시리즈 아키텍처 버전 코어 기능
ARM1 ARMv1 ARM1 캐시 x
ARM2 ARMv2a ARM2 곱샘 명령 추가, 4MIPS, 8Mhz
ARM3 ARMv2a ARM2a ARM 프로세서서 최초로 캐시 사용 4k, 7MIPS, 12MHz
ARM6 ARMv3 ARM60 최초 32비트 메모리 지원, 10 MIPS, 12MHz
ARM7 ARMv3 ARM700 8k 캐시, 40MHz
ARM7500FE Soc, FPA와 EDO 메모리 커트롤러 추가(FE), 56MHz
ARM8 ARMv4 ARM810 5단계 파이프라인, 고정된 예측 분기, 84MIPS, 72MHz
ARM9TDMI ARMv4 ARM9TDMI 5단계 파이프라인
ARM9E ARMv5TE ARM946E-S 향상된 DSP, 가변 메모리 밀착형 MPU
ARM11 ARMv6 ARM1136J-S SIMD(단일 명령어 다중 데이터), 8단계 파이프라인 532-665MHz

 

 

 

ARM Cortex-A 아키텍처

- 스마트폰에 적합한 고성능 아키텍처, 이 아키텍처 + 메모리 + 제어기를 한칩 SoC에 만들어 사용

시리즈 아키텍처버전 코어 기능
Cortex-A ARMv7-A Cortex-A5 저전력 초소형 프로세서, 8단계 싱글 파이프라인
    Cortex-A7 멀티코어, 1.2GHz (ex : 엑시노스 5410)
    Cortex-A9 저전력 최적 멀티코어 프로세서(많이씀) (ex:엔비디아 테그라2)
    Cortex-A15 Armv7-A 중 가장 고성능
    Cortex-A17 Big litttle 지원
  Armv8-A Cortex-A32 32비트 기반 가장 작은 공간, MCU 소형 임베디드 시스템 중 고성능
    Cortex-A35 64비트 Armv8-A
    Cortex-A65AE 차량용 멀티스레드 Cortex-A CPU
    Cortex-76AE 자율주행차 같은 안전 어플리케이션용
    Cortex-A77 5G 솔루션, 고성능

 

 

ARM Cortex-A9 프로세서

- ARMv7 + 다중 슈퍼스케일러, 비순차 추론 8단계 파이프라인을 이용한 고성능 프로세서

- 슈퍼 스케일러 파이프라인 : 최대 성능, 저전력

- Neon 엔진 : 미디어, 신호 처리 가속화 엔진

- 부동 소수점 처리장치 : 이전 ARM FPU 성능 2배 개선

- Thumb-2 : 기존 코드 성능을 유지하며 메모리양 최대 30% 절감

- Trust Zone : 보안 어플리케이션 안전 실행 보장

- L2 캐쉬 컨트롤러 : 2MB 캐쉬 메모리까지 저 지연, 고 대역 액세스 제공

 

임베디드 시스템 개발 프로세스

- 분석 -> 설계 -> 개발 -> 테스트 -> 양산 -> 유지 보수

 

 

1. 분석

- 수요/기술 조사, 요구사항 평가, 사양, 비용, 디자인 등 정리

- output : 제품 기획서, 요구 명세서, 디자인 설계서

 

2. 설계

- 하드웨어 회로/기구/소프트웨어 설계

- output : 회로도, 기구설계도면, 소프트웨어 흐름 차트, UI 설계서

회로도 기구설계도
UI 설계서 소프트웨어 흐름도

 

 

3. 개발

- 하드웨어 PCB(printed circuit board), PBA(printed board assembly)  개발 후 SW 개발 디버깅 진행

- output : PCB, PBA, BOM, 아트웍 데이터, 소스코드

 

4. 테스트

- 기능, 신뢰성, 성능등을 시험

- ex : 유닛 테스트, HW 테스트,  통합 테스트, 필드 테스트, 환경 테스트

 

5. 양산 : 시제품 양산 - 부품 구입, PCB/SMT/기구 제작 및 포장

6. 유지보수 : 업데이트, AS

 

 

 

 

임베디드 프로세서 분류 방식

1. 명령어(시스템 구조)에 의한 분류

2. 버스 크기에 의한 분류

3. CPU 연산 장치 개수 분류

4. 아키텍처 분류

5. 용도에 따라 분류

 

 

1. 명령어(시스템 구조로 분류)

- CISC Complex Instruction Set Computer : 명령어가 길고 복잡하고 실행 사이클도 다양한 컴퓨터. 적은 명령어 사용

   ex) Interl x86(78년 인텔 8086에 사용된 아키텍처와 후속작), AMD64(x86의 64bit 확장 명령어셋 amd가 99년 발표)

- RISC Reduced ISC : CISC의 단점 개선. 명령어가 짧고, 간단, 빠름. 그렇다고 성능이 좋은건 아니며 명령어 많이 필요.

   ex) ARM, AArch64(arm의 64비트 확장 명령어셋) , RISC-V(버클리서 만든 무료 오픈소스 RISC ISA)

 

2. 데이터 버스 크기에 따른 프로세서

- 버스 크기가 클수록 많이 처리해서 좋지만, 용도나 비용, 전원 소모 등에 따라 적은 비트의 프로세서도 여전히 많이씀

- 4비트 : Intel 4004 71년 인텔에서 출시한 4비트 CPU 최초의 마이크로 프로세서

- 8비트 : PC에 사용된 Intel 8080(74년 출시), 모토로라 6800 등이 있고, MCU 용으로 8051(인텔), AVR(아트멜), PIC (마이크로칩)이 가전, 센서 등에 지금도 많이 씀.

- 16비트 : 8비트 보다 고성능, intel 8086이 78년 최초 제작(이후 186, 286 등). 32비트에 밀려 잘안씀.

- 32비트 : 가장 오래 사용됨 intel 80386, 80486, MIPS, ARM 등에서도 많이 출시

- 64비트 :  32비트 마이크로 프로세서의 확장. IA-64(intel과 hp가 개발), x86-64(amd64), armv8-A(arm의 64비트 ISA, 예시로 퀄컴 스냅드래곤, 삼성 엑시노스 등)

4비트 마이크로 프로세서 : 인텔 4004 8비트 마이크로 컨트롤러 : 아트멜사의 Atmega128
16비트 마이크로 프로세서 : 인텔 8086 32비트 마이크로 프로세서 : 인텔 80386

 

 

3. 코어 수로 분류

- 처음에는 ALU(산술연산장치/정수) 하나 뿐이었으나 필요에 따라 FPU(부동 소수점 연산)가 추가 되거나 여러개로 구성

 * 부동 소수점 : 소수점이 둥둥 떠다닌다. 지수에 따라서 소수점이 이동되서인듯 싶다.

- 클록 속도를 높이는 대신 코어를 높여 성능 향상. 싱글 코어, 듀얼 코어, 쿼드코어, 헥사 코어 등

 

 

 

4.용도에 따라 분류

- CPU(MPU) : pc or 워크스테이션에 사용됨. 제어기(명령어 해석 및 실행), 레지스터, ALU 등 구성

- MCU : cpu보다 저성능이지만 마이크로 프로세서에 메모리, 주변 장치 제어기, 입출력 인터페이스 내장. 

- DSP(digital signal processor) : 디지털 신호 처리를 위해 행렬 연산에 최적화됨. ex) 오디오, 영상 처리

* 컴퓨터가 실수 저장하는 방식  고정 소수점, 부동 소수점 : 10비트로 고정소수점은 1024개 수 표현 가능. 부동 소수점 방식에서 그 중 2비트를 자리수로 쓴다면 2^8(0~254) x 10^3(0, 10, 100, 1000) -> 25만개 표현 가능. 고정 소수점보다 세밀

- GPU(graphics processing unit) : 그래픽, 음성 신호를 다루기 위해 병렬처리에 특화되어 캐시 메모리가 작은 대신 수 많은 ALU가 덜 정밀하더라도 동시에 처리해 고속화됨. 

- FPU(floating point unit) : cpu 내에 부동 소수점 연산에 최적화된 논리회로

 

 

 

 

 

원래 KUT-128에는 LCD가 바로 연결되지 않고 LCD 커넥터에다가 연결하도록 되어있다.

시뮬레이터 상에서는 만들 필요 없으니 그냥 바로 LCD 를 연결시켜서 만들었다.

회로 자체 만드는건 어렵지는 않았는데,

LCD 써보려고 하니까 글이 잘 안읽히더라

조금 찾아보니까 이분이 LCD 내용을 잘 정리하셨더라.

https://kogun.tistory.com/23

 

AVR(ATmaga128)로 텍스트LCD 장난하기

안녕하세요 고군입니다~ 이번 시간에는 텍스트LCD에 대하여 알아보고 AVR을 사용하여 화면을 표시해보도록 하겠습니다. LCD는 저렴한 가격으로 인해 산업현장에서는 아직도 많이 사용되고 있으

kogun.tistory.com

 

내가 정리한것 보다는 위 링크 보는게 이해하기 좋을거같다.

 

 

LCD 핀

- RS 핀 : 0은 명령어, 1은 데이터  

- DB4~7핀 : 8비트 or 4비트 모드 사용가능한데 4비트 모드 사용시 이 4개 핀 사용

- RW 핀 : 0이 W, 1이 R

 

LCD 

- 레지스터들 : 8비트 IR(명령), DR(데이터)가 존재. RS핀으로 선택

- IR : DDRAM(디스플래이 데이터), CGRAM(문자 생성) 주소 설정,메모리클리어, 디스플래이 onoff 명령어 등 CPU가 쓴다.

- DR : DDRAM, CGRAM에 쓴 데이터나 읽은 데이터 일시 저장. DR에 쓴 데이터는 DDRAM, CGRAM에 써진다. 렘으로부터 읽을때 IR에 주소를 넣으면 DR에 들어옴

- Busy Flag BF : LCD가 명령 받을수 있는지 표현. BF가 1이면 못받음. 0이면 받을 수 있음.RS=0, RW=1이면 BF 읽음

- DDRAM display data ram : 8비트 문자 데이터 표시. 16 x 2 lcd이나 실제로는 최대 80글자 기억

- CGROM 문자 생성 롬 : 5x7, 5x10 크기의 도트 문자 보관. CGROM의 문자 코드를 DDRAM에 써주면 표시됨.

- CGRAM 문자 생성 램 : 사용자가 정의한 문자를 보관. 8개 까지.

- 어드레스 카운터 : DDRAM, CGRAM 어드레스 지정시 사용. 

 

아래의 링크에서도 정말 잘 정리되어 있으니 참고하는게 좋겠다.

https://electronicsdo.tistory.com/entry/ATmega128%EC%8B%A4%EC%A0%84-CLCD-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

https://electronicsdo.tistory.com/entry/ATmega128%EC%8B%A4%EC%A0%84-CLCD-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

 

코드는 그대로 한거같은데 무슨이유에서인지 동작하지 않는다..

 

아무래도 비트 단위로 적어가면서 확인해봐야겠다.

 

명령어 하나 당 실행 시간이 40us인데 40us를 대기하는게하나도 없다.

 

일단 이제 0617 00시 됬으니 잠시 중지

 

-----

 

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

//function set 인터페이스 길이, 표시 행 수, 문자 폰트 설정
// DL=1은 8비트, DL=0은 4비트, 1 or 2줄, 도트 크기
//   dl NF    -> DL = 0, NF : 10 -> 2 라인, 5 x 7도트 
// 0010 1000 
#define FUNCSET	0x28
//entry mode set 110
//I/D = 1 어드레스 + 1하고 커서 우측 이동
//S = 0, DDRAM에 데이터 쓴 후 화면 좌 또는 우이동?
#define ENTMODE	0x06	// entry mode set
#define ALLCLR	0x01	//all clear
//display on/off
// 0000 1100 = 0x0c
// 0000 1DCB 
// D= 1 display on, C=1 cursor on, B=1 cursor Blink
#define DISPON	0x0E	//display on
#define DISPOFF 0x04	//display off
#define LINE1	0x80
#define LINE2	0xC0	//2nd line move

void lcd_init();
//flash 는 flash 변수. flash 메모리에 저장
void lcd_string(char*);
void busy();
void command(unsigned char);
void data(unsigned char);

void main(){
	lcd_init();
	
	/*
	while(1){
		command(DISPOFF);
		_delay_us(100);
		command(DISPON);
		_delay_us(100);
	}
	*/
	
	lcd_string("hello! kut-128");
	command(LINE2);
	lcd_string("atmel atmega128");
	while(1);
}

void lcd_init(){
	DDRD = 0xff;
	PORTD &= 0xfb;
	
	_delay_ms(20);
	command(0x30);
	_delay_ms(10);
	command(0x30);
	_delay_ms(1);
	command(0x30);
	_delay_ms(1);
	command(0x20);
	_delay_ms(1);
	
	command(FUNCSET);
	command(DISPON);
	command(ALLCLR);
	command(ENTMODE);
}

void lcd_string(char *str){
	char *pstr = 0;
	
	pstr = str;
	while(*pstr)
		data(*pstr++);
}

void command(unsigned char byte){
	busy();	
	PORTD = (byte & 0xf0);
	PORTD &= 0xfe;
	PORTD &= 0xfd;
	_delay_ms(1);
	PORTD |= 0x04;
	_delay_ms(1);
	PORTD &= 0xfb;
	
	
	PORTD = ((byte<<4) & 0xf0);
	PORTD &= 0xfe;
	PORTD &= 0xfd;
	_delay_ms(1);
	PORTD |= 0x04;
	_delay_ms(1);
	PORTD &= 0xfb;

	/*
	busy();
	
	// 인스트럭션 상위 바이트
	PORTD = (byte & 0xf0);	//데이터
	PORTD &= 0xfe;			//rs=0
	PORTD &= 0xfd;			//rw=0;
	_delay_us(1);
	PORTD |= 0x04;			//e = 1;
	_delay_us(1);
	PORTD &= 0xfb;			//e = 0;
	
	//인스트럭션 하위 바이트
	PORTD = ((byte << 4) & 0xf0);
	PORTD &= 0xfe;
	PORTD &= 0xfd;
	_delay_us(1);
	PORTD |= 0x04;
	_delay_us(1);
	PORTD &= 0xfb;
	*/
}

void data(unsigned char byte){
	busy();
	PORTD = (byte & 0xf0);
	PORTD |= 0x01;
	PORTD &= 0xfd;
	_delay_ms(1);
	PORTD |= 0x04;
	_delay_ms(1);
	PORTD &= 0xfb;
	
	PORTD = ((byte<<4) & 0xf0);
	PORTD |= 0x01;
	PORTD &= 0xfd;
	_delay_ms(1);
	PORTD |= 0x04;
	_delay_ms(1);
	PORTD &= 0xfb;
	/*
	busy();
	
	PORTD = (byte & 0xf0);
	PORTD |= 0x01;
	PORTD &= 0xfd;
	_delay_us(1);
	PORTD |= 0x04;
	_delay_us(40);
	PORTD &= 0xfb;
	
	PORTD = ((byte << 4) & 0xf0);
	PORTD |= 0x01;
	PORTD &= 0xfd;
	_delay_us(1);
	PORTD |= 0x04;
	_delay_us(40);
	PORTD &= 0xfb;
*/
}


void busy(){
	_delay_ms(2);
	//_delay_us(400);
}

 

----------

지금 시간이 일요일 새벽 1시

결국 lcd 4비트 모드로 제어하려고 별짓을 다해봤지만 안됬다.

 

구글링해서 봐도 영어 실력이 부족해서 잘 읽혀지지가 않았다.

코드를 다 뜯어고쳐서 써보자니 이럴때는 아얘 다날리고 쓰는게 맞긴한데

그러기는 너무 싫더라

코드 바꾸기는 싫고 이래저래 시뮬레이션 시간, 딜레이 시간 조절해가면서 이래저래 시도해보다보니 시간이 이렇게 됬다.

 

며칠간 이걸로 한참 삽질했는데

그냥 디버깅 툴이랑 주변 장치 컨트롤러를 여러 라인에 딜레이 주는 식으로 어떻게 초기화하고 값을 입력시키는지 이해한걸로 만족해야 될거같다.

나중에 기회되면 다시 시도해야지.

 

이 다음에는 모터 시뮬도 돌리려했지만 타이머/카운터를 다루는 내용이 나온다.

이 부분은 학교 수업에서 진행하니 나중에 진도 나가고 하고 싶어지면 해야지.

 

일단 프로테우스 아트메가 시뮬레이션 글은 여기까지로 마쳐야겠다.

이 다음에는 임베디드 간단하고 넓게 정리해보고,

나빌로스 만들기 나 학교에 있는 임베디드 키트 가지고 놀아볼 생각이다.

임베디드 시스템

- 일반 PC 같은 범용 목적과는 달리 특수 목적용에 맞게 최적화되어 설계된 시스템

- 특수 목적 예시 : 가전(TV, 냉장고 등), 산업용, 특수 환경(군용, 위성)

https://jeongchul.tistory.com/90

 

임베디드 HW

1. 임베디드 프로세서

- 사용 환경에 맞게 저전력화 하거나 고사양으로 설계함.

- SoC : CPU 뿐만 아닌 타이머, 인터럽트/DMA/ LCD 컨트롤러 등을 하나의 칩에 집적하여 크기와 원가절감

- 프로세서 선정 기준 : 재고나 단종 여부, 단가, 동작 환경, 속도, 실시간성 등을 고려한다.

 

2. 임베디드 기억 장치

- 휘발성 : SRAM(고가, 고속, 캐시메모리), DRAM(저가, 상대적 저속, 저렴, 주기억장치)

- 비휘발성 : EEPROM(고가, 소용량 데이터/프로그램 저장), NAND Flash(저가, 데이터 저장)

 

3. 임베디드 입출력 장치

- IO 컨트롤러는 시리얼 혹은 네트워크로 IO 장치와 디지털 or 아날로그로 통신, CPU와는 디지털로 통신

 

 

 

임베디드 SW

- 부트로더(Bootstrap loader) : 운영체제를 주기억 장치에 적재

- 디바이스 드라이버 : 하드 디스크, 어뎁터, 모니터 등 디바이스 제어를 위한 프로그램.

 + 디바이스는 디바이스 본체와 제어기로 구성. 제어기가 디바이스 드라이브와 디바이스 사이 인터페이싱

- 운영 체제 : 자원 관리, 스케줄링

- 부트 코드 : 시스템 시작 시 하드웨어 초기화, SW 동작 설정하는 프로그램.

 

실시간 임베디드 시스템

- 실시간이면서 임베디드인 시스템. 주어진 시간 제약내에 결과를 내야 함.

- Hard 실시간 임베디드 시스템 : 시간 제약 내 처리하지 못하면 큰일나는 시스템. 무조건 지켜야함.

  ex) 미사일 제어기, 자동차 에어백 등

- Soft 실시간 임베디드 시스템 : 큰일은 나지 않지만 성능 저하

  ex) 동영상 플레이어, 통신기기

 

임베디드 운영체제 종류

- Firmware : OS를 사용하지 않은 SW. 단순한 작업이라 테스크가 적고 순위 부장이 필요없는 경우.

- 실시간 운영체제 RTOS :실시간성(정한 시간 내 결과 출력)을 보장하는 운영체제, 선점형 멀티테스킹, 모듈화와 라운드 로빈 스케쥴링 따름. 예시로 NEOS, velos 등

- Non-RTOS : 여러 태스크가 같은 자원 사용시 OS가 중재(비선점형), 예시로 Windows CE, 임베디드 리눅스 등

 

 

 

 

 

 

아날로그 비교기 추가

- 우측 아래에 가변 저항 2개가 AIN0, AIN1에 연결되어 있다.

 

아날로그 비교기 예제 1

- 풀링 방식으로 비교 후 LED shift

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>


/*
AIN1 핀 가변 저항과 AIN0 핀 가변저항 조절
AIN0 >= AIN1 -> LED 순차 점멸
아날로그 비교기 출력 ACO를 풀링으로 체크
*/
unsigned char led = 0xfe;

int main()
{
	DDRC = 0xff;
	DDRE = 0b00000010; //AIN(PE2), AIN1(PE3) 입력 설정
	ACSR = 0x0; // Analog Comparator Control and Status Registor
	SFIOR = 0x0; // Special Function IO Registor 
				 // 3번째 비트 ACME = 0 -> AIN1에 음 입력 전압
	
	PORTC = led;
	
	while(1){
		if(ACSR & 0x20){ // ACSR의 0x20 = ACO 아날로그 비교기 출력 비트가 1인지 확인
			led <<= 1;
			led |= 0x01;
			if(led == 0xff)
				led = 0xfe;
			PORTC = led;
			_delay_ms(1000);
		}
		
	}
}

 

풀링 방식은 잘 되는데,

인터럽트 방식에서는 토글이 잘 안되선지 인터럽트가 한번만 동작하고 만다. 그냥 pass

 

 

ADC도 fnd 쓰기도하고, 입력 받는데서 자꾸 워닝뜨길래 pass

 

 

 

USART

- atmega128에서는 USART 2개 내장, 클럭부, 송신부, 수신부로 구성

- 관련 레지스터로 UDR(IO 데이터 레지스터), UCSRA/B/C(제어 상태 레지스터) 3개, 보레이트 레지스터 UBRRH, UBRRL 2개로 총 6개

- UDR을 송신 데이터 버퍼 레지스터, 수신 데이터 버퍼 레지스터 두 용도로 사용, 같은 주소를 가지나 실제로는 분리되어 송신시 송신 데이터 버퍼 TXBn에 쓰고, 수신시 수신 데이터 버퍼 RXBn의 값을 읽는다.

 

USART 데이터 포맷과 통신 순서

1. 제어 레지스터로 통신 설정(동기/비동기, 데이터 비트 수, 정지 비트수 등)

2. 보레이트 레지스터로 전송속도 설정

 

 

 

USART를 추가한 KUT-128 회로

- 주의사항 : virtual terminal에서 rx/tx polarity를 inverted로 설정해야한다. normal로 했더니 보드레이트나 클럭을 잘 맞춰도 글자가 깨진다.

- 이걸 normal로 해놓고 rxd, txd를 거꾸로 연결해도 동작이 안된다.

 

USART 송신 하기

- 보레이트 9600bps, 정지비트 1비트, 패리티 x, 비동기 데이터 8비트

- 추가 : 아 그냥 문자열만 주면 줄바꿈이 안되서 뒤에 \r\n을 추가했다.

ref : https://www.avrfreaks.net/forum/uart-newline-n-issue

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

void putch(char);

int main()
{
	char str[] = "This is USART0 control program\r\n";
	char *pstr;
	
	UCSR0A = 0x0;
	UCSR0B = 0b00001000;	//송신 인에이블 txen = 1 ->TxDn이 범용 IO포트가 아닌 송신 단자로 동작
	UCSR0C = 0b00000110;	// 비동기 데이터 8비트 모드	bit2/1 전송 데이터 비트 수 설정 11 -> 데이터 전송 8비트
	//UBRR 보 레이트 레지스터
	UBRR0H =0;				//Xtal = 16hz시 buad = 9600
	UBRR0L = 103;
	
	pstr = str;
	while(1){
		while(*pstr){
			putch(*pstr++);
			_delay_ms(1000);
		}
		pstr = str;
		_delay_ms(1000);
	}
}


void putch(char data){
	/*
	UDRE0 = 1?   UCRS0A의 5번째 비트 UDRE
	USART Data Register Emtry로 비어있으면 1 = 송신 준비 완료 인터럽트 발생
	*/
	while(!(UCSR0A & 0x20)){
		_delay_ms(1000);
	}
	// st -> 0 ~ 7(8개 데이터비트) -> (페리티 설정 x) -> stop bit(현재 1개)
	UDR0 = data;				// USART IO register에 데이터 전송
}

 

 

 

virtual terminal test 하기

 USART 송신 후 송수신 실험을 하려고 했는데, 입력을 해도 제대로 동작이 안됬다.

terminal에 입력한게 재대로 전송이 되고 있는지 확인하기 위해 잠깐 구글링 해봤더니

두 터미널을 연결해서 타이핑하면 반영이 되더라 아래 링크는 그 내용

ref: https://electronics.stackexchange.com/questions/420487/cant-type-on-virtual-terminal-proteus

추가 : 또 보다보니 실제 COM 포트를 프로테우스 시뮬레이션 상으로 연동해주는게 있었다.

기회되면 한번 만져봐도 좋을거같다.

ref : https://www.theengineeringprojects.com/2013/05/how-to-use-virtual-terminal-in-proteus.html

 

 

USART 송수신 테스트

- 지금 실제 kut-128 키트가 아닌 proteus 시뮬레이션 환경에서만 사용하다보니, 예제처럼 제대로 동작되지 않는다.

- 애초에 가상 터미널 1개에다가 송신 모드로 잡아놓고  쓰다보니 그 터미널을 echo type 설정을 해서 쓴다고 USART0로부터 값을 수신을 못하니 원하는데로 동작안하는게 당연했다.

- 그래서 atmega128에서는 USART 2개가 제공되므로 가상 터미널 2개를 놓고, 하나는 타이핑 입력 송신 터미널, 남은 하나는 결과 수신 터미널로 잡고 약간 회로와 코드를 변경해서 구현했더니 잘 동작하더라.

 

 

- 천천히 칠땐 괜찮지만 비동기 통신에다가 패리티 체크도 안하다보니, 타이핑을 빠르게 하면 수신 터미널에서 제대로 전달받지 못한다.

 

 

 

마지막으로 이걸 인터럽트로 바꿔보자

고치다가 찾은건데 USART 하나로 송수신 할수 있더라.

이게 전이중 방식이 가능한걸 잊었다.

----

인터럽트 처리가 잘 안되서 일단 여기까지 하고 해결하면 추가 예정

 

--------

220616-1821

아직 인터럽트 문제는 해결 못했고, 아래 표의 포멧처럼 USART 데이터가 날라가는지 보기위해 한번 실험해보았다.

전송 속도는 9600bps이니까

1bit 전송에 대강 0.1ms 정도 걸리겠다.

아래의 코드 대로 first, second, third 처럼 찍어서 보내게 했다.

 

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>


unsigned char first = 0b00110001;
unsigned char second = 0b00110010;
unsigned char third = 0b10000001;
unsigned char fourth = 0b10100101;

int main()
{
	DDRC = 0xff;
	PORTC = 0xff;
	// 송신 to ocsil
	UCSR0A = 0x0;
	//송신 완료 인터럽트 벡터 인에이블, 송신 인에이블 txen = 1 ->TxDn이 범용 IO포트가 아닌 송신 단자로 동작
	UCSR0B = 0b01001000;
	// 비동기 데이터 8비트 모드	bit2/1 전송 데이터 비트 수 설정 11 -> 데이터 전송 8비트
	UCSR0C = 0b00000110;
	//UBRR 보 레이트 레지스터
	UBRR0H = 0;	
	UBRR0L = 103;

	while(1){
		putch(first);
		_delay_ms(20);
		putch(second);
		_delay_ms(20);
		putch(third);
		_delay_ms(20);
		putch(fourth);
		_delay_ms(1000);
	}
}

void putch(char data){
	while(!(UCSR0A & 0x20));
	UDR0 = data;
}

 

프로테우스에서 제공하는 오실로스코프 크기 조절이 안되서

일단 전체 USART 데이터를 볼수 있도록 스케일을 낮춰놨다.

대강 1bit당 0.1ms 가까이 나온다.

 

 

unsigned char first = 0b00110001;
unsigned char second = 0b00110010;
unsigned char third = 0b10000001;
unsigned char fourth = 0b10100101;

 

first 변수에는 1을 2진화 한 값을 담아 보냈다.

이걸 USART 프레임으로 만들면 데이터는 8비트, 스탑 비트 스타트비트는 각각 1개이니 총 10비트로

9600bps이므로 1개는 0.1ms 이고, 10개이므로 1ms 정도 걸린다.

 

max232에서는 반전된 결과가 나오고 있어서 원래 뒤집히도록 나오는걸 알고 있었지만

왜 데이터 비트자리에 0b00110001를 반전해서 안나오나 싶었는데

위의 프레임 포멧을 자세히 보면 데이터 비트 LSB가 가장 앞에서 나오고 있으므로

00110001이 반대로 10001100으로 나오고 앞뒤로 스타트 스탑 비트가 붙는거였다.

  

 

 

 

나머지 값도 이런식으로  나올테니 넘어가고

원래는 왜 인터럽트 처리가 안되는지 보려고 했는데

지금 와서 보니까 이전에 저장한 프로젝트의 코드까지 현재 코드의 내용들로 덮어씌워져서 다날라갔다.

여기다가 중간 중간에 코드블록 해서 올렸는데, 폴링 방식으로 송수신한 코드도 사라졌다.

 

일단 USART는 여기까지 봤으니 통신은 넘어가고 나머지 하드웨어도 다뤄봐야겠다. 

+ Recent posts