Vous êtes sur la page 1sur 63

Guillermo

Alberto Prez Guilln












Projects With PIC18F2550 And C18


Compiler

















INDEX




1. Introduction
2. Blink a LED
3. USB Frequency Counter And Voltmeter
4. USB PC Oscilloscope
5. USB PC Automation Home
6. Capacitance Meter







This work is authors property, and has been registered on the Website
http://www.safecreative.com with the registration code 1609269275953 and protected
under the License Creative Commons Attribution-NonCommercial-NoDerivatives 4.0

1. INTRODUCTION

The main goal is to make a compendium of useful projects to solve practical problems.

In the future I intend to add more projects; and I assume that you know electronic and
Microchip C18 compilerand C++ language.

These projects have been compiled with MPLAB C18, and the board that I have used is
PIC18F2550.

The main sensors and electronic modules that I have been used in this compendium were
the following:

US1881
LM35DZ
MQ-2
MQ-7
PIR
FAN
MOTOR CD
PUMP
LED

Each chapter has a simple explanation, electronic diagram, list of part, source code,
photographs and links of a video, tutorial and download source.

My Youtube channel and blogs are the following:

https://www.youtube.com/channel/UCuePeN-Qvq3lvUVQavo4jiQ
http://hubpages.com/@guillengap
http://guillengap.blogspot.mx/

Email: guillengap@gmail.com









Features
Full Speed USB 2.0 (12Mbit/s) interface
1K byte Dual Port RAM + 1K byte GP RAM
Full Speed Transceiver
16 Endpoints (IN/OUT)
Internal Pull Up resistors (D+/D-)
48 MHz performance (12 MIPS)
Pin-to-pin compatible with PIC16C7X5
Program Memory Type: Flash
Program Memory (KB): 32
CPU Speed (MIPS): 12
RAM Bytes: 2,048
Data EEPROM (bytes): 256
Digital Communication Peripherals: 1-UART, 1-A/E/USART, 1-SPI, 1-I2C1-
MSSP(SPI/I2C)
Capture/Compare/PWM Peripherals: 2 CCP
Timers: 1 x 8-bit, 3 x 16-bit
ADC: 10 ch, 10-bit
Comparators: 2
USB (ch, speed, compliance): 1, FS Device, USB 2.0
Temperature Range (C): -40 to 85
Operating Voltage Range (V): 2 to 5.5
Pin Count: 28






2. BLINK A LED

Circuit Diagram

Components:

Microcontroller PIC18F2550
Crystal 4 MHz
Capacitor 22 pF





















Source code with the explanation in the comments and compiled with C18 code.


#pragma config FOSC = XT_XT,FCMEN = OFF,IESO = OFF, CPUDIV = OSC1_PLL2
#pragma config PWRT = ON,BOR = OFF,BORV = 0
#pragma config WDT = OFF,WDTPS = 32768
#pragma config MCLRE = ON,LPT1OSC = OFF,PBADEN = OFF,CCP2MX = OFF
#pragma config STVREN = OFF,LVP = OFF,XINST = OFF,DEBUG = OFF
#pragma config CP0 = ON,CP1 = ON,CP2 = ON
#pragma config CPB = ON,CPD = ON
#pragma config WRT0 = ON,WRT1 = ON,WRT2 = ON
#pragma config WRTB = ON,WRTC = ON,WRTD = ON
#pragma config EBTR0 = ON,EBTR1 = ON,EBTR2 = ON
#pragma config EBTRB = ON
#include p18f2550.h
#include delays.h
void main (void)
{
TRISB = 0b01111111; // PORTB bit 7 to output (0) ; bits 6:0 are inputs (1)
while (1)
{
LATBbits.LATB7 = ~LATBbits.LATB7; // toggle LATD
Delay1KTCYx(50); // Delay 50 x 1000 = 50,000 cycles; 200ms @ 1MHz
}
}



























The next picture shows us a test.




Links:

Video:
https://youtu.be/g8d5MTMCVq8

Source code:
https://drive.google.com/file/d/0B8XMvcdJvBBYdEJ4d2dSVnAyY00/view?
usp=sharing














3. USB FREQUENCY COUNTER AND VOLTMETER

Using PIC18F2550 for connecting analogue and digital signals to the USB port. Included
Visual Basic 6 and Microchip C18 code. The PIC microcontroller has 10 bit analogue to
digital converter, by selecting 8 bits conversion the 2 LSB are ignored. The circuit is
powered by the USB. The interface to the PC is HID class. The frequency counter has a
range of up to 4MHz (24bits). Inputs samplings can be done at rates of 1 per second and 1
every 0.1 second. HID class is a class of devices like the mouse and the keyboard; the
data transfer rate is limited to 64KB/S.

Circuit Diagram




Components:

Microcontroller PIC18F2550
USB Type A
Crystal 4 MHz
Capacitor 22 pF, o.22 uF








Source code with the explanation in the comments and compiled with C18 code.

#include <p18f2550.h>
#include <stdio.h>
#include <usart.h>
#include usb.h

