[ATmega128] C-LCD, DC모터, ADC컨버터, Uart 통신통합코드정리-1/ 드디어 최종과제 종료

uart통신으로 골머리를 앓고 있었습니다.다행히도 거의 과제를 나왔지만, 요구하는 조건을 완전히 채우지 못했어요.세월이 흐르고 흐르는, 코로나라는 악재 때문에(?)다시 볼 기회가 생겼습니다.그런데 결론에서 보면 내가 처음부터 생각했던 방식이 전혀 도움이 되지 않고 if조건문 하나만 넣으면 끝나는 것이었습니다.내가 생각한 수정안은 Uart의 수신 버퍼의 While문을 if문으로 변경하고 코드를 구성한다.LCD헤더 관련 코드에 들어가딜레이를 사용하지 않고 작동하도록 코드를 구성한다.이것이 가능한 방안이라고 생각했지만, 편협한 시선이었던 것 같습니다.문제를 해결하는 방법을 좀 더 단순히 접근하고 있으면 바로 해결했을 일인데 아쉬울 따름입니다.첫째로 DC모터의 시계 방향, 2번에 DC모터의 시계 반대 방향이라는 선택 사항이 최초의 한계였습니다.나는 스위치를 누르고 모드를 오가는 상황에서 모드에 입력 값을 인식하기 전에 Uart통신의 데이터 버퍼의 확인이 빨리 이를 인지할 수 없는 것을 해결한다고 머리를 틀었는데, 관점을 틀면 의외로 쉽게 해결했습니다.3번 선택하고 수신 버퍼 데이터를 사용한 것처럼,”3번을 입력하면 모드를 처음으로 돌아오게 하는 “을 추가함으로써 결국 원하는 기능은 준비할 수 있었습니다.보면 좀 자신이 당황스럽다고 생각했다.그래도 문제 해결은 해결이므로 이를 다시 먼 길을 이렇게 돌아온 것일까라고 생각했다.물론 이런 삽의 덕에 다른 기능도 갖추고 나온 게 좋겠어요.전체 코드는 main.c에 집중하던 시계, LCD, Uart관련 코드를 헤더 파일에 분리하여 코드를 구성하였습니다.차분히 코드를 봅시다.<main.c>

uart 통신 때문에 골머리를 앓고 있었어요. 운 좋게도 거의 과제를 마쳤지만 요구하는 조건을 완전히 충족시키지 못했어요. 시간이 흐르고, 흐르고, 코로나라는 악재 덕분에(?) 다시 볼 기회가 생겼습니다. 그런데 결론부터 보니까 제가 처음부터 생각해왔던 방식이 전혀 도움이 되지 않고 if 조건문 하나만 넣으면 끝나는 거였어요.내가 생각한 수정안은 Uart의 수신 버퍼의 While문을 if문으로 변경하여 코드를 구성한다.LCD 헤더 관련 코드에 들어가는 딜레이를 사용하지 않고 작동하도록 코드를 구성한다.이게 가능한 방안이라고 생각해왔는데 편협한 시선이었던 것 같아요. 문제를 해결하는 방법을 조금만 더 단순하게 접근했더라면 바로 해결했을 문제였는데 아쉬울 뿐입니다. 1번에 DC 모터 시계 방향, 2번에 DC 모터 반시계 방향이라는 선택지가 첫 번째 한계였습니다. 나는 스위치를 눌러 모드를 넘나드는 상황에서 모드에 입력값을 인식하기도 전에 Uart 통신의 데이터 버퍼 확인이 빨라서 이를 인지하지 못하는 것을 해결하려고 머리를 삐끗했는데 관점을 삐끗했더니 의외로 쉽게 해결했어요.3번 선택지, 수신 버퍼 데이터를 사용했던 것처럼 ‘3번을 입력하면 모드를 처음으로 돌아가도록 한다’를 추가함으로써 결국 원하는 기능은 준비할 수 있었습니다.생각해보니 좀 당황스럽다는 생각이 들었어요. 그래도 문제 해결은 해결이기 때문에 이걸 또 먼 길을 이렇게 돌아왔나 싶었어요. 물론 이러한 삽 덕분에 다른 기능도 몸에 익혔기 때문에 좋다고 생각합니다.전체 코드는 main.c에 집중되어 있던 시계, LCD, Uart 관련 코드를 헤더 파일로 분리하여 코드를 구성하였습니다. 차분히 코드를 살펴봅시다.<main.c>

ATmega128의 경우 포트의 지금처럼 여러 포트를 한꺼번에 구성할 경우 포트의 배치, 포트 내 핀의 기능을 고려해야 합니다.

가장 좋은 예로 PF0~7을 보면 ADC 관련 기능이 배치되어 있음을 알 수 있습니다. 그래서 포트 F는 ADC 컨버터를 위한 자리로 반드시 사용해야 함을 알 수 있습니다.

