찬찬히 로봇 메이커 :: 찬찬히 로봇 메이커
반응형

그 동안 바빴었고, 또 바빴다...라고도 생각했지만 이젠 잘 모르겠다.....

오랜만에 쓰려니 전에 했던 것도 벌써 다 잊어버린 느낌이다. 그래도 해야하긴 하니까..... 벌써부터 힘이 빠지는 것 같지만 다시 한번 힘을 내야겠다.

이번엔 저번에 공부한 ADC에 연관된 DMA를 포스팅한다. DMA는 Direct Memory Access의 약자로 메모리 직접 접근의 약자이다. 이게 무엇이고 왜 쓰이냐 하면...

원래 ADC를 사용할 때에는 ADC의 SOC(start of conversion)을 해주고 변환된 값을 레지스터에서 내가 만든 변수에 옮겨주는 일을 해야했다. 그리고 레지스터에 저장된 변환된 값을 지우고, 다시 값을 받고 내가 만든 변수에 옮기고...의 반복을 해야했다. 게다가 혹시라도 값이 잘못 들어가면 안되니까 내가 만든 변수에 값을 옮겨주고 다기 초기화를 해야할 때도 있을 것이다. 그렇게 되면 아무리 짧은 코드라도 연속적으로 반복이 되니 별로 효율적이진 않을 것이다. 그래서 DMA라는 기능을 사용한다. 

위에서 설명한 레지스터에서 내가 만든 변수에 옮겨주는 일을 DMA가 직접 해준다. HAL라이브러리를 쓰면 DMA에 관한 함수가 있다. 그 함수를 쓰면 내가 만든 배열, 어느 정도 자료형(크기)에 넣을껀지를 한 줄로 써서 사용할 수 있다. 물론 설정은 많다.

위에 사진은 설정에 관한 것이고 아래 사진은 IRQHandler가 불려져서 내가 만든 함수 DMA 인터럽트 서비스 루틴이 실행되는 것을 보여준다. 일단 위에 함수를 보면 많이 복잡하고 여려워 보이지만 생각보다 어렵진 않고 당연히 설정해줘야 하는 것들로 이루어져있다.

DMA 맵을 보면 ADC1은 채널 0에 스트림0과 4에서 사용할 수 있는 것을 확인할 수 있다. 
direction은 'ADC'에서 'CPU memory에 있는 변수'이므로 Peripheral(외부장치)에서 memory(내부장치)이다. 
PeriphInc는 Increment Peripheral Adress라는 뜻으로, 값을 한 번 받을 때 마다 요청하는 Peripheral의 주소값을 한 칸씩 미루는 기능을 말한다. 아마 여러 개가 붙어 있는 센서를 사용하거나 할 때 쓰이는 기능같다. 하지만 나는 각자 개별적인 ADC를 사용하기 때문에 disable로 놓는다.
MemInc도 똑같이 한 번 DMA를 동작을 할 때마다 다음 값을 받는 주소값을 미루는 것을 말한다. 이것은 여러 개의 값을 여러 곳에 넣을 땐 필요한 레지스터이다. 예를 들어 값을 받을 때에는 배열에 받는다. 배열을 arr[]라 할 때, adc 하나는 arr[0]에, adc 다른 하나는 arr[1]에... 이런식으로 받게 되는데 배열은 포인터이기도 하고, 자료형 크기로 서로 붙어있으니 주소값이 하나씩 옆으로 가면서 배열에 하나씩 값을 넣을 수 있게 되는 것이다. 그래서 순차적으로 배열에 값을 넣을 수 있게 된다. 따라서 enable해준다.
DataAligment는 Data 저장되는 크기로 word는 32비트 (4바이트=int)크기로 저장이 된다는 뜻이다. 참고로 half word는 16비트, byte는 8비트의 크기로도 받을 수 있다.
마무리로는 DMA 인터럽트를 쓸 것인지를 설정하고 다른 인터럽트 쓸 때 처럼 인터럽트의 순위를 정해주면 끝이다.

그러면 마무리로 main에 DMA를 사용하겠다고 써주면 DMA가 작동이 된다. g_ADCBuffer는 내가 만든 배열의 이름으로 첫번째배열의 주소값이 된다. 4는 배열의 크기를 말한다.

추가로 이건 내가 직접 레지스터를 건드려서 설정해본 것인데...... 작동이 안되어 주석처리를 면치 못했다. 도대체 뭐가 문제인지......아 아직 멀었구나...

