Sie sind auf Seite 1von 15

http://www.todopic.com.ar/foros/index.php?topic=20047.

80

PIC's, Hardware mnimo y Antecedentes varios.

Este proyecto es una implementacin del ejemplo de CCS C


ex_usb_serial2.c que ha sido mnimamente modificado para que funcione
correctamente con Windows XP Profesional.
El hardware especfico que he utilizado es el de la RRBOARD2 con el
adaptador USB y la placa auxiliar RS232 x 2. Sin embargo sta ltima no es
necesaria ya que solo la uso para ir monitorizando lo que se recibe o enva
por el USB. De todas formas abajo os muestro un esquema del hardware
mnimo necesario para hacer funcionar este proyecto:

En caso de utilizar un Cristal distinto del de 20 Mhz os recomiendo que


consultis el artculo titulado Consiguiendo 4 Mhz para los 48 Mhz necesarios
en los PIC's con USB 2.0 en esta misma pgina.
Todo lo que aqu se explica es aplicable a la familia de PIC's 18Fxx5x que
son los que soportan el USB 2.0 (Documento 39632b.pdf de Microchip
dedicado a los 18F2455-2550-4455-4550 Descargar 7.912 Kbytes)
Descripcin del proyecto.

Lo que pretendemos en este proyecto es implementar una comunicacin


bidireccional serie, Communications Devices Class, entre el PIC y
cualquier Software del PC que use un puerto COM Serie estndar pero
emulndolo va USB 2.0 a full speed.
Vamos a realizar los ajustes necesarios en el Firmware del PIC para que sea
reconocido por el Windows como un dispositivo Serie estndar y lo registre
como un puerto COM Virtual. Como intermediario vamos a utilizar un
recurso que nos provee Microchip: El Driver .inf para Windows
mchpcdc.inf.
Para el firmware vamos a utilizar como base el ejemplo y descriptor USB
que trae como ejemplos el CCS C, adaptndolo a nuestras necesidades,
fundamentalmente darles los VID&PID que espera encontrar el driver para
Windows
De la parte del PC vamos a utilizar los programas de que disponemos para
monitorizar un puerto COM serie estndar: O el HyperTerminal de Windows
o Siow de CCS C.
En el PC es imprescindible instalar el Driver Windows mchpcdc.inf para
Windows XP que nos ofrece Microchip, que nos va a servir de puente entre
estos softwares con el canal USB del PC pero emulado como un puerto COM.
Este .inf Es quien define los VID&PID que vamos a utilizar.

Firmware, Driver, Software y procedimientos de instalacin.

< > Firmware para el PIC 18Fxx5x realizado en CCS C


Este firmware est compilado con el compilador PCH CCS C versin 3.242.

Las palabras clave y los puntos de inters de este firmware estan marcados
en negrita.

El descriptor USB est incluido en el fichero rr2_USB_Monitor.h que


aparece marcado en rojo. (Se incluye mas abajo)
#fuses HSPLL y PLL5
La frecuencia de oscilacin necesaria para el USB 2.0 es de 48 Mhz. Como estamos
utilizando en nuestro hardware un cristal de cuarzo de 20 Mhz necesitamos hacer
uso del mdulo PLL interno del PIC. Para ello utilizamos el fuse HSPLL. Como el
mdulo PLL requiere una oscilacin de entrada de 4 Mhz debemos utilizar el divisor
1:5 indicado con el fuse PLL5 para obtener los 20:5 = 4 Mhz requeridos. (Para
mas detalles consultar Consiguiendo 4 Mhz para los 48 Mhz necesarios en los PIC's
con USB 2.0 en esta misma pgina)
#include rr2_USB_Cdc_Monitor.h
En el fichero rr2_usb_cdc_monitor.h, cargado con el correspondiente include,
se definen las estructuras y parmetros necesarios para la conexin USB. Se
discutir su contenido un poco mas abajo donde adems se muestra su contenido
completo.
RR_USB_Cdc_Monitor.c