// Note: there are timing related problems associated with GET_FEATURE
// when run at less than 48 MHz
//#define CLK_48MHZ 1

#pragma config PLLDIV=1, CPUDIV=OSC1_PLL2, USBDIV=2, FOSC=XTPLL_XT//,
FCMEM=OFF //CPUDIV=OSC1_PLL2=48MHz, CPUDIV=OSC3_PLL4=24MHz
#pragma config IESO=OFF, PWRT=OFF, BOR=ON_ACTIVE, BORV=3,
VREGEN=ON, WDT=OFF
#pragma config MCLRE=OFF, PBADEN=OFF, CCP2MX=OFF, STVREN=ON,
LVP=OFF, XINST=OFF, DEBUG=OFF

// HID feature buffer
volatile unsigned char HIDFeatureBuffer[HID_FEATURE_REPORT_BYTES];
#pragma code low_vector=0x8
void low_interrupt (void)
{
}
#pragma code

// Allocate buffers in RAM for storage of bytes that have either just
// come in from the SIE or are waiting to go out to the SIE.
unsigned char txBuffer[HID_INPUT_REPORT_BYTES];
unsigned char rxBuffer[HID_OUTPUT_REPORT_BYTES];
unsigned int timestamp=0;
extern byte transferType;

unsigned char timebase, freq3; //counters vars
//prototypes
void UserInit(void);
void ProcessIO(void);

//*****************************************************************
// Entry point of the firmware
void main(void)
{
// Set all I/O pins to digital
//ADCON1 |= 0x0F;

// Initialize USB
UCFG = 0x14; // Enable pullup resistors; low speed=0x10, full speed mode=0x14

deviceState = DETACHED;
remoteWakeup = 0x00;
currentConfiguration = 0x00;

// Call user initialization function
UserInit();
while(1)
{
// Ensure USB module is available
EnableUSBModule();

// As long as we arent in test mode (UTEYE), process USB transactions.
if(UCFGbits.UTEYE != 1)
ProcessUSBTransactions();

// Application specific tasks
ProcessIO();
}
}
//********************************************************************
// Entry point for user initialization
void UserInit(void)
{
TRISCbits.TRISC0=1; //counters input
TRISBbits.TRISB4=1;
TRISBbits.TRISB5=0;
TRISAbits.TRISA0=1;
TRISAbits.TRISA1=1;
ADCON1=0B1000; //ref 5v, ch0-4 analogue
ADCON2=0B101110; //Ttad, left just.
ADCON0=0B101; //input on ch.1, adc ON
T1CON=0B01000110; //prescale=1:1, timer=off, osc=off, input=pin11
T2CON=0B1111011; //prescale=1:16, output=1:16, timer=off
PR2=233; //5mS period
timebase = 0;
}

#define LOBYTE(x) (*((char *)&x))
#define HIBYTE(x) (*(((char *)&x)+1))

//********************************************************************

// Central processing loop. Whenever the firmware isnt busy servicing
// the USB, we will get control here to do other processing.
void ProcessIO(void)
{
byte rxCnt;

// User Application USB tasks
if ((deviceState < CONFIGURED) || (UCONbits.SUSPND==1))
return;

// Find out if an Output report has been received from the host.
rxCnt = HIDRxReport(rxBuffer, HID_OUTPUT_REPORT_BYTES);
// If no bytes in, then nothing to do
if (rxCnt == 0)
return;

ADCON0bits.GO_DONE = 1; //start ADC
//Frequency Counter
TMR1L = TMR1H = freq3 = 0; //clear timers
PIR1bits.TMR1IF = 0;
PIR1bits.TMR2IF = 0;
PORTBbits.RB5 = rxBuffer[1]; //1 sec time base
LED
if(rxBuffer[1]){timebase = 200;} //time base=1 sec
else{timebase = 20;}

T1CONbits.TMR1ON = 1; //start count
T2CONbits.TMR2ON = 1;

while(timebase){
while(!PIR1bits.TMR2IF){
if(PIR1bits.TMR1IF){++freq3; PIR1bits.TMR1IF = 0;}
}
PIR1bits.TMR2IF = 0;
timebase;
}

T1CONbits.TMR1ON = 0; //stop count
T2CONbits.TMR2ON = 0;

//Data to send to host
txBuffer[0]=ADRESH;
txBuffer[1]=ADRESL;
txBuffer[2]=timebase;
txBuffer[3]=TMR1L;
txBuffer[4]=TMR1H;
txBuffer[5]=freq3;

// As long as the SIE is owned by the processor, we let USB tasks continue.
while (ep1Bi.Stat & UOWN)
ProcessUSBTransactions();

// The report will be sent in the next interrupt IN transfer.
HIDTxReport(txBuffer, HID_INPUT_REPORT_BYTES);
}

//*********************************************************************
// Initialization for a SET_FEATURE request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupFeatureReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer.
inPtr = (byte*)&HIDFeatureBuffer;
}
}

// Post processing for a SET_FEATURE request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetFeatureReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID == 0)
{
// Set the state of PORTB based on the first byte
// of the feature report.
LATB = HIDFeatureBuffer[0];
// x10 to signal feature transfer
LATBbits.LATB1=1;
LATBbits.LATB0=0;
}
}

