[MODULE]/AUDIO2008. 5. 1. 12:03

[ PCM2906 ] USB Aodio DAC

[ PCM2906 ] USB Aodio DAC

출처

ORcad LIB




Pinmap



블럭도





응용회로
Posted by nexp
TAG USB

댓글을 달아 주세요

[INTERFACE]/USB_FTDI2008. 4. 20. 17:07

[FT2232 EVM, FT245 EVM] VB테스트 프로그램 작성

[FT2232 EVM, FT245 EVM] VB테스트 프로그램 작성

사용자 삽입 이미지


FTDI사 최신 드라이버 및 DLL파일



VB예제 소스



먼저 최신 드라이버 파일을 설치한다.

새로운 프로젝트를 생성하고 간단한 폼을 하나 만든다.




FT245, FT2232 제어를 위한 DLL함수 정의 모듈 등록
VB 모듈










등록되면 아래 그림과 같이 추가된것을 확인 할 수 있다.




프로그램 작성
장치 초기화
1)장치를 초기화 하기 위해 FT_Open()함수를 이용하여 장치를 열고 디바이스 핸들을 얻는다.
2)FT_SetBitMode() 함수를 이용하여 Bit제어 모드를 설정한다.
3)FT_SetBaudRate() 함수를 이용해 전송 속도를 설정한다.

    '장치 열기
    If FT_Open(DEVICE_NO, m_DeviceHandle) <> FT_OK Then
        Label1.Caption = "장치 열기 실패"
        Exit Sub
    Else
        Label1.Caption = "장치 열기 성공"
    End If


    'BitBang모드 설정.b0-b7=Out, BitBangMode(1)
    If FT_SetBitMode(m_DeviceHandle, &HFF, &H1) <> FT_OK Then
        Label1.Caption = "모드설정 실패"
        Exit Sub
    End If

   
    '보레이트 설정
    FT_SetBaudRate m_DeviceHandle, 57600


Data Write
FT245, FT2232 FIFO로 1Byte 쓰기위해 FT_WriteByte()함수를 이용한다.
첯번째 인자는 디바이스 핸들이고, 두번째는 쓸 데이터, 세번째는 바이트 수, 성공한 바이트 수 이다.
    'USB FIFO로 1Byte 쓰기
    ret = FT_WriteByte(m_DeviceHandle, &H0, 1, 0)


장치 닫기
    '프로그램 종류시 장치 닫기 -> 반드시 장치를 Close해야 함
    'Close하지 않고 프로그램이 종료되는 경우 USB커넥터를 다시 연결해야 함, 혹은 리셋
    If FT_Close(m_DeviceHandle) <> FT_OK Then
        Label1.Caption = "장치 닫기 실패"
    End If



좀더 추가하여 타이머 컨트롤을 이용하여 Led를 시프트 하면서 점등하는 예제를 작성해 보았다.




테스트 동영상
FT245 EVM을 이용하여 VB프로램으로 LED를 시프트 하는 예제





작성한 프로그램은 [FT245 EVM], [FT2232 EVM] 에서 적용가능하다

[FT245 EVM]




[FT2232 EVM]
사용자 삽입 이미지


앞으로 C#에서 적용해 보면 더 좋을듯한 생각이 든다...
Posted by nexp
TAG FT2232, FT245, USB

댓글을 달아 주세요

[INTERFACE]/USB_FTDI2008. 4. 19. 08:45

[FT245 EVM] 보드 제작

[FT245 EVM] 보드 제작