/////////////////////////////////////////////////////////////////////
////
//// ////
//// RR2_USB_Cdc_Monitor.c ////
//// ////
/////////////////////////////////////////////////////////////////////
////

#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

#include ".\include\usb_cdc.h"

#rom int 0xf00000={1,2,3,4}

void main() {

BYTE i, j, address, value;

delay_ms(300);
usb_cdc_init();
usb_init();
while(!usb_cdc_connected()) {}

do{
usb_task();
if (usb_enumerated()) {
printf(usb_cdc_putc, "\r\n\nEEPROM:\r\n"); // Display contents
of the first 64
for(i=0; i<=3; ++i) { // bytes of the data EEPROM in hex
for(j=0; j<=15; ++j) {
printf(usb_cdc_putc, "%2x ", read_eeprom( i*16+j ) );
}
printf(usb_cdc_putc, "\n\r");
}
printf(usb_cdc_putc, "\r\nLocation to change: ");
address = gethex_usb();
printf(usb_cdc_putc, "\r\nNew value: ");
value = gethex_usb();
write_eeprom( address, value );
}
}while (TRUE);
}

El el fichero rr2_USB_Cdc_Monitor.h vamos a incluir


las estructuras y parmetros necesarios para una
correcta conexin con el driver del PC.
Es un tema absolutamente complejo e inacabable, muy
propio de la gente de Microsoft, que debe adaptarse a
la estructura que espera recibir el driver del Windows
XP. Nosotros vamos a centrarnos nicamente en un par
de puntos que generan la mayora de las consultas que
recibo: El concepto del VID&PID y la modificacin de
la tabla USB_STRING_DESC[].
VID&PID
El VID es un nmero de 16 bits que significa Vendor
Identification o cdigo que identifica al fabricante del
hardware a conectar. En nuestro caso utilizamos el nmero
04D8h que identifica a Microchip.
El PID es un nmero de 16 bits que significa Product
Identification o cdigo que identifica al dispositivo en
concreto hardware a conectar. En nuestro caso utilizamos el
nmero 000Bh que identifica a la familia de los PIC18 de este
fabricante.
Tened en cuenta que la conjuncin de estos dos numeros
VID&PID es la que nos va a servir para conectar con el
Driver de Windows XP Cuando el S.O. conecte con nuestro
firmware recibir el VID&PID y buscar entre sus drivers
instalados para encontrar el que corresponde a esta
identificacin, si no la encuentra nos preguntar sobre donde
ha de buscar un driver adecuado y deberemos indicarle su
ubicacin. Este driver deber estar configurado para conectar
con un hardware cuyo VID&PID sea el mismo. No olvidad que
el driver para puertos serie ya existe en Windows, aqu solo
debemos darle el enlace con el .inf para que conecte
correctamente con el firmware que tiene el PIC.
USB_STRING_DESC[].
La tabla USB_STRING_DESC contiene la descripcin del
dispositivo detectado por el Driver de Windows XP y que nos
va a mostrar en la correspondiente entrada en la lista del
Hardware Instalado en el Sistema.
Consta de dos partes o tablas, la propiamente dicha
USB_STRING_DESC que contiene las descripciones
requeridas y una tabla accesoria llamada
USB_STRING_DESC_OFFSET que contiene los offset, o
desplazamientos con respecto al inicio de USB_STRING_DESC
en donde se encuentran las correspondientes cadenas. Ambas
constan de tres elementos cada una de ellas.
USB_STRING_DESC_OFFSET tiene tres nmeros que
indican cada uno de ellos donde comienza el correspondiente
dato en la tabla USB_STRING_DESC. As un contenido de
{0,4,12} nos dice que que el primer string comienza en el
byte 0, el segundo en el byte 4 y el tercero se encuentra a
partir del byte nmero 12. Si cambiamos la longitud de
cualquiera de los strings deberemos reordenar esta tabla
correspondientemente con solo contar los caracteres y apuntar
en esta tabla el nmero de byte donde comienza cada uno de
ellos.
USB_STRING_DESC contiene los tres strings en concreto que
deseamos transmitir con el descriptor USB. Cada uno de ellos
tiene la misma estructura que consta de un primer byte que
indica la longitud total de la correspondiente cadena, un
segundo byte que indica el tipo de dato que viene a
continuacin y por ltimo tantos bytes como sean necesarios
como contenido del string.

