태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

쭈중이 교육용 STL 예제를 만들어봄.

2010/04/09 11:44
결과는 http://codepad.org/e8w9rAF8

그냥 간단하게 vector/list/map/pair 조금 써서 삽입삭제/이터레이터 정도만.

그냥 맛보기용 샘플.

// Made by YuriHan. 2010.04.09.
// YuriHan's Dream Factory(TM)
// http://blog.yurihan.net/

#include<vector>
#include<string>
#include<list>
#include<map>
#include<utility>	// pair
#include<algorithm>

using namespace std;

void usingVector();
void usingList();
void usingMap();
void usingPair();

int main(void)
{
	usingVector();
	usingList();
	usingMap();
	usingPair();
}

void usingVector()
{
	printf("----------vector----------\n");

	vector<int> vec;
	vec.push_back(123);
	vec.push_back(456);
	vec.push_back(789);

	for(unsigned int i=0;i<vec.size();i++)		// size는 내부 데이터의 갯수.
		printf("vec[%d] = %d\n",i,vec[i]);	// 배열처럼 접근 가능.
	
	// iterator 는 반복자. 이터레이터를 이용해 내부 데이터를 순회할 수 있음.
	// vec.begin()은 첫번째 객체의 이터레이터를 리턴.
	// vec.end()은 마지막 객체 +1의 이터레이터를 리턴.
	// 역방향 이터레이터도 존재함. rbegin / rend
	// 이터레이터로 다음 객체에 접근할때는 증감연산자 사용. --는 이전. ++는 다음.
	// ++it 는 내부에서 복사가 일어나지 않지만 it++는 내부에서 복사가 한번 일어나니 오버헤드가 좀 있음. (모든 연산자 오버로딩에 해당.)
	int i=0;
	for(vector<int>::iterator it = vec.begin() ; it != vec.end() ; ++it ) // 전체 데이터 순회
		printf("vec[%d] = %d\n",i++,*it); // *연산자가 오버로딩 되어있음. 요소를 꺼냄.

	vec.clear();

	return;
}

void usingList()
{
	printf("---------- list ----------\n");

	list<int> lst;
	lst.push_back(123);
	lst.push_back(456);
	lst.push_back(789);

	// 배열처럼 접근 불가.
	int i=0;
	for(list<int>::iterator it = lst.begin() ; it != lst.end() ; ++it ) // 전체 데이터 순회
		printf("list[%d] = %d\n",i++,*it); // *연산자가 오버로딩 되어있음. 요소를 꺼냄.

	// 두번째 요소 삭제
	list<int>::iterator iterase = lst.begin();
	++iterase; // advance(iterase,1);
	lst.erase(iterase);
	i=0;
	for(list<int>::iterator it = lst.begin() ; it != lst.end() ; ++it ) // 전체 데이터 순회
		printf("list[%d] = %d\n",i++,*it);

	//삽입
	list<int>::iterator itinsert = lst.begin();
	advance(itinsert,1);	//++itinsert; 
	lst.insert(itinsert,456);
	i=0;
	for(list<int>::iterator it = lst.begin() ; it != lst.end() ; ++it ) // 전체 데이터 순회
		printf("list[%d] = %d\n",i++,*it);

	lst.clear();

	return;
}

void usingMap()
{

	printf("---------- map ----------\n");

	// 선언은 map<key,value> 
	map<string,int> mapp;

	// 맵에 추가
	// 배열처럼 추가하면 됨. [] 안에는 키, 뒤쪽에는 값. map[key] = value;
	mapp["abc"] = 123;
	mapp["def"] = 456;
	mapp["ghi"] = 789;

	//배열처럼 접근하면됨
	printf("abc : %d\n",mapp["abc"]); // 키가 abc 인것을 리턴
	printf("def : %d\n",mapp["def"]); // 키가 def 인것을 리턴
	printf("ghi : %d\n",mapp["ghi"]); // 키가 ghi 인것을 리턴
	// 주의할점.
	// 추가되어있지 않은 키값을 리턴받으려고 할 경우,
	// ( 예 - printf("asdf : %d",mapp["asdf"]); )
	// map은 asdf라는 키값을 "생성"하고 value 는 기본 값을 리턴한다. (value가 int 이면 0을 리턴)

	// 그래서 요소가 있는지 찾을때는 find 를 사용. find는 이터레이터 리턴.
	
	map<string,int>::iterator itfind;
	itfind = mapp.find("abc");
	if(itfind != mapp.end()) // 요소가 없으면 map.end()를 리턴.
		printf("%s : %d\n",itfind->first.c_str(),itfind->second);	//first 가 key값 second 가 value값
	itfind = mapp.find("def");
	if(itfind != mapp.end())
		printf("%s : %d\n",itfind->first.c_str(),itfind->second);
	itfind = mapp.find("ghi");
	if(itfind != mapp.end())
		printf("%s : %d\n",itfind->first.c_str(),itfind->second);
	
	// it->first 는 (*it).first

	for(map<string,int>::iterator it = mapp.begin() ; it != mapp.end() ; ++it ) // 전체 데이터 순회
		printf("%s : %d\n",it->first.c_str(),it->second); // 내부에서 검색을 위해 마음대로 정렬해놓음. 넣은순서와는 관계없이 나옴.

	mapp.clear();

	return;
}

