Documente noi - cercetari, esee, comentariu, compunere, document
Documente categorii

SM - Convertor USB-I2C


SM

~Convertor USB-I2C~


Cerinte

Sa se proiecteze un convertor USB - I2C.

Caracteristici:

  • convertorul va trebui sa asigure conectarea unui PC, prin intermediul portului USB, la o magistrala I2C;
  • se vor asigura rolurile de master si slave pentru PC
  • se vor preciza performantele convertorului

Standardul I2C (Inter-Integrated Circuit Bus)




O magistrala seriala de tip I2C permite interconectarea componentelor unui microsistem : microcontrolor (ex : 80C552), memorie de program (EPROM), memorie de date (SRAM), convertoare A/D si D/A si alte dispozitive periferice. Aceasta magistrala inlocuieste o magistrala clasica de sistem, care are un numar relativ mare de linii de adresa, date si control. Utilizarea unei magistrale seriale reduce semnificativ costurile de cablaj, si timpul de realizare a unor prototipuri. Este solutia ideala pentru realizarea unor sisteme incapsulate bazate pe microcontroloare. Dezavantajul utilizarii unei astfel de magistrale este reducerea semnificativa a vitezei de comunicatie intre componentele sistemului. Acest dezavantaj este diminuat in cazul microcontroloarelor la care majoritatea componentelor sunt in acelasi circuit integrat ( unitate centrala, memorie ROM, memorie RAM, porturi de intrare/iesire, etc.) si numai anumite componente specifice aplicatiei (ex : convertoare) trebuie sa comunice pe magistrala seriala.

Pe magistrala I2C transmisia este seriala sincrona ; se utilizeaza un semnal separat de ceas alaturi de semnalul de date. Circuitele de emisie sunt cu colector in gol, ceea ce permite conectarea pe acelasi semnal a mai multor iesiri de circuit. Astfel se realizeaza un « SI-cablat » intre iesirile de circuite. In figura 1 s-a reprezentat modul de conectare a componentelor pe o magistrala I2C.





Vcc

rez.

rez.









SDA (Serial Data Line)




Vcc







SCL (Serial Clock Line)






















































CLK1


Data1



CLK1


Data2







out


out



out


out























CLK1


Data1



CLK1


Data2








in


in



in


in
























Figura 1. Conectarea pe magistrala I2C



Pe magistrala se pot conecta module master ( care au drept de initiativa in transferul de date) si module slave (care pot fi interogate de modulele master). Un modul master poate sa initieze un transfer daca magistrala este libera. In cazul in care doua unitati master initiaza simultan un transfer de mesaj, atunci va avea cistig de cauza mesajul care contine valoarea zero pe primul bit diferit intre cele doua mesaje. Aceasta se datoreaza faptului ca la un « SI cablat » valoarea zero este dominanta. In figura 2 s-a reprezentat structura mesajelor de transmisie si receptie.

S

Adresa slave

R

A

Data

A

Data

A

P

unitatea master receptioneaza date de la unitatea slave

S

Adresa slave

W

A

Data

A

Data

A

P



unitatea master transmite date unitatii slave

unde:

S-cond. de start

P

cond. de stop

A - acceptare data (acknowlidge)

R/W

cit./scr.

- transmis de master

- transmis de slave

Figura 2. Structura mesajelor I2C

Magistrala USB (Universal Serial Bus)

Magistrala USB (Universal Serial Bus) a fost dezvoltata in anul 1995 de un grup de firme care cuprinde Compaq, Hewlett Packard, Intel, Lucent, Microsoft, NEC si Philips. Aceste firme sunt reunite in asociatia USB Implementers Forum. Principalele motivatii care au stat la baza elaborarii acestei magistrale au fost urmatoarele:

. Simplificarea interconexiunilor dintre un calculator si periferice. Fiecare calculator PC dispune de porturi paralele, porturi seriale, conectori pentru monitor, tastatura, mouse, difuzoare. Poate exista de asemenea un conector pentru retea sau telefon, un conector SCSI, un conector MIDI (Musical Instruments Digital Interface), un conector pentru preluarea imaginilor de la o

sursa video externa (camera video, aparat video sau televizor). Toate aceste periferice necesita un numar mare de conectori si cabluri. Unul din scopurile elaborarii magistralei USB a fost reducerea numarului de cabluri care se conecteaza la calculator si utilizarea aceluiasi tip de

conector pentru principalele periferice, deci, realizarea unei interconexiuni universale.

