Vous êtes sur la page 1sur 8

Construction

Two-Channel PC-
based Oscilloscope
 Gerard Samblancat crocontroller are given here in the box. its pins 5, 6 and 7.
This microcontroller has a USB2.0-com-

M
The MCP6S91 amplifier is designed
ore and more experiments pliant transceiver and a CPU running with CMOS input devices. It is de-
are now ‘PC-assisted.’ Also up to 12 MIPS. signed to not exhibit phase inversion
conventional acquisition sys- Fig. 1 shows the circuit of the when the input pins exceed the supply
tems are very expensive. Since portable two-channel PC-based oscilloscope. voltages. The maximum voltage that
PCs are today common and a USB link MCP6S91 from Microchip Technology can be applied to the input pin is –0.3V
is a better solution than an old ISA bus, is an analogue programmable gain am- (VSS) to +0.3V (VDD). Input voltages that
plifier that is well suited exceed this absolute maximum rating
to driving analogue-to- can cause excessive current into or out
digital converters (ADCs) of the input pins. Current beyond ±2
and an analogue input to mA can cause reliability problems. Ap-
a PIC microcontroller. plications that exceed this rating must
Two MCP6S91 pro- be externally limited with a resistor to
grammable gain ampli- the input pin.
fiers (IC2 and IC3) make Vref (pin 3), which is an analogue
it possible to choose the input, should be at a voltage between
input ranges for each of VSS and VDD. The voltage at this pin
the two channels, by se- shifts the output voltage. The SPI
lecting a gain from 1:1 to interface inputs are chip-select (CS),
32:1. The amplifiers are serial input (SI) and serial clock (SCK).
small, cheap and easy to These are Schmitt-triggered, CMOS
use. A simple three-wire logic inputs.
serial peripheral inter- The only disadvantage is that these
Author’s prototype face (SPI) allows the PIC amplifiers accept only positive signals.
to control them through That’s why voltage-shifting ampli-
here we present an oscilloscope using fiers LF353 (IC4A
USB port of the PC that operates at up Features of PIC18F2550 and IC5A) are used,
to 10 kHz with ±16V input voltage. It Programming one each for each
has much more improved features than 1. Up to 32 kB of flash memory, 2kB RAM and 256-byte EEPROM channel input (see
the PC-based oscilloscope and LED 2. Extended instruction set (optimised for ‘C’ compiler) Fig. 1). The LF353
scope for audio servicing published in 3. 8x8 single-cycle multiplier is a JFET input op-
EFY Dec. 2002 and Electronics Projects 4. Single-supply serial programming and easy debugging erational amplifier
Vol. 8, respectively. The oscilloscope USB transceiver with an internally
uses IC PIC18F2550 from Microchip 1. USB1.1 and 2.0 from 1.5 MB/s to 12 MB/s compensated input
as the main controller, which makes 2. Isochronous, bulk and interrupt transfer modes
offset voltage. The
3. 1 kB of access RAM usable with 32 endpoints (64 bytes each)
the oscilloscope compact as there is no JFET input device
Multiple oscillator and power modes
need of additional power supply for provides wide band-
1. From internal 31 kHz to external 48 MHz with PLL
the entire circuit board. The prototype 2. Possible software switching between ‘run,’ ‘idle’ and sleep width, low input
of the circuit along with the enclosure modes. In sleep mode, current is down to 0.1 µA. bias currents and
is shown above. 3. Wide operating voltage range (2.0V to 5.5V). Useful for battery offset currents. This
operations. voltage-shifting am-
Circuit description Complete set of classical peripherals plifier results in a
At the heart of this oscilloscope is 1. Several input/output (I/O) ports, four timers with capture/ high input imped-
USB2.0-compliant microcontroller compares ance and an attenu-
PIC18F2550 from Microchip. You 2. Synchronous and asynchronous enhanced modules
ation factor of 1:4.5.
can also use PIC18F2445 in place of 3. Streaming parallel port
A ±16V input signal
4. 10-bit ADC module with up to 13-channel multiplexer.
PIC18F2550. Specifications of this mi- is then shifted to the

6 0 • D e c e m b e r 2 0 0 6 • e l e c t ro n i c s f o r yo u w w w. e f y m ag . co m
Construction
0-5V range when the pro-

Fig. 1: Two-channel PC-based oscilloscope circuit


grammed gain is 1:1.
Two halves of the
LF353 (IC4B and IC5B) are
used as voltage follow-
ers to provide a low-im-
pedance shifting voltage
(Vref) to the program-
mable amplifiers. This
voltage must be precisely
adjusted with two 4.7-kilo-
ohm presets to measure
precisely 2.5V level on
the inputs of IC2 and IC3
when the input signals are
grounded.
Because LF353 op-
amps need a symmetrical
supply voltage, a small
DC-DC voltage converter
ICL7660 (IC6) is used
to feed –5V to LF353.
With its small 8-pin DIP
package, it needs only
two polarised capacitors.
ICL7660 can be replaced
with a MAX1044. The
MAX1044 and ICL7660
are monolithic, CMOS
switched-capacitor volt-
age converters that invert,
double, divide or multiply
a positive input voltage.
These are pin compatible
with the industry-stan-
dard LTC1044.