// Handle a feature report request on the control pipe
void GetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(GetFeatureReport(0x%uhx): 0x%hx, 0x%hx\r\n,
// (byte)reportID, (byte)HIDFeatureBuffer[0],
// (byte)HIDFeatureBuffer[1]);
#endif

if (reportID == 0)
{
// Handle report #0
outPtr = (byte *)&HIDFeatureBuffer;
HIDFeatureBuffer[0]=PORTA;
HIDFeatureBuffer[1]=0xF1; //this is to differentiate between different
transfer types
HIDFeatureBuffer[2]=HIBYTE(timestamp);
HIDFeatureBuffer[3]=LOBYTE(timestamp);
wCount = HID_FEATURE_REPORT_BYTES;
transferType=0;
}

}

// Handle control out. This might be an alternate way of processing
// an output report, so all thats needed is to point the output
// pointer to the output buffer
// Initialization for a SET_REPORT request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupOutputReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer
inPtr = (byte*)&HIDRxBuffer;
}
}

// Post processing for a SET_REPORT request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetOutputReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetOutputReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID != 0)
return;

LATB=HIDRxBuffer[0];
// x11 to signal SET_REPORT transfer
LATBbits.LATB1=1;
LATBbits.LATB0=1;
}

// Handle a control input report
void GetInputReport(byte reportID)
{
#if DEBUG_PRINT
printf(GetInputReport: 0x%uhx\r\n, reportID);
#endif
if (reportID == 0)
{
byte i;
// Send back the contents of the HID report
// TBD: provide useful information
outPtr = (byte *)&HIDTxBuffer;
HIDTxBuffer[0]=PORTA;
HIDTxBuffer[1]=0xF2; //this is to differentiate between different
transfer types
HIDTxBuffer[2]=HIBYTE(timestamp);
HIDTxBuffer[3]=LOBYTE(timestamp);
for(i=4;i<HID_INPUT_REPORT_BYTES;i++)
HIDTxBuffer[i]=HIDRxBuffer[i];
// The number of bytes in the report (from usb.h).
wCount = HID_INPUT_REPORT_BYTES;
transferType=0;
}
}


Visual Basic 6 Code

You can get the code at the end of the chapter.












The next picture shows us a test.






Links:

Video:
https://youtu.be/Fa8h23ewx04

Source code:
https://drive.google.com/file/d/0B8XMvcdJvBBYaEg0UkJndVB5ZXc/view?
usp=sharing














4. USB PC OSCILLOSCOPE
This is a simple analog oscilloscope with the following characteristics:
Low frequencies with the following frequencies (milliseconds per screen):
5,10,50,100 and 500
Range between 0 - 5 Volts
Dont use to measure negative voltages and use dimmers signal or voltage dividers if we
want to measure voltage signals larger.
USB low frequency oscilloscope, bandwidth is DC to 1KHz.. Here we can see the
electrical circuit diagram. Trigger point we owe to ground to measure the signal correctly.
We can also stop signal by the stop button.
Circuit Diagram


Components:

Microcontroller PIC18F2550
USB Type A
Crystal 4 MHz
Capacitor 22 pF, o.22 uF
Electrolytic capacitor 1 uF
Resistor 2K2, 1M



Source code with the explanation in the comments and compiled with C18 code.

#include <p18f2550.h>
#include <stdio.h>
#include <usart.h>
#include usb.h

// Note: there are timing related problems associated with GET_FEATURE
// when run at less than 48 MHz
//#define CLK_48MHZ 1

#pragma config PLLDIV=1, CPUDIV=OSC1_PLL2, USBDIV=2, FOSC=XTPLL_XT//,
FCMEM=OFF //CPUDIV=OSC1_PLL2=48MHz = fast,OSC3_PLL4 = slow usb.
#pragma config IESO=OFF, PWRT=OFF, BOR=ON_ACTIVE, BORV=3,
VREGEN=ON, WDT=OFF
#pragma config MCLRE=OFF, PBADEN=OFF, CCP2MX=OFF, STVREN=ON,
LVP=OFF, XINST=OFF, DEBUG=OFF

// HID feature buffer
volatile unsigned char HIDFeatureBuffer[HID_FEATURE_REPORT_BYTES];
#pragma code low_vector=0x8
void low_interrupt (void)
{
}
#pragma code

// Allocate buffers in RAM for storage of bytes that have either just
// come in from the SIE or are waiting to go out to the SIE.
unsigned char txBuffer[HID_INPUT_REPORT_BYTES];
unsigned char rxBuffer[HID_OUTPUT_REPORT_BYTES];
unsigned int timestamp=0;
extern byte transferType;

//prototypes
void UserInit(void);
void ProcessIO(void);

