有用过NI 公司NET9914芯片的吗,就是GPIB协议的芯片?

2020-01-02 19:39发布

有用过NET9914芯片的朋友吗?我看了它的PDF文档,我不明白里面说的可以有两种模式,即MODE 9914 各MODE 7210模式。到底应该怎么样初始化它啊?是不是两种模式都要进入进行设置呢?有用过的可以讲一下吗?谢谢了!
90条回答
iamlangzi
2020-01-04 18:01
本帖最后由 iamlangzi 于 2012-11-27 21:53 编辑

//Gpibdev5.c
/*
gpibdevc.c 7/28/97
GPIB DEVICE implementation for a small microcontroller operating in tandem
with a NAT9914 chip. This C code is designed for a microcontroller. It implements a
GPIB voltage query, tare, Group Execute Trigger, and DCAS commands.
At startup, this code initializes the microcontroller and the NAT9914 and then waits
in an idle state until the NAT9914 sends an interrupt. The device interprets the
interrupt and tares, resets, executes on the G.E.T. command, reads the voltage and
stuffs it into a buffer, or outputs the contents of the buffer to the Active GPIB
listener.
read_voltage(), handle_GET_trigger(), and adjust_tare() are device specific and
shown here as stubs. The NAT9914 interrupts the microcontroller for BI, BO, GET,
and SDC/DCL.
*/
/* assert() statements draw attention to internal errors */
/* #include <assert.c> */
#include "avr/io.h"
#define assert(a) {}
#include "gpibdevc.h"
#pragma interrupt_handler route_nat9914_interrupts
#define USING_INTERRUPTS
/* to input and output on a microcontroller, read or write to a memory location
*/
#define inp(io_address) *(unsigned char *)io_address
#define outp(io_address, o_data) *( unsigned char *)io_address = o_data;
/* state variable. one of the following values
idle_state 1
reading_state 2
writing_state 3
*/
u_8 GPIB_state;
/* buffer variables
Index is an offset from the base address of the i/o buffer.
io_buffer is both the GPIB input and output buffer.
*/
u_8 Index;
u_8 io_buffer[BUFFER_SIZE];
/* isr0_byte and isr1_byte hold data from the NAT9914 status registers which has not yet
* been processed.
*/
u_8 isr0_byte;
u_8 isr1_byte;


int main(void) {
initialize_device();
do{
/*
* all non-GPIB device code goes in this loop
*/
//#ifndef USING_INTERRUPTS
route_nat9914_interrupts();
//#endif
}while(1);
}



/*
*
* Initialization routines
*
*
*
*/
void initialize_device(void) {
/* initialization sequences for both the microcontroller and the NAT9914
*/
initialize_microcontroller();
/* initialize software variables before the device begins accepting GPIB commands
*/
Index = 0;
GPIB_state = idle_state;
initialize_NAT9914();
asm("cli");
}
void initialize_microcontroller(){
/* initialize the microcontroller
* ...these are microcontroller defaults
* expanded memory mode (set by hardware pins)
* set clock speed
* set hardware interrupt to match capabilities of nat9914
* disable watchdog
*/
}
void initialize_NAT9914(){
/* this routine initializes the NAT9914 and enables the device to receive commands from
* the GPIB network.
*/
u_8 my_gpib_address;
/* ...Make sure GPIB chip is in 9914 mode.
*/
outp(r7210_auxmr, c7210_sw9914);
/* ...Reset the NAT9914. Logically remove device from the GPIB. The device will
* ignore GPIB activity until it is initialized.
*/
outp(r_auxcr, c_ch_rst);
/* ...clear the status registers.
*/
isr0_byte = 0;
isr1_byte = 0;
/* ...set clock speed
*/
outp(r_accr, f_icr | f_2mhz);
/* ...set T1 delay
*/
outp(r_auxcr, c_vstdl);
/* ...enable interrupts
*/
outp(r_imr0, b_bo_ie | b_bi_ie);
outp(r_imr1, b_dcas_ie | b_get_ie);
#ifndef USING_INTERRUPTS
outp(r_auxcr, c_piimr2);
outp(r_imr2, 0x00); /* clear GLINT bit */
#endif
/* ...configure the NEWLINE character to end incoming and outgoing GPIB messages
*/
outp(r_auxcr, c_pieosr);
outp(r_eosr, NEWLINE);
outp(r_auxcr, c_piaccr);
outp(r_accr, f_accra | b_xeos | b_reos);
/* ...set the GPIB address of the device
*/
my_gpib_address = get_gpib_address();
outp(r_adr, my_gpib_address);
/* ...enable the device to receive data and commands from the GPIB network
*/
outp(r_auxcr, c_nswrst);
}
u_8 get_gpib_address(void){
/* read the GPIB address from DIP switches. This device specific function reads the
* address from a set of DIP switches connected to port D.
*/
u_8 gpib_address;
gpib_address = inp(PORT_D);
/* convert the invalid address, 31(decimal) into 30
*/
if(gpib_address == 31)
gpib_address = 30;
return gpib_address;
}
/*
*
* Handle Interrupt Routines
*
*
*
*/
void route_nat9914_interrupts(void) {
/* route_nat9914_interrupts handles the hardware interrupt from the NAT9914.
* It determines what caused the interrupt and calls the appropriate function.
* If no interrupts are pending, then it does nothing.
*/
/* ...read isr0 and isr1, the values must be saved because the act of reading the bits
* in the registers clears the bits.
*/
isr0_byte = isr0_byte | inp(r_isr0);
isr1_byte = isr1_byte | inp(r_isr1);
/* ...determine the cause of the interrupt and handle it
*/
if (isr0_byte & b_bo) handle_BO_int();
if (isr0_byte & b_bi) handle_BI_int();
if (isr1_byte & b_get) handle_GET_trigger();
if (isr1_byte & b_dcas) handle_DCAS_int();
}
void handle_DCAS_int(void) {
/* This routine resets only the GPIB interface of the device and not
* the device itself. Its primary use is recovering after an error on the GPIB.
* If a GPIB error occurs and the device locks up or appears to hang, the GPIB
* controller can issue the SDC or DCL command and place the device into its idle GPIB
* state, clear its buffers and start over.
*/
/* ...reinitialize variables and buffers
*/
Index = 0;
GPIB_state = idle_state;
outp(r_auxcr, c_rhdf);
isr0_byte = 0x00;
isr1_byte = 0x00;
/* ...update serial poll response byte
*/
clear_status_byte_bits( b_mav |
b_rsv |
error_reading |
error_writing |
error_unknown_command);
/* ...acknowledge command received and processed by releasing DAC holdoff
*/
outp(r_auxcr, c_nonvalid);
}