. Asigurarea unei rate de transfer ridicate. Porturile seriale permit o rata de transfer maxima de 115,2 Kbiti/s (14 KB/s), iar porturile paralele ECP/EPP asigura o rata de transfer de 3 MB/s. Exista numeroase periferice care necesita rate de transfer mult mai ridicate.

. Usurinta utilizarii. Interfetele de I/E ale calculatoarelor IBM PC, cum sunt porturile seriale si paralele, interfetele pentru tastatura si mouse, nu au atribute de tip "Plug and Play".

. Adaugarea simpla a perifericelor. Adaugarea perifericelor externe este limitata de numarul porturilor disponibile. In general, interfetele existente sunt specifice diferitelor tipuri de periferice, pentru fiecare nou tip de periferic fiind definita o noua interfata.

. Eliminarea restrictiilor datorate resurselor hardware insuficiente. Fiecare interfata a calculatorului necesita propria linie de intrerupere. Un calculator PC are numai 16 linii de intrerupere, din care doar un numar redus raman disponibile pentru instalarea perifericelor.

In prezent, practic toate calculatoarele noi dispun de unul sau mai multe porturi USB, iar cei mai multi producatori de periferice dezvolta echipamente conforme cu specificatiile USB. Calculatorul prevazut cu o magistrala USB detecteaza adaugarea unui nou periferic si determina in mod automat care sunt resursele necesare acestuia, inclusiv driverul software si rata de transfer. Adaugarea si eliminarea unui periferic se poate realiza fara a deschide carcasa calculatorului, fara oprirea si repornirea acestuia. Unul din perifericele calculatorului, de exemplu, tastatura sau monitorul, se conecteaza la conectorul USB al calculatorului. Alte periferice se conecteaza la un distribuitor ("hub") aflat in cadrul tastaturii sau monitorului, fiind posibila realizarea unor conexiuni sub forma de arbore. Toate perifericele USB utilizeaza un conector standard, eliminandu-se necesitatea utilizarii unor conectoare diferite pentru fiecare tip de periferic.

Solutia Hardware


PDIUSBD11, fabricat de Philips semiconductor, permite aproape pentru toate microcontrolere sa aibe interfata USB. Interfata sa de I2C poate sa aiba o viteza teoretica maxima de transfer de 568 KB/s. In tabelul 1. sunt specificate functionalitatile piniilor.

PDIUSBD11 este controlat de catre microcontrolerul PIC16F876. Pe figura 3 este prezentata modul conectarii microcontrolerului PIC la PDIUSBD11. Schema permite sa fie citite 5 tensiuni analogi de la cei 5 intrari multiplexate ADC ale microcontrolerului PIC16F876.

LED-ul conectat pe pinul RB3 lumineaza atunci, cand instrumentul este configurat. PDIUSBD11 mai are nevoie de un regulator de 3.3 V.

Figura 3. Schema convertorului USB-I2C

Solutia Software


Codul este scris in limbajul C si este compatibil si cu PIC16F877, permite un numar maxim de 8 canale analoage.

Fisierul usbfull.h arata in felul urmator:


typedef struct USB_SETUP_REQUEST, *PUSB_SETUP_REQUEST;


typedef struct USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;


typedef struct USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;


typedef struct USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;


typedef struct USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;


typedef struct USB_HID_DESCRIPTOR, *PUSB_HID_DESCRIPTOR;


typedef struct USB_CONFIG_DATA, *PUSB_CONFIG_DATA;


typedef struct MANUFACTURER_DESCRIPTOR, *PMANUFACTURER_DESCRIPTOR;


typedef struct LANGID_DESCRIPTOR, *PLANGID_DESCRIPTOR;


void I2C_Write(unsigned char byDevId, const unsigned char * pbyData, unsigned char byCount);

void I2C_Read(unsigned char byDevId, unsigned char pbyData[], unsigned char byCount);

void I2C_Init(void);

void I2C_Start(void);

void I2C_Stop(void);

unsigned char I2C_Read_Byte(unsigned char Ack);

void I2C_Write_Byte(unsigned char byte);

void USB_Init(void);

void USB_Disconnect(void);

void D11CmdDataWrite(unsigned char Command, const unsigned char *Buffer, unsigned char Count);

void D11CmdDataRead(unsigned char Command, unsigned char Buffer[], unsigned char Count);

unsigned char D11ReadEndpoint(unsigned char Endpoint, unsigned char *Buffer);

void D11WriteEndpoint(unsigned char Endpoint, const unsigned char *Buffer, unsigned char Bytes);

void WriteBufferToEndPoint(void);

void loadfromcircularbuffer(void);

void GetDescriptor(PUSB_SETUP_REQUEST SetupPacket);