El primer dato de esta tabla es:

4, USB_DES_STRING_TYPE, 0x09, 0x04 que puede leerse


como 4 : Longitud en bytes del dato incluido l mismo.
USB_DES_STRING_TYPE que es una constante cuyo valor e 3
y que dice que lo que sigue es un string. Y 0x09, 0x04 que le
indica al Windows que los strings que siguen estn escritos en
correcto ingles americano (US-English)

Los dos siguientes datos son los dos strings que definen
nuestro dispositivo y cuya estructura es idntica al caso
anterior:

8, USB_DES_STRING_TYPE, 'R', 0, 'R', 0, '2', 0 que define


el string el nombre "RR2" de mis Hardware. Total 8 bytes ya
que "RR2" se codifica aadiendo un 0x00 tras cada uno de los
caracteres.

Y 22, USB_DESC_STRING_TYPE, 'R', 0, 'e', 0, 'd', 0, 'P',


0, 'i', 0, 'c', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0 que define el
nombre de mi dispositivo como "RedPic USB"

rr2_USB_Cdc_Monitor.h

///////////////////////////////////////////////////////////////////////////
//// usb_desc_cdc.h ////
//// ////
//// An example set of device / configuration descriptors for use with ////
//// CCS's CDC Virtual COM Port driver (see usb_cdc.h) ////
//// ////
//// Two examples are provided: ////
//// ex_usb_serial.c ////
//// ex_usb_serial2.c ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// ////
//// Version History: ////
//// ////
//// 10/28/05: ////
//// Bulk endpoint sizes updated to allow more than 255 byte ////
//// packets. ////
//// Changed device to USB 1.10 ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2005 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

//////////////////////////////////////////////////////////////////
///
/// start config descriptor
/// right now we only support one configuration descriptor.
/// the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

#DEFINE USB_TOTAL_CONFIG_LEN 67 //config+interface+class+endpoint+endpoint


(2 endpoints)

const char USB_CONFIG_DESC[] = {


//IN ORDER TO COMPLY WITH WINDOWS HOSTS, THE ORDER OF THIS ARRAY MUST BE:
// config(s)
// interface(s)
// class(es)
// endpoint(s)

//config_descriptor for config index 1


USB_DESC_CONFIG_LEN, //length of descriptor size ==0
USB_DESC_CONFIG_TYPE, //constant CONFIGURATION (CONFIGURATION 0x02) ==1
USB_TOTAL_CONFIG_LEN,0, //size of all data returned for this config ==2,3
2, //number of interfaces this device supports ==4
0x01, //identifier for this configuration. (IF we had more than one
configurations) ==5
0x00, //index of string descriptor for this configuration ==6
0xC0, //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we
don't), bits 0-4 unused and bit7=1 ==7
0x32, //maximum bus power required (maximum milliamperes/2) (0x32 = 100mA)
==8

//interface descriptor 0 (comm class interface)


USB_DESC_INTERFACE_LEN, //length of descriptor =9
USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04) =10
0x00, //number defining this interface (IF we had more than one interface)
==11
0x00, //alternate setting ==12
1, //number of endpoints ==13
0x02, //class code, 02 = Comm Interface Class ==14
0x02, //subclass code, 2 = Abstract ==15
0x01, //protocol code, 1 = v.25ter ==16
0x00, //index of string descriptor for interface ==17

//class descriptor [functional header]


5, //length of descriptor ==18
0x24, //dscriptor type (0x24 == ) ==19
0, //sub type (0=functional header) ==20
0x10,0x01, // ==21,22 //cdc version

