11-27-2005 02:28 PM
11-29-2005 04:18 AM - edited 11-29-2005 04:18 AM
Hi, I'm new to this DDK prorgamming on m-series cards myself. I've successfully programming the PCI-6254 , a similar card to yours. I've got interrupts, analog reading and counters to work. If I give any bad advise you have been warned!!
To do interrupts first you must register your interrupt routine with the operatating system you are using, in my case RTX:
// Attach the interrupt
interrupt_handles[interrupt_count] = RtAttachInterruptVector( NULL, 0, pRoutineIST, this, 127, PCIBus, bus_number, interrupt_level, interrupt_vector);
(note: This is operation system dependant so you will have to specify the OS your using before I can help)
Bear in mind you have to find the IRQ number, bus number and device number before you can register the routine. You get these through scanning the bus when you enumulate all the cards. Email me if you want help with this.
Next you need to enable the appropriate interrupt registers. These determine what causes an interrupt to occur. For interrupts on the end of every scan ->
board->Interrupt_A_Enable.setAI_Error_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_FIFO_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_SC_TC_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_START1_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_START2_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_START_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_STOP_Interrupt_Enable(1);
board->Interrupt_A_Enable.flush();
// Next you need to clear any existing interrupts that may have occured
board->Interrupt_A_Ack.setAI_Error_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_SC_TC_Error_Confirm(1);
board->Interrupt_A_Ack.setAI_SC_TC_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START1_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START2_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_STOP_Interrupt_Ack(1);
board->Interrupt_A_Ack.flush();
Message Edited by studio_uk on 11-29-2005 04:18 AM
Message Edited by studio_uk on 11-29-2005 04:20 AM
11-29-2005 04:18 AM
// Now you need to enable the appropriate interrupt group
board->Interrupt_Control.setInterrupt_Group_A_Enable(1);
board->Interrupt_Control.setInterrupt_Group_B_Enable(0);
board->Interrupt_Control.flush();
// If you use the FIFO interrupt you need to set what FIFO state will cause an interrupt
board->AI_Mode_3.setAI_FIFO_Mode(tMSeries::tAI_Mode_3::kAI_FIFO_ModeNot_Empty);
board->AI_Mode_3.flush();
Then you arm the card and interrupts will start being created.
Bear in mind, some interrupts require you to call one of the "board->Interrupt_A_Ack.writeAI_XXX_Interrupt_Ack(1);" or only one interrupt will be triggered. I beleive FIFO interrupts are the only ones where you don't need to do this.
// As for these functions
configureTimebase (), pllReset (), analogTriggerReset (), aiReset (), aiPersonalize (), aiClearConfigurationMemory (), aiConfigureChannel (), aiSetFifoRequestMode (), aiEnvironmentalize (), aiHardwareGating (), aiTrigger (), aiSampleStop (), aiNumberOfSamples (), aiSampleStart (), aiConvert (),
These all setup the card for the specific task you want to perform with the card. The first thing to do is to reset the card. Bear in mind from my experience you have to reset "everything". That includes timers and analog out. If you don't it doesnt seem to work properly, I wouldnt cut any of this code out of your program. As for configuring the card, the order of running each of the functions you've listed is very important. Follow the examples, if you get the order wrong or miss a function call it won't work. The E-Series DDK manual is very well documented. The M and E-Series cards are very similar in operation however the registers are very different. So reading that should shed some light on why all these functions are required.
aiClearConfiguationMemory() and aiConfigureChannel: These functions setup the scanning order. I.e. The card will process every channel you add via "aiConfigureChannel" until they have all been processed, then start again (on the M-Series card you have a maximum of 4096 entries). The results of the scans will be stored in the AI FIFO. Which you can read either via "board->AI_FIFO_Data.readRegister ()" or via a DMA transfer. Note, you do "not" need to reread the EPROM every set of inputs / outputs. The values will not change. Also note the scaling constants are the same for every channel because the card only has one DAC.
One final suggestion is don't remove any functions to save code size/comprexity. They are all needed.
You can contact me on john@itsolutions-uk.net if you have any more questions as this board doesnt get looked at very often.
Regards
John
11-29-2005 10:50 AM
11-29-2005 12:33 PM
11-29-2005 01:09 PM
02-10-2006 12:01 AM
board->Interrupt_A_Ack.setAI_Error_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_SC_TC_Error_Confirm(1);
board->Interrupt_A_Ack.setAI_SC_TC_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START1_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START2_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_STOP_Interrupt_Ack(1);
board->Interrupt_A_Ack.flush();
board->Interrupt_B_Ack.setAO_Error_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_STOP_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_START_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_UPDATE_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_START1_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_BC_TC_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_UC_TC_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_STOP_Interrupt_Ack(1);
board->Interrupt_B_Ack.flush();
InterruptStatus();
// responds "AI Status 1 = 10, AO Status 1 = 1000000000010, AO Status 2 = 0, readAI_FIFO_Empty_St = 0"
board->Interrupt_A_Enable.setAI_Error_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_FIFO_Interrupt_Enable(0); //was 0
board->Interrupt_A_Enable.setAI_SC_TC_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_START1_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_START2_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_START_Interrupt_Enable(0);
board->Interrupt_A_Enable.setAI_STOP_Interrupt_Enable(0);
board->Interrupt_A_Enable.flush();
board->Interrupt_B_Enable.setAO_BC_TC_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_START1_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_UPDATE_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_START_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_STOP_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_Error_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_UC_TC_Interrupt_Enable(0);
board->Interrupt_B_Enable.setAO_FIFO_Interrupt_Enable(0);
board->Interrupt_B_Enable.setG1_TC_Interrupt_Enable(0);
board->Interrupt_B_Enable.setG1_Gate_Interrupt_Enable(0);
board->Interrupt_B_Enable.setPass_Thru_1_Interrupt_Enable(0);
board->Interrupt_B_Enable.flush();
InterruptStatus();
// responds "AI Status 1 = 10, AO Status 1 = 1000000000010, AO Status 2 = 0, readAI_FIFO_Empty_St = 0"
aiClearFifo(board);
board->Interrupt_Control.setInterrupt_Group_A_Enable(0);
board->Interrupt_Control.setInterrupt_Group_B_Enable(0);
board->Interrupt_Control.flush();
InterruptStatus();
// responds "AI Status 1 = 1000000000000, AO Status 1 = 1000000000010, AO Status 2 = 0, readAI_FIFO_Empty_St = 1"
board->Interrupt_A_Ack.setAI_Error_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_SC_TC_Error_Confirm(1);
board->Interrupt_A_Ack.setAI_SC_TC_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START1_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START2_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_START_Interrupt_Ack(1);
board->Interrupt_A_Ack.setAI_STOP_Interrupt_Ack(1);
board->Interrupt_A_Ack.flush();
board->Interrupt_B_Ack.setAO_Error_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_STOP_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_START_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_UPDATE_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_START1_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_BC_TC_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_UC_TC_Interrupt_Ack(1);
board->Interrupt_B_Ack.setAO_STOP_Interrupt_Ack(1);
board->Interrupt_B_Ack.flush();
InterruptStatus();
02-10-2006 12:02 AM
// responds "AI Status 1 = 1000000000000, AO Status 1 = 1000000000010, AO Status 2 = 0x0, readAI_FIFO_Empty_St = 1"
02-10-2006 03:53 AM
02-10-2006 10:59 PM
My polling frequency was 0.1 Hz. I believe I found my problem, which I probably should have picked up sooner because of the code you supplied earlier. I set:
board->Interrupt_A_Enable.setAI_FIFO_Interrupt_Enable(1);
and
board->Interrupt_A_Enable.setAI_STOP_Interrupt_Enable(0);
I thought the FIFO would interrupt whenever the FIFO was not empty, but it appears to be the opposite. When I instead enable the STOP interrupt, everything works normally. Is this true or do you think there is some subtle mistake somewhere else? Thanks.