Wednesday 10 June 2009

PIC 18F4550, Interrupts and USB

One of the main challenges for this unit is to read data, store it and also have USB connectivity.
Obviously the data must be read with high precision timings so I decided to use an interrupt in order to accurately take data samples.
The PIC18F4550 is capable of doing high and low priority interrupt service routines.
I decided to use a high priority interrupt service routine (HISR) for the data acquisition samples and a low priority interrupt service routine (LISR) for doing other things, such as checking if any switches have been pressed and updating the LCD display.

I based all of the code on the Microchip USB framework 2.4 examples, using the 'USB Device - MCHPUSB - Generic Driver Demo' as the basis for my program.

After a lot of going around in circles here are some notes and pointers and things I have learnt:

You must use the polling method for USB if you are using the HISR for something else.
As log as the USB routine is polled every 100ns or so then its all OK. Do not try to use interrupts along with interrupt driven USB, as they dont get along, as much as I have found. There is probably a way to do this but still...

The clock frequency is not the same as the oscillator frequency. I am using an oscillator freq of 20MHz, but, in order to use the USB routines, there is an internal phase locked loop (PLL) which changes the frequency to 48MHz. This is the clock frequency being used. This messed up all my timings and caused much head scratching for quite a while.

Most other things are pretty simple - I'm using timer0 for the HISR and timer 2 for the LISR, with priority set in the interrupt set-up parameters.

I can now read data in the HISR, display data and look at the switches in the LISR, all while the USB connection is working in the background.

Now I need to sort out saving data onto SDcards....

2 comments:

  1. Hello, I am very much interested in the project you have developed. I am attempting a similar project with a 18F4455 chip. I would appreciate it very much if you are able to share your C# and PIC code with me on meththas at gmail.com.
    Thank you.

    ReplyDelete
  2. Hi Chunky,
    I have been struggling to communicate with PIC(LPT to USB). I am not able to communicate the v.COM port through Hyper Terminal also.
    I would like to capture .pcl files received on usb end of PIC by accessing virtual COM port created. PLEASE HELP!(Reply cbrao hotmail com)
    Here is what I am using:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.IO.Ports;
    using System.Threading;

    namespace SerialPortComm3
    {
    public partial class Form1 : Form
    {
    SerialPort com = null;
    List bBuffer = new List();
    string sBuffer = String.Empty;
    int intBytes;


    public Form1()
    {
    InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    com = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
    //com.Handshake = Handshake.XOnXOff;

    //com.DtrEnable = true;
    //com.RtsEnable = true;
    //com.ReadTimeout = 500;
    //com.WriteTimeout = 250;
    //com.DataBits = 8;
    //com.ReadBufferSize = 100;

    //com.Handshake = System.IO.Ports.Handshake.None;

    com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
    com.Open();
    Thread.Sleep(250);
    //this.Invoke(new SerialDataReceivedEventHandler(com_DataReceived));

    //// Write a set of bytes
    //com.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);
    }

    void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {

    com.ReceivedBytesThreshold = 9;

    // Use either the binary OR the string technique (but not both)

    // Buffer and process binary data
    //while (com.BytesToRead > 0)
    //{
    // bBuffer.Add((byte)com.ReadByte());
    // ProcessBuffer(bBuffer);
    //}


    //// Buffer string data
    //sBuffer += com.ReadExisting();
    //ProcessBuffer(sBuffer);

    //Another way
    //SerialPort sPort=(SerialPort) sender;
    //intBytes = sPort.BytesToRead;
    //byte[] bytes = new byte[intBytes];
    //sPort.Read(bytes, 0, intBytes);
    //txtDataReceived.Text += intBytes.ToString() + ";";
    this.Invoke(new EventHandler(SetText));

    }


    void SetText(object sender, EventArgs e)
    {
    SerialPort sPort = (SerialPort)sender;
    intBytes = sPort.BytesToRead;
    byte[] bytes = new byte[intBytes];
    sPort.Read(bytes, 0, intBytes);
    txtDataReceived.Text += intBytes.ToString() + ";";
    }

    private void ProcessBuffer(string sBuffer)
    {

    // Look in the string for useful information

    // then remove the useful data from the buffer

    txtDataReceived.AppendText(sBuffer);
    }



    private void ProcessBuffer(List bBuffer)
    {

    // Look in the byte array for useful information

    // then remove the useful data from the buffer

    }


    }
    }

    ReplyDelete