//*****************************************************************
// Entry point of the firmware
void main(void)
{

// Initialize USB
UCFG = 0x14; // Enable pullup resistors; low speed=0x10, full speed mode=0x14

deviceState = DETACHED;
remoteWakeup = 0x00;
currentConfiguration = 0x00;

// Call user initialization function
UserInit();
while(1)
{
// Ensure USB module is available
EnableUSBModule();

// As long as we arent in test mode (UTEYE), process USB transactions.
if(UCFGbits.UTEYE != 1)
ProcessUSBTransactions();

// Application specific tasks
ProcessIO();
}
}
//********************************************************************
// Entry point for user initialization
void UserInit(void)
{
TRISA = 0B1111; //RA0-RA3 are inputs
ADCON1=0B1000; //ref 5v, ch0-4 analogue
ADCON2=0B101110; //Ttad, right just.
ADCON0=0B101; //input on ch.1
T1CON = 0B110001; //timer1 84mS, timer ON
CMCON = 0B111110; //inputs pins: 4,5
CVRCON = 0B10001000; //comp. ref
}

#define LOBYTE(x) (*((char *)&x))
#define HIBYTE(x) (*(((char *)&x)+1))

//********************************************************************

// Central processing loop. Whenever the firmware isnt busy servicing
// the USB, we will get control here to do other processing.
void ProcessIO(void)
{
byte rxCnt,trigger,i;
unsigned int timebase,j;

// User Application USB tasks
if ((deviceState < CONFIGURED) || (UCONbits.SUSPND==1))
return;

// Find out if an Output report has been received from the host.
rxCnt = HIDRxReport(rxBuffer, HID_OUTPUT_REPORT_BYTES);
// If no bytes in, then nothing to do
if (rxCnt == 0)
return;

//selecting timebase
switch(rxBuffer[0])
{
case 2: timebase = 21; break;
case 4: timebase = 43; break;
case 20: timebase = 216; break;
case 40: timebase = 436; break;
case 200: timebase = 2160; break;
}
trigger = rxBuffer[1]; //trigger off = false

if(trigger){
i = 0;
while(CMCONbits.C2OUT && i<64) //wait for
falling edge
{
for(j=0;j<timebase;j++); //delay for next sample
i++;
}

i = 0;
while(!CMCONbits.C2OUT && i<64); //wait for rising edge
{
for(j=0;j<timebase;j++); //delay for next sample
i++;
}
}
PIR1bits.TMR1IF = 0; //reset timer1

//Data to send to host
for(i=0;i<63;i++)
{
ADCON0bits.GO_DONE = 1; //start ADC
for(j=0;j<timebase;j++); //delay for next sample
txBuffer[i] = ADRESH; //ADC reading
}
while(!PIR1bits.TMR1IF); //wait for at least 84 ms
PIR1bits.TMR1IF = 0;

// As long as the SIE is owned by the processor, we let USB tasks continue.
while (ep1Bi.Stat & UOWN)
ProcessUSBTransactions();

// The report will be sent in the next interrupt IN transfer.
HIDTxReport(txBuffer, HID_INPUT_REPORT_BYTES);
}

//*********************************************************************

// Initialization for a SET_FEATURE request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupFeatureReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer.
inPtr = (byte*)&HIDFeatureBuffer;
}
}

// Post processing for a SET_FEATURE request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetFeatureReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID == 0)
{
// Set the state of PORTB based on the first byte
// of the feature report.
LATB = HIDFeatureBuffer[0];
// x10 to signal feature transfer
LATBbits.LATB1=1;
LATBbits.LATB0=0;
}
}

// Handle a feature report request on the control pipe
void GetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(GetFeatureReport(0x%uhx): 0x%hx, 0x%hx\r\n,
// (byte)reportID, (byte)HIDFeatureBuffer[0],
// (byte)HIDFeatureBuffer[1]);
#endif

if (reportID == 0)
{
// Handle report #0
outPtr = (byte *)&HIDFeatureBuffer;
HIDFeatureBuffer[0]=PORTA;
HIDFeatureBuffer[1]=0xF1; //this is to differentiate between different
transfer types
HIDFeatureBuffer[2]=HIBYTE(timestamp);
HIDFeatureBuffer[3]=LOBYTE(timestamp);
wCount = HID_FEATURE_REPORT_BYTES;
transferType=0;
}

}

// Handle control out. This might be an alternate way of processing
// an output report, so all thats needed is to point the output
// pointer to the output buffer
// Initialization for a SET_REPORT request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupOutputReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer
inPtr = (byte*)&HIDRxBuffer;
}
}

// Post processing for a SET_REPORT request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetOutputReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetOutputReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID != 0)
return;

LATB=HIDRxBuffer[0];
// x11 to signal SET_REPORT transfer
LATBbits.LATB1=1;
LATBbits.LATB0=1;
}

// Handle a control input report
void GetInputReport(byte reportID)
{
#if DEBUG_PRINT
printf(GetInputReport: 0x%uhx\r\n, reportID);
#endif
if (reportID == 0)
{
byte i;
// Send back the contents of the HID report
// TBD: provide useful information
outPtr = (byte *)&HIDTxBuffer;
HIDTxBuffer[0]=PORTA;
HIDTxBuffer[1]=0xF2; //this is to differentiate between different
transfer types
HIDTxBuffer[2]=HIBYTE(timestamp);
HIDTxBuffer[3]=LOBYTE(timestamp);
for(i=4;i<HID_INPUT_REPORT_BYTES;i++)
HIDTxBuffer[i]=HIDRxBuffer[i];
// The number of bytes in the report (from usb.h).
wCount = HID_INPUT_REPORT_BYTES;
transferType=0;
}
}