Overview of the
universal serial
bus
The specifications of the
USB can be found on web-
site ‘www.usb.org.’ One
of its major advantages
is the ability to drive 5V,
100mA devices.
All the data is trans-
mitted on the D+/D- sym-
metrical pins using a vari-
able bit rate. The position
of a resistor (R13) on D+ speed USB. The UPUEN bit (UCFG=4) tions.
or D- allows you to choose between enables the internal pull-ups. In this You can also ‘hot-plug’ a new de-
the full-speed (12 Mbps) and low- project, R13 is not used. External pull- vice. When this is done, the host PC
speed modes (1.5 Mbps). Note that the up may also be used. The VUSB pin starts an enumeration process to iden-
PIC18F2550/2455 devices have built-in may be used to pull up D+ or D-. The tify the device. The device sends the in-
pull-up resistors designed to meet the pull-up resistor must be 1.5 kilo-ohms formation to the PC by way of different
requirements of low-speed and full- (±5%) as required by the USB specifica- ‘descriptors.’ Each descriptor contains

w w w. e f y m ag . co m e l e c t ro n i c s f o r yo u • D e c e m b e r 2 0 0 6 • 6 1
Construction
nels. The two inputs have to be
grounded.
4. Command 85h: Initiates mea-
surement of the input signals.
The PIC software consists of
eight ‘C’ program source files, 14
header files and a linker file all un-
der ‘aquis.mcp’ project. The main
‘C’ program source files (‘main.c’
and ‘user.c’) are given at the end of
this article. The rest of the program
files are included in the EFY-CD.
Programming the chip. Program-
ming the PIC18F2455/2550 is easy
with an ICD2 module or PICSTART
Plus development board along with
Fig. 2: Layered framework of a USB device MPLAB software. But many serial
programmers for PIC16F84 are not
a specific kind of information about The first command byte determines compatible here. While using the
the device (vendor ID, serial number, the chip actions. The four possible ac- PICSTART Plus development board,
format and type of data transmitted). tions are: you can copy the hex file into the
You can see in Fig. 2 that each 1. Command 80h: Clears the EE- MPLAB IDE using ‘import’ command
device is structured in a layered frame- PROM calibration memory from ‘file’ menu bar. Select the device
work of descriptors. The first layer con- 2. Command 81h: Receives param- as ‘PIC18F2550’ and configure the bits
taining the configuration descriptors eters, and stores the gain-error com- as per this device from ‘config’ menu.
describes the power mode. pensation for the two channels. Installation of the USB driver. 1. If
Each configuration may have dif- 3. Command 83h: Initiates a zero everything is fine, plug the oscilloscope
ferent interfaces and each interface calibration sequence of the two chan- with a USB cable to your PC (running
may have different endpoints. An Windows 98SE or higher version). A
interface can use several endpoints “new hardware detected–USB2-Min-
Parts List iOscilloscope” dialogue box must im-
and an endpoint can be ‘IN’ (data from
Semiconductors:
device to the host) or ‘OUT’ (from host mediately appear on the screen.
IC1 - PIC18F2550 microcon-
to the device). With such an opened troller 2. Now you can start the driver in-
structure, it’s important to carefully IC2, IC3 - MCP6S91 program- stallation process. The driver has been
design the descriptors. mable gain amplifier included in the EFY-CD. The goal is
A 64-byte buffer is allocated to IC4(A, B), to select a good driver (mchpusb.inf)
IC5(A, B) - LF353 dual operational by choosing the ‘specific location’ op-
each of the 32 possible endpoints. Here
amplifier
only one is used and the more possible IC6 - ICL7660 switched-ca- tion. Don’t let Windows take a generic
amount of RAM buffer is then reallo- pacitor voltage convert- driver by default.
cated to store the measured values. ers 3. When you are done with
Resistors (all ¼-watt, ±5% carbon): installation, go to ‘device manager’
The PIC software R1, R7 - 1-mega-ohm and check whether ‘USB2-MiniOscillo-
The program for the microcontroller R2, R8 - 82-kilo-ohm scope’ is under ‘other device’ in ‘view
R3, R9 - 33-kilo-ohm
is written in ‘C’ language. MPLAB devices by type’ option. Otherwise,
R4, R10 - 220-kilo-ohm
7.31 along with MPLAB_C18 is used R5, R11 - 150-kilo-ohm repeat Steps 1 and 2.
as the software tool for develop- R6, R12 - 1-kilo-ohm User interface program and op-
ment. The software tools can be Capacitors: erations. A user-interface software
downloaded for free from website C1, C2 - 2.7pF ceramic written in Visual Basic 6, called ‘Os-
‘www.microchip.com.’ C3, C4, cilloPIC,’ is included in the EFY-CD.
C5, C6 - 68nF ceramic Run the set up program from the
Based on Microchip’s application
C7 - 0.022µF polyester
notes, the program for the chip is cen- C8 - 150nF ceramic ‘Setup_files’ folder included in the
tered on a main loop continually poll- C9 - 10µF, 16V electrolytic EFY-CD. This will automatically install
ing the USB transceiver state. This loop C10 - 47µF, 16V electrolytic the ‘OscilloPIC’ user-interface pro-
never stops and each USB operation is Miscellaneous: gram. Alternatively, you can open the
done in one pass. All operations are X1 - 4MHz crystal oscillator ‘Source_VB6’ folder, compile and run
initiated by the host (the PC), which CON1 - USB socket (type-B) for the ‘Synchropic’ program using Visual
PCB
sends a 16-byte command. Basic 6. Now run the ‘OscilloPIC.’ The