void D11GetIRQ(void);

void InitUART(void);

void putch(unsigned char byte);

void puthex(unsigned char byte);



void Process_EP0_OUT_Interrupt(void);

void ErrorStallControlEndPoint(void);


#define D11_SET_HUB_ADDRESS                  0xD0

#define D11_SET_ADDRESS_ENABLE                           0xD1

#define D11_SET_ENDPOINT_ENABLE  0xD8

#define D11_SET_MODE                                 0xF3

#define D11_READ_INTERRUPT_REGISTER   0xF4

#define D11_READ_LAST_TRANSACTION     0x40

#define D11_SET_ENDPOINT_STATUS                         0x40

#define D11_READ_ENDPOINT_STATUS       0x80

#define D11_READ_BUFFER        0xF0

#define D11_WRITE_BUFFER                         0xF0

#define D11_CLEAR_BUFFER                          0xF2

#define D11_VALIDATE_BUFFER                    0xFA

#define D11_ACK_SETUP                                0xF1


#define D11_ENDPOINT_EP0_OUT                              0x02

#define D11_ENDPOINT_EP0_IN                   0x03

#define D11_ENDPOINT_EP1_OUT                              0x05

#define D11_ENDPOINT_EP1_IN                   0x04

#define D11_ENDPOINT_EP2_OUT                              0x06

#define D11_ENDPOINT_EP2_IN                   0x07

#define D11_ENDPOINT_EP3_OUT                              0x08

#define D11_ENDPOINT_EP3_IN                   0x09


#define D11_CMD_ADDR 0x36

#define D11_DATA_ADDR_WRITE                 0x34

#define D11_DATA_ADDR_READ                   0x35


#define D11_INT_BUS_RESET                        0x4000

#define D11_INT_EP0_OUT         0x0004

#define D11_INT_EP0_IN 0x0008

#define D11_INT_EP1_OUT         0x0020

#define D11_INT_EP1_IN 0x0010

#define D11_INT_EP2_OUT         0x0040

#define D11_INT_EP2_IN 0x0080

#define D11_INT_EP3_OUT         0x0100

#define D11_INT_EP3_IN 0x0200


#define D11_LAST_TRAN_SETUP                   0x20


#define STANDARD_DEVICE_REQUEST                         0x00

#define STANDARD_INTERFACE_REQUEST   0x01

#define STANDARD_ENDPOINT_REQUEST    0x02

#define VENDOR_DEVICE_REQUEST                             0x40

#define VENDOR_ENDPOINT_REQUEST                       0x42


#define GET_STATUS  0

#define CLEAR_FEATURE  1

#define SET_FEATURE  3

#define SET_ADDRESS  5

#define GET_DESCRIPTOR  6

#define SET_DESCRIPTOR  7

#define GET_CONFIGURATION  8

#define SET_CONFIGURATION  9

#define GET_INTERFACE   10

#define SET_INTERFACE    11

#define SYNCH_FRAME  12

#define VENDOR_GET_ANALOG_VALUE                     1

#define VENDOR_SET_RB_HIGH_NIBBLE      2


#define  ENDPOINT_HALT 0


#define TYPE_DEVICE_DESCRIPTOR 1

#define TYPE_CONFIGURATION_DESCRIPTOR2

#define TYPE_STRING_DESCRIPTOR 3

#define TYPE_INTERFACE_DESCRIPTOR 4

#define TYPE_ENDPOINT_DESCRIPTOR  5

#define TYPE_HID_DESCRIPTOR                     0x21


#define USB_ENDPOINT_TYPE_CONTROL     0x00

#define USB_ENDPOINT_TYPE_ISOCHRONOUS          0x01

#define USB_ENDPOINT_TYPE_BULK                           0x02

#define USB_ENDPOINT_TYPE_INTERRUPT  0x03



Fisierul usbfull.c:

#include <pic.h>

#include <stdio.h>

#include <string.h>

#include 'usbfull.h'


const USB_DEVICE_DESCRIPTOR DeviceDescriptor = ;


const USB_CONFIG_DATA ConfigurationDescriptor = ,

,

,


const LANGID_DESCRIPTOR LANGID_Descriptor = ;


const MANUFACTURER_DESCRIPTOR Manufacturer_Descriptor = ;


#define MAX_BUFFER_SIZE 80


bank1 unsigned char circularbuffer[MAX_BUFFER_SIZE];

unsigned char inpointer;

unsigned char outpointer;


const unsigned char * pSendBuffer;

unsigned char BytesToSend;

unsigned char CtlTransferInProgress;

unsigned char DeviceAddress;

unsigned char DeviceConfigured;