Visual Basic 6 Code

You can get the code at the end of the chapter.








The next picture shows us a test.






Links:

Video:
https://youtu.be/RBVdsxXV0O0

Source code:
https://drive.google.com/file/d/0B8XMvcdJvBBYSEZMNXJZVFhId3c/view?
usp=sharing














5. USB PC AUTOMATION HOME
Using PIC18F2550 for connecting analogue and digital signals to USB port. Included
Visual Basic 6 code and Microchip C18 code, and a circuit diagram. The PIC
microcontroller has 10 bit analogue to digital converter. The circuit is powered by the
USB. The interface to the PC is HID class. The inputs and outputs are updated every
10ms.

Circuit Diagram



Components:

Microcontroller PIC18F2550
USB Type A
Crystal 4 MHz
Capacitor 22 pF, 0.22 uF
Electrolytic capacitor 1 uF
Resistor 1K

Source code with the explanation in the comments and compiled with C18 code.

#include <p18f2550.h>
#include <stdio.h>
#include <usart.h>
#include usb.h

// Note: there are timing related problems associated with GET_FEATURE
// when run at less than 48 MHz
//#define CLK_48MHZ 1

#pragma config PLLDIV=1, CPUDIV=OSC3_PLL4, USBDIV=2, FOSC=XTPLL_XT//,
FCMEM=OFF //CPUDIV=OSC1_PLL2=48MHz
#pragma config IESO=OFF, PWRT=OFF, BOR=ON_ACTIVE, BORV=3,
VREGEN=ON, WDT=OFF
#pragma config MCLRE=OFF, PBADEN=OFF, CCP2MX=OFF, STVREN=ON,
LVP=OFF, XINST=OFF, DEBUG=OFF

// HID feature buffer
volatile unsigned char HIDFeatureBuffer[HID_FEATURE_REPORT_BYTES];
#pragma code low_vector=0x8
void low_interrupt (void)
{
}
#pragma code

// Allocate buffers in RAM for storage of bytes that have either just
// come in from the SIE or are waiting to go out to the SIE
unsigned char txBuffer[HID_INPUT_REPORT_BYTES];
unsigned char rxBuffer[HID_OUTPUT_REPORT_BYTES];
unsigned int timestamp=0;
extern byte transferType;

//prototypes
void UserInit(void);
void ProcessIO(void);

//*****************************************************************
// Entry point of the firmware
void main(void)
{

// Initialize USB
UCFG = 0x10; // Enable pullup resistors; low speed=0x14, full speed mode=0x14

deviceState = DETACHED;
remoteWakeup = 0x00;
currentConfiguration = 0x00;

// Call user initialization function
UserInit();
while(1)
{
// Ensure USB module is available
EnableUSBModule();

// As long as we arent in test mode (UTEYE), process USB transactions.
if(UCFGbits.UTEYE != 1)
ProcessUSBTransactions();

// Application specific tasks
ProcessIO();
}
}
//********************************************************************
// Entry point for user initialization
void UserInit(void)
{
TRISB = 0B11110000; //RB4-RB7 are inputs
TRISA = 0B1111; //RA0-RA3 are inputs
ADCON1=0B1111; //ref 5v, ch0-3 analogue
ADCON2=0B10101110; //Ttad, right just.
ADCON0=0B01; //input on ch.0
}

#define LOBYTE(x) (*((char *)&x))
#define HIBYTE(x) (*(((char *)&x)+1))

//********************************************************************

// Central processing loop. Whenever the firmware isnt busy servicing
// the USB, we will get control here to do other processing.
void ProcessIO(void)
{
byte rxCnt;

// User Application USB tasks
if ((deviceState < CONFIGURED) || (UCONbits.SUSPND==1))
return;

// Find out if an Output report has been received from the host.
rxCnt = HIDRxReport(rxBuffer, HID_OUTPUT_REPORT_BYTES);
// If no bytes in, then nothing to do
if (rxCnt == 0)
return;

PORTB = rxBuffer[1]; //write RB0-RB3 outputs
//Data to send to host
ADCON0=0B0011; //read input ch.0
while(ADCON0bits.GO_DONE){} //wait until ADC done
txBuffer[0] = ADRESL;
txBuffer[1] = ADRESH;
ADCON0=0B0111; //read input ch.1
while(ADCON0bits.GO_DONE){} //wait until ADC done
txBuffer[2] = ADRESL;
txBuffer[3] = ADRESH;
ADCON0=0B1011; //read input ch.2
while(ADCON0bits.GO_DONE){} //wait until ADC done
txBuffer[4] = ADRESL;
txBuffer[5] = ADRESH;
ADCON0=0B1111; //read input ch.3
while(ADCON0bits.GO_DONE){} //wait until ADC done
txBuffer[6] = ADRESL;

TRISB = 0B11110000; //RB4-RB7 are inputs

txBuffer[7] = ADRESH | (PORTB & 0B11110000); //add inputs to ADRESH
// As long as the SIE is owned by the processor, we let USB tasks continue.
while (ep1Bi.Stat & UOWN)
ProcessUSBTransactions();

// The report will be sent in the next interrupt IN transfer.
HIDTxReport(txBuffer, HID_INPUT_REPORT_BYTES);
}