void usingPair()
{
	//구조체 만들기 귀찮을때 씀.
	//두가지의 데이터를 하나로 묶어서 관리.
	printf("---------- pair ----------\n");

	vector<pair<string,int> > vecpair; // 이렇게 선언할때는 vector<pair<string,int>> 로 하면 끝부분 >> 를 연산자로 판단해서 에러 남.. 그래서 > > 로 한칸 띄어줌.

	vecpair.push_back(make_pair("abc",123));
	vecpair.push_back(make_pair("def",456));
	vecpair.push_back(make_pair("ghi",789));

	for(unsigned int i=0;i<vecpair.size();i++)		
		printf("%s = %d\n",vecpair[i].first.c_str(),vecpair[i].second);	// first , second 로 접근.	

	for(vector<pair<string,int> >::iterator it = vecpair.begin() ; it != vecpair.end() ; ++it ) // 이터레이터도 마찬가지.
		printf("%s = %d\n",it->first.c_str(),it->second);	// first , second 로 접근.

	vecpair.clear();

	return;
}




진리는 http://www.cplusplus.com/reference/stl/
크리에이티브 커먼즈 라이선스
Creative Commons License

유리한 땜쟁이/저작

  1. 어머 친절한 오빠네~

  2. 코딩셔틀

  3. Blog Icon
    잘난코

    어머 친절한 아빠네~

유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #End. 인생은 도박.

2009/09/23 13:06



DCINSIDE 프로그래밍 갤러리 연재.

링크정리 -
http://gall.dcinside.com/list.php?id=programming&no=49897






마지막 강좌는 그냥 이것으로 대체하겠다.

ADC라던지 SPI라던지.. 남은 분량은 산더미 이지만..

지금까지 휘갈겨 쓴 개념이면 알아서 습득하리라 애써 자위해본다..

뭐 이미 싼 강좌..ㅠㅜ




갑작스럽게 선물로 줄것이 필요해졌다.

그래서 닥치고 만들기 시작한 Shake Dice~!

흔들면 숫자가 나오는 주사위다.

점심시간에 밥값내기를 하던

쉬는시간에 커피내기를 하던

퇴근시간에 술내기를 하던

야비군 훈련가서 야바위를 하던

알아서 잘 이용해먹기 바란다.





목표는 월요일 완성 화요일 택배 수요일 도착..



일단 일이 급하니 엘레xx 에서 잽싸게 퀵으로 부품을 주문했다.

대략 3시간만에 받은듯.. 따끈함이 느껴지나?




부품은 대략 ATMega8 / Tilt Switch / 3V 동전형 건전지 / 스위치 등등..

작업시작시간은 퇴근후부터.

일단 닥치고 일하는거다?






자. 퇴근시간이다. 닥치고 작업다이에 부품올리고 땜질 시작

하려는데.. 배가 고프다.

다 먹고살자고 하는짓.






오늘의 메뉴는 볶음밥. 일단 먹고 보는거다?







일단 모서리를 잘 잘라주고.. LED를 일곱개 박는다.

깔끔하게 땜질해서 다리를 잘라내고..





벼..별로 깔끔하게 땜이 되질 않았네?

이런건 다 내공이 부족한 탓이야..

거 뭐시기 고온에도 견디는 땜용 양면테이프가 있어. 20장에 오천원인가..

그거 조그맣게 잘라서 붙이고 그 위에 ic를 살포시~ 붙여주면 ㅇㅋ.


그리고 얇은 점프선(혹은 래핑와이어 라고도 하지)으로 땜질을 시작하는거지.




LED를 저항(array저항을 썼어.)이랑 연결하는중..

내가 좀 수전증이 있어서.. 식은땀이 줄줄나지.

양쪽 귀퉁이에 구멍 내는건





드릴머신..

까지 이용할 필요는 없고 그 근처에서 그냥




핸드드릴로 뚫으면 된다. 우왕ㅋ굳ㅋ





밑판에는 슬라이드스위치(전원on/off용) Tilt 스위치(기울기 스위치.. 15도 이상 기울이면 접점이 붙어.) 콘덴서 한놈, 밧데리 홀더를 달아줬어.

땜질도 어느정도 되어가는중. 땀이 삐질삐질 눈물이 찔끔찔끔..

근데 저렇게 보니까 얼마나 빡센지 잘 안느껴지지?































존나 빡세.

더이상 표현할 말이 없어.

악!짜증!






내공이 현저히 딸리는지라 고수들처럼 깔끔한 마무리가 안된다..

그보다 atmega8의 0.65미리의 압박.. 다리사이 간격이 0.65미리임..

기타 다른 수동소자를 붙이지 않은 이유라면..

내부 발진자가 있어서 크리스탈 (클럭을 만들어주는놈.. 뭐 심장박동이라고 생각하면 좋겠지?)을 따로 달 필요가 없다.(물론 내부발진은 1MHz밖에 안됨. 외부달면 16MHz던가..12MHz던가..)
뭐 원체 자리가 좁아서 더 달수도 없고..





윗면 완성된 모습..

대략 땜질 완성시간이 12시경..

밥쳐먹고 DC질 하면서 땜질하니 시간이 오래걸렸어..ㅠㅜ




근데..


다..

완성했다고...

좋아했는데..

인식 불가..


다운로드가 안된다..

아니, 인식조차 안된다..ㅠㅜ

회로를 아무리 수정해도.. 도통 방법이 없다..

내공부족으로 ic를 죽여먹은건가..
(인두 오래 대고있으면 ic는 금방 끽~ 고온에 약함.)








회사에 있던 변환기판을 몰래 빼돌려서 사이드를 자르고 위에다 붙였다..