#define PROGRESS_IDLE 0

#define PROGRESS_ADDRESS 3


void main (void)



void USB_Init(void)



void D11GetIRQ(void)



if (Irq & D11_INT_EP0_OUT)


if (Irq & D11_INT_EP0_IN)

else

}


if (Irq & D11_INT_EP1_OUT)

loadfromcircularbuffer(); //Kick Start

}


if (Irq & D11_INT_EP1_IN)


if (Irq & D11_INT_EP2_OUT)


if (Irq & D11_INT_EP2_IN)


if (Irq & D11_INT_EP3_OUT)


if (Irq & D11_INT_EP3_IN)



void Process_EP0_OUT_Interrupt(void)


else

break;


case SET_DESCRIPTOR:

default:

/* Unsupported - Request Error - Stall */

ErrorStallControlEndPoint();

break;


}

break;


case STANDARD_INTERFACE_REQUEST:

printf('Standard Interface Requestnr');

switch (SetupPacket.bRequest) /* else fall through as RequestError */


//case CLEAR_FEATURE:

//case SET_FEATURE:

/* Interface has no defined features. Return RequestError */

default:

ErrorStallControlEndPoint();

break;


}

break;


case STANDARD_ENDPOINT_REQUEST:

printf('Standard Endpoint Requestnr');

switch (SetupPacket.bRequest)

D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0);

} else

break;


case GET_STATUS:

/* Get Status Request to Endpoint should return */

/* Halt Status in D0 for Interrupt and Bulk */

switch (SetupPacket.wIndex & 0xFF)

if (Buffer[0] & 0x08) Buffer[0] = 0x01;

elseBuffer[0] = 0x00;

Buffer[1] = 0x00;

D11WriteEndpoint(D11_ENDPOINT_EP0_IN, Buffer, 2);

break;


default:

/* Unsupported - Request Error - Stall */

ErrorStallControlEndPoint();

break;

}

break;

case VENDOR_DEVICE_REQUEST:

case VENDOR_ENDPOINT_REQUEST:

printf('Vendor Device bRequest = 0x%X, wValue = 0x%X, wIndex = 0x%Xnr',

SetupPacket.bRequest, SetupPacket.wValue, SetupPacket.wIndex);

switch (SetupPacket.bRequest)

break;

default:

printf('UnSupported Request Type 0x%Xnr',SetupPacket.bmRequestType);

ErrorStallControlEndPoint();

break;

}

} else



void GetDescriptor(PUSB_SETUP_REQUEST SetupPacket)


if (BytesToSend > SetupPacket->wLength)

BytesToSend = SetupPacket->wLength;

WriteBufferToEndPoint();

break;

default:

ErrorStallControlEndPoint();

break;

}



void ErrorStallControlEndPoint(void)


/*9.2.7 RequestError - return STALL PID in response to next DATA Stage Transaction */

D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP0_IN, Buffer, 1);

/* or in the status stage of the message. */

D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + D11_ENDPOINT_EP0_OUT, Buffer, 1);



unsigned char D11ReadEndpoint(unsigned char Endpoint, unsigned char *Buffer)


return D11Header[1];



void D11WriteEndpoint(unsigned char Endpoint, const unsigned char *Buffer, unsigned char Bytes)



void WriteBufferToEndPoint(void)

else if (BytesToSend >= 8) else



void loadfromcircularbuffer(void)

while (count < 8); // Maximum Buffer Size

// Now load it into EP1_In

D11WriteEndpoint(D11_ENDPOINT_EP1_IN, Buffer, count);


void D11CmdDataWrite(unsigned char Command, const unsigned char *Buffer, unsigned char Count)



void D11CmdDataRead(unsigned char Command, unsigned char Buffer[], unsigned char Count)



void I2C_Read(unsigned char byDevId, unsigned char pbyData[], unsigned char byCount)


I2C_Stop();



void I2C_Write(unsigned char byDevId, const unsigned char * pbyData, unsigned char byCount)


I2C_Stop();



void I2C_Init(void)



void I2C_Start(void)



void I2C_Stop(void)



void I2C_Write_Byte(unsigned char byte)



unsigned char I2C_Read_Byte(unsigned char Ack)



void InitUART(void)



void putch(unsigned char byte)





Performantele convertorului


  • Interfata seriala I2C  (pana la 1 Mbit/s)
  • Oscilator cu cristal de 12 MHz (12 MHz to 48 MHz Clock Multiplier PLL)
  • Frecventa de tact programabil (Programmable output clock frequency)
  • PDIUSBD11 - Full Speed Device 12Mbps