//*********************************************************************

// Initialization for a SET_FEATURE request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupFeatureReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer.
inPtr = (byte*)&HIDFeatureBuffer;
}
}

// Post processing for a SET_FEATURE request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetFeatureReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID == 0)
{
// Set the state of PORTB based on the first byte
// of the feature report.
LATB = HIDFeatureBuffer[0];
// x10 to signal feature transfer
LATBbits.LATB1=1;
LATBbits.LATB0=0;
}
}

// Handle a feature report request on the control pipe
void GetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(GetFeatureReport(0x%uhx): 0x%hx, 0x%hx\r\n,
// (byte)reportID, (byte)HIDFeatureBuffer[0],
// (byte)HIDFeatureBuffer[1]);
#endif

if (reportID == 0)
{
// Handle report #0
outPtr = (byte *)&HIDFeatureBuffer;
HIDFeatureBuffer[0]=PORTA;
HIDFeatureBuffer[1]=0xF1; //this is to differentiate between different
transfer types
HIDFeatureBuffer[2]=HIBYTE(timestamp);
HIDFeatureBuffer[3]=LOBYTE(timestamp);
wCount = HID_FEATURE_REPORT_BYTES;
transferType=0;
}

}

// Handle control out. This might be an alternate way of processing
// an output report, so all thats needed is to point the output
// pointer to the output buffer
// Initialization for a SET_REPORT request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupOutputReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer
inPtr = (byte*)&HIDRxBuffer;
}
}

// Post processing for a SET_REPORT request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetOutputReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetOutputReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID != 0)
return;

LATB=HIDRxBuffer[0];
// x11 to signal SET_REPORT transfer
LATBbits.LATB1=1;
LATBbits.LATB0=1;
}

// Handle a control input report
void GetInputReport(byte reportID)
{
#if DEBUG_PRINT
printf(GetInputReport: 0x%uhx\r\n, reportID);
#endif
if (reportID == 0)
{
byte i;
// Send back the contents of the HID report
// TBD: provide useful information
outPtr = (byte *)&HIDTxBuffer;
HIDTxBuffer[0]=PORTA;
HIDTxBuffer[1]=0xF2; //this is to differentiate between different
transfer types
HIDTxBuffer[2]=HIBYTE(timestamp);
HIDTxBuffer[3]=LOBYTE(timestamp);
for(i=4;i<HID_INPUT_REPORT_BYTES;i++)
HIDTxBuffer[i]=HIDRxBuffer[i];
// The number of bytes in the report (from usb.h).
wCount = HID_INPUT_REPORT_BYTES;
transferType=0;
}
}
Visual Basic 6 Code

You can get the code at the end of the chapter.




























The next picture shows us a test.





Links:

Video:
https://youtu.be/Jl4Lp8W7CiU

Source code:
https://drive.google.com/file/d/0B8XMvcdJvBBYT0FUa1UzLTIzdW8/view?
usp=sharing















6. CAPACITANCE METER

Using PIC18F2550 for connecting analogue and digital signals to USB port . Included
Visual Basic 6 software, PIC C code and a circuit diagram. The PIC microcontroller has
10 bit analogue to digital converter, by selecting 8 bits conversion the 2 LSB are ignored.
The circuit is powered by the USB. The interface to the PC is HID class.
The frequency meter has a range of up to 4MHz (24bits). The meter accuracy is 0.2% or
better.
Inputs samplings can be done at rates of 1 per second and 1 every 0.2 second.
The cap meter (max 50uF) measures the period of charging the cap to the Vref. The
accuracy is about 5%, it depends on the charge resistors, can be calibrated by trimming
1K5 and 1M5 resistors or by the VB code.

Circuit Diagram


Components:

Microcontroller PIC18F2550
USB Type A
Crystal 4 MHz
Transistor NPN
Diode 1N4148
Capacitor 22 pF, 0.22 uF
Electrolytic capacitor 1 uF
Resistor 1K, 1K5, 10K, 1M5





Source code with the explanation in the comments and compiled with C18 code.

#include <p18f2550.h>
#include <stdio.h>
#include <usart.h>
#include usb.h
#include <delays.h>

// Note: there are timing related problems associated with GET_FEATURE
// when run at less than 48 MHz
//#define CLK_48MHZ 1

#define dis PORTBbits.RB0
#define range1 PORTBbits.RB1
#define range2 PORTBbits.RB2
#define puls PORTBbits.RB3