포트 F = ADC 포트 B = DC 포트 C = LCD Data Port D = LCD Control포트 배치는 위와 같이 배치하고 타이머 카운트 2에 시계를 사용하고 타이머 카운트 0은 모터를 위해 사용했습니다. 메인 구문에 들어가기 전에 초기 보드 세트를 메서드처럼 작성했습니다.LCD의 포트는 맨 위의 define으로 해결하고 DC 모터는 포트의 특정 핀 번호에 직접 입력하는 아래와 같은 방법으로 처리하기 위해 DDRF만 그렇게 표시해 두었습니다.main의 전체 구조 발굴물 / / (mode == 0)주 문은 크게 2가지 기능을 구별하는 것입니다.mode==0일 때는 Uart통신을 통한 컴퓨터 측과 LCD에 시계를 표시하는 모터 속도를 표시하는 상태 mode==하루의 때는 Uart통신을 통해서 컴퓨터로 입력한 대로 모터의 속도와 회전 방향을 결정하는 상태이므로 mode이 하루 시간을 벗어나면 기존의 ADC변환치와 타이머 카운트 2의 계산 상황으로 돌아오는 방식입니다.우선 LCD에는 2줄을 디스플레이할 수 있는 최초의 행 중앙에 시계를 표시하도록 했습니다.ATmega128의 최대 주파수는 16MHz에 나는 타이머 카운트 2의 CS를 1,0,0에 배치하고 우선 256을 나누어 OCR2를 125에 체크하는 새치기를 사용하도록 했습니다.그래서 오른쪽 사진에서 count 5개를 헤아리면ck_count를 센 ck_count가 100을 세니(5X 100)500을 카운트하도록 하고 이를 1초로 했습니다.(256*125*5*100=16,000,000)메인 도어는 크게 두 가지 기능을 구분하는 것입니다. mode == 0일 때는 Uart 통신을 통한 컴퓨터측과 LCD에 시계를 표시하여 모터의 빠르기를 표시하는 상태 mode == 1일 때는 Uart 통신을 통해 컴퓨터에서 입력한 대로 모터의 속도와 회전 방향을 결정하는 상태이기 때문에 mode가 1일 때를 벗어나면 기존 ADC 변환값과 타이머 카운트2의 계산 상황으로 돌아오는 방식입니다.먼저 LCD에는 두 줄을 디스플레이 할 수 있는 첫 줄 중앙에 시계를 표시하도록 했습니다. ATmega128의 최대 주파수는 16MHz이고 나는 타이머 카운트 2의 CS를 1,0,0으로 배치하고 우선 256을 나누고 OCR2를 125로 체크하는 인터럽트를 사용하도록 했습니다. 그래서 오른쪽 사진으로 count 5개를 세었더니 ck_count를 세고 ck_count가 100을 세면 (5X100) 500을 카운트하도록 하여 이것을 1초로 했습니다.(256 * 125 * 5 * 100 = 16,000,000)ADC 컨버터는 data_bin에 1024(8bit, 2^8)로 환산하는데 그치는 구간도 고려하여 504에서 520 사이의 16 정도는 멈추는 구간, 나머지는 시계/반시계 회전을 하여 마지막으로 회전할수록 최고 속도에 도달하도록 OCR0에 속도 값을 부여하도록 하였습니다. Uart 통신을 통해 속도 값을 주고받기 위해 시계는 data_bin1, 반시계는 data_bin2에 값을 입력하도록 구분하였습니다.그리고 LCD 디스플레이의 2열 맨 왼쪽에 회전 방향과 속도를 표시하도록 했습니다. 그리고 마지막 Uart 통신을 통해서 PC에 타이머 카운트 2에서 돌아오는 시간을 표시할 수 있도록 하는 코드 부분입니다. ASCII 코드에 맞춰 숫자는 48에서 0이 시작됩니다. 그래서 타이머 카운트에서 사용하는 숫자에 열 자리, 일 자리에 각각 시, 분, 초에 해당하는 숫자의 변수를 두 개씩 할당하도록 했습니다.그리고 While이 돌아가는 동안 스위치를 입력하면 mode=1이 실행되도록 함으로써 mode=0에서 일어나는 코드의 분석입니다. main의 전체 구조 발굴물 / / (mode == 1)mode == 1일 때는 먼저 usart0_rx_string()부터 분기가 계속해서 나뉩니다. 이 메소드를 한 번 볼까요?입력된 데이터가 들어올 때까지 while(!) (UCSR0A & & (1<<RXC))) 그래서 시퀀스가 계속 머물러 있게 됩니다. 이 부분 때문에 특정 입력 코드가 인식이 안 되고 이 rxuart 메소드가 우선적으로 빠져 버려서 다루기가 어려웠습니다.그래서 위에서 이야기한 것처럼 3번이라는 선택지를 만들어서 데이터 입력의 범위를 넓히는 것으로 간단하게 해결을 했습니다. 뭘 그렇게 어렵게 다닐 생각을 했나 싶을 정도네요.입력된 데이터(data1)가 1일 때 시계방향임을 인지한 것을 PC로 전송하여 회전방향을 바꿉니다. 이어서 Input Speed(~255), 속도에 해당하는 값을 OCR0에 입력할 수 있도록 rx_string()에서 대기합니다. 값을 입력하면 OCR0에 속력까지 입력하고 첫 번째 선택지로 돌아갑니다.여기서 다시 2번과 3번 중에서 3번을 선택하면 mode = 0이 되고 다시 첫 시간과 ADC 컨버터에 해당하는 값의 상태로 DC 모터가 돌아옵니다. 전체적인 구동을 살펴봅시다?보드에 있는 Port G의 스위치 하나를 mode 변환으로 사용하여 전체적인 부품을 보드에 통합해 보았습니다. 여기에 추가로 쓰는 코드는 C++이기 때문에 개인적인 공부를 위해 이 모든 것을 C++로도 변환을 완료했는데 약간의 지연, 계산 오차가 있는지 1초 계산의 정확도가 떨어지는 문제가 생겼습니다.이것도 다듬어지면 한 번 정리해서 봐야 해요.