//class descriptor [acm header]


4, //length of descriptor ==23
0x24, //dscriptor type (0x24 == ) ==24
2, //sub type (2=ACM) ==25
2, //capabilities ==26 //we support Set_Line_Coding,
Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.

//class descriptor [union header]


5, //length of descriptor ==27
0x24, //dscriptor type (0x24 == ) ==28
6, //sub type (6=union) ==29
0, //master intf ==30 //The interface number of the Communication or Dat a
Cl ass interface, designated as the masteror controlling interface for the
union.
1, //save intf0 ==31 //Interface number of first slave or associated
interface in the union. *

//class descriptor [call mgmt header]


5, //length of descriptor ==32
0x24, //dscriptor type (0x24 == ) ==33
1, //sub type (1=call mgmt) ==34
0, //capabilities ==35 //device does not handle call management itself
1, //data interface ==36 //interface number of data class interface

//endpoint descriptor
USB_DESC_ENDPOINT_LEN, //length of descriptor ==37
USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05) ==38
USB_CDC_COMM_IN_ENDPOINT | 0x80, //endpoint number and direction
0x03, //transfer type supported (0x03 is interrupt) ==40
USB_CDC_COMM_IN_SIZE,0x00, //maximum packet size supported ==41,42
250, //polling interval, in ms. (cant be smaller than 10) ==43

//interface descriptor 1 (data class interface)


USB_DESC_INTERFACE_LEN, //length of descriptor =44
USB_DESC_INTERFACE_TYPE, //constant INTERFACE (INTERFACE 0x04) =45
0x01, //number defining this interface (IF we had more than one interface)
==46
0x00, //alternate setting ==47
2, //number of endpoints ==48
0x0A, //class code, 0A = Data Interface Class ==49
0x00, //subclass code ==50
0x00, //protocol code ==51
0x00, //index of string descriptor for interface ==52

//endpoint descriptor
USB_DESC_ENDPOINT_LEN, //length of descriptor ==60
USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05) ==61
USB_CDC_DATA_OUT_ENDPOINT, //endpoint number and direction (0x02 = EP2 OUT)
==62
0x02, //transfer type supported (0x02 is bulk) ==63
// make8(USB_CDC_DATA_OUT_SIZE,0),make8(USB_CDC_DATA_OUT_SIZE,1), //maximum
packet size supported ==64, 65
USB_CDC_DATA_OUT_SIZE & 0xFF, (USB_CDC_DATA_OUT_SIZE >> 8) & 0xFF,
//maximum packet size supported ==64, 65
250, //polling interval, in ms. (cant be smaller than 10) ==66

//endpoint descriptor
USB_DESC_ENDPOINT_LEN, //length of descriptor ==53
USB_DESC_ENDPOINT_TYPE, //constant ENDPOINT (ENDPOINT 0x05) ==54
USB_CDC_DATA_IN_ENDPOINT | 0x80, //endpoint number and direction (0x82 =
EP2 IN) ==55
0x02, //transfer type supported (0x02 is bulk) ==56
// make8(USB_CDC_DATA_IN_SIZE,0),make8(USB_CDC_DATA_IN_SIZE,1), //maximum
packet size supported ==57, 58
USB_CDC_DATA_IN_SIZE & 0xFF, (USB_CDC_DATA_IN_SIZE >> 8) & 0xFF, //maximum
packet size supported ==64, 65
250, //polling interval, in ms. (cant be smaller than 10) ==59
};
//****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
//since we can't make pointers to constants in certain pic16s, this is an
offset table to find
// a specific descriptor in the above table.

//the maximum number of interfaces seen on any config


//for example, if config 1 has 1 interface and config 2 has 2 interfaces
you must define this as 2
#define USB_MAX_NUM_INTERFACES 2

//define how many interfaces there are per config. [0] is the first config,
etc.
const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={2};

//define where to find class descriptors