DMA는 확실히 옮겨주기만 하는 녀석이라 옮겨주는 위치, 크기 방향등만 설정하면 쉽게 사용할 수 있었다. 역시 문제는 ADC... 아직 더 파볼게 많은 것 같다. 다음 포스팅은 언제가 될지... 일본 마우스 대회가 곧이라... 공부할 것도 많고 공모전, 대회도 많고, 학업도 많고, 그 와중에 하고픈 것도 많다. 질풍노도의 시기라면 지금을 말하는게 아닐지... 그래도 이왕 시작했으니 끝은 봐야겠다.

반응형
반응형

아이디어의 도용 및 게시물의 무단 복사는 절대 용납하지 않으니 주의해주시기 바랍니다.※

 

여름방학이 시작되었다. 여름방학이 되면 자유롭고 여유롭게 마우스 준비나 하게 될 줄 알았는데... 뜻하지 않게 학교 방학 프로젝트를 맡게 되었다. 4Dream 프로젝트는 나를 포함해서 4명의 단국대학교 학생들과 함께 한  여름방학 프로젝트로, 응용컴퓨터공학과 1학년 한 명과 전자전기 공학부 2학년 3명이 모였다. 이 프로젝트는 여름방학기간 동안 6주에 걸쳐서 직접 창업을 하고 계신 분들을 외부 강사로 초청해서  3D 프린터에 대한 설명과 종류, 사용법을 가르쳐주고, 아두이노와 여러 센서들의 설명과 사용법을 알려주며, 창업에 도움을 주는 학교 프로젝트이다.

여러 아이디어를 생각했지만, 일단 1달정도 밖에 안 되는 개발 기간과 당시 하고 있는 일이 여러 겹쳤기에 어떤 작품을 할까 고민을 많이 했었다. 여러 가 이 아이디어가 쏟아져 나왔고, 그중에 하나 건진 아이디어가 알람 수면 안대였다.

기본적인 외향은 수면 안대이고, 눈에 닫는 쪽의 위치에 LED를 달아놨다. 관자놀이 쪽에는 진동센서가 달려있고, 안에는 HC-06 블루투스 모듈과 아두이노 미니가 연결되어 있다. 

사용법은 휴대폰에 알람 수면 안대 어플을 다운받는다. 그러면 어플에서 두 가지 기능을 사용할 수 있는데 하나는 위치 알람이고 하나는 시간 알람이다. 이 알람이 울리면 블루투스로 연결되어 있는 안대가 작동해 LED를 켜주고 진동을 울려서 자고 있는 사람을 깨워줄 수 있는 안대이다.

간단하지만 대단한 아이디어라고 생각했다. 우리 동아리 특성상 늦게 자는 건 다반사인데, 늦게 자고 일찍 일어나서 청계천을 가야 하는 일도 있고, 다른 먼 곳을 가야 하는 일이 있는데, 그때마다 지하철으나 버스를 타고 간다. 근데 피곤은 해서 자고 싶지만 정거장을 노칠 염려를 항상 하는 것도 피곤한 일이다. 그런 사람들을 위해 간단하지만 효과적인 알람 수면 안대를 만든 것이다. 또한 청각 장애인들도 사용할 수 있다. 일반적인 알람들은 소리와 진동으로 깨워주는 일이 대부분인데 빛으로 깨워준다면 얼마나 효과적인가를 생각해 보았다. 그리고 빛으로 깨워주는 이유는 눈이 사람의 인체에서 가장 민감한 부위일 뿐만 아니라 눈에 빛을 쬐면, 멜라토닌이 감소하는 효과가 나타나 잠에서 쉽게 깰 수 있다고 한다.

이런 아이디어로 4Dream 경연대회에 나갔고 당당히 1등 해서 공과대학장 상을 받았다.ㅠㅠ
또한 공학교육혁신센터 거점대학이라 성균관대학교에서 하는 지역 대회도 나갔다. 10월 11일에 호서대학교로 갔었고, 거기서는 아쉽게도 장려상을 받았다. 그래도 선전했다고 생각했다. 바쁜 와중이었고 그 와중에 좋은 성적 거둔 거 같아서 다행이었다.

그리고 11월 7, 8, 9일에는 2박3일로 일산 킨텍스로 내려가 공학교육혁신센터 최종 심사를 했었다. 생각보다 큰 행사를 했고,

