TMS320F28X 개발보드 V2 예제
[F28P65x / CPU1] 28X 칩의 eQEP로 로터리 엔코더를 읽어 7-세그먼트에 00~99 표시하기 예제 (Bitfield/DriverLib/FreeRTOS)
1. 실습 안내
본 예제는 TMS320F28P65x(F28P650DK9 산업용 / F28P659DK8-Q1 차량용) 제어 모듈이 탑재된 TMS320F28X 개발보드(EVM) V2를 대상으로 합니다.개발보드 '(14) 엔코더 & TACT 스위치' 회로의 로터리 엔코더(24P/R)를 F28P65x 칩의 eQEP1(쿼드러처 엔코더 펄스 모듈)로 읽어서, '(13) 7-SEGMENT' 회로의 7-세그먼트 2개에 00~99로 표시합니다.
- 엔코더를 오른쪽으로 돌리면 +1, 왼쪽으로 돌리면 -1 (00과 99에서 멈추고 넘치지 않습니다)
- 엔코더 노브를 누르면 00으로 리셋되고, 누르고 있는 동안 점(DP) 2개가 켜집니다
- 7-세그먼트는 자리마다 BCD 디코더(CD4543B)가 값을 유지하므로 다이내믹 스캔이 필요 없습니다
학습 목적에 따라 Bitfield / DriverLib / FreeRTOS 3가지 구현을 모두 제공합니다.
2. 실습 준비
본 예제는 아래의 개발환경에서 컴파일/링크를 확인했습니다.1) CCS 버전 : Code Composer Studio v12.x / v20.x / v21.x (Theia)
2) 컴파일러 버전 : TI v22.6.3.LTS 이상
3) 개발보드 : TMS320F28X 개발보드 V2
4) 프로세서 모듈 : 싱크웍스 TMS320F28P65x 모듈 (F28P650DK9 / F28P659DK8-Q1)
5) 예제버전 : v1.00
6) 기타 : 점퍼 케이블 13개 (엔코더 3개 + 7-세그먼트 10개)
7) 프로젝트 구성 : 학습 목적에 따라 3가지 버전을 모두 제공합니다.
- Bitfield : DriverLib을 전혀 호출하지 않고 레지스터 비트필드 구조체(EQep1Regs, GpioDataRegs 등)만으로 구현
- Driverlib : TI 표준 HAL API 라이브러리(GPIO_*, EQEP_*)를 활용한 구현. 값 계산 모듈을 PC에서 돌려 보는 호스트 테스트 포함
- FreeRTOS : 엔코더 입력 / 표시 태스크 2개, 완전 정적 메모리 할당(Zero Heap), 출력이 바뀔 때만 표시 태스크를 깨움
(값 계산
seg_counter.c/.h는 칩과 무관한 순수 C이고 세 버전이 같은 파일을 씁니다.)8) 확인 범위 : 세 버전 모두 컴파일/링크(CPU1_RAM, CPU1_FLASH)와 PC 호스트 테스트까지 확인했습니다. 보드에서의 동작(회전 방향, 눈금당 카운트, 노브 리셋, DP 점등, 7-세그먼트 자리 대응)은 아직 확인하지 않았습니다.
3. 실습 예제 다운로드 (GitHub ZIP 다운로드 안내)
초보자분들도 손쉽게 다운로드하여 사용하실 수 있도록 전체 소스 코드를 GitHub에 공개해 두었습니다.아래 안내에 따라 ZIP 압축 파일로 다운로드하세요.
[다운로드 순서]
① 아래의 링크를 클릭하여 GitHub 저장소 페이지로 이동합니다.
>> [GitHub] EVM_V2_F28P65x_13_14_SevenSeg_Encoder 저장소 바로가기
(※ 다이렉트 ZIP 다운로드 : EVM_V2_F28P65x_13_14_SevenSeg_Encoder.zip 클릭하여 바로받기)
② GitHub 페이지 우측 상단의 초록색 <> Code ▼ 버튼을 클릭합니다.
③ 나타나는 메뉴 맨 아래의 Download ZIP 항목을 클릭하여 압축 파일을 다운로드합니다.
④ 다운로드한 ZIP 파일의 압축을 해제합니다.
- 권장 설치 경로 : C:/SyncWorks/TMS320F28X_EVM_V2_28P65x/13_14_SevenSeg_Encoder
(※ 주의 : 경로 상에 한글이나 공백이 포함되지 않도록 주의해 주세요.)
4. CCS 프로젝트 불러오기 (CCS V20 기준) 및 컴파일
>> [유튜브] CCS V20 예제 프로젝트 불러오기 방법 소개 영상① Code Composer Studio(CCS)를 실행합니다.
② 상단 메뉴에서 File > Import Projects... 를 클릭합니다.
③ Specify Search Directory 버튼을 눌러 앞서 압축을 해제한 폴더를 선택합니다. (ZIP 파일을 바로 "Select archive file"로 지정해도 됩니다.)
④ 검색된 프로젝트 목록 중 실습하고자 하는 프로젝트(13_14_SevenSeg_Encoder_Bitfield, 13_14_SevenSeg_Encoder_Driverlib, 13_14_SevenSeg_Encoder_Freertos 중 원하는 프로젝트)를 체크하여 선택합니다.
⑤ Finish 버튼을 클릭하여 프로젝트를 워크스페이스로 불러옵니다.
⑥ 프로젝트를 마우스 우클릭하여 Build Project를 수행합니다. (CPU1_RAM은 디버깅용, CPU1_FLASH는 전원을 껐다 켜도 실행)
5. 예제 실행을 위한 하드웨어 점퍼선 연결 안내
아래와 같이 F28P65x 모듈의 핀-헤더와 개발보드 각 회로 블록을 점퍼 케이블로 연결합니다. 7-세그먼트와 엔코더 모두 A Side 핀-헤더를 사용합니다.| 번호 | 신호 | EVM V2 핀-헤더 | 할당 신호명 | 연결 대상 |
| 1~4 | 1번 자리 BCD (A=LSB) | A Side 65, 67, 69, 71번 핀 | GPIO0, 1, 2, 3 | (13) 블록 "A1, B1, C1, D1" |
| 5 | 1번 자리 점(DP) | A Side 73번 핀 | GPIO4 | (13) 블록 "DP1" |
| 6~9 | 2번 자리 BCD (A=LSB) | A Side 75, 77, 79, 81번 핀 | GPIO5, 6, 7, 8 | (13) 블록 "A2, B2, C2, D2" |
| 10 | 2번 자리 점(DP) | A Side 83번 핀 | GPIO9 | (13) 블록 "DP2" |
| 11 | 엔코더 A상 | A Side 105번 핀 | GPIO20 / EQEP1_A | (14) 블록 "A" |
| 12 | 엔코더 B상 | A Side 107번 핀 | GPIO21 / EQEP1_B | (14) 블록 "B" |
| 13 | 엔코더 노브 스위치 | A Side 109번 핀 | GPIO22 (일반 입력) | (14) 블록 "S/W" |
* (13) 블록 헤더는 A1 B1 C1 D1 DP1 A2 B2 C2 D2 DP2 순서의 10핀이고, GPIO0~9도 같은 순서입니다. 점퍼선을 핀 순서대로 나란히 꽂으면 됩니다. 자리마다 BCD 4핀 + 점(DP) 1핀이며, A가 LSB(최하위 비트), DP는 High일 때 점이 켜집니다.
* 1번 자리가 왼쪽(십의 자리), 2번 자리가 오른쪽(일의 자리)이라고 가정하고 만들었습니다. 이 대응은 보드에서 아직 확인하지 않았습니다. 반대로 나오면 알려 주세요.
* (14) 블록 헤더는 A B S/W 3핀입니다. 엔코더 A/B는 보드에서 슈미트 트리거 버퍼를 거쳐 나오고, 노브 스위치는 10k 풀다운 회로(누르면 High)입니다. 그래서 이 세 입력은 칩 내부 풀업을 켜지 않습니다.
* GPIO20/21은 TI의 eQEP 예제와 같은 핀입니다.