//first dimension is the config number
//second dimension specifies which interface
//last dimension specifies which class in this interface to get, but most
will only have 1 class per interface
//if a class descriptor is not valid, set the value to 0xFFFF
const int16 USB_CLASS_DESCRIPTORS[USB_NUM_CONFIGURATIONS]
[USB_MAX_NUM_INTERFACES][4]=
{
//config 1
//interface 0
//class 1-4
18,23,27,32,
//interface 1
//no classes for this interface
0xFFFF,0xFFFF,0xFFFF,0xFFFF
};

#if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)


#error USB_TOTAL_CONFIG_LEN not defined correctly
#endif

//////////////////////////////////////////////////////////////////
///
/// start device descriptors
///
//////////////////////////////////////////////////////////////////

//device descriptor
char const USB_DEVICE_DESC[USB_DESC_DEVICE_LEN] ={
USB_DESC_DEVICE_LEN, //the length of this report
0x01, //constant DEVICE (0x01)
0x10,0x01, //usb version in bcd
0x02, //class code. 0x02=Communication Device Class ==4
0x00, //subclass code
0x00, //protocol code
USB_MAX_EP0_PACKET_LENGTH, //max packet size for endpoint 0. (SLOW SPEED
SPECIFIES 8)
0xD8,0x04, //vendor id (0x04D8 is Microchip)
0x0A,0x00, //product id
0x01,0x00, //device release number
0x01, //index of string description of manufacturer. therefore we point to
string_1 array (see below)
0x02, //index of string descriptor of the product
0x00, //index of string descriptor of serial number
USB_NUM_CONFIGURATIONS //number of possible configurations
};

//////////////////////////////////////////////////////////////////
///
/// start string descriptors
/// String 0 is a special language string, and must be defined. People in
U.S.A. can leave this alone.
///
/// You must define the length else get_next_string_character() will not
see the string
/// Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string.


//offset[0] is the start of string 0, offset[1] is the start of string 1,
etc.
const char USB_STRING_DESC_OFFSET[]={0,4,12};

#define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET)

char const USB_STRING_DESC[]={


//string 0
4, //length of string index
USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
0x09,0x04, //Microsoft Defined for US-English
//string 1 --> la compaia del producto ???
8, //length of string index
USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
'R',0,
'R',0,
'2',0,
//string 2 --> nombre del dispositivo
22, //length of string index
USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
'R',0,
'e',0,
'd',0,
'P',0,
'i',0,
'c',0,
' ',0,
'U',0,
'S',0,
'B',0
};
#ENDIF

< > Driver para Microsoft Windows XP suministrado por


Microchip.
Antes de conectar nuestro PIC al PC vamos a empezar por darle a
ste la informacin necesaria para que lo detecte correctamente
cuando procedamos a conectarlo. Para ello abriremos un explorador
de Windows y encontraremos la ubicacin del fichero que nos provee
Microchip y que se llama mchpcdc.inf. Haremos Click con el botn
derecho del ratn y elegiremos la opcin Instalar del men
desplegable.

Tened en cuenta que esto no produce resultado visible alguno en


nuestro PC (la procesin va por dentro) Tras haber realizado esta
operacin podremos continuar.
Con el Hardware correctamente montado, con su firmware
debidamente programado en l y con su cable USB conectando
ambos, el PIC y el PC es cuando el Sistema Operativo Windows lo
detectar recibiendo su VID&PID y buscar entre sus drivers
instalados para encontrar el que corresponde a esa identificacin, si
no la encuentra nos preguntar sobre donde ha de buscar un driver
adecuado y entonces deberemos indicarle su ubicacin:
< > Software Monitor Siow de CCS C Hyperterminal de Windows
Abriendo ahora cualquier programa monitor del puerto serie podremos ponernos en
contacto con nuestro PIC. Solo debemos seleccionar el COMK recin instalado como
Puerto COM Virtual:

Das könnte Ihnen auch gefallen