거기에서는 순위권에 못든 사람들도 발표를 하고 특별상을 받는 게 있어서 열심히 설명을 했다.  그 결과...

월드클래스 300 기업협회장상을 받았다. 외국인들이 우리의 작품을 기발하다고 생각하며 좋아해 준 것 같다. 아마 내년에도 이 프로그램을 꼭 참여하고 싶은데, 일단 큰 기회를 얻는 것이기도 하고 학교에서의 지원도 너무 편안해서 하는 내내 즐거웠다. 앞으로도 더 나은 아이디어로 좋은 프로젝트 즐겁게 했으면 좋겠다.

4개월간의 여정이 끝이 났다. 역시 프로젝트가 끝나면서 홀가분한 마음이 컸던 것 같다. 처음부터 끝까지 돌이켜 보면서 이번에 한 프로젝트가 즐겁게 한 좋은 프로젝트였다는 생각이 들었다. 이런 사람들과 언제 다시 만날까... 참 행복했던 시간이었다.

 

아이디어의 도용 및 게시물의 무단 복사는 절대 용납하지 않으니 주의해주시기 바랍니다.※

반응형
반응형

이번엔 m4보드에서 adc를 사용해보려고 한다. adc를 사용하는 순서는 이렇다.

1. ADC 클록 활성화
2. 사용하려는 핀에 대해 GPIO 클럭을 사용하도록 설정합니다.
3. GPIO 핀을 아날로그 입력으로 구성하십시오.
4. ADC 속도 구성 (프리스케일러 / 샘플링 시간)
5. 연속 측정 모드 사용

사실 2번, 3번,  GPIO설정은 필요하지 않을 때가 있다. 바로 내부 ADC를 사용할 때인데, m4보드에는 16개의 외부 ADC와 3개의 내부 ADC가 있다. 16개의 외부ADC는 각각의 GPIO핀에 할당되어있다.

이 외에 3개의 내부 ADC는 각각 CPU내부의 온도센서, 전류측정, 배터리 전압측정을 할 수 있는 ADC들이 들어있다. 이제부터 한번 사요을 해보자.
일단 ADC설정에 필요한 항목들을 들여다보자.

▶Clock Prescaler : ADC에 사용할 클럭을 몇으로 나누어주느냐를 설정한다.
Resolution : m4보드에서는 ADC를 12bit, 10bit, 8bit, 6bit중 원하는 설정으로 받을 수 있다. bit가 커질수록(더 정밀하게 받을수록) 값을 받는 시간은 늘어난다. 각 설정당 한 2~3 cycle정도? 10~20ns정도인듯하다.
Data Alignment : 받은 데이터를 우로 정렬할건지 좌로 정렬 할건지 정한다. 보통은 다 우로 정렬(Right aligment)을 한다.
Scan Conversion Mode : 여러개의 ADC를 동시에 사용할 때, 각각의 ADC를 따로 받을건지(?), 아니면 한번에 쭉 받을 건지를 결정한다. 여러개의 ADC를 받을 때에는 Enable하는 것이 좋다.
Continuous Conversion mode : ADC를 한번만 받을 것인지, 계속해서 받을 것인지를 설정한다.
Discontinuous Conversion Mode : Continuous Conversion mode와 반대인듯하다. 솔찍히 왜 있는지 정확히는 모르겠다.
<Specifies whether the conversions sequence of regular group is performed in Complete-sequence/Discontinuous-sequence (main sequence subdivided in successive parts).
일반 그룹의 변환 시퀀스가 ​​전체 시퀀스 / 불연속 시퀀스 (연속 된 부분으로 세분화 된 주 시퀀스)에서 수행되는지 여부를 지정합니다.>라는데........  어쨌든 Continuous Conversion mode가 Enable이 되면 자동으로 설정이 버려진다고 되어있다.
DMA Continuous Requests : DMA를 사용할 것인지를 물어본다. DMA란 직접 메모리 접근( Direct Memory Access,DMA )로, ADC값을 받는 식을 따로 써주지 않고, 그냥 배열 하나 정해놓고 여기다 자동으로 값을 넣어주세요...하면 넣어주는 기능을 하는 레지스터이다. 편리하긴 하나 추가적으로 설정을 해주어야 한다.
End Of Conversion Selection : 하나의 채널을 마치고 EOC flag를 넣어줄건지, 모든 ADC를 마치고 EOC flag를 넣어줄 건지를 결정을 한다.