6 2 • D e c e m b e r 2 0 0 6 • e l e c t ro n i c s f o r yo u w w w. e f y m ag . co m
Construction
application program looks like a
small digital oscilloscope as shown
in the screenshot below.
Various settings for operations
are given in the following menu
bars:
1. Inputs: Selects the active
channels
2. Sampling: Sets time-base and
number of samples
3. Trigger: Sets the triggering
condition
4. Cursors: Selects horizontal or
vertical cursor positions
5. Num: Shows numerical
sampled values, with an export Fig. 3: An actual-size, single-side PCB layout of the two-channel PC-based USB oscilloscope
command (text file format)
6. Config: Configures gain and
offset errors
Calibration is to be done as
described below before reading
the output signals on the monitor
screen by clicking ‘channels cali-
bration’ under ‘config’ menu bar.
Feed the input waveforms (say,
sine, rectangular, sawtooth, etc)
from the source. Click ‘go’ but-
ton. The output waveform will be
displayed on the monitor screen.
Channel-1 and channel-2 output
waveforms can be differentiated by
green and red lines, respectively.
By default, the time base is 200 µs Fig. 4: Component layout for the PCB
per division and amplitude is 4V
per division. You can set these param- kilo-ohm presets until pin 2 of both and the measured levels (with the cur-
eters as per your requirements. MCP6S21 is at 2.5V. A more precise sors) for the two channels. The gain er-
Test and calibration. The first tuning can be achieved through ‘Oscil- ror is less than 0.1 per cent. The number
step is to adjust the zero offset error. loPIC’ software. Choose the smallest of samples can be set between ‘10’ and
Connect the two analogue inputs to calibration value at ±0.5V for both the ‘500.’ The minimum sampling rate is
the ground level and tune the two 4.7- inputs. 5 µs for one channel and 10 µs for two
The ‘zero calibration’ channels.
command tells the PIC
to start its own internal Construction
compensation for all cali- An actual-size, single-side PCB layout
brations. Don’t forget to for the two-channel PC-based USB os-
connect the inputs to the cilloscope circuit is shown in Fig. 3 and
ground while calibrat- its component layout in Fig. 4. Since
ing. the circuit is compact, the construction
The second parameter is easy. It is advised to use IC bases for
to check is the gain error. mounting IC2 through IC6 on the PCB
By clicking the ‘gain cali- for easy troubleshooting. The USB con-
bration’ command, it’s nector (CON1) must be firmly soldered
possible to specify a small and fixed on the board. It is located on
correction factor. This the extreme right of the board (refer
can be done after several Fig. 4).
Screenshot: Oscilloscopic program output screen along with typical measurements. You have Two BNC connectors can be used
sine and triangular waveforms to know the actual levels for the input signals for channels ‘1’

w w w. e f y m ag . co m e l e c t ro n i c s f o r yo u • D e c e m b e r 2 0 0 6 • 6 3
Construction
and ‘2,’ respectively. The connectors AD9238 (20 MS/s) is a good choice. be done with an analogue switch on all
can be fixed on the front panel of the This fast, parallel ADC converter could input signals.
enclosure. be used with a powerful DSP PIC. A EFY Note. All the relevant software
The performance of the oscilloscope PIC18Fx455 could be used for its USB of this article have been included in
can be improved by changing the PIC link. An auto-zero-level calibration this month’s EFY CD.
and its ADC with a faster model. system could be a good idea. This can

main.c
/********************************************************** void timer_isr(void) { tialization routine.
* FileName: main.c //Reset l’it du timer 1 * All required USB initialization routines
* Dependencies: See INCLUDES section below INTCONbits.TMR0IF=0; are called from
/** I N C L U D E S ************************************/ TMR0H= 256-183; * here.
#include “p18f2550.h” TMR0L= 0; * User application initialization routine
#include “typedefs.h” // Required should also be
#include “usb.h” // Required timeout++; // incremente le compteur time-out !! * called from here.
#include “io_cfg.h” // Required } **********************************************************
#include “user.h” // Modifiable *******************/
/*#pragma code _LOW_INTERRUPT_VECTOR = static void InitializeSystem(void) {
/** V A R I A B L E S ***********************************/ 0x000818 ADCON1 |= 0x0F; // Default all pins to digital
#pragma udata void low_ISR (void) {
; #if defined(USE_USB_BUS_SENSE_IO)
extern unsigned char voie1[256]; }*/ tris_usb_bus_sense = INPUT_PIN; // See io_cfg.
extern unsigned char voie2[256]; h
extern unsigned char voiesH1[64],voiesH2[64]; /** D E C L A R A T I O N S **************************/ #endif
extern char ordre, timeout; #pragma code
/****************************************************** #if defined(USE_SELF_POWER_SENSE_IO)
/** P R I V A T E P R O T O T Y P E S ****************/ **** tris_self_power = INPUT_PIN;
static void InitializeSystem(void); * Function: void main(void) #endif
void USBTasks(void); * PreCondition: None UserInit(); // See user.c & .h
void timer_isr(void); * Input: None mInitializeUSBDriver(); // See usbdrv.h
* Output: None }//end InitializeSystem
/** V E C T O R M A P P I N G *********************/ * Side Effects: None
* Overview: Main program entry point. /*********************************************************
extern void _startup (void); // See c018i.c in * Note: None *********************
//your C18 compiler dir ********************************************************** * Function: void USBTasks(void)
#pragma code _RESET_INTERRUPT_VECTOR = *******************/ * PreCondition: InitializeSystem has been called.
0x000800 void main(void) { * Input: None
void _reset (void) { InitializeSystem(); * Output: None
_asm goto _startup ordre=0; * Side Effects: None
_endasm while(1) { * Overview: Service loop for USB tasks.
} USBTasks(); // USB Tasks **********************************************************
#pragma code ProcessIO(); // See user\user.c & .h *******************/
}//end while void USBTasks(void) {
#pragma code low_vector = 0x18 }//end main /* Servicing Hardware */
void low_interrupt (void) { USBCheckBusStatus(); // Must use
_asm goto timer_isr _endasm /********************************************************* polling method
} ********************* if(UCFGbits.UTEYE!=1)
#pragma code * Function: static void InitializeSystem(void) USBDriverService(); // Interrupt or
* PreCondition: None polling method
* Input: None
#pragma interruptlow timer_isr * Output: None }// end USBTasks
//Fixe une periode de 1 seconde pour le time-out * Side Effects: None
//aquisition * Overview: InitializeSystem is a centralize ini- /** EOF main.c ****************************************/

user.c
/********************************************************** //Compteur et pointeur des buffers de voies /** D E C L A R A T I O N S **************************/
* FileName: user.c unsigned char acqcyc, timeout; #pragma code
* Processor: PIC18 unsigned char ordre;
******************************************************** unsigned char vH1, vH2, nptsH, nptsL; /***********************************************************
************/ unsigned char testH, testL; * Initialisation des ports, timer1, Adcon
unsigned char tt1, tt2, tt3; *
/** I N C L U D E S ************************************/ unsigned char savFSR1L, savFSR1H,savFSR2L, ********************************************************
#include “p18f2550.h” savFSR2H; **********/
#include “typedefs.h” void UserInit(void) {
#include “usb.h” //--- Reservation de 640 octets pour la voie 1 ----- //!!! NE PAS RALENTIR AVANT L’ENUM USB !!!
#include “io_cfg.h” // I/O pin mapping // de 0x100 a 0x37F //Reglage ADC voie AN0 ok
#include “user.h” #pragma udata voieA = 0x100 ADCON0 = 0x01; //
unsigned char voie1A[256]; adc on
/** V A R I A B L E S **********************************/ #pragma udata voieB = 0x200 ADCON1 = 0b00001101; // no ref , AN0-1
#pragma udata unsigned char voie1B[256]; ADCON2 = 0b10001100; // 2.Tad Fosc/4
DATA_PACKET databuff; #pragma udata voiesMSB = 0x300
unsigned char voiesH1[128]; PORTA = 0b11110011;
//Caracteristiques de l’acquisition TRISA = 0b11100011; //cde MCP6S ch0
unsigned char t_basethh, t_baseth, t_basetl; //--- La voie 2 est UsbRam de 0x500 a 0x77f ----- TRISB = 0xff;
unsigned char t_seuilh, t_seuill; PORTC = 0b11111100;
unsigned int t_nbpts; /** P R I V A T E P R O T O T Y P E S ***************/ TRISC = 0b11111000; //cde MCP6S ch1
void CopyData(unsigned int addr);
//Boucle de dechargement vers le bus Usb unsigned char RdEEPROM(unsigned char ad); send1_pts = send2_pts = 0;
int send1_pts, send2_pts, s_shift; void WrEEPROM(unsigned char ad, unsigned char send1H_pts = send2H_pts = 0;
int send1H_pts, send2H_pts, sendoffs; dat); sendoffs=0;
}

6 4 • D e c e m b e r 2 0 0 6 • e l e c t ro n i c s f o r yo u w w w. e f y m ag . co m
Construction
SCK_CH1=1; ADCON0=1;
/*********************************************************** nn<<=1; _asm
* Function: Lecture data eeprom SCK_CH1=0; //lance la mesure voie 1
**************************************************************/ } bsf ADCON0,1,0
unsigned char RdEEPROM(unsigned char ad) { // lance aquis
EEADR=ad; //Envoie le gain (SPI 0.0) waitv1: btfsc ADCON0,1,0
_asm nn=gain; bra waitv1
bcf EECON1,7,0 for (q=0;q<8;q++) { _endasm
// clear EEPGD if (nn&128) SI_CH1=1; else SI_CH1=0; }
bcf EECON1,6,0 SCK_CH1=1;
// clear CFGS nn<<=1; /***********************************************************
bsf EECON1,0,0 SCK_CH1=0; * Function: void ProcessIO(void)
// set RD } * Overview: This function is a place holder for
_endasm CS_CH1=1; other user routines.
return(EEDATA); } * It is a mixture of both USB and non-USB
} tasks.
/************************************************************ ***********************************************************/
/*********************************************************** * Function: CopyData (int) void ProcessIO(void) {
* Proc: Ecriture data eeprom * Overview: Recopie un bloc de 64 octets vers unsigned char ordrelen, pt;
******************************************************** databuff. unsigned int level;
***********/ * avant envoie sur le bus USB. unsigned long int sum32;
void WrEEPROM(unsigned char ad, unsigned char ***************************************************************/
dat) { void CopyData(unsigned int addr) { // User Application USB tasks
EEADR=ad; _asm if((usb_device_state < CONFIGURED_
EEDATA=dat; decf FSR1L,1,0 //!!! adr sur 8 STATE)||(UCONbits.SUSPND==1)) return;
_asm bits
bcf EECON1,7,0 decf FSR1L,1,0 ordrelen=(USBGenRead((byte*)&databuff,16));
// clear EEPGD movf INDF1,0,0 / / r e c u p l e
bcf EECON1,6,0 Msb //Verifie que le prefixe est recu
// clear CFGS movwf FSR0H,0 if (ordrelen!=0) ordre=databuff._byte[0];
bsf EECON1,2,0 decf FSR1L,1,0
// set WREN movf INDF1,0,0 // recup le Lsb //====================================
movwf FSR0L,0 // RECEPTION COMMANDE RAZ
movlw 0x55 //ETALONNAGE
movwf EECON2,0 //Sauve FSR2 //====================================
movlw 0xAA movf FSR2H,0,0 if (ordre==0x80) {
movwf EECON2,0 movwf vH2,1 //Raz premier eeprom location
movf FSR2L,0,0 pt=0xff;
bsf EECON1,1,0 movwf tt2,1 WrEEPROM(2,pt); // msb zero shift = ff
// set WR WrEEPROM(4,pt); // ‘’ ‘’
_endasm movlw databuff // adr sur 16
bits //Lance l’emission des offs en accusé de recep-
while (EECON1bits.WR!=0) { ; } movwf FSR2L,0 tion
movlw 0 sendoffs=64;
_asm // !!!! ordre=0;
bcf EECON1,2,0 movwf FSR2H,0 } //fin si ordre=80
// raz WREN movlw 64
_endasm movwf vH1,1 //====================================
} // RECEPTION COEFFICIENTS DE GAIN
//Boucle de copie //====================================
/*********************************************************** copydo: movf POSTINC0,0,0 if (ordre==0x81) {
* Function: void SetGain0(char) movwf POSTINC2,0 //Sauve les coeff de gain Voie 1
* Overview: Change le gain program- decfsz vH1,1,1 pt=databuff._byte[1];
mable ampli voie0. bra copydo WrEEPROM(9,pt);
***********************************************************/ //Voie 2
void SetGain0(unsigned char gain) { incf FSR1L,1,0 pt=databuff._byte[2];
unsigned char nn, q; incf FSR1L,1,0 WrEEPROM(10,pt);
incf FSR1L,1,0
CS_CH0=0; //Restitue FSR2 //Lance l’emission des offs en accusé de recep-
//Envoie cde ecriture registre gain (SPI 0.0) movf vH2,0,1 tion
nn=0b01000000; movwf FSR2H,0 sendoffs=64;
for (q=0;q<8;q++) { movf tt2,0,1 ordre=0;
if (nn&128) SI_CH0=1; else SI_CH0=0; movwf FSR2L,0 } //fin si ordre=81
SCK_CH0=1; _endasm
nn<<=1; } //====================================
SCK_CH0=0; // RECEPTION COMMANDE REGLAGE DU
} /*********************************************************** //ZERO
* Function: Mesure sur voies sur les ADC //====================================
//Envoie le gain (SPI 0.0) **************************************************************/ if (ordre==0x83) {
nn=gain; unsigned int doADC(unsigned char voie) { //Met les calibres +/-16v
for (q=0;q<8;q++) { if (voie==0) ADCON0=5; else ADCON0=1; SetGain0(0);
if (nn&128) SI_CH0=1; else SI_CH0=0; _asm SetGain1(0);
SCK_CH0=1; //lance mesure voie sum32=0;
nn<<=1; bsf ADCON0,1,0 //Moyenne de 256 acquisitions
SCK_CH0=0; // lance aquis for (level=0;level<0x100;level++) {
} waitvn: btfsc ADCON0,1,0 sum32+=doADC(0);
CS_CH0=1; bra waitvn for (tt1=0;tt1<64;tt1++) { ; }
} _endasm }
return(ADRES); //Sauve moyenne Voie0+/-16v en eeprom 1-2
/*********************************************************** } pt=sum32>>8;
* Function: void SetGain1(char) void doADC0(void) { WrEEPROM(1,pt);
* Overview: Change le gain program- ADCON0=5; pt=sum32>>16;
mable ampli voie1. _asm WrEEPROM(2,pt);
*****************************************************************/ //lance mesure voie 0
void SetGain1(unsigned char gain) { bsf ADCON0,1,0 //Moyenne de 256 acquisitions
unsigned char nn, q; // lance aquis sum32=0;
waitv0: btfsc ADCON0,1,0 for (level=0;level<0x100;level++) {
CS_CH1=0; bra waitv0 sum32+=doADC(1);
//Envoie cde ecriture registre gain (SPI 0.0) _endasm for (tt1=0;tt1<64;tt1++) { ; }
nn=0b01000000; } }
for (q=0;q<8;q++) {
if (nn&128) SI_CH1=1; else SI_CH1=0; void doADC1(void) { //Sauve moyenne Voie1+/-16v en eeprom 3-4

w w w. e f y m ag . co m e l e c t ro n i c s f o r yo u • D e c e m b e r 2 0 0 6 • 6 5
Construction
pt=sum32>>8; decfsz FSR0L,1,0
WrEEPROM(3,pt); bra raz4 //Si synchro sur VOIE 2
pt=sum32>>16; incf FSR0H,1,0 else {
WrEEPROM(4,pt); clrf FSR0L,0 if (t_seuilh & 0x20) {
raz5: clrf INDF0,0 doADC1();
//=================================== decfsz FSR0L,1,0 while (ADRES>=level)
//Met les calibres +/-1v bra raz5 { doADC1(); if (timeout==15) break; }
SetGain0(6); while (ADRES<level)
SetGain1(6); incf FSR0H,1,0 { doADC1(); if (timeout==15) break; } }
movlw 127 else {
sum32=0; // met les msb a 512 //Sync sur front descendant
//Moyenne de 256 acquisitions - voie 0 movwf FSR0L,0 doADC1();
for (level=0;level<0x100;level++) { raz6: movlw 0xAA while (ADRES<level)
sum32+=doADC(0); movwf INDF0,0 { doADC1(); if (timeout==15) break; }
for (tt1=0;tt1<64;tt1++) { ; } } decfsz FSR0L,1,0 while (ADRES>=level)
bra raz6 { doADC1(); if (timeout==15) break; } }
//Sauve moyenne Voie0+/-1v en eeprom movwf INDF0,0 } // fin si voie2
pt=sum32>>8;
WrEEPROM(5,pt); //------------ Prepare Acquisition ---------------- INTCON=0;
pt=sum32>>16; }
WrEEPROM(6,pt); incf nptsH,1,1 // compense les decfsz...
//====================================
//Moyenne de 256 acquisitions - voie 1 movf FSR1H,0,0 // sauve FSR1 // AQUISITION DE LA VOIE 0 SEULE - MINI
sum32=0; movwf savFSR1H,1 // pour apres //MUM 5 uS
for (level=0;level<0x100;level++) { aquis //====================================
sum32+=doADC(1); movf FSR1L,0,0 // if ((t_seuilh & 0x18)==0x08) {
for (tt1=0;tt1<64;tt1++) { ; } } movwf savFSR1L,1 // _asm
movlw 0x01
//Stocke ecarts en eeprom movf FSR2H,0,0 // sauve FSR2 movwf ADCON0,0
pt=sum32>>8; movwf savFSR2H,1 // pour apres bsf ADCON0,1,0
WrEEPROM(7,pt); aquis // lance aquis
pt=sum32>>16; movf FSR2L,0,0 // nop
WrEEPROM(8,pt); movwf savFSR2L,1 // nop

//Lance l’emission des offs en accusé de recep- movlw 0x1 loopv0: movff ADRESL,POSTINC0
tion movwf FSR0H,0 // stocke lsb voie 0
sendoffs=64; movlw 0x5
ordre=0; movwf FSR2H,0 bcf STATUS,0,0 // prend les deux bits
} //fin si ordre=83 clrf FSR0L,0 // fsr0 ptr de lsb rlcf vH1,1,1
voie 0 rlcf vH1,0,1 // decale de 2 et OR
//==================================== clrf FSR2L,0 // fsr2 ptr de lsb iorwf ADRESH,0,0
// RECEPTION COMMANDE ACQUISITION voie 1
//==================================== movwf vH1,1
if (ordre==0x85) { movlw 0x3 //Test si cycle de Msb
//Met les calibres demandés movwf FSR1H,0 decfsz acqcyc,1,1 // decr ctr
SetGain0(databuff._byte[8]); clrf FSR1L,0 // fsr1 ptr de bra stoh0
SetGain1(databuff._byte[9]); msb v0&v1
//Stocke les 4*2 bits finis
//Prend le mode et seuil de declenchement movlw 4 movf vH1,0,1
t_seuilh=databuff._byte[1]; // raz paquet de poids forts movwf POSTINC1,0 // FSR1 pointeur MSB
t_seuill=databuff._byte[2]; movwf acqcyc,1 clrf vH1,1
// raz next msb
//Prend la base de temps sur 24 bits clrf vH1,1 movlw 4
t_basethh=databuff._byte[3]; clrf vH2,1 movwf acqcyc,1 // raz acqcyc
t_baseth=databuff._byte[4]; _endasm bra dosui0
t_basetl=databuff._byte[5];
//-------- Conditions declenchement --------- stoh0: movlw 1 // tempo compens
//Prend le nombre de points // t_seuilh - b7 =1 : synchro pti1: decfsz WREG,1,0 //
nptsH = databuff._byte[6]; // b6 =0 : voie0, =1:voie1 bra pti1
nptsL = databuff._byte[7]; // b5 =1 : montant, =0:descen- //
t_nbpts= nptsL + 256*nptsH; dant nop
// b4 =1 : voie1 active //
//--------- Vidage de la memoire courbes --------- // b3 =1 : voie0 active
_asm // t_seuilh 1:0 +seuill = niveau vu par ADC direct. //Relance next aquisition
movlw 1 dosui0: bsf ADCON0,1,0
// Voie 1 - 100h/37fh if (t_seuilh & 0x80) { // lance aquis
movwf FSR0H,0 //Si synchro sur un seuil alors
clrf FSR0L,0 level = t_seuill+0x100*(t_seuilh&0x3); //Tempo d’une periode d’ech basehh->33mS
raz1: clrf INDF0,0 T0CON=0b10010110; movff t_basethh, tt3
decfsz FSR0L,1,0 TMR0H= 256-183; movff t_baseth, tt2
bra raz1 TMR0L= 0; movff t_basetl, tt1
incf FSR0H,1,0 INTCON=0b10100000; tpo1: decfsz tt1,1,1
clrf FSR0L,0 timeout=0; bra tpo1
raz2: clrf INDF0,0 decfsz tt2,1,1
decfsz FSR0L,1,0 //Si synchro sur VOIE 1 bra tpo1
bra raz2 if (t_seuilh & 0x40) { decfsz tt3,1,1
bra tpo1
incf FSR0H,1,0 //Sync sur front montant
movlw 127 if (t_seuilh & 0x20) { //Compte le nombre de points sur 16 bits
// met les msb à 512 doADC0(); decfsz nptsL,1,1
movwf FSR0L,0 while (ADRES>=level) bra loopv0
raz3: movlw 0xAA { doADC0(); if (timeout==15) break; } decfsz nptsH,1,1
movwf INDF0,0 while (ADRES<level) bra loopv0
decfsz FSR0L,1,0 { doADC0(); if (timeout==15) break; } } _endasm
bra raz3 else { }
movwf INDF0,0 //Sync sur front descendant
doADC0(); //====================================
movlw 5 while (ADRES<level) // AQUISITION DE LA VOIE 1 SEULE - MINI
// Voie 2 - 500h/77fh { doADC0(); if (timeout==15) break; } //MUM 5 uS
movwf FSR0H,0 while (ADRES>=level) //====================================
clrf FSR0L,0 { doADC0(); if (timeout==15) break; } } if ((t_seuilh & 0x18)==0x10) {
raz4: clrf INDF0,0 } // fin si voie1 _asm

6 6 • D e c e m b e r 2 0 0 6 • e l e c t ro n i c s f o r yo u w w w. e f y m ag . co m
Construction
movlw 0x7 stoh2: movlw 1 // tempo compens //Voit si envoie les 128 Msb max
movwf FSR1H,0 // msb voie2 en ptit1: decfsz WREG,1,0 // if (send1_pts<=0) {
0x7xx bra ptit1 // send1H_pts=128; // lance les 128 msb
nop s_shift=0x300; }
movlw 0x05 // while(mUSBGenTxIsBusy()) { }
movwf ADCON0,0 USBGenWrite((byte*)&databuff,USBGEN_EP_
bsf ADCON0,1,0 // lance aquis //-------- Acquisition sur Voie 1 (AN1) --------- SIZE);
nop do_v2: movlw 0x01 }
movwf ADCON0,0 else {
loopv1: movff ADRESL,POSTINC2 bsf ADCON0,1,0 /****** ENVOI DE LA VOIE 1 - POIDS FORTS ******/
// sto lsb voie1 (fsr2) nop if (send1H_pts>0) {
nop //Envoi le premier groupe des 128 msb de la
bcf STATUS,0,0 // prend les nop Voie 1
deux bits movff ADRESL,POSTINC2 // stocke lsb voie 2 CopyData(s_shift);
rlcf vH1,1,1 s_shift+=64;
rlcf vH1,0,1 // decale de 2 et OR bcf STATUS,0,0 // prend 2 Msbs send1H_pts-=64;
iorwf ADRESH,0,0 rlcf vH2,1,1 //Voit si envoie les 128 Msb max
movwf vH1,1 rlcf vH2,0,1 if (send1H_pts<=0) {
iorwf ADRESH,0,0 send2_pts= t_nbpts; // lance envoi voie 2
//Test si cycle de Msb movwf vH2,1 s_shift=0x500; }
decfsz acqcyc,1,1 // decr ctr while(mUSBGenTxIsBusy()) { }
bra stoh1 //Test si cycle de Msb USBGenWrite((byte*)&databuff,USBGEN_EP_
decfsz acqcyc,1,1 SIZE); }
//Stocke les 4*2 bits finis bra stoh3 else {
movf vH1,0,1 //Stocke les 4*2 bits finis /************ ENVOI DE LA VOIE 2 *****************/
movwf POSTINC1,0 movlw 0x4 if (send2_pts>0) {
// FSR1 pointeur MSB addwf FSR1H,1,0 // passe en 0x7.. //Envoi le premier groupe de 64oc de la Voie 1
clrf vH1,1 // raz next msb movf vH2,0,1 CopyData(s_shift);
movlw 4 movwf POSTINC1,0 s_shift+=64;
movwf acqcyc,1 // raz acqcyc movlw 0x4 send2_pts-=64;
bra dosui1 subwf FSR1H,1,0 // repasse en 0x3.. //Voit si envoie les 128 Msb max
clrf vH2,1 // raz next Msb if (send2_pts<=0) {
stoh1: movlw 1 // tempo compens movlw 4 send2H_pts=128; // lance les 128 msb
pti2: decfsz WREG,1,0 // movwf acqcyc,1 // raz acqcyc s_shift=0x700; }
bra pti2 bra do_sui while(mUSBGenTxIsBusy()) { }
// USBGenWrite((byte*)&databuff,USBGEN_EP_
nop stoh3: movlw 3 // tempo compens SIZE); }
// ptit2: decfsz WREG,1,0 // else {
bra ptit2 // /******* ENVOI DE LA VOIE 2 - POIDS FORTS *****/
//Relance next aquisition nop if (send2H_pts>0) {
dosui1: bsf ADCON0,1,0 // lance aquis // //Envoi le premier groupe des 128 msb de la
Voie 1
//Tempo d’une periode d’ech basehh->33mS //Tempo d’une periode d’ech basehh->33mS CopyData(s_shift);
movff t_basethh, tt3 do_sui: movff t_basethh, tt3 s_shift+=64;
movff t_baseth, tt2 movff t_baseth, tt2 send2H_pts-=64;
movff t_basetl, tt1 movff t_basetl, tt1 sendoffs=64;
tpo2: decfsz tt1,1,1 tp1: decfsz tt1,1,1 //Voit si envoi des Offsets
bra tpo2 bra tp1 while(mUSBGenTxIsBusy()) { }
decfsz tt2,1,1 decfsz tt2,1,1 USBGenWrite((byte*)&databuff,USBGEN_
bra tpo2 bra tp1 EP_SIZE); }
decfsz tt3,1,1 decfsz tt3,1,1 else
bra tpo2 bra tp1
/********* ENVOI DES OFFSETS VOIE 0 & 1 *********/
//Compte le nombre de points sur 16 bits //Compte le nombre de points sur 16 bits if (sendoffs>0) {
decfsz nptsL,1,1 decfsz nptsL,1,1 //Envoi le premier groupe offsets à +/-16v
bra loopv1 bra loopaq databuff._byte[0]=RdEEPROM(1); //
decfsz nptsH,1,1 decfsz nptsH,1,1 Lsb voie 0
bra loopv1 bra loopaq databuff._byte[1]=RdEEPROM(2); //
_endasm _endasm Msb
} } databuff._byte[2]=RdEEPROM(3); //
Lsb voie 1
//==================================== //==================================== databuff._byte[3]=RdEEPROM(4); //
// AQUISITION DES DEUX VOIES - MINIMUM //Remet contexte fsr apres aquisitions msb
//10 uS _asm //Envoi le second groupe offsets à +/-1v
//==================================== movf savFSR1H,0,1 // remet FSR1 databuff._byte[4]=RdEEPROM(5); //
if ((t_seuilh & 0x18)==0x18) { movwf FSR1H,0 Lsb voie 0
_asm movf savFSR1L,0,1 databuff._byte[5]=RdEEPROM(6); //
// Acquisition de la Voie 0 movwf FSR1L,0 Msb
loopaq: movlw 0x05 databuff._byte[6]=RdEEPROM(7); //
movwf ADCON0,0 movf savFSR2H,0,1 // remet FSR2 Lsb voie 1
bsf ADCON0,1,0 // lance aquis movwf FSR2H,0 databuff._byte[7]=RdEEPROM(8); //
nop movf savFSR2L,0,1 msb
nop movwf FSR2L,0
movff ADRESL,POSTINC0 // stocke lsb voie 1 _endasm //Calibration des gains sauvés en eeprom
databuff._byte[8]=RdEEPROM(9); //
bcf STATUS,0,0 // prend les ordre=0; voie 0
deux bits databuff._byte[9]=RdEEPROM(0x0a); //
rlcf vH1,1,1 //Lance la retransmission voie 1
rlcf vH1,0,1 // decale de 2 et OR send1_pts = t_nbpts;
iorwf ADRESH,0,0 s_shift = 0x100; //envoie les octets offset + cal gains
movwf vH1,1 send1H_pts = send2_pts =send2H_pts = send- while(mUSBGenTxIsBusy()) { }
offs=0; USBGenWrite((byte*)&databuff,USBGEN_
//Test si cycle de Msb } //fin if ordre=85 EP_SIZE);
decfsz acqcyc,0,1 // (decr sans modifier) sendoffs=0;
bra stoh2 }
//Stocke les 4*2 bits finis /******** ENVOI DE LA VOIE 1 *****************/ }
movf vH1,0,1 if (send1_pts>0) { }
movwf INDF1,0 //Envoi le premier groupe de 64oc de la Voie 1 }
clrf vH1,1 // raz new msb CopyData(s_shift); }//end ProcessIO
bra do_v2 s_shift+=64; /****************************************************/
send1_pts-=64; 

w w w. e f y m ag . co m e l e c t ro n i c s f o r yo u • D e c e m b e r 2 0 0 6 • 6 7

Vous aimerez peut-être aussi