#pragma config PLLDIV=1, CPUDIV=OSC1_PLL2, USBDIV=2, FOSC=XTPLL_XT//,
FCMEM=OFF //CPUDIV=OSC1_PLL2=48MHz, CPUDIV=OSC3_PLL4=24MHz
#pragma config IESO=OFF, PWRT=OFF, BOR=ON_ACTIVE, BORV=3,
VREGEN=ON, WDT=OFF
#pragma config MCLRE=OFF, PBADEN=OFF, CCP2MX=OFF, STVREN=ON,
LVP=OFF, XINST=OFF, DEBUG=OFF

// HID feature buffer
volatile unsigned char HIDFeatureBuffer[HID_FEATURE_REPORT_BYTES];
#pragma code low_vector=0x8
void low_interrupt (void)
{
}
#pragma code

// Allocate buffers in RAM for storage of bytes that have either just
// come in from the SIE or are waiting to go out to the SIE.
unsigned char txBuffer[HID_INPUT_REPORT_BYTES];
unsigned char rxBuffer[HID_OUTPUT_REPORT_BYTES];
unsigned int timestamp=0;
extern byte transferType;

unsigned char timebase, freq3; //counters vars
//prototypes
void UserInit(void);
void ProcessIO(void);

//*****************************************************************
// Entry point of the firmware
void main(void)
{
// Set all I/O pins to digital
//ADCON1 |= 0x0F;

// Initialize USB
UCFG = 0x14; // Enable pullup resistors; low speed=0x10, full speed mode=0x14

deviceState = DETACHED;
remoteWakeup = 0x00;
currentConfiguration = 0x00;

// Call user initialization function
UserInit();
while(1)
{
// Ensure USB module is available
EnableUSBModule();

// As long as we arent in test mode (UTEYE), process USB transactions.
if(UCFGbits.UTEYE != 1)
ProcessUSBTransactions();

// Application specific tasks
ProcessIO();
}
}
//********************************************************************
// Entry point for user initialization
void UserInit(void)
{
TRISCbits.TRISC0=1; //counters input timers 1,2,3 to be done
TRISBbits.TRISB0=0; //discharge
TRISBbits.TRISB1=0; //range1
TRISBbits.TRISB2=0; //range2
TRISBbits.TRISB3=0; //puls
TRISBbits.TRISB4=1;
TRISBbits.TRISB5=0;
TRISAbits.TRISA0=1;
TRISAbits.TRISA1=1; //V input
TRISAbits.TRISA2=1; //comp2 in
TRISAbits.TRISA3=1; //comp1 in
CMCON = 0b1110; //2 comparators, inputs RA3 RA2
ADCON1=0B1000; //ref 5v, ch0-4 analogue
ADCON2=0B101110; //Ttad, left just.
ADCON0=0B101; //input on ch.1, ADC on
T1CON=0B1000110; //prescale=1:1, timer=off, osc=off, input=pin11
T0CON=0B110; //prescale=1:128, timer=off, 16bits
T2CON=0B1111011; //prescale=1:16, output=1:16, timer=off
PR2=233; //5mS period
}

#define LOBYTE(x) (*((char *)&x))
#define HIBYTE(x) (*(((char *)&x)+1))

//********************************************************************
// Central processing loop. Whenever the firmware isnt busy servicing
// the USB, we will get control here to do other processing.
void ProcessIO(void)
{
byte rxCnt;
unsigned char counts;
//timebase = 0;
// User Application USB tasks
if ((deviceState < CONFIGURED) || (UCONbits.SUSPND==1))
return;

// Find out if an Output report has been received from the host.
rxCnt = HIDRxReport(rxBuffer, HID_OUTPUT_REPORT_BYTES);
// If no bytes in, then nothing to do
if (rxCnt == 0)
return;

//delay of 0.7 sec for 1 sec sampling option.
if(rxBuffer[1]){
TMR0L = TMR0H = INTCONbits.TMR0IF = 0; //reset TMR0
T0CONbits.TMR0ON = 1;
while(!INTCONbits.TMR0IF){} //loop for 0.7 sec
T0CONbits.TMR0ON = 0;
}
ADCON0bits.GO_DONE = 1; //start ADC
//Frequency Meter
TMR1L = TMR1H = freq3 = 0; //clear timers
PIR1bits.TMR1IF = 0;
PIR1bits.TMR2IF = 0;
T1CONbits.TMR1ON = 1; //start count
T2CONbits.TMR2ON = 1;
for(counts=0;counts<40;++counts){ //loop for
200mS
while(!PIR1bits.TMR2IF){
if(PIR1bits.TMR1IF){++freq3; PIR1bits.TMR1IF = 0;}
}
PIR1bits.TMR2IF = 0;
}
T1CONbits.TMR1ON = 0; //stop count
T2CONbits.TMR2ON = 0;

if(rxBuffer[2]==2){ //L meter
CVRCON = 0b10100000; //Vref=0V
Delay10TCYx(40);
T3CON = 0b10000; //1:2, timer off, internal osc
TMR3H=0; TMR3L=0; PIR2bits.TMR3IF=0;
puls=1;
Delay10TCYx(12); //10uS
puls=0;
while(CMCONbits.C2OUT){} //first oscillation cycle
while(!CMCONbits.C2OUT){}
while(CMCONbits.C2OUT){} //second oscillation cycle
T3CONbits.TMR3ON=1;
while(!CMCONbits.C2OUT){}
T3CONbits.TMR3ON=0;

}else{ //C meter
if(rxBuffer[2]==1){range2=1;}
if(rxBuffer[2]==0){range2=0;}
CVRCON = 0b10100100; //Vref=0.83V
Delay10TCYx(40);
T3CON = 0b110000; //1:8, timer off, internal osc
TMR3H=0; TMR3L=0; PIR2bits.TMR3IF=0; dis=0;
range1=1; //reset counter
T3CONbits.TMR3ON=1; //charge

while(CMCONbits.C1OUT){} //wait for comp
T3CONbits.TMR3ON=0;
range1=0; range2=0; dis=1; //discharge
}

//Data to send to host
txBuffer[0]=ADRESH; //Voltage
txBuffer[1]=ADRESL;
txBuffer[2]=PIR2bits.TMR3IF; //cap meter overflow
txBuffer[3]=TMR1L; //Frequency
txBuffer[4]=TMR1H;
txBuffer[5]=freq3;
txBuffer[6]=TMR3L; //Cap meter
txBuffer[7]=TMR3H;

// As long as the SIE is owned by the processor, we let USB tasks continue.
while (ep1Bi.Stat & UOWN)
ProcessUSBTransactions();

// The report will be sent in the next interrupt IN transfer.
HIDTxReport(txBuffer, HID_INPUT_REPORT_BYTES);
}