* 그림에서 실선 10가닥은 (13) 7-세그먼트, 점선 3가닥은 (14) 엔코더 연결입니다.
6. 예제 실행 및 동작 확인
① 점퍼선 13개를 연결합니다. 이 예제에는 USB 케이블이나 외부 회로가 필요 없습니다.② JTAG 에뮬레이터를 연결하고 디버그(Debug, F11) 후 실행(Resume, F8)합니다.
③ 동작 확인 : 시작하면 7-세그먼트에
00이 표시됩니다.- 엔코더를 오른쪽(시계 방향)으로 돌리면
01, 02, 03 ... 처럼 눈금(클릭) 하나에 1씩 올라갑니다.- 왼쪽으로 돌리면 1씩 줄어들고,
00에서 더 돌려도 00에서 멈춥니다. 반대쪽 끝은 99입니다.- 엔코더 노브를 누르면 표시가
00으로 돌아가고, 누르고 있는 동안 점(DP) 2개가 켜집니다.※ 위 동작은 코드와 PC 테스트로 확인한 설계 동작이며, 보드에서는 아직 확인하지 않았습니다.
④ 실시간 값 관찰 : CCS View > Watch (기존 CCS v12 이하는 View > Expressions) 창에 아래 변수를 등록하고 엔코더를 돌려 보세요.
-
displayValue : 표시 값(0~99) / encoderPos : eQEP 위치 카운터 / knobPressed : 노브 스위치 상태 / segOutput : GPIO0~9로 내보낸 출력 워드- FreeRTOS 버전은
displayUpdateCount(표시 태스크가 7-세그먼트를 갱신한 횟수)도 있습니다. 엔코더를 돌릴 때만 올라가고, 가만히 두면 멈춰 있어야 합니다.⑤ 동작이 다를 때 조정하는 방법
- 오른쪽으로 돌렸는데 값이 줄어든다 : 엔코더 A/B 점퍼선(105번/107번)을 서로 바꿔 꽂거나, 코드에서 A/B 입력을 바꿉니다. DriverLib/FreeRTOS 버전은
EQEP_setDecoderConfig()의 EQEP_CONFIG_NO_SWAP을 EQEP_CONFIG_SWAP으로, Bitfield 버전은 EQep1Regs.QDECCTL.bit.SWAP = 1로 바꿉니다.- 한 칸 돌렸는데 값이 2씩 바뀌거나, 반 칸마다 바뀐다 :
seg_counter.h의 SEGCNT_COUNTS_PER_STEP(기본 4)을 바꿉니다. eQEP는 쿼드러처 모드에서 A/B 네 에지를 모두 세므로 펄스 하나(눈금 하나)가 위치 카운터 4에 해당한다고 가정한 값입니다.- 십의 자리와 일의 자리가 바뀌어 보인다 : (13) 블록의 1번 자리와 2번 자리 점퍼선 5개씩을 서로 바꿔 꽂습니다.
⑥ 동작 원리 요약 : 메인 루프(FreeRTOS 버전은 엔코더 태스크)가 10 ms마다 위치 카운터와 노브 스위치를 읽습니다. 눈금 여러 개를 한 번에 돌려도 놓치지 않고, 눈금보다 작은 나머지 카운트는 다음 주기로 넘겨 누적합니다. 값은 00~99로 제한하고, 결과를 BCD 두 자리 + DP 비트로 만든 10비트 워드를 GPIO0~9에 한꺼번에 내보냅니다.
7. 참고 — 3가지 버전 실측 메모리 사용량 비교
동일한 동작을 세 가지 방식으로 구현했을 때 메모리 사용량이 얼마나 달라지는지 실제로 빌드해서 비교했습니다. 링커 맵의 영역별 사용량을 합산한 값이며, 단위는 워드(1워드 = 16비트 = 2바이트)입니다.| 버전 | CPU1_RAM 구성 합계 | CPU1_FLASH 구성 Flash 사용량 | CPU1_FLASH 구성 RAM 사용량 | Flash 사용률 (FLASH_BANK0 기준) |
| Bitfield | 4,739 | 4,929 | 307 | 약 3.8% |
| DriverLib | 5,721 | 5,166 | 1,267 | 약 3.9% |
| FreeRTOS | 9,585 | 8,001 | 2,296 | 약 6.1% |
CPU1_RAM 구성은 코드까지 RAM에 올라가므로 값이 크고, 스택과 힙 설정이 포함됩니다. RAM 차이의 대부분은 프로젝트의 스택/힙 설정에서 옵니다(Bitfield 스택 0x100워드, DriverLib 스택 0x3F8워드 + 힙 0x200워드). 힙은 쓰지 않아도 합계에 잡힙니다. FreeRTOS 버전은 커널 자체 코드/데이터(태스크 스택, TCB, 스케줄러)가 추가되어 Flash와 RAM이 모두 가장 큽니다. 측정은 최적화 없음(
--opt_level=off) 기준입니다.| 번호 | 제목 | 작성자 | 날짜 |
|---|
- 1