[##_1C#_ATTACH_PATH_##]/ek200000000038.jpg_##]


USB2FIFO [FT245 EVM] 보드를 제작했다.
크기는 기존 FT EVM 보드와 동일하게 제작했고 사이즈는 상당히 작다







동작 테스트는 문제 없고 드라이버까지 잘 올라 온다.



FT2232와 동일한 예제로 LED제어 했는데 문제 없이 잘 동작한다.
Posted by nexp
TAG FT245, USB

댓글을 달아 주세요

[INTERFACE]/USB_FTDI2008. 3. 18. 15:33

[VNC1L-1A] 을 이용한 PIC 마이크로컨트롤러에 USB 플래시 드라이버 인터페이싱 하기

PIC 마이크로컨트롤러에 USB 플래시 드라이버 인터페이싱 하기




최근 저비용 플래시 메모리 드라이브와 각종 USB 주변기기가 출시됨에 따라 USB 인터페이스는 어디에서든 찾아볼 수 있다. 그러나 이들 주변기기를 8비트 또는 16비트 임베디드 분야에 사용하려고 할 때에는 구현, 비용 및 전력 소모가 중요한 문제가 된다. 이 글에서는 최고 속도의 USB 2.0 인터페이스를 통해 저비용 PIC 마이크로컨트롤러를 플래시 드라이브로 연결하는 방법과 관련 프로그래밍에 대해 설명하고자 한다.

본고에서는 최고 속도의 USB 2.0 인터페이스를 통해 저비용 PIC 마이크로컨트롤러를 플래시 드라이브로 연결하는 방법과 관련 프로그래밍에 대해 자세히 설명하고자 한다. PIC 마이크로컨트롤러 및 Vinculum USB 인터페이스 칩 주변에 위치한 임베디드 인터페이스의 하드웨어 설계와 더불어 다양한 임베디드 애플리케이션에서 유비쿼터스 USB 플래시 드라이브가 착탈식 스토리지로 사용될 수 있도록 하는 일반적인 프로그래밍에 대해 살펴볼 예정이다.

서론
저비용 플래시 메모리 드라이브와 각종 USB 주변기기가 출시됨에 따라 USB 인터페이스는 오늘날 어디에서든 찾아볼 수 있다. 그러나 이들 대부분은 PC 업계에 집중되어 있다. 또한 이들 주변기기를 8비트 또는 16비트 임베디드 분야에 사용하려고 할 때에는 구현, 비용 및 전력 소모가 중요한 문제가 된다. 이러한 문제는 그러한 시스템에 사용되는 임베디드 컨트롤러도 마찬가지이다. 마이크로칩의 PIC 컨트롤러 제품군과 같은 디바이스들은 다양한 메모리 집적도 및 주변기기와 함께 사용되지만, USB 호스트 컨트롤러를 포함시키기 위한 인터페이스, 리소스 및 성능이 부족하다.
이 애플리케이션 예에서 VNC1L Vinculum 컨트롤러 IC는 시스템 컨트롤러로써의 PIC와 USB 2.0 최고 속도 포트 사이에 인터페이스를 제공한다. 이로써, 예를 들어, USB 플래시 메모리 드라이브 연결 시 구현 시간과 오버헤드를 최소화 할 수 있다.

Vinculum
이 컨트롤러는 데이터 전송을 가속화 하기 위한 쌍둥이 DMA(direct memory access) 엔진과 파일 시스템을 위한 계산을 최적화하기 위한 32비트 수치 코프로세서(numeric co?processor)와 함께 맞춤형 프로세서 주변에 위치해 있다. 이 모든 것은 64Kbyte의 임베디드 플래시 프로그램 메모리와 4Kbyte의 내부 데이터 SRAM을 탑재한 싱글칩에 결합되어 있다. Vinculum은 특별히 임베디드 USB 컨트롤러 시장을 겨냥해 고안되었으며, 최소한의 외부 부품만 있으면 된다. Vinculum 코어의 한 가지 핵심 특징은 일반 MCU 코어와 비교해 코드 길이가 매우 짧아졌다는 것이다. 코어의 코드 오버헤드를 줄임으로써 온칩 e-Flash 메모리에 더 많은 기능을 포함시킬 수 있다. 이와 같은 특징들은 PIC 기반의 임베디드 시스템에 보완적 역할을 한다. 그림 1은 이러한 시스템의 다이어그램을 나타낸 것으로, Vinculum을 사용해 소형 PIC MCU를 USB ‘A’ 커넥터, 그리고 USB 플래시 드라이브에 연결했다.

개요 설명
이 PIC는 시스템의 컨트롤러로, 범용 I/O 핀(핀 9, 10, 11에서 RC0, RC1, RA2)을 통해 센서 또는 다른 소스로부터 데이터를 받아서 플래시 드라이브에 있는 파일로의 스트림에서 데이터 포맷 변환 및 데이터 쓰기를 한다. 명령과 데이터는 TXD(핀 6)을 통해 VNC1L RXD(핀 32)로 보내진다. VNC1L은 FAT 12/16/32 파일 생성과 USB 플래시 드라이브에서의 데이터 스토리지를 담당하며, 핀 28, 29에서 USB2DM 및 USB2DP를 통해 드라이브와 통신한다. 데이터는 같은 핀을 통해 플래시 드라이브로부터 읽혀지고, PIC의 VNC1L TXD(핀 31)에서 RXD(핀 5)로 보내져 시스템 펌웨어에 의해 사용된다.
이 시스템은 PIC의 펌웨어에 의해 제어되는데, PIC가 내린 명령에 의해 전송이 제어되고, Vinculum의 표준 펌웨어에 의해 해석된다. 이는 시스템을 간단하게 설명한 것으로, 설계를 완성하는 데에는 더 복잡한 것들이 요구된다. 이들 디바이스는 전력, 클록 제어를 위한 크리스털을 필요로 하며, 이들은 프로그래밍 작업도 거쳐야 한다.
PIC의 핀 2, 3에서 20MHz의 크리스털을 사용함으로써 UART 인터페이스에서 최대 115200bps의 높은 변조 속도가 가능해 (내부 8MHz의 오실레이터를 이용하면 최대 9600bps 정도 밖에 얻지 못한다) 시스템의 성능을 향상시킬 수 있다. PIC 펌웨어에 의해 사용되는 PIC IO 핀 RC2 및 RC3은 VNC1Ls UART 인터페이스로 RTS/CTS 핸드세이크 신호(handshake signal)를 시뮬레이트 한다.
250mA에서 5V의 레귤레이트 된 PSU가 필요하며, USB ‘A’ 커넥터에서 최대 200mA를 제공한다. VNC1L에 전력을 공급하는 데에는 25mA, PIC16F688은 25mA의 전력이 필요하다. VNC1L은 3.3V의 공급 전압을 필요로 하는데, 이는 3.3V LDO 레귤레이터에서 제공되며, 레벨 시프터를 사용하지 않고 PIC로 연결될 수 있도록 하는 5V의 허용오차 I/O핀을 가지고 있다.
저전력 애플리케이션을 위해 VNC1L은 필요 없을 경우 2mA의 슬립 모드로 설정될 수 있다. 다시 디바이스를 활성화시키기 위해서는 UART 인터페이스의 링 인디케이터(RI) 핀을 스트로브(strobe) 한다. 여기에서처럼, 이것이 RXD 라인에 연결되면, 들어오는 더미 명령(dummy command)에 의해 트리거링 되어 디바이스를 활성화시킬 수 있다.
이 디자인은 또한 핀 16 및 18로부터 전력을 공급받는 2가지색 LED 인디케이터를 포함하고 있다. 이는 USB 드라이브의 성공적인 열거(enumeration)과 파일 시스템으로의 액세스를 나타내준다.

VNC1L 펌웨어
ViNC1L은 VDAP(Vinculum Disk and Peripheral)라는 표준 펌웨어로 프로그래밍되며, 이는 PIC로부터의 명령을 해석한다. 이들 VDAP 명령은 DIR, RD 및 WR 등 DOS와 같은 명령이다. 이 명령셋은 또한 마이크로프로세서 제어 방식에 가장 적합한 싱글 바이트 헥스(hex) 명령어를 지원한다.
VDAP 명령은 PIC 펌웨어에 포함되어 있으며, USB 플래시 드라이브로의 액세스를 제어한다. 일반적인 시퀀스는 파일을 생성하고, 파일로의 데이터 읽기/쓰기 및 파일 닫기에 사용된다.

VNC1L 및 PIC 프로그래밍
개발 환경이 요구된다고 가정하여 이 설계는 각각의 디바이스를 위한 2개의 프로그래밍 헤더(header)를 포함하고 있다. 생산 설계를 위해 두 디바이스 모두 PCB에서 삽입 전에 미리 프로그래밍 될 수 있어 헤더와 점퍼(jumper)를 제거한다.
일반 동작 동안 J1 및 J2는 파퓰레이트(populate) 되어야 하고, 다른 점퍼들은 오픈 상태로 있어야 한다. VNC1L을 프로그래밍하기 위해 J1과 J2 점퍼를 제거해 VNC1L UART 입력을 PIC 출력으로부터 절연시킨다. 5V PSU를 차단하고 TTL-232R-3V3 케이블을 H2에 연결시킨다. 이 케이블의 USB 사이드를 VPROG 프로그래밍 유틸리티가 설치된 PC로 연결시킨다. VNCL1A의 PROG# 핀을 낮게 당기기 위해 J4를 파퓰레이트 한 후 디바이스를 리셋하고 프로그래밍 모드로 들어가게 하기 위해 일시적으로 J3을 단락시킨다. 프로그래밍 이후에는 점퍼 설정을 동작 모드로 재저장 하는 것을 잊지 말아야 한다.
PIC용 프로그래밍 헤더는 디바이스의 핀 RA0 및 RA1과 MCLR#에 연결되고, 헤더를 통해 5V 프로그래밍 전압/서플라이가 공급된다. PIC 마이크로컨트롤러 프로그래밍 이전에 5V PSU를 차단해야 한다. PICKit2와 같은 표준 PIC 개발 환경에 헤더를 연결해 마이크로칩의 디버그 및 다운로딩 툴을 사용할 수도 있다.
PIC가 제공하는 샘플 C 코드는 플래시 디스크가 감지되고 hello.txt라는 파일을 열 때까지 기다린다. 그 다음 캐리지 리턴(carriage return) 및 라인 피드(line feed) 캐릭터와 함께 텍스트 ‘Hello World’가 파일로 쓰여진다. 그리고 나서 파일을 닫고, 디스크가 제거될 때까지 기다린다.

결론
FTDI의 Vinculum VNC1L은 사용하기 쉬우며, 저비용 마이크로컨트롤러와 USB 2.0 저/고속 주변기기 간의 인터페이스 프로그래밍도 쉽게 할 수 있다. DOS와 같은 명령셋을 통해 마이크로컨트롤러 환경 내에서 데이터 전송 루틴을 쓰고, 디버깅을 쉽게 할 수 있다. 단순한 레이아웃 또한 임베디드 시스템을 위한 저비용 USB 호스트 구현이 가능하도록 해준다. 이로써 저비용, 유비쿼터스 USB 플래시 드라이브를 시스템을 위한 데이터 스토리지 미디어로 사용할 수 있을 뿐만 아니라 필드에서 소프트웨어 업그레이드 제공이 가능하다. 이 글의 주제에서 약간 벗어나긴 하지만, VNC1L 디바이스는 또한 매스 스토리지 디바이스 외에 다른 많은 USB 주변기기를 연결하는데도 사용될 수 있다.
Vinculum IC는 또한 USB 인터페이스의 전력 예산의 10% 정도만 추가하면 되며, 시스템 전력 예산에는 이보다 훨씬 적게 든다. USB2.0 호스트 컨트롤러는 휴대용 디바이스에 쉽고 간단하게 추가될 수 있다.
VDAP 펌웨어와 완전한 명령셋이 기술된 문서는 FTDI의 Vinculum 웹사이트(http://www.vinculum.com)에서 다운로드 할 수 있다.

소스 코드

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Code for logging data directly to a USB Flash disk
// using a PIC16F688 and the VNC1L.
// Commands received through UART.
// The PIC only handles Tx and Rx automatically
// for the UART, so handshaking must
// be implemented in code.
//
// Author: FTDI
//
// Code written for PIC16F688 using SourceBoost C compiler
// (www.sourceboost.com)
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Pin definitions for PIC16F688 on VPIC board
//
// PIC16F688 Pin Number Designation Function
// 1 VDD Power
// 2 RA5 OSC_IN
// 3 RA4 OSC_OUT
// 4 MCLR# MCLR#
// 5 RC5 Rx (UART)
// 6 RC4 Tx (UART)
// 7 RC3 CTS# (connects to RTS# on TTL cable)
// 8 RC2 RTS# (connects to CTS# on TTL cable)
// 9 RC1 Analogue/Digital Input
// 10 RC0 Analogue/Digital Input
// 11 RA2 Analogue/Digital Input (Stop button)
// 12 RA1 Analogue/Digital Input (Start button)
// 13 RA Analogue/Digital Input (Use this one for analog input)
// 14 GND Ground
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
#include
#include

#pragma DATA 0x2007, _HS_OSC & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _FCMEN_OFF;
#pragma CLOCK_FREQ 20000000;

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Constants and variables for serial port
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
// Define serial port flags
char _RTS = 0x04 // RTS# is RC2 (Port C bit 2)
char _CTS = 0x08; // CTS# is RC3 (Port C bit 3)
char FLOW_NONE = 0x00;
char FLOW_RTS_CTS = 0x01;
char FLOW_CONTROL_ENABLED = 0x00; // Initialise FLOW_ CONTROL_ENABLED to off

// Define serial port Rx buffer variables
char SERIAL_RX_FIFO[0x20]; // Allocate buffer for RX FIFO USE MULTIPLE OF 0x04!
char RX_FIFO_SIZE = sizeof(SERIAL_RX_FIFO); // Initialise FIFO size variable
char RX_FIFO_COUNT = 0x00; // Reset RX FIFO count
char 쪹 RX_FIFO_HEAD_PTR = &SERIAL_RX_FIFO[0x00]; // Initialise head pointer
char 쪹 RX_FIFO_TAIL_PTR = &SERIAL_RX_FIFO[0x00]; // Initialise tail pointer
char 쪹 RX_FIFO_START = RX_FIFO_TAIL_PTR; // Set lowest address of RX_FIFO
char 쪹 RX_FIFO_END = RX_FIFO_START + RX_FIFO_SIZE; // Set highest address of RX_FIFO
char RX_STATUS = 0x00; // Reset RX status
char RX_FIFO_OVERRUN = 0x01;

char RX_FIFO_UPPER_LIMIT = 0x03 쪻(RX_FIFO_SIZE / 0x04); // Buffer limit for handshaking
char RX_FIFO_LOWER_LIMIT = (RX_FIFO_SIZE / 0x04); // Buffer limit for handshaking

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Define states for state machine
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

enum { // Enum states
VNC1L_Idle, // Idle state
VNC1L_DiskAvailable,
VNC1L_CreateFile,
VNC1L_WriteFile,
VNC1L_EndFile,
VNC1L_WaitForRemove
};
char VNC1L_State = VNC1L_Idle; // Initialise state to idle

char Synchronised = 0x01;
char GotDisk = 0x01;

//////////////////////////////////////////////////////////////////////
//
// Routines for serial port
//
//////////////////////////////////////////////////////////////////////

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Reset Rx FIFO
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void serial_resetrxfifo()
{
pie1.RCIE = 0x00; // Disable interrupts
intcon.GIE = 0x00;
intcon.PEIE = 0x00;
RX_FIFO_COUNT = 0x00; // Reset FIFO count to 0
RX_STATUS = 0x00; // Reset FIFO status
RX_FIFO_HEAD_PTR = (&SERIAL_RX_FIFO[0x00]); // Set FIFO head pointer to address of first byte of SERIAL_RX_FIFO
RX_FIFO_TAIL_PTR = (&SERIAL_RX_FIFO[0x00]); // Set FIFO tail pointer to address of first byte of SERIAL_RX_FIFO
pie1.RCIE = 0x01; // Enable interrupts for Rx byte
intcon.GIE = 0x01;
intcon.PEIE = 0x01;
if (FLOW_CONTROL_ENABLED == 0x01) // If using flow control
{
portc &= ~_RTS; // Set RTS# active (low)
}
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Initialise serial port (Baud rate, handshaking, interrupt enable, enable receiver)
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void serial_init(long BaudRate, char Handshaking) // Set up serial port
{
pie1.RCIE = 0x00; // Disable interrupts
intcon.GIE = 0x00;
intcon.PEIE = 0x00;

baudctl = 0x00;
ansel &= 0x3F; // Digital IO on RC2, RC3
trisc = 0xDB; // Set RC4 (Tx) & RC2 (RTS#) as output,RC5 (Rx) & RC3 (CTS#) as input
// TRISC bits 1 for input, 0 for output
portc |= _RTS; // Set RTS# high (inactive) at this stage
txsta = 0x04; // Enable UART module and set 8,n,1 - Set BRGH to 1
rcsta.SPEN = 0x01; // Enable serial port

switch (BaudRate) // Set Baud rate
{
case 9600:
spbrg = 0x81;
break;
case 19200:
spbrg = 0x40;
break;
case 57600:
spbrg = 0x15;
break;
case 115200:
spbrg = 0x0A;
break;
default:
spbrg = 0x81; // Default to 9600 if not a valid achievable Baud rate
}
spbrgh = 0x00;


if (Handshaking == FLOW_RTS_CTS)
{
portc &= ~_RTS; // If handshaking is required, set RTS# active (low)
FLOW_CONTROL_ENABLED = 0x01; // Set flow control enabled flag
}

serial_resetrxfifo(); // Reset Rx FIFO

pir1.RCIF = 0x00; // Clear Rx interrupt flag
pie1.RCIE = 0x01; // Enable interrupts for Rx byte
intcon.GIE = 0x01;
intcon.PEIE = 0x01;
rcsta.CREN = 0x01; // Enable receiver
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Send a byte directly from the transmit register
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void serial_sendbyte(char TX_BYTE)
{
if (FLOW_CONTROL_ENABLED == 0x01)
{
while (portc & _CTS); // Wait for CTS# to become active (low)
}
while (!txsta.TRMT); // Wait for TSR to be empty
txreg = TX_BYTE; // Move byte to send into TXREG
txsta.TXEN = 1; // Start transmission
while (!txsta.TRMT); // Wait for TSR to be empty - indicates sending is complete
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Read a byte directly from the receive character register
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
void serial_receivebyte(char RX_BYTE)
{
RX_BYTE = rcreg;
pir1.RCIF = 0x00; // Clear Rx interrupt flag
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Add a byte from the receive character
// register to the receive FIFO buffer
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void serial_addtorxfifo()
{
if (RX_FIFO_COUNT >= RX_FIFO_SIZE) // If Rx FIFO is full
{
RX_STATUS = RX_STATUS | RX_FIFO_OVERRUN; // Set overrun flag
if (FLOW_CONTROL_ENABLED == 0x01) // If using flow control
{
portc |= _RTS; // Set RTS# inactive (high)
}
return;
}

if (RX_FIFO_COUNT >= RX_FIFO_UPPER_LIMIT) // Keep some space in the FIFO for bytes already being sent
{
if (FLOW_CONTROL_ENABLED == 0x01) // If using flow control
{
portc |= _RTS; // Set RTS# inactive (high)
}
}

intcon.GIE = 0x00; // Disable interrupts
intcon.PEIE = 0x00;

쪹RX_FIFO_HEAD_PTR++ = rcreg; //Add received byte to RX_FIFO and then increment head pointer
RX_FIFO_COUNT++; // Increment byte count

if (RX_FIFO_HEAD_PTR >= RX_FIFO_END) // If head pointer is greater than allocated FIFO end address
{
RX_FIFO_HEAD_PTR = RX_FIFO_START; // Wrap-around buffer to start address again (circuluar FIFO)
}

if ((RX_FIFO_COUNT < RX_FIFO_UPPER_LIMIT) && (FLOW_CONTROL_ENABLED == 0x01)) // If Rx FIFO is not full
{
portc &= ~_RTS; // Set
RTS# active (low)
}

intcon.GIE = 0x01; // Re-enable interrupts
intcon.PEIE = 0x01;
}
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Read a byte out of the receive FIFO buffer
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void serial_readfromrxfifo(char 쪹RX_FIFO_BYTE)
{
if (RX_FIFO_COUNT == 0) // If FIFO is empty
{
return; // Exit - no data to read
}

intcon.GIE = 0x00; // Disable interrupts
intcon.PEIE = 0x00;

쪹RX_FIFO_BYTE = 쪹RX_FIFO_TAIL_PTR++; // Read a byte from the FIFO at position given by RX_FIFO_TAIL_PTR and then increment tail pointer
RX_FIFO_COUNT--; // Decrement byte count

if (RX_FIFO_TAIL_PTR >= RX_FIFO_END) // If tail pointer is greater than allocated FIFO end address
{
RX_FIFO_TAIL_PTR = RX_FIFO_START; // Wrap-around buffer to start address again (circuluar FIFO)
}

intcon.GIE = 0x01; // Re-enable interrupts
intcon.PEIE = 0x01;

if ((RX_FIFO_COUNT < RX_FIFO_LOWER_LIMIT) && (FLOW_CONTROL_ENABLED == 0x01)) // If using flow control
{
portc &= ~_RTS; // Set RTS# active (low)
}
}

//////////////////////////////////////////////////////////////////////
//
// VNC1L VDAP commands go here
//
//////////////////////////////////////////////////////////////////////

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Echo command using E - same for short command set or
// long command set
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void VNC1L_Big_E()
{
serial_sendbyte('E'); // Send 'E'
serial_sendbyte(0x0D); // Send carriage return
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Echo command using e - same for short command set or
// long command set
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
void VNC1L_Small_e()
{
serial_sendbyte('e'); // Send 'e'
serial_sendbyte(0x0D); // Send carriage return
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Synchronise to the VNC1L using the e and E echo commands
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

char VNC1L_Sync()
{
char LoopCount = 0x00;
char FIFOByte1 = 0x00;
char FIFOByte2 = 0x00;
char Got_Big_E = 0x00;
char Got_Small_e = 0x00;

serial_resetrxfifo(); // Reset FIFO before synchronising

while ((Got_Big_E == 0x00) && (LoopCount < 0xFF))
{
VNC1L_Big_E(); // Send Big E echo
LoopCount++; // Increment loop count
while (RX_FIFO_COUNT < 0x02)
{
delay_ms(100); // Wait for 2 byte response
}

if (RX_FIFO_COUNT > 0x00) // If data is available
{
while (RX_FIFO_COUNT > 0x02) // Read all data available except last 2 bytes
{
serial_readfromrxfifo(&FIFOByte1); // If more than 2 bytes available, read surplus ones

}
serial_readfromrxfifo(&FIFOByte1); // Check that remaining 2 bytes are 'E' and 0x0D
serial_readfromrxfifo(&FIFOByte2);
if ((FIFOByte1 == 'E') && (FIFOByte2 == 0x0D))
{
Got_Big_E = 0x01;
}
else
{
delay_ms(10); // Wait a bit and retry synchronisation
}
}
}

if (Got_Big_E == 0x01)
{
VNC1L_Small_e();
while (RX_FIFO_COUNT < 0x02)
{
delay_ms(10); // Wait for 2 byte response
}
serial_readfromrxfifo(&FIFOByte1); // Check that remaining 2 bytes are 'e' and 0x0D
serial_readfromrxfifo(&FIFOByte2);
if ((FIFOByte1 == 'e') && (FIFOByte2 == 0x0D))
{
Got_Small_e = 0x01; // If small e found, then synchronised
}

}

return Got_Small_e;

}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Look for disk - assumes long command set being used
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

char VNC1L_FindDisk() // Return 0x01 if disk is found, else return 0x00
{
char FIFOByte1 = 0x00;
char FIFOByte2 = 0x00;
char FIFOByte3 = 0x00;
char FIFOByte4 = 0x00;
char FIFOByte5 = 0x00;

serial_sendbyte(0x0D); // Send carriage return
while (RX_FIFO_COUNT < 0x05); // Wait until at least 5 bytes in the Rx FIFO
serial_readfromrxfifo(&FIFOByte1); // Read bytes out of Rx FIFO
serial_readfromrxfifo(&FIFOByte2);
serial_readfromrxfifo(&FIFOByte3);
serial_readfromrxfifo(&FIFOByte4);
serial_readfromrxfifo(&FIFOByte5);

if ((FIFOByte1 == 'D') && (FIFOByte2 == ':') && (FIFOByte3 == 0x5C) && (FIFOByte4 == '>') && (FIFOByte5 == 0x0D)) // Check for prompt
{
return 0x01; // If prompt found, then return disk available
}
else
{
while (RX_FIFO_COUNT > 0x00)
{
serial_readfromrxfifo(&FIFOByte1); // Read any additional bytes out of the FIFO
}
return 0x00; // Return no disk available
}

}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Open file for write command (OPW) using long command set
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void VNC1L_OpenFile()
{
char FIFOByte = 0x00;

serial_sendbyte('O'); // Send 'O'
serial_sendbyte('P'); // Send 'P'
serial_sendbyte('W'); // Send 'W'
serial_sendbyte(' '); // Send ' '
serial_sendbyte('h'); // Send 'h'
serial_sendbyte('e'); // Send 'e'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('o'); // Send 'o'
serial_sendbyte('.'); // Send '.'
serial_sendbyte('t'); // Send 't'
serial_sendbyte('x'); // Send 'x'
serial_sendbyte('t'); // Send 't'
serial_sendbyte(0x0D); // Send carriage return
while (RX_FIFO_COUNT < 0x05) // Wait until at least 5 bytes in the Rx FIFO
{
delay_ms(10); // Wait for 5 byte response("D:\>" + 0x0D)
}
while (RX_FIFO_COUNT > 0x00)
{
serial_readfromrxfifo(&FIFOByte); // Read response bytes form FIFO
}
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Write to file command (OPW) using long command set
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void VNC1L_WriteToFile()
{
char FIFOByte = 0x00;

serial_sendbyte('W'); // Send 'W'
serial_sendbyte('R'); // Send 'R'
serial_sendbyte('F'); // Send 'F'
serial_sendbyte(' '); // Send ' '
serial_sendbyte(0x00); // Send 0x00 - Number of bytes to write MSB
serial_sendbyte(0x00); // Send 0x00
serial_sendbyte(0x00); // Send 0x00
serial_sendbyte(0x0E); // Send 0x0E - Number of bytes to write LSB
serial_sendbyte(0x0D); // Send carriage return
serial_sendbyte('H'); // Send 'H'
serial_sendbyte('e'); // Send 'e'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('o'); // Send 'o'
serial_sendbyte(' '); // Send ' '
serial_sendbyte('W'); // Send 'W'
serial_sendbyte('o'); // Send 'o'
serial_sendbyte('r'); // Send 'r'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('d'); // Send 'd'
serial_sendbyte('!'); // Send '1'
serial_sendbyte(0x0D); // Send carriage return
serial_sendbyte(0x0A); // Send line feed
serial_sendbyte(0x0D); // Send carriage return

while (RX_FIFO_COUNT < 0x05) // Wait until at least 5 bytes in the Rx FIFO
{
delay_ms(10); // Wait for 5 byte response("D:\>" + 0x0D)
}

while (RX_FIFO_COUNT > 0x00)
{
serial_readfromrxfifo(&FIFOByte); // Read response bytes form FIFO
}

}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Close file command (CLF) using long command set
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void VNC1L_CloseFile()
{
char FIFOByte = 0x00;

serial_sendbyte('C'); // Send 'C'
serial_sendbyte('L'); // Send 'L'
serial_sendbyte('F'); // Send 'F'
serial_sendbyte(' '); // Send ' '
serial_sendbyte('h'); // Send 'h'
serial_sendbyte('e'); // Send 'e'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('l'); // Send 'l'
serial_sendbyte('o'); // Send 'o'
serial_sendbyte('.'); // Send '.'
serial_sendbyte('t'); // Send 't'
serial_sendbyte('x'); // Send 'x'
serial_sendbyte('t'); // Send 't'
serial_sendbyte(0x0D); // Send carriage return

while (RX_FIFO_COUNT < 0x05) // Wait until at least 5 bytes in the Rx FIFO
{
delay_ms(10); // Wait for 5 byte response("D:\>" + 0x0D)
}

while (RX_FIFO_COUNT > 0x00)
{
serial_readfromrxfifo(&FIFOByte); // Read response bytes form FIFO
}

}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Interrupt routines go here
// Use receive character interrupt to add received characters
// to the RX FIFO
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void interrupt()
{
if (pir1.RCIF)
{
serial_addtorxfifo(); // Add received byte to Rx FIFO
pir1.RCIF = 0x00; // Clear RCIF flag
}
}

//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//
// Main line code
//
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻
//쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻쪻

void main()
{
char Sync = 0x00;

VNC1L_State = VNC1L_Idle; // Initialise state to idle
serial_init(9600, FLOW_RTS_CTS); // Initialise Baud rate and flow control
delay_s(1); // Allow some time for power up
if (VNC1L_Sync() == Synchronised) // Synchronise to Vinculum
{
while (1) // Main state machine - do not return from here
{
switch (VNC1L_State)
{
case VNC1L_Idle:
Sync = VNC1L_Sync();
if (VNC1L_FindDisk() == GotDisk) // Check for disk
{
VNC1L_State = VNC1L_DiskAvailable; // Update state to indicate disk found
}
break;

case VNC1L_DiskAvailable:
VNC1L_OpenFile(); // Send open file for write command (OPW) - file name "hello.txt"
VNC1L_State = VNC1L_WriteFile; // Update state to indicate file has been created and can be written
break;

case VNC1L_WriteFile:
VNC1L_WriteToFile(); // Send write file command (WRF) - write "Hello World!"
VNC1L_State = VNC1L_EndFile; // Update state to indicate file has been written and can now be closed
break;

case VNC1L_EndFile:
VNC1L_CloseFile(); // Send close file command (CLF)
VNC1L_State = VNC1L_WaitForRemove; // Update state to indicate witing for disk to be removed
break;

case VNC1L_ WaitForRemove:
Sync = VNC1L_Sync();
if (VNC1L_ FindDisk() != GotDisk) // Check for disk
{
VNC1L_State = VNC1L_Idle; // Update state to indicate disk has been removed and return to idle
}
break;

default:
VNC1L_State = VNC1L_Idle; / Default to idle state
}
}
}
}

Posted by nexp

댓글을 달아 주세요

[FreeScale]/M92008. 3. 6. 23:56

[MC9S08JM] USB Microcontroller를 제작해 보자

[MC9S08JM] USB Microcontroller를 제작해 보자
일단 Freescale S08시리즈 툴(http://nexp.tistory.com/132)도 있고 전에 샘플로 얻어둔 MC9S08JM이 있으니 이걸로 시작 해 볼 생각이다.
48pin QFN타입의 소형이 저전력에 USB기능 까지 있으니... 소형의 테스트 보드 만들기에 적합하다.
8bit <-> 32bit 호환이 자유롭다는 것이 눈에 들어온다.

The ColdFire®-based MCF51JM128  and the S08-based MC9S08JM60 belong to the Flexis JM family. The Flexis JM family devices expand the Freescale Controller Continuum by providing pin, peripheral and tool compatibility between 8- and 32-bit controllers with USB functionality. By using the JM family of devices, product designers can easily upgrade industrial or consumer applications with USB functionality to provide more control and communications options. The JM family offers full hardware and software solutions to get you through the development process quickly and easily.





핀맵은 아래와 같고 약간의 생소한 핀들이 눈에 보인다.





데이터시트에 회로구성에 대한 간략하고 전반적인 블럭도가 있어 한눈에 들어온다. 이런식으로 회로구성도를 그려두면 이해하기 편할것 같다. 역시 외국넘들은 문서화에 강하다 말야..





메모리 구조




특이한 기능
USB Keyboard처리를 위한 특수기능핀이 있다.
 




개발보드
[ODBM]Flash Write 및 Debug Tool) http://nexp.tistory.com/132_
사용자 삽입 이미지


8bti, 32bit 호환되는 개발보드

Posted by nexp

댓글을 달아 주세요