//*********************************************************************
// Initialization for a SET_FEATURE request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupFeatureReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer.
inPtr = (byte*)&HIDFeatureBuffer;
}
}

// Post processing for a SET_FEATURE request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetFeatureReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID == 0)
{
// Set the state of PORTB based on the first byte
// of the feature report.
LATB = HIDFeatureBuffer[0];
// x10 to signal feature transfer
LATBbits.LATB1=1;
LATBbits.LATB0=0;
}
}

// Handle a feature report request on the control pipe
void GetFeatureReport(byte reportID)
{
#if DEBUG_PRINT
//printf(GetFeatureReport(0x%uhx): 0x%hx, 0x%hx\r\n,
// (byte)reportID, (byte)HIDFeatureBuffer[0],
// (byte)HIDFeatureBuffer[1]);
#endif

if (reportID == 0)
{
// Handle report #0
outPtr = (byte *)&HIDFeatureBuffer;
HIDFeatureBuffer[0]=PORTA;
HIDFeatureBuffer[1]=0xF1; //this is to differentiate between different
transfer types
HIDFeatureBuffer[2]=HIBYTE(timestamp);
HIDFeatureBuffer[3]=LOBYTE(timestamp);
wCount = HID_FEATURE_REPORT_BYTES;
transferType=0;
}

}

// Handle control out. This might be an alternate way of processing
// an output report, so all thats needed is to point the output
// pointer to the output buffer
// Initialization for a SET_REPORT request. This routine will be
// invoked during the setup stage and is used to set up the buffer
// for receiving data from the host
void SetupOutputReport(byte reportID)
{
if (reportID == 0)
{
// When the report arrives in the data stage, the data will be
// stored in HIDFeatureBuffer
inPtr = (byte*)&HIDRxBuffer;
}
}

// Post processing for a SET_REPORT request. After all the data has
// been delivered from host to device, this will be invoked to perform
// application specific processing.
void SetOutputReport(byte reportID)
{
#if DEBUG_PRINT
//printf(SetOutputReport(0x%hx)\r\n, reportID);
#endif
// Currently only handling report 0, ignore any others.
if (reportID != 0)
return;

LATB=HIDRxBuffer[0];
// x11 to signal SET_REPORT transfer
LATBbits.LATB1=1;
LATBbits.LATB0=1;
}

// Handle a control input report
void GetInputReport(byte reportID)
{
#if DEBUG_PRINT
printf(GetInputReport: 0x%uhx\r\n, reportID);
#endif
if (reportID == 0)
{
byte i;
// Send back the contents of the HID report
// TBD: provide useful information
outPtr = (byte *)&HIDTxBuffer;
HIDTxBuffer[0]=PORTA;
HIDTxBuffer[1]=0xF2; //this is to differentiate between different
transfer types
HIDTxBuffer[2]=HIBYTE(timestamp);
HIDTxBuffer[3]=LOBYTE(timestamp);
for(i=4;i<HID_INPUT_REPORT_BYTES;i++)
HIDTxBuffer[i]=HIDRxBuffer[i];
// The number of bytes in the report (from usb.h).
wCount = HID_INPUT_REPORT_BYTES;
transferType=0;
}
}

Visual Basic 6 Code

You can get the code at the end of the chapter.












The next picture shows us a test.



Links:

Video:
https://youtu.be/b8xIBp80f_Q

Source code:
https://drive.google.com/file/d/0B8XMvcdJvBBYa0xzLVYtdmlsWWc/view?
usp=sharing

Vous aimerez peut-être aussi