와.......정말 많다. 블로그에 직접 쓰는 것도 힘들었지만 직접 사용할 때에도 설정이 너무 많아서 힘들었다. 게다가 각각의 기능들을 알아야하니.... 더 슬픈점은 이것이 끝이 아니다. 아직 더 많은 기능이 남아있으니.. 바로  ADC채널설정이다.

Number Of Conversion : 몇개의 ADC를 변환을 할 것이냐를 정해준다.
Rank : 여러개의 ADC를 설정해 줄 경우, 어떤 순서대로 값을 받을지를 정해준다.
SamplingTime : 이게 꽤 중요한데, Resolution이 12bit값을 받을 때, 15ADC Clock cycles가 필요하다고 나온다. 즉 15cycle 이하로 놓으면 값이 잘 안 받아 진다는 소리! 그러므로 무조건 빠르다고 좋은 것이 아니라 적당히 설정을 해야 한다.

여기까지가 대략적인 ADC설정이다. GPIO는 솔찍히 설정할 것이 몇 없고, Timer Interrupt는 정당히 있었는데, ADC는 개많다. ㅠㅠ

일단 인터넷에서 본(아마 CUBEMX로 돌린) ADC설정 소스이다. 나는 CPU내부의 온도센서를 이용해서 LED의 밝기를 변화시키는 소스를 짰었는데 일단 ADC값을 받고, 인터럽트를 돌린다. 인터럽트 서비스 루틴 소스에 LED를 키고 끄기를 설정해 놓았다. 위 그림에서는 ADC_ISR 함수가 그 소스이다. 나는 일단 DMA도 사용을 할 것이라 DMA도 Enable로 놓았다. 위 설정대로 한 뒤에, HAL_ADC_Start_IT(&g_AdcHandle);라고 main에 써주면 바로 된다. b^^ 

이렇게 기본 설정만 알아봐도 많았는데... 이걸 레지스터로 보려니 약간은 막막했다. 어차피 기능은 똑같았지만 더 막막한 느낌이랄까...뭐가 필수인지도 모르겠고...에휴.

다음 포스팅에선 DMA설정에 대해 자세히 알아보자!

- 11월 21일 추가 -
왜 인터럽트를 실행하면 xxx_IRQHandler로 들어가는지 궁금했는데 디버거를 사용해보니 임의의 주소에서 저 함수를 호출하는 게 발견되었다. 타고 들어가보니 어셈으로 짜여져있는 것을 확인했고... 결국 내 맘대로 바꾸고 싶으면 어셈블리어를 공부해야 한다. 흠... 능력있는 사람이 되기 힘들구만
또한 ADC는 기능이 많다. 여러가지 경우의 수(가능한 조합)이 30가지는 넘는다고 하고, 그 모든 조합에 대한 설명이 있는 매뉴얼도 찾아보면 있다고 한다. 여기에서 가장 내 목적에 맞는 조합으로 쓰면 될 듯하다.
※혹시 틀린 것, 알려주고 싶은 내용, 궁금한 점은 댓글로 달아주세요 ^^.

반응형
반응형

지난번 GPIO에 이어 이번엔 타이머 인터럽트를 사용하였다.

결론적으로 말하면 2809를 쓸 때와 비슷하다는 것을 느꼈다. 많은 함수들을 거친 결과 결국 레지스터로 값이 입력이 되어 결과가 도출된다는...
그리고 공부에 방법으로 가장 최적화(속성과정)은 CUBEMX로 원하는 소스를 만들어 본 다음, 소스를 타고 들어가서 내가 원하는 것을 하려면 무엇이 필요한 가를 찾아보는 것이 가장 도움이 된다는 것도 느꼈다. 

이제 이 레지스터들을 가지고 나만의 소스를 만들어야 하는데....ㅠㅠ 할 일은 항상 태산이다...

일단 큐브맥스로 타이머를 설정하고 소스를 만들어 보았다. 눈이 돌아갈 것 같지만 침착하게 한번 보자.
우선 TIM_HandleTypeDef가 있다. 이것을 타고 들어가보니, 