저러면 인두를 대고있는 시간이 현저히 줄거라는 기대에..ㄲㄲ


완전히 퍼져서 사진을 안찍었다..ㅡㅡ;;

그것 뿐만이 아니라..

납땜이 제대로 날림이다.

아까것도 개판인데 이건 더 개판!!

특히나 밑판 뒷면만 봐도 이건 뭐..ㅠㅜ



하여간 납땜완료하고 라이팅 확인하고나니 새벽세시를 넘겼음!!


일단 집으로 ㄱㄱㅆ~~








오늘 짬내서 테스트한것..








이것이 변환기판..

같이 주문했는데 재고가 없었던 관계로..

어제 퀵으로 안오고 오늘 왔다.


저걸로 땜질을 다시 할까..하다가 포기.

그냥 이놈으로 가기로 하고..

퇴근시간 넘어서..밥먹고..

대략 두시간동안 닥코딩해서..

완성..

물론 코드는 내가봐도 캐안습 ㄲㄲ

시간만 있었어도..ㅠㅠ

결국 택배는 포기. 내일 퀵으로 서울로 올려보낸다. ㄲ










소스는 너무 간단하고..

회로도도 간단한데..

내가 설명해주는것보다는

네이버에서 검색하는게 좋을거다.

당근이의 avr에서 주사위 검색하면

당근이 님하고 알피0님 꺼 봐라.

내공차이 ㅎㄷㄷ;;



참고로 그쪽 카페의 '유리한' 님과 나는 동닉이인이다.
크리에이티브 커먼즈 라이선스
Creative Commons License

유리한 땜쟁이/저작 avr

  1. 오웅 저도 당근 카페 가입했었는데, 잘보고 갑니다 ㅎㅎ

    저도 센서 모트 갖고 놀때마다 느끼지만, 진리는 데이터시트임 ㅠㅅㅠㅋㅋㅋ

    다음엔 가속도 센서 어떠심?!ㅋ

  2. 더러운 임베에서 해방된지 일년 팔개월이 지났습니다.
    지금은 솦트업체에서 근무중.

  3. 읭?! 게시일만 보구 근황인지 알았네여,

    저능 인제 발을 들여야 할 타이밍임 -ㅅ-;

  4. 믹시쪽 업뎃이 안되서 게시일만 최신으로 바꿈.
    그냥 끌어올리기 한거임. 링크 타고 실제 연재된 날짜를 확인하라능.

    2007-06-26 15:02:09 에 첫 강좌글이 올라왔고
    2007-10-16 23:14:19 에 마지막 강좌가 끝났음.

    2007-11-23 09:39:15 에 링크 정리.

  5. 예전 강좌였네영ㅋ
    링크 타고 가봤는데,
    좀 훈훈하고 좋네요 -ㅅ-b

유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #9. 돌아라~

2009/09/23 13:05



DCINSIDE 프로그래밍 갤러리 연재.

링크정리 -
http://gall.dcinside.com/list.php?id=programming&no=49897






한번 삭제 됐다가 알바한테 찌질대서 다시 살려낸 게시물.

지금 또 짤릴까 걱정되서 짤방은 그냥..

(물론 개념없는 듣보잡 찌질이가 신고한걸 무개념 먹튀알바가 확인없이 날린거였겠지만
그래도 바꿨다.)

그리고 인간적으로 관심 1g 좀.. 맆흘수가 어째..






유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #9. 돌아라~


벌써 9번째 강좌 되시겠다.

별로 올린것도 없는데 9번째 강좌라니..

감동이다.

오늘 진도는 모터에 관한 내용이다. 로봇을 만들때는 필수지.

자, 흔히 MCU로 제어하는 모터는 크게 세가지.

DC모터, 스테핑모터, 서보모터 가 있겠다.


<DC기어모터>

<스테핑모터>

<서보모터>
(사진출처 : 엘레파츠)

사진을 보면 대충 감이 오나?

dc모터는 그냥 미니카에 들어가던 모터. 일명 문방구 모터 되시겠다.

사진에 있는건 기어를 달아놔서 속도는 느려도 힘은 작살인 기어모터 되시겠다.

dc모터의 선은 두가닥이다. 말안해도 알겠지? 전원을 어느 라인에 걸어주느냐에 따라서

회전 방향이 바뀐다.

주의할점은 io포트에 다이렉트로 엮으면 역기전류때문에 칩이 뒈질수가 있다.

포토커플러나 TR, FET같은걸로 전원단을 분리해주는게 좋다.

(간단하게 io포트 출력으로 스위치를 껐다 켰다 하듯이 조절하라는거다.)

이건 스테핑모터도 마찬가지다.

스테핑모터를 보자면 좀 묵직하게 생겼다.

뭐하는 놈인고 하니 나름 정확한 각도제어가 가능 하시겠다.

선을 보면 6가닥으로 되어있다. 전원/접지를 제외하면 남는핀은 네개.

신호선이 네가닥 되시겠다.

A,  B, /A, /B 로 표현하는데.. 번갈아가면서 신호를 주면 돌아간다.

뭐 구동방법은 몇가지가 있긴한데.. 용어는 기억이 안난다.ㅋ

하여간.. 간단히 알아보자.

A B /A /B 순으로 나간다.

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

이렇게 주는 방법이 있지만 좀 부드럽지 못하다는 단점이 있지.

그래서 나온 방식이

1 1 0 0
0 1 1 0
0 0 1 1
1 0 0 1

