{***************************************************************************** * SAMPLE2.PAS : TIMER DRIVEN INTERRUPTS * * * * The program will display sixteen channels using timer driven interrupts. * * * * The board should be set as follows: * * * * -- Polarity set to bipolar -- S2 TO BIP * * -- On board clock set to 1 MHz -- CLOCK JUMPER TO 1MHZ * * -- 16 channel single ended -- S3 TO 16CH * * * * LAST MODIFICATION: 2/3/98 * * * *****************************************************************************} program startup; {$L aa16drv} {$F+} USES crt; type param_array = array[1..7] of integer; dat_array = array[1..200] of integer; pnt_array = array[1..200] of word; { all of the parameters passed to the driver must be declared globally, including the buffers which have their offset passed inside the params array } var task,status :integer; params :param_array; ch :char; pntbuf :pnt_array; datbuf :dat_array; function AskForBaseAddress(OldOne : String) : Word; const Msg : string[4] = '0'; var NewOne, Success, Dummy, Error : Word; AddrInputPosX, AddrInputPosY : Word; begin if (OldOne = 'OLD') then OldOne := Msg; WriteLn('Please enter the Base Address (0000-FFFF) for your card (in hex)'); WriteLn('or press ENTER for ', OldOne, '. '); Write('>'); AddrInputPosX := WhereX; AddrInputPosY := WhereY; repeat GotoXY(AddrInputPosX, AddrInputPosY); ClrEol; Readln(Msg); Val('$' + Msg, NewOne, Error); if (error=0) then begin Success := 1; Dummy := NewOne; end else if (Msg = '') then begin GotoXY(AddrInputPosX, AddrInputPosY); WriteLn(OldOne); Msg := OldOne; Success := 1; Val('$' + Msg, Dummy, Error); end; until (Success = 1); AskForBaseAddress := Dummy; end; { end of AskForBaseAddress } procedure aa16drv(t_off:word;p_off:word;st_off:word);external; {*************************************************************************** * PROCEDURE: call_driver -- local routine * * * * PURPOSE: Performs the call to the driver package. * * * * INPUT: None. * * * * CALLS: aa16drv - entry point to driver package. * * * * OUTPUT: None. * * * ***************************************************************************} procedure call_driver; begin aa16drv(ofs(task),ofs(params[1]),ofs(status)); { this section checks for an error code } if status > 0 then begin WriteLn('A status error code of ',status,' was detected.'); WriteLn('Program terminated.'); end; end; { call_driver } {***************************************************************************** * FUNCTION: setup -- local routine * * * * PURPOSE: Sets up the driver package to read all 16 A/D channels. * * * * INPUT: None. * * * * CALLS: call_driver - entry point to driver package. * * * * OUTPUT: Returns the error code supplied by the driver routine. * * * *****************************************************************************} procedure setup; var Address : word; begin ClrScr; WriteLn(' SAMPLE2.PAS : TIMER DRIVEN INTERRUPTS'); WriteLn; WriteLn(' The program will display sixteen channels using timer driven interrupts.'); WriteLn; Address := AskForBaseAddress('350'); ClrScr; WriteLn; WriteLn; WriteLn; WriteLn('Board Configuration:'); WriteLn; WriteLn(' -- RANGE: 5 Volt Range (required)'); WriteLn(' -- POLARITY: set to bipolar--S2 to BIP (required)'); WriteLn(' -- 16 channel single ended--S3 to 16CH (required)'); WriteLn(' -- On board clock set to 1 MHz -- CLOCK JUMPER TO 1MHZ (required)'); WriteLn(' -- All other jumper settings are irrelevant'); WriteLn; WriteLn; WriteLn; WriteLn('Press any key to continue; press "E" to exit the program.'); ch:=ReadKey; { initialize the board } task := 0; params[1] := Address; { assigned board address } params[2] := 5; { 5 volt range } call_driver; if status <> 0 then exit; { Set up the timers to divide the 1MHz clock by 1000 } task := 14; params[1] := 1; { set up counter 1 } params[2] := 3; { use mode 3 } params[3] := 100; { use 100 as divsor } call_driver; if status <> 0 then exit; task := 14; params[1] := 2; { set up counter 2 } params[2] := 3; { use mode 3 } params[3] := 10; { use 100 as divsor } call_driver; if status <> 0 then exit; { set the sample and hold settle count, this is only needed for faster computers such as 386's etc. } task := 11; params[1] := 5; { sub task 5, set settle count } params[2] := 50; { set settle count to 50 } call_driver; if status <> 0 then exit; { Clear the point list } task := 11; params[1] := 2; { sub task 2, clear point list } call_driver; if status <> 0 then exit; { Install 16 channels of an AIM-16P attached to channel 0 of A/D } task := 5; params[1] := 0; { lower point address in range } params[2] := 15; { upper point address in range } call_driver; if status <> 0 then exit; { Install reference junction to point address 0 } task := 10; params[1] := 2; { sub task 2, assign curve to point address } params[2] := 0; { point address 0 is to be assigned } params[3] := 84; { ASCII T = reference junction } params[4] := 70; { ASCII F = degrees F as unit of measure } call_driver; if status <> 0 then exit; { Install type t thermocouple to point address 1 } task := 10; params[1] := 2; { sub task 2, assign curve to point address } params[2] := 1; { point address 1 is to be assigned } params[3] := 116; { ASCII t = type t thermocouple } params[4] := 70; { ASCII F = degrees F as unit of measure } call_driver; if status <> 0 then exit; { assign proper gain code for point address 1 "t" type thermocouple } task := 4; params[1] := 1; { lower point address in range } params[2] := 1; { upper point address in range } params[3] := 5; { gain code to assign } call_driver; end; {procedure setup } {***************************************************************************** * FUNCTION: get_readings -- local routine * * * * PURPOSE: Reads the 16 A/D channels and displays them on the screen. * * * * INPUT: None. * * * * CALLS: call_driver - entry point to driver package. * * * * OUTPUT: Returns the error code supplied by the driver routine. * *****************************************************************************} procedure get_readings; var I :integer; begin { Reset the point list index } task := 11; params[1] := 1; { sub task 1, reset point list index } call_driver; if status <> 0 then exit; { set up the driver to do the interrupts } task := 9; params[1] := 1; { sub task 1, install interrupt } params[2] := 5; { use IRQ 5 } params[3] := 16; { do 16 conversions } params[4] := ofs(datbuf[1]); { offset of data buffer } params[5] := ofs(pntbuf[1]); { offset of point/gain buffer } params[6] := 1; { use timers for start of conversion } call_driver; if status <> 0 then exit; { repeatedly check status of background task until the driver indicates that it is done } task := 9; params[1] := 2; { sub task 2, check background task status } repeat call_driver; until (params[2] = 0); { 0 indicates background task complete } { display results to screen } ClrScr; WriteLn; WriteLn(' POINT ADDRESS GAIN VALUE'); WriteLn(' ------------- ---- -----'); for I := 1 to 16 do WriteLn(pntbuf[I] div 256:10,(pntbuf[I] and $ff):10,datbuf[I] / 10:10:1); end; { get_readings } {************************************************************************** * PROCEDURE: main -- local routine * * * * PURPOSE: Controls program flow, detects when user is ready to exit. * * * * INPUT: None. * * * * CALLS: setup - set up program and drivers. * * get_readings - read the A/D channels and display. * * * * OUTPUT: None. * * * **************************************************************************} BEGIN setup; { set up program and the driver } while (status = 0) and (ch <> 'E') and (ch <> 'e') do begin { display current values for the 8 channels } get_readings; if status = 0 then { check for program exit } begin { if status > 0 then error } WriteLn; WriteLn('Press E to exit the program. Press any other key to rescan the data...'); ch:=readkey; { wait for key press } end; end; END. { main program }