이것들이 있었다. 맨 위에 Instance는 타이머 레지스터들이 쭉 나열되어 있었다. 즉 이것만 설정을 잘 해도 타이머를 사용하는 데는 문제 없다는 뜻이다. 하지만 모든 레지스터를 처음부터 끝까지 설정하는 것은 조금 귀찮은 문제이다. 그래서 두 번째 Init이 있는 것 같다. STRUCT 이름 자체가 TIM_Base_InitTypeDef이다. 즉 기본적인 설정이라는 뜻인거 같은데, 위에 소스처럼 Instance에 어떤 타이머를 쓸지 정하고, 그 밑에 Init Prescaler Period, CounterMode를 정해주고 HAL_TIM_Base_Init함수를 쓰면 타이머를 사용할 준비는 끝이 난다.  물론 이 타이머를 사용할 때에도 clock_enable은 해주어야 한다. 그래서 __HAL_RCC_TIM7_CLK_ENABLE이 있는 것이다. Error_Handler는 혹시 모를 위험을 막기 위해 있는 듯 하다. 실제로 들어가 보면 while문 안에 갇혀버리는 것을 알 수 있다. 
밑에 NVIC는 인터럽트를 인가해주고, 우선순위를 정해줄 수도 있다. 이는 인터럽트끼리 겹치는 Pending현상을 막기 위한 것으로 보이는데 사실 서브까지 필요한 지는 모르겠다. HAL_NVIC_SetPriority함수가 우선순위를 정하고, HAL_NVIC_EnableIRQ가 해당 타이머의 인터럽트를 인가해 준다.소스를 정리해 보았다.

원래는 인터럽트가 발생을 하면 TIM2_IRQHandler라는 함수가 실행이 되고 그 안에 HAL_TIM_IRQHandler라는 함수가 실행이 된다. 그 안에  UPDATE EVENT가 발생이 하면  HAL_TIM_PeriodElapsedCallback함수로 들어가 함수가 실행이 되는 구조이다. 나는 그냥 그것을 끄집어 내와, UPDATE EVENT가 발생하면 함수 Timer_ISR이 실행이 되게 소스를 짜보았다.
현재 Timer_ISR안에 소스는 delay를 사용하지 않고, 인터럽트의 주기를 바꾸어 핀 14번에 있는 LED를 1초 끄고, 5초 켜게 만든 소스이다. 또한 그 밑에  config_Timer_IT함수는 편하게(?) Prescaler와 Period를 바꿀 수 있게 하는 소스이다.

사실 큐브맥스를 보면서 공부해서인지 크게 바뀐 것은 없다. 그냥 필요 없어 보이는 예외처리들을 없애서 오히려 위험성이 높아진 듯 하다. 하지만 일단 깔끔하게 소스를 정리하고 이해했다는 것에 만족을 느낀다.

main문의 소스를 이렇게 짜 보았다. 내가 만든 주기 정하는 함수로 주기를 정하고, 그 밑에 인터럽트 시작 함수를 쓰면 인터럽트가 실행이 된다. 이때, 주의 사항으로는 timer.c에서 선언한 timerInitstruct main.c에서 사용이 안된다는 것이다. 그래서 timer.h에서 extern으로 timerInitstruct을 한번 더 선언해 주었다. 결과적으로는 매우 잘 작동 되었다.

 

serviceapi.nmv.naver.com/flash/convertIframeTag.nhn?vid=D81EF661D8D436303480BB9EAD3D6B3A7A4A&outKey=V1248770e4c0851ecd8fb346ff3fb11fe605ac099a51f3c05f70d346ff3fb11fe605a&width=544&height=306

 

STM32F407 2장. 타이머 인터럽트(TRUESTUDIO, HAL_Driver)

 

serviceapi.nmv.naver.com

오른쪽 LED가 반짝이는 것을 볼 수 있다.

 

확실히 GPIO를 할 때와는 차원이 다른 어려움이 느껴졌다. 하지면 2809에서 인터럽트를 사용해 보아서 그런지 결과적으로 친숙하게 배울 수 있었고, 어떤 방식으로 접근해야 하는지를 조금이나마 알게 되었다. ADC는 훨월~~씬 어렵다는데 벌써부터 걱정이다.ㅠㅠ

 

※혹시 틀린 것, 알려주고 싶은 내용, 궁금한 점은 댓글로 달아주세요 ^^.

반응형
반응형

처음으로 STM32F407 디스커버리 보드를 사용해보게 되었다. 전에 아두이노나 2809를 사용할 때와 다르게 나만의 프로젝트 파일을 만드는 것을 목표로 두었기에, 완벽한 이해를 목적으로 공부를 하고 범용적이고 직관적인 코드를 짜는 것을 목표로 삼았다.

