Выбрать главу

unsigned char num;

//

// Timer interrupt service routine

//

void interrupt() {

 HID_InterruptProc(); // Keep alive

 TMR0L = 100;         // Re-load TMR0L

 INTCON.TMR0IF = 0;   // Re-enable TMR0 interrupts

}

//

// Start of MAIN program

//

void main() {

 ADCON1 = 0xFF; // Set PORTB to digital I/O

 TRISB = 0;     // Set PORTB to outputs

 PORTB = 0;     // Clear all outputs

 //

 // Set interrupt registers to power-on defaults

 // Disable all interrupts

 //

 INTCON=0;

 INTCON2=0xF5;

 INTCON3=0xC0;

 RCON.IPEN=0;

 PIE1=0;

 PIE2=0;

 PIR1=0;

 PIR2=0;

 //

 // Configure TIMER 0 for 3.3ms interrupts. Set prescaler to 256

 // and load TMR0L to 100 so that the time interval for timer

 // interrupts at 48MHz is 256*(256-100)*0.083 = 3.3ms

 //

 // The timer is in 8-bit mode by default

 //

 T0CON = 0x47;      // Prescaler = 256

 TMR0L = 100;       // Timer count is 256-156 = 100

 INTCON.TMR0IE = 1; // Enable T0IE

 T0CON.TMR0ON = 1;  // Turn Timer 0 ON

 INTCON = 0xE0;     // Enable interrupts

 //

 // Enable USB port

 //

 Hid_Enable(&Read_buffer, &Write_buffer);

 Delay_ms(1000);

 Delay_ms(1000);

 //

 // Read from the USB port. Number of bytes read is in num

 //

 for(;;) // do forever

 {

  num=0;

  while(num != 4) // Get 4 characters

  {

   num = Hid_Read();

  }

  if (Read_buffer[0] == 'P' && Read_buffer[1] == '=' &&

   Read_buffer[3] == 'T') {

   PORTB = Read_buffer[2];

  }

 }

 Hid_Disable();

}

Figure 8.22: Microcontroller program with USB code

Inside the main program PORTB is defined as digital I/O and TRISB is cleared to 0 so all PORTB pins are outputs. All the interrupt registers are then set to their power-on-reset values for safety. The timer interrupts are then set up. The timer is operated in 8-bit mode with a prescaler of 256. Although the crystal clock frequency is 8MHZ, the CPU is operated with a 48MHz clock, as described later. Selecting a timer value of TMR0L . 100 with a 48MHz clock (CPU clock period of 0.083μs) gives timer interrupt intervals of:

 (256 – 100) * 256 * 0.083μs

or, about 3.3ms. Thus, the keep-alive messages are sent every 3.3ms.

The USB port is then enabled by calling function Hid_Enable. The program then enters an indefinite loop and reads data from the USB port with Hid_Read. When 4 bytes are received at the correct format (i.e., byte 0=“P,” byte 1=“.”, and byte 3=“T”) then the data byte is read from byte 2 and sent to PORTB of the microcontroller.

It is important to note that when data is received using the Hid_Read function, the function returns the number of bytes received. In addition, the first byte received is the first actual data byte and not the report ID.

Microcontroller Clock

The USB module of the PIC18F4550 microcontroller requires a 48MHz clock. In addition, the microcontroller CPU requires a clock that can range from 0 to 48MHz. In this project the CPU clock is set to be 48MHz.

There are several ways to provide the required clock pulses.

Figure 8.23 shows part of the PIC18F4550 clock circuit. The circuit consists of a 1:1–1:12 PLL prescaler and multiplexer, a 4:96MHz PLL, a 1:2–1:6 PLL postscaler, and a 1:1–1:4 oscillator postscaler. Assuming the crystal frequency is 8MHz and we want to operate the microcontroller with a 48MHz clock, and also remembering that a 48MHz clock is required for the USB module, we should make the following choices in the Edit Project option of the mikroC IDE:

• Set _PLL_DIV2_1L so the 8MHz clock is divided by 2 to produce 4MHZ at the output of the PLL prescaler multiplexer. The output of the 4:96MHZ PLL is now 96MHz. This is further divided by 2 to give 48MHz at the input of multiplexer USBDIV.

• Check _USBDIV_2_1L to provide a 48MHz clock to USB module and to select ÷2 for the PLL postscaler.

• Check CPUDIV_OSC1_PLL2_1L to select PLL as the clock source.

• Check _FOSC_HSPLL_HS_1H to select a 48MHz clock for the CPU.

• Set the CPU clock to 48MHz in mikroC IDE (using Edit Project).

Figure 8.23: PIC18F4550 microcontroller clock

The clock bits selected for the 48MHz USB operation with a 48MHz CPU clock are shown in Figure 8.24.

Figure 8.24: Selecting clock bits for USB operation

Setting other configuration bits in addition to the clock bits is recommended.

The following list gives all the bits that should be set in the Edit Project option of the IDE (most of these settings are the power-on-reset values of the bits):

PLLDIV_2_1L

CPUDIV_OSC1_PLL2_1L

USBDIV_2_1L

FOSC_HSPLL_HS_1H

FCMEM_OFF_1H

IESO_OFF_1H

PWRT_ON_2L

BOR_ON_2L

BORV_43_2L

VREGEN_ON_2L

WDT_OFF_2H

WDTPS_256_2H

MCLRE_ON_3H

LPT1OSC_OFF_3H

PBADEN_OFF_3H

CCP2MX_ON_3H

STVREN_ON_4L

LVP_OFF_4L

ICPRT_OFF_4L

XINST_OFF_4L

DEBUG_OFF_4L

Testing the Project

Testing the project is relatively easy. The steps are:

• Construct the hardware

• Load the program (Figure 8.22) into the PIC18F4550 microcontroller

• Copy or run the PC-based Visual Basic program

When the microcontroller is connected to one of the USB ports of the PC, a message should be visible at the bottom right-hand corner of the screen similar to the one in Figure 8.25. This message shows that the new USB HID device has been plugged in and is recognized by the PC.

Figure 8.25: USB connection message

In addition, the device manager display should show an HID-compliant device and a USB human interface device as in Figure 8.26. The properties of these drivers can be displayed to make sure the VIP is 0x1234 and the PID is 1.