void handle_BI_int(void) {
/* The Byte In handler reads a byte from the NAT9914 and stores it in the input buffer.
* If the device has not finished writing data from a previous command message, the
* device overwrites the old data and issues an error message to the GPIB controller.
*/
assert( GPIB_state==idle_state ||
GPIB_state==reading_state ||
GPIB_state==writing_state);
assert(Index <= BUFFER_SIZE);
/* ...update the gpib state
*/
if (GPIB_state == idle_state) {
Index = 0;
GPIB_state = reading_state;
}
/* ...if the controller is sending data to the device while the device is trying to
* send data to the controller, set an error flag in the status byte to warn the
* controller.
*/
else if (GPIB_state == writing_state){
clear_status_byte_bits(b_mav);
set_status_byte_bits(b_rsv | error_reading);
GPIB_state = reading_state;
Index = 0;
outp(r_auxcr, c_nbaf);
}
/* read data from the NAT9914 into the input buffer. To improve performance loop
* instead of exiting the interrupt handler and then calling the interrupt handler
* again.
*/
do{
/* read the data into the buffer. If the buffer is full, then
* the routine doesn't accept the new byte.
*/
if(Index < BUFFER_SIZE) {
io_buffer[Index]= (u_8) inp(r_dir);
Index++;
}
assert(Index <= BUFFER_SIZE);
/* check for another incoming byte unless the end of the string
* is detected.
*/
isr0_byte = isr0_byte & ~b_bi;
if(!(isr0_byte & b_end)){
isr0_byte = isr0_byte | (u_8) inp(r_isr0);
}
}while (isr0_byte&b_bi);
/* ..if a complete message has been received, interpret before exiting
*/
if (isr0_byte & b_end) parse_input_buffer();
}