일단 GPIO란 범용적 입출력 핀이라는 뜻으로 내가 5V를 출력하거나 입력을 받고 싶을 때, 핀의 설정을 GPIO로 설정해놓고 쓸 수 있다. GPIO라고 꼭 5V가 출력이 되는 것은 아니다. 쓰는 CPU마다 다를 수 있으니 manual을 보고 칩의 스펙을 확인한 뒤 써야한다. 확인해보니, 사용할 수 있는 GPIO의 갯수는 82개이고, 5V입출력을 가진다.
아래 표와 같이 15개씩 9개의 구역으로 나뉘어져 있다.(ABCDEFGHI) 이중 핀 100개짜리 칩은 Ports F, G를 사용하지 않는다고 한다.


일단 이 칩의 manual을 읽어보니, GPIO로 사용할 때, 두 가지 방식이 있었다. PP방식과 OD 방식으로 PP는 PUSH-PULL방식을 말하는 것이고, OD 는 OPEN-DRAIN 방식을 말하는 것이다. 나는 기본적으로 PULL-DOWN에 원할 때 5V를 인가주고 싶어서 PUSH-PULL을 선택했다. 또한 AF 라고 해서 Alternate function이라고 있는데, 핀을 다른 용도로 사용(ex. 통신)하고 싶을 때 사용한다.

이 밖에 다양한 레지스터 설정들이 있는데.... 결론적으로 사용하는 코드는 아래와 같다.

몇 번째 핀을 쓸 것인지, 모드는 어떤 것을 쓸 것인지, PULL-UP인지 PULL-DOWN인지 그리고 핀의 속도는 어떻게 쓸 건지를 정하고 HAL_DRIVER에 함수 HAL_GPIO_INIT을 쓰면 핀을 사용할 준비가 된다. 이때 속도는 4개로 분류되는데 속도가 느릴수록 원하는 값에 도달하는 속도가 늦어지지만, 속도가 빠를수록 정밀도가 떨어진다고 한다. 그래서 나는 3번째 빠르기로 사용을 한다. 이 밖에 다른 설정들도 있었지만, 단순히 GPIO에서 입출력만 쓸 때에는 이정도 설정만으로 충분하다. 더 알고싶으면 GPIO함수들이나 MANUAL을 읽고 공부를 해야한다.

그리고 device.h는 다른 헤더파일들을 모아놓은 것으로  따로 만든 헤더파일이다. 원래는 gpio.h로 되어있을 것이다.

그리고 마지막으로 CLOCK_ENABLE이 남아있다. CPU는 어떠한 일을 수행하던간에 무조건 시스템 클럭을 기준으로 한다. 그래서 GPIO를 켜던, 인터럽트를 사용하건, 통신을 할때도 CLOCK을 ENABLE시켜줘야 작동을 한다.
__HAL_RCC_GPIOC_CLK_ENABLE();
이것이 HAL라이브러리에서 제공하는  CLOCK_ENABLE함수로, 원하는 구역에 클럭을 제공한다. 위에 함수는 GPIOC_CLK_ENABLE이기 때문에 GPIOC구역에 해당하는 애들만 사용할 수 있게 해준다.

이제 GPIO로 불을 켤 준비가 되었다.HAL_Delay, HAL_GPIO_ReadPin,
HAL_GPIO_WritePin 을 사용해서 불을 깜빡일 수 있다. 이때, 토글을 안 쓰는 이유는 토글이 그렇게 좋은 함수는 아니라는 선배님의 조언을 들었기 때문이다. 토글함수는 안 쓰는 버릇을 기르자. 

처음엔 2809를 사용했을 때와 많이 다르다고 생각을 했지만 결과적으로 레지스터에 값을 넣어줌으로 해서 원하는 설정을 할 수 있다는 점을 깨달았다.  또한 초기 설정시 입출력 방향을 정해주거나 핀을 어떤 용도로 쓸 건지 등에 대한 방식이 같았다.

이제 이 방식을 가지고 범용적인 코드를 짜야하는데 확실히 머리가 아파옴을 느꼈다. 어떻게하면 편하게 설정하고 쓸 수 있을 것인가... 앞으로 생각해봐야할 것 같다.

※혹시 틀린 것, 알려주고 싶은 내용, 궁금한 점은 댓글로 달아주세요 ^^.

반응형

+ Recent posts