이런 방식이나

1 0 0 0
1 1 0 0
0 1 0 0
0 1 1 0
0 0 1 0
0 0 1 1
0 0 0 1
1 0 0 1

같은 방식이 있겠고..

1 1 0 0
1 1 1 0
0 1 1 0
0 1 1 1
0 0 1 1
1 0 1 1
1 0 0 1
1 1 0 1

이라던지..

뭐 맘에 드는 방법으로 써라.

간단하게 소스 나가신다.

 1
 2
 3 /*  초단순 스텝모터 드라이빙 함수
 4  *  Step Moter == PORTD
 5  *  A   -   0x01    PD0
 6  *  B   -   0x02    PD1
 7  *  /A  -   0x04    PD2
 8  *  /B  -   0x08    PD3
 9  */
10
11
12 #define     MOT_PORT    PORTD
13 #define     FORWARD     1
14 #define     BACKWARD    -1
15
16 void Step_Mot(char Direction,int Delay_Time)
17 {
18     static signed char Mot_Step=0;
19
20     if(Direction==FORWARD)
21         ++Mot_Step;
22     else if(Direction==BACKWARD)
23         --Mot_Step;
24     else return;
25
26     if(Mot_Step==-1)
27         MOT_Step=3;
28     if(Mot_Step==4)
29         Mot_Step=0;
30
31     MOT_PORT=1<<Mot_Step;
32     delay_ms(Delay_Time);
33
34     return;    
35 }
36



지금 대충 만들어서 잘 돌아갈지는 장담 못한다.
뭐 이런식으로 돌리면 된다는걸 말해주는것 뿐이다.
딜레이는 필수로 줘야되는데, 안주면 뭐 안돈다. 속도생각해서 알맞게 주도록 하고..
저놈 사용하려면 for(i=0;i<1000;++i) Step_mot(FORWARD,100); 형태로 루프 돌려야 된다. ㅇㅋ?

A -> B - > /A -> /B 까지 한사이클을 돌면 1.8도가 움직이는거야.

180도를 움직이고 싶다면 100번 사이클을 돌려주면 되는거지. 저 함수의 경우에는 100*4 번 돌리면 될테고. ㅇㅋ?

추가하자면, 따로 IC칩을 쓰면 알아서 신호를 돌려주는 놈도 있다. 전류값에 따라 알아서 신호를 준다더라. 써본적 없으니 패스.


자, 이제 서보모터 한개 남았다.

어디다 쓰는 놈이냐? -90~+90도 까지 180도 밖에 안움직인다.

디지털 도어락에도 사용되고

로봇 관절에 사용된다. 자동차 와이퍼도 서보모터 쓰던가?

원운동이지만 직선운동도 가능하게 할수 있다.

이놈은 선이 세개다.

역시 전원 1 접지 1 한개는 신호선.

근데 디지털 신호가 아니라 아날로그 신호다.
(물론 디지털 서보나 rs-232나 485를 지원하는 서보도 있다더라. 써본적 없으니 역시 패스.)

20ms 주기로 0.7~2.3m 까지 PWM 신호를 주면 -90~+90 까지 움직인덴다.
(PWM개념은 초반 강좌에 있을꺼다.)
 
지금은 테스트할 방법이 없으니

역시 발로 짠 소스를 보자.

 1
 2 // 비트 토글
 3 #define     ServoOn     PORTD|=0x01;
 4 #define     ServoOff    PORTD&=~0x01;
 5
 6 ISR(TIMER0_OVF_vect)
 7 {
 8     static unsigned int cnt;
 9     TCNT0 = 0x00;  //계산하기 귀찮아. 하여간 100us.
10     if(cnt<200)
11         cnt++;
12     else cnt=0;
13     if(Servo<cnt)
14         ServoOn;
15     else ServoOff;
16 }
17

주기는 알아서 100us로 맞춰라. 자세한 내용은 강좌 중 delay 부분에 있다.

100us * 200은 20ms 되시겠고..

0.7~2.3이라고 했으니 서보모터를 움직이고 싶을때 Serv0 값을 7~23 까지 주고싶은데로 주면

-90~+90까지 움직이겠지?



오늘 강좌는 이것으로 끝이다.

사족을 붙이자면 dc모터 속도제어도 PWM 방식으로 가능하다.

스텝은 딜레이 따라 속도가 달라지고

서보는 속도조절 그딴거 업ㅂ다



다들 즐거운 하루 되시라

난 휴가 마지막 날이다..ㅠㅠ

그리고 캐생키들

관심좀..ㅠㅠ 굽신굽신

뻘글도 맆흘이 두자린데 이건뭐..


다음번 강좌는 뭘로할까?

초음파센서나 할까?

adc도 해야되나..?


크리에이티브 커먼즈 라이선스
Creative Commons License

유리한 땜쟁이/저작 avr

유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #8. L ! C ! D !

2009/09/23 13:05


DCINSIDE 프로그래밍 갤러리 연재.

링크정리 -
http://gall.dcinside.com/list.php?id=programming&no=49897




유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #8. L ! C ! D !



싸지 않기위해 자신을 다잡고 있다

근데 숏나 귀찮은건 어쩔수 없더라.

하여간 말이다, 횽이 지금 CLCD 보유하고있는게 없어..

공돌이 특성상 이것저것 모아놓는 습관이 있어야되는데..

이상하게 CLCD가 없다. (부품욕심이 좀 있긴한데..요상하다..)

그렇다고 TFT를 하자니 회로 수정하기 귀찮고 강좌쓸 엄두가 안난다.

GLCD를 하자니 땜질이 잘못 됐는지 화면이 너무 흐려.

그냥 CLCD 가자. 소스는 예전에 만들어놓은거 쓰고.

(CLCD 굉장히 중요해. CLCD가 중요한건 아닌데 대부분의 모듈이 이것과 거의 같은 방식으로 동작해.)


/*
CLCD - Character LCD. 그냥 글자만 나오는거. 16x2를 많리쓴다. 16칸x2줄
GLCD -  Graphic LCD. 그림도 그릴수 있다. 보통 128x64(픽셀) 사이즈를 많이 사용..
TFT 는 말 안해도 알지? STN타입은 나도 써본적없으니 패스..
*/


http://blog.naver.com/meelin/50008650683 참고해라.


http://blog.naver.com/meelin/50018421989 요놈은 TFT-LCD.

그럼 소스부터 나간다.(첨부파일 참조)

/* avr-gcc로 C++ 컴파일 된다는 얘기를 듣고
   C++ 하루 공부해서 만든 나름 C++ 소스..
   그냥 처음으로 짜본 C++프로그램이니까 태클걸지마.
   레퍼런스 안쓰고 포인터 썼다고 까면 맞는다.*/


/* Header File */

/************************************************
*                                                                                               *
*                       YuriHan's Dream Factory™                       *
*                                                                                               *
*                       Made By, Choi Hyun Seok.                        *
*                                                                                               *
*                       "   LCD_Device_Module   "                       *
*                                                                                               *
*                                                                       version 1.0     *
*                                                                       2006.11.22      *
************************************************/


enum onoff{on,off};


class LCD_Module
{
        private :
                void rsw(unsigned char rsw_switch);
                void E_Pulse(onoff sw); // E펄스를 조작. rs와 rw, 데이터를 입력후 불러옴
               
                unsigned char cs_pos;
                volatile uint8_t* LCD_DATA;
                volatile uint8_t* LCD_RSW;


        public :
                void LCD_init(volatile uint8_t* RSW_Port,volatile uint8_t* DATA_port);
                void print_str(char* string);
                void print_char(char* ch);
                void LCD_ON_OFF(unsigned char on1off2);
                void ReturnHome(void);
                void Cursor_Position(unsigned char x,unsigned char y);
                void LCD_clear(void);
//              void fputc(char* ch);
};


/* Cpp */

/************************************************
*                                                                                               *
*                       YuriHan's Dream Factory™                       *
*                                                                                               *
*                       Made By, Choi Hyun Seok.                        *
*                                                                                               *
*                       "   LCD_Device_Module   "                       *
*                                                                                               *
*                                                                       version 1.0     *
*                                                                       2006.11.22      *
************************************************/


#include<avr/io.h>
#include<util/delay.h>
//#include<stdio.h>
#include"LCD_Device_Module.h"

void LCD_Module::E_Pulse(onoff sw)
{
        _delay_ms(2);
        switch(sw)
        {
                case on :
                        *LCD_RSW = *LCD_RSW | 0x04; //xxxx x1xx ON
                        break;
                case off :
                        *LCD_RSW = *LCD_RSW & 0xFB; //xxxx x0xx OFF
                        break;
        }
        _delay_ms(2);
}

void LCD_Module::rsw(unsigned char rsw_switch) //rs와 rw의 상태를 변경. 따로 함수지정 안하고 한큐에 선언했습니다.
{
        switch(rsw_switch) // s값을 먼저 적고 w값을 적으면됩니다. 00,01,11,10.
        {
                case 00 :
                        *LCD_RSW = *LCD_RSW & 0xFC; //xxxx xx00
                        break; 
                case 01 :
                        *LCD_RSW = *LCD_RSW & 0xFE; //xxxx xxx0
                        *LCD_RSW = *LCD_RSW | 0x02; //xxxx xx1x
                        break;
                case 10 :
                        *LCD_RSW = *LCD_RSW | 0x01; //xxxx xxx1
                        *LCD_RSW = *LCD_RSW & 0xFD; //xxxx xx0x
                        break; 
                case 11 :
                        *LCD_RSW = *LCD_RSW | 0x03; //xxxx xxx1
                default : break;
        }
}

void LCD_Module::LCD_init(volatile uint8_t* RSW_Port,volatile uint8_t* DATA_port)
{
        LCD_RSW=RSW_Port;
        LCD_DATA=DATA_port;
        LCD_ON_OFF(0); // lcd를 끕니다.
        E_Pulse(on);
        rsw(00); // 0 0 0011 1100
        *LCD_DATA=0x3C; // 펑션 셋.
        E_Pulse(off); // 실행
        LCD_clear(); // lcd 화면 클리어
        LCD_ON_OFF(1);
        ReturnHome();
}

void LCD_Module::print_str(char* string)
{
        while((*string)!=0)
        {
                print_char(string++); //wri_ch에 위치의 문자를 "보낸후" 1증가.
        }
}

void LCD_Module::print_char(char* ch)
{
        rsw(10); // 0 1 xxxx xxxx (x는 chh데이터.)
        E_Pulse(on);
        *LCD_DATA=*ch;
        E_Pulse(off); //실행
        cs_pos++;
        if(cs_pos==16)
                Cursor_Position(0,1);
        if(cs_pos==33)
        {
                LCD_clear();
                ReturnHome();
                cs_pos=0;
        }
       
}


void LCD_Module::LCD_ON_OFF(unsigned char on1off2)
{
        rsw(00);
        E_Pulse(on);
        if(on1off2==1)
                *LCD_DATA=0x0f; // 0 0 0000 1111 lcd 켜기
        else if(on1off2==2)
                *LCD_DATA=0x08; // 0 0 0000 1000 lcd 끄기
        E_Pulse(off); // 실행
}


void LCD_Module::ReturnHome(void)
{
        rsw(00); // 0 0 0000 0010 커서를 맨 앞으로 가져다 놓습니다.
        E_Pulse(on);
        *LCD_DATA=0x02;
        E_Pulse(off);
        cs_pos=0;
}


void LCD_Module::Cursor_Position(unsigned char x,unsigned char y)
{
        rsw(00);
        E_Pulse(on);
        if(y==0) //첫째줄
                *LCD_DATA=x+0x80;
        else //둘째줄
                *LCD_DATA=x+0xc0;
        E_Pulse(off);
        cs_pos=(x+(y*16));
}


void LCD_Module::LCD_clear(void)
{
        rsw(00);
        E_Pulse(on);
        *LCD_DATA=0x01; // 0 0 0000 0001 화면 클리어
        E_Pulse(off); //실행
}



/* Main */


// C++ Class TEST...
// LCD Device Module Test.

#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
#include"LCD_Device_Module.h"
//#include<stdio.h>

//#include"rprintf.h"

//#define F_CPU 16000000UL


int main(void)
{
        LCD_Module lcd;
       
        cli();
        DDRA=0xff;
        DDRB=0xff;
        DDRC=0xff;
        DDRD=0xff;
        DDRE=0xff;
        DDRF=0xff;
        sei();

        lcd.LCD_init(&PORTA,&PORTB);
        lcd.print_str("C++ Test Program");
        lcd.Cursor_Position(0,1);
        lcd.print_str("Made by, YuriHan");

        return 0;
}



이래저래 좀 길다..


일단 간단하게 설명하고 넘어가자,


CLCD는 명령을 주기위한 핀 3개와 데이터 핀 8개로 구성되어 있어.
(꼭 그렇지만도 않은게 데이터는 4비트로 주고받을수도 있어,)


RS / RW / E / DATA(8bit) 로 되어있지.


RS 는 레지스터 셀렉트. IR과 DR 선택에 사용해.
IR은 인스트럭션 레지스터. 즉, 명령.
DR은 데이터 레지스터. 즉, 데이터

R/W 는 Read Write. 제조사 마다 신호가 약간씩 달라.

E는 Enable 신호.

명령이나 데이터를 보내준 뒤에 튕겨주면 되는데,
쉽게 보자면 동기를 맞춰주는 놈이라고 보면 되.

데이터 버스야 말 안해도 알테고..


그럼 시작하자.

타이밍도 나가신다.





쌩뚱맞은 그림 나오셨다.


하지만 임베쪽 하다보면 허구헌날 보게될 그림.


타이밍도!!


뭐 어려워보이지만 별로 어려울건 없다.


Write를 보자.

RS가 교차되는 지점이 보이나? 저런식으로 교차되는건 0이든 1이든 상관 없다는 뜻이다.
하지만 데이터가 바뀌어야 한다면 저 타이밍에 바뀌어야 한다는걸 의미한다.

R/W 를 보면 아래로 떨어젼다. High였든 Low였든 그 타이밍에는 떨어뜨려줘야 한다.
E신호가 올라갔다가 내려가는거 보이지?
데이터 교차되는것도 보일테고..


간략하게 순서를 보자면..

RS,RW가 제일 먼저 바뀌고
Enable 신호를 올려주고 데이터를 넣은 상태에서 Enable 신호를 떨어뜨린다.
(그 이후로도 그림이 있지만 봐줄 필요는 없다. Enable신호가 제일 중요하다. 왜? Enable이니까.)


Read도 마찬가지다.
Rs,RW 바뀌고 E 올리고 데이터 넣고 E 내리고.

거창한 그림에 비해 볼건 없다.

명령주는 순서만 잘 지켜주면 된다는 내용의 그림이다.


대충 감이 오지?

그럼 이제 어떤식으로 명령을 줘야되는지 보자.





데이터 시트보면 다 나와있다. 저런식으로 주면 되는거다.

지연시간도 나와있고..(execution time 이면 실행시간에 가깝겠네)

소스코드처럼 따로 명령을 미리 만들어놓고 쓰면 매우 편리하겠지?

순서 알려줬지, 명령 알려줬지, 더이상 가르칠게 없는거다.

소스코드 들여다 보면서 어떤식으로 명령준건지 명령표랑 맞춰서 봐.

그럼 오늘은 이만 접지.


항상 얘기하지만 공부는 혼자 스스로 하는거야.

개판이긴 해도 소스는 열심히 짠거니까 분석하면서 동작 원리를 잘 파악해보라구.



수고.




크리에이티브 커먼즈 라이선스
Creative Commons License

유리한 땜쟁이/저작 avr

유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #7. 시리얼 통신 !!

2009/09/23 13:05



DCINSIDE 프로그래밍 갤러리 연재.

링크정리 -
http://gall.dcinside.com/list.php?id=programming&no=49897







유리한과 함께하는 AVR로 임베디드 개념쌔우기 - #7. 시리얼 통신 !!




아..정말 미안하다.

귀차니즘이 극에 달해서 조낸 오래 쉰것같다..

쥐도새도 모르게 싸려고 했는데..

밑에 햏햏횽 때문에 쌀수가 없었다. 제기랄.


날이 갈수록 소스가 길어진다.

이해해주길 바래.

오늘 할것은 PC와 avr간의 통신이야.
USART / UART 라는 놈이지.

usart는
The Universal Synchronous and Asynchronous serial Receiver and Transmitter
되시겠다.
직렬 동기/비동기화 통신 되시겠고..

uart는
The Universal Asynchronous serial Receiver and Transmitter
비동기 직렬되시겠다.

stop, start 비트가 존재해서
먼저 비트 보내주면 수신대기상태로 들어가고
레지스터 셋팅된대로 데이터 받아들여서 처리해주는 놈 되시겠다.

쉽게 생각하면.. 모뎀이랑 비슷하다.ㅋ



언제나 말하지만 개념쌔우기지 avr 심화 강좌가 아니야.

인터럽트는 RX 인터럽트만 사용할거고..
UART0만 사용할거다.


바로 소스랑 주석 나간다.


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


#define F_CPU   16000000UL      //16MHz


void uart0_init(unsigned long BaudRate);
int putch(char ch);
void putstr(char* str);


int main(void)
{
    cli();                  // clear interrupt. sei()와 더불어 사용. 크리티컬섹션의 역할.
    uart0_init(38400);      // uart0 initialize. baudrate = 38400
    fdevopen(putch, NULL);  // 반드시 함수의 return형은 int, arg는 char형이어야 함
    DDRA=0xFF;              // PORTA 출력핀으로 설정
    PORTA=0x01;
    sei();                  // set enable interrupt


    while(1);


    return 0;
}


void uart0_init(unsigned long BaudRate)
{
    // Not Double mode, Not multi_communication
    UCSR0A=0x00;
    // 0b 1001 1000 RXCIE,TXCIE,UDRIE,RxEN,TxEN,xxx
    UCSR0B=0x98;
    UCSR0C=0x06;
    // Setting BaudRate
    UBRR0H=0x00;
    UBRR0L=(F_CPU/BaudRate/16 - 1);
}


int putch(char ch)
{
    if (ch == '\n')                     //개행문자..
        putch('\r');
    while((UCSR0A&0x20)==0x00);         // 스트림 버퍼가 비면
    UDR0=ch;                            // 데이터 날려줌
    return 0;
}


void putstr(char* str)
{
    while(*str) putch(*str++);
}


ISR(USART0_RX_vect)
{
    char buf;
    buf=UDR0;


    switch(buf)
    {
        case ',' :
            PORTA=PORTA<<1;
            if(!PORTA)PORTA=0x80;
            break;
        case '.' :
            PORTA=PORTA>>1;
            if(!PORTA)PORTA=0x01;
            break;
        case 'a' :
            putstr("Hell'o World!!\n");
            break;
        case 's' :
            printf("Now PORTA is %#04x\n",PORTA);
            break;
        default :
            break;
    }
}


뭐 필요한 사람은 첨부된 소스 / makefile 가져가라. 컴파일은 make all 하면 되시겠다.

프로그램을 설명하자면.. 터미널로 ,랑.을 찍으면 LED가 한칸씩 왔다리 갔다리 하고..

a를 누르면 터미널상에 Hell'o World!! 가 찍히고..
s를 누르면 터미널상에 현재 PORTA의 값을 출력해주는 놈이다.



일단 실행 화면.


원래는 새롬데이타맨을을 주로사용하지만..

실행 동영상. 내방이다.ㅋ




이 소스에서 중요한곳은 딱 두군데.

void uart0_init(unsigned long BaudRate);
ISR(USART0_RX_vect);
겠지?

지금까지 착실하게 공부했으면 ISR(USART0_RX_vect)가 뭐하는 놈인지는
벌써 감이 팍!! 올게다.
ISR(USART0_RX_vect)는 데이터 수신이 완료되면 호출되는 인터럽트 서비스 루틴이다.

(혹시나 꼬꼼화를 위해 사족을 붙이자면.. RX는 수신 TX는 송신 되시겠다.)


void uart0_init(unsigned long BaudRate)
{
    // Not Double mode, Not multi_communication
    UCSR0A=0x00;
    // 0b 1001 1000 RXCIE,TXCIE,UDRIE,RxEN,TxEN,xxx
    UCSR0B=0x98;
    UCSR0C=0x06;
    // Setting BaudRate
    UBRR0H=0x00;
    UBRR0L=(F_CPU/BaudRate/16 - 1);
}

일단 USART에 대해 데이터 시트를 먼저 펴보는 기민함을 보여라.

172~198페이지니까 잘 보도록 해라. 귀찮아서 캡쳐는 생략한다.

UCSR은 USART Control and Status Register. 감이 오지?
A,B,C 세가지가 있다.
A는 거진 status 레지스터라 리드 전용이라고 봐도 무방하다.

double 모드랑 multi processor 설정하는게 있는데..
나도 잘 모르니 패스.

UCSRnB는 좀 중요하다.
// 0b 1001 1000 RXCIE,TXCIE,UDRIE,RxEN,TxEN,xxx
라고 친절히 주석도 달려있지?
인터럽트 관련 셋팅이다.

MSB 수신완료인터럽트/송신완료인터럽트/버퍼엥꼬 인터럽트/Rx활성화/
         Tx활성화/캐릭터사이즈/rx data bit/tx data bit                                LSB

인데.. 자세한건 역시 데이터 시트 찾아봐라.
뒷쪽 세개는 주석에도 xxx라고 표시했듯이 별로 중요치 않다.

우리는 송수신 다쓰고 수신 인터럽트를 사용한다.

UCSR0C=0x06;

0x06은 0b0000 0110 이지?
데이터 시트 뒤져봐라.
캐릭터 사이즈 8bit로 셋팅한거다.
더이상의 자세한 설명은 생략한다?

UBRR 은 baudrate. 즉, 통신속도 설정이다.
(보통 1200 2400 4800 9600 14400 19600 38400 59600 129600 bps(bit per sec)다..)

데이터 시트에 클럭별 속도설정에 관한 내용이 좌악~ 나와있다.
간단하게 식으로 요약하면
UBRR0L=(F_CPU/BaudRate/16 - 1);
되시겠다.

모르겠으면 닥치고 외우자.

근데 보통 저렇게 해서 라이브러리로 만들어놓고 함수 불러다 쓴다.


뭐 이정도로 정리하자.



uart는 방식이 이렇다.

먼저 start bit 로 1비트를 날려주면 그걸 받고 대기모드로 들어간다.
그다음 통신속도 맞춰서 한비트씩 순서대로 날려준다. (FIFO방식으로 기억한다.)

그리고 끝난다는 표시로 stop bit 날려주고..

레지스터 셋팅으로 데이터 비트의 갯수도 바꿀수 있고,
뒤에 패리티비트도 추가시킬수 있다.(오류검증) odd,even 원하는대로..

비동기 통신 보다보면
rs-232네 rs-485네 뭐네 하는 말들이 자주 나오는데..

컴퓨터 시리얼 포트는 rs-232를 쓴다.
뭐 크게 다를건 없고.. 전압이 다르다.
그래서 그냥 uart보다는 232가 멀리가고
232보다는 485가 멀리가는거다.

485부터는 멀티드랍이라고 1대n 통신도 가능하다.

자세한건 각자 검색해보도록!




자, 다음으로 넘어가서..

PORT의 입출력은 어떻게 한다고 했지?

PORTx=data 로 출력하고
data=PINx; 로 입력받는다고 했다.

근데 uart는 더 단순하다.

UDRn..막강하다.(우린 uart0를 사용하니 UDR0다. ATMega128은 2개의 포트를 제공한다,)

수신은 data=UDR0;
송신은 UDR0=data;

위치따라 달라진다. 웃기는 놈이다.ㅋ

UDR0를 얘기하는데 (UCSR0A&0x20) 를 무시하고 지나갈수는 없겠지?

UCSRnA의 5번째 비트는 버퍼가 비어있으면 0, 차있으면 1이다.
쉽게 말해서 수신완료되면 0되고
송신 완료되면 0으로 떨어지는 놈이다.

수신은 몰라도 송신할때는 꼭 신경써줘야 된다.

int putch(char ch)
{
    if (ch == '\n')                     //개행문자..
        putch('\r');
    while((UCSR0A&0x20)==0x00);         // 스트림 버퍼가 비면
    UDR0=ch;                            // 데이터 날려줌
    return 0;
}

에서 처럼 빌때까지 기다려줘야 된다.

안그러면 데이터가 깨져서 날라가겠지?

fdevopen(putch, NULL);  // 반드시 함수의 return형은 int, arg는 char형이어야 함

는 printf를 사용하기 위해서 쓴건데..

인자로 함수를 넘겨준다.

저걸 잘 이용하면 간단하게 printf로 LCD에 출력할수도 있단거다.
참 편한 세상이지.

어쨌든 a누르면 문자열이 그냥 날라가고
s누르면 printf 호출해서 날라간다.

그냥 보여주려고 다르게 만든거니 신경쓰지 말자.


일단은 졸리니..

정리를 하게될지 그냥 닥치고 이대로 냅둘지는 모르겠지만..

수정은 나중에..


그럼 다음시간에 봐요~





p.s 혹시 무협 좋아하는 횽 없어?
      난 취미생활로 무협드라마를 본다..
      짱께들 스케일이 커서 그런지 무협드라마 만들었다 하면 기본 40부작이라 ㅎㄷㄷ해.
      06 신조협려 41부작중에서.. 40화는 내가 대본/싱크작업한건데..(자막에 내 닉 나온다.)
      무미랑전기도 한편인가 두편은 내가 싱크작업한거고..
      뭐 그냥 그렇다고.


크리에이티브 커먼즈 라이선스
Creative Commons License

유리한 땜쟁이/저작 avr

  1. Blog Icon
    이훈석

    안녕하십니까
    대학교 4학년 학생으로

    atmega128로
    초음파 통신을 하려고 합니다.

    시리얼 통신도 필요없이
    두 초음파 센서간에 송신부에 신호가 있으면
    수신부에 led에 불이 들어오면 되는 간단한 실험인데

    제가 avr 코드나 c언어에 잼뱅이라 힘이 듭니다.
    혹시 도움을 좀 주실수 있습니까?

  2. 뭐 그다지 어렵지는 않습니다만..
    초음파로 통신이라면 센서 두개로 통신하겠다는 건가요?
    적외선이 훨씬 나을텐데요..

  3. Blog Icon
    이훈석

    초음파로 통신해야 하는것이 목적이라서...

    혹시소스 코딩이 복잡하지 않으시다면 조금 도와주시면 안됩니까?