void handle_BO_int(void) {
/* This routine places the next byte from the output buffer into the NAT9914. If
* the device was reading data and received a spurious command to write, the function
* issues an error message to the GPIB controller and exits.
*/
assert( GPIB_state==idle_state ||
GPIB_state==reading_state ||
GPIB_state==writing_state);
/* ...update the GPIB state
*/
if (GPIB_state == idle_state) {
/* ...only write if data has been written to the output buffer
*/
if (Index == 0) {
isr0_byte= isr0_byte & ~b_bo;
}
else {
Index = 0;
GPIB_state = writing_state;
}
}
/* ...If the controller and the device are both trying to read data, set an error
* flag in the serial poll response byte
*/
else if (GPIB_state == reading_state){
set_status_byte_bits(error_writing);
isr0_byte = isr0_byte & ~b_bo;
}
/* ...write the data bytes to the NAT9914 until the listener stops listening or the
* device runs out of data. To improve performance loop instead of exiting the
* interrupt handler and then calling the interrupt handler again.
*/
while (isr0_byte&b_bo){
assert(Index <= BUFFER_SIZE);
/* ...output a byte from the output buffer
*/
outp(r_cdor, io_buffer[Index]);
Index++;
/* ...check if NAT9914 is ready to send another byte
*/
isr0_byte = isr0_byte & ~b_bo;
isr0_byte = isr0_byte | (u_8) inp(r_isr0);
/* ...If the device is out of data, update the serial poll response register, stop
* sending data and reset the buffer
*/
if (io_buffer[Index-1] == NEWLINE) {
clear_status_byte_bits(b_mav | b_rsv);
GPIB_state = idle_state;
Index=0;
isr0_byte = isr0_byte & ~b_bo;
}
}
assert( (Index>=0)&&(Index<=BUFFER_SIZE) );
}
/*
*
* Device Dependent Routines
*
*
*
*/
void handle_GET_trigger(void) {
/* This routine performs a device specific trigger action.
*/
/*
* insert code to implement the device specific trigger action
*/
/* release DAC holdoff to acknowledge to other routines and to the GPIB controller
* that the device specific trigger action has been completed.
*/
isr1_byte = isr1_byte & ~b_get;
outp(r_auxcr, c_nonvalid);
}
void read_voltage(void) {
/* This routine is an example of a device specific execute query.
*/
/* ...read the device specific data
*/
/* ...format the device specific data
*/
/* ...output the data to the output buffer
*/
output_data_to_io_buffer('1');
output_data_to_io_buffer('.');
output_data_to_io_buffer('2');
output_data_to_io_buffer('V');
}
void adjust_tare(void) {
/* adjust_tare is an example of a device specific execute command.
*/
/*
* insert your device specific code here
*/
}
/*
*
* GPIB Buffer Routines
*
*
*
*/
void output_data_to_io_buffer( u_8 data_out) {
/* output_data_to_io_buffer writes data to the output buffer. Because its input is
* provided by other functions, it has no error checking.
*/
/* ...check ranges on variables
*/
assert( GPIB_state==idle_state ||
GPIB_state==reading_state ||
GPIB_state==writing_state);
assert((Index>=0)&&(Index<BUFFER_SIZE));
/* ..place the data byte on the output buffer
*/
io_buffer[Index] = data_out;
Index = Index + 1;
}
void parse_input_buffer() {
/* parse the message and call the correct routine. Also, reset the buffer and set the
* device in idle state. If the command just received is invalid, send an error message
* to the GPIB controller.
*/
/* ...check ranges on variables
*/
assert( GPIB_state==idle_state ||
GPIB_state==reading_state ||
GPIB_state==writing_state);
assert((Index>=0) && (Index <= BUFFER_SIZE));
/* ...reset the state variables, since the device now has stopped reading GPIB data
*/
Index = 0;
GPIB_state = idle_state;
isr0_byte = isr0_byte & ~b_end;
/* ...parse the message in the input buffer
*/
if ( io_buffer[0]=='V' &&
io_buffer[1]=='O' &&
io_buffer[2]=='L' &&
io_buffer[3]=='T' &&
io_buffer[4]=='?' ) {
read_voltage();
/* ...terminate the data string and request service now that the data is
* in the buffer
*/
output_data_to_io_buffer(NEWLINE);
set_status_byte_bits(b_mav | b_rsv);
}
else if ( io_buffer[0]=='T' &&
io_buffer[1]=='A' &&
io_buffer[2]=='R' &&
io_buffer[3]=='E' )
adjust_tare();
else{
/* ...if the device received an unrecognized command, send an error
* message
*/
set_status_byte_bits(b_rsv | error_unknown_command);
}
}
/*
*
* Status Byte management routines
*
*
*
*/
void set_status_byte_bits(u_8 srq_byte) {
/* this routine encapsulates writes to the NAT9914's spmr register. It allows the
* calling routine to set any combination of bits without affecting the others. It
* presents a consistent interface for requesting serial polls. Its counterpart is
* clear_status_byte_bits()
*/
u_8 srq_response_byte;
srq_response_byte = (u_8) inp(r_spsr);
srq_response_byte = srq_response_byte | srq_byte;
srq_response_byte = srq_response_byte & ~b_rsv;
outp(r_spmr, srq_response_byte );
/* ...use the rsv2 command to request a serial poll instead of the rsv bit. The rsv2
* command clears itself after the serial poll and mixing rsv2 and rsv can cause
* undefined behavior.
*/
if(srq_byte & b_rsv){
outp(r_auxcr, c_rsv2);
}
}
void clear_status_byte_bits(u_8 srq_byte) {
/* this routine encapsulates writes to the NAT9914's spmr register. It allows the
* calling routine to clear any combination of bits without affecting the others by
* clearing the bits corresponding to the asserted bits of its input. It presents a
* consistent interface for ceasing to request serial polls. Its counterpart is
* set_status_byte_bits().
*/
u_8 srq_response_byte;
srq_response_byte = (u_8) inp(r_spsr);
srq_response_byte = srq_response_byte & ~srq_byte;
srq_response_byte = srq_response_byte & ~b_rsv;
outp(r_spmr, srq_response_byte );
/* ...use the rsv2 command to stop requesting a serial poll instead of the rsv bit.
* The rsv2 command clears itself after the serial poll and mixing rsv2 and rsv can
* cause undefined behavior.
*/
if(srq_byte & b_rsv){
outp(r_auxcr, c_nrsv2);
}
}

一周热门 更多>