⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dualdma.c

📁 rt采集卡dos下dm6430驱动源代码
💻 C
字号:
/***************************************************************************

	FILE NAME: DUALDMA.C

	FILE DESCRIPTION: DUALDMA (Direct Memory Acces with the PC's DMA chip)

	 Sample program that demonstrates how to use dual DMA transfers.

	 This program transfers data using two DMA channels. When the first DMA
	 buffer is full, the board will automatically switch to the second DMA
	 buffer and continue acquiring data. The program then writes the first
	 buffer to a file. When the second buffer is full, the board switches
	 back to the first and the program writes the second buffer to the file.
	 Since the DMA controller is programmed for autoinitialize, the data
	 acquisition continues with no gaps.

	 1. Make two DMA buffers.
	 2. Program DMA controller.
	 3  Set up board pacer clock,channel,gain,triggers and dual DMA.
	 4. Program the interrupt controller to interrupt on DMA done.
	 5. On DMA done write Buffer to disk.

	PROJECT NAME: DUALDMA (Part of DM6430 DOS Driver)

	DRIVER VERSION: 1.1

	COMPILER: Borland C++ 3.1

	TARGET: Real-Mode DOS

	Copyright 2003 RTD Embedded Technologies

***************************************************************************/
#include <alloc.h>
#include <conio.h>
#include <dos.h>
#include <mem.h>
#include <stdio.h>
#include "drvr6430.h"
#include "dio5812.h"
#include "dmautil.h"
#include "pcutil.h"
#include "vgraph.h"

/***************************************************************************
	Defines

	Change these constants to alter the program parameters.
****************************************************************************/

#define DMA_BUF_SIZE   10000l	   		// The size of the DMA buffer (32768 max).
#define BASE_ADDRESS   768             // Base address.


#define CHANNEL         0              // A/D channel.
#define GAIN            0              // Gain.
#define SE_DIFF         0              // Single ended.
#define RATE     100000.0              // Sampling rate.
#define ADDMAChannel1   6              // First DMA Channel.
#define ADDMAChannel2   7              // Second DMA Channel.
#define IRQ_CHANNEL    10              // IRQ Channel.

// To set DMA Mode Register
#define MODE_REGISTER (DMA_AUTOINITIALIZATION | DMA_DEMAND_TRANSFER | DMA_WRITE | DMA_INCREMENT_COUNTER)


volatile int Transfers = 0;
volatile Error = 0, Busy = 0;
volatile int i = 0;
unsigned long NumberofBytes;
int far * DMAPtr1;
int far * DMAPtr2;
unsigned int DMAPage[2], DMAPageOffset[2];




/****************************************************************************
  NewISR()

  The NewISR function is called whenever an interrupt is generated on the
  specified IRQ. It simply checks the busy flag to see if the last transfer
  was completed, swaps the buffers to transfer to disk, increments the
  "Transfers" variable and clears the DMA done flag.

  Do not try to access any functions that use DOS calls (disk access, screen
  writes, read keyboard, etc) and do not use floating point operations in
  this function. DOS and the Floating Point Emulator are not reentrant and
  will cause unexpected happenings if used inside an interrupt.

  Before exiting the function passes the End of Interrupt (EOI) command
  to the 8259 interrupt controller. Don't forget the EOI command; it is
  required even if your ISR does nothing.
****************************************************************************/

#ifdef __cplusplus
 void interrupt NewISR(...)            // C++ style interrupt function.
#else
 void interrupt NewISR(void)           // C style interrupt function.
#endif
{
	if (Busy == 1) Error = 1;           // Make sure write to disk is done
	if (i == 0)                         // before switching DMA buffer pointer.
		i = 1;
	else
		i = 0;
	Transfers++;
	ClearADDMADone6430();               // Clear Board DMA done
	ClearIRQ16430();							// Clear IRQ on DM6430.
	EndOfIT(IRQ_CHANNEL);               // VERY IMPORTANT !!! Clear interrupt

}




/***************************************************************************
	SetProgramScreen()

	The SetProgramScreen() function initializes the screen.
****************************************************************************/

void SetProgramScreen(void)
{
	clrscr();

	// Print header and footer.
	gotoxy(1,1);   cprintf(TitleString6430());
	gotoxy(50, 1); cprintf("DMA Example");
	gotoxy(1, 25); cprintf("Press enter key to start. . .   ");

	gotoxy(30, 8); cprintf("Transfers =");
} //SetProgramScreen




int main(void){

	FILE* DataFile;
	unsigned long ClockRate;
	int Test;
	float Range;
	float Slope;
	unsigned NumberOfPoints;
	unsigned long NumberofBytes;
	double Actual_PACER_RATE;

	clrscr();

	NumberofBytes = (long)(DMA_BUF_SIZE) * 2L;

	// Allocating first memory buffer for DMA.
	DMAPtr1 = allocdmabuffer(NumberofBytes, ADDMAChannel1, &DMAPage[0], &DMAPageOffset[0]);
	if (DMAPtr1 == NULL)  {
		cprintf("Buffer 1 allocation has failed.");
		getch();
		return 1;
	} //if
	_fmemset(DMAPtr1, 0x00, NumberofBytes );		// Set buffer to all 0.

	// Allocating second memory buffer for DMA.
	DMAPtr2 = allocdmabuffer(NumberofBytes, ADDMAChannel2, &DMAPage[1], &DMAPageOffset[1]);
	if (DMAPtr2 == NULL)  {
		cprintf("Buffer 2 allocation has failed.");
		getch();
		return 1;
	} //if
	_fmemset(DMAPtr2, 0x00, NumberofBytes );		// Set buffer to all 0.

	SetProgramScreen();
	Test = 0;

	SetBaseAddress(BASE_ADDRESS);       // Set BaseAddress

	InitBoard6430();                    // Initialize board.
	Actual_PACER_RATE = SetPacerClock6430(RATE);	// Program the pacer clock.
	SetChannelGain6430(CHANNEL, GAIN, SE_DIFF); // Set channel and gain.
	SetTriggerRepeat6430(0);            // Single Cycle.
	SetStartTrigger6430(0);             // Start Trigger = Software.
	SetStopTrigger6430(0);              // Stop Trigger = Software.
	SetConversionSelect6430(1);         // Conversion = Pacer Clock.

		// Set up data file and write header.
	ClockRate = Actual_PACER_RATE;	// Clock rate.
	Range = 20;								// A/D input range.
	Slope = (20.0/65536.0);				// A/D volt per bit.
	NumberOfPoints = DMA_BUF_SIZE;	// Number of samples in 1 buffer.
	DataFile = fopen("DUALDMA.DAT", "wb");		// Open data file.
	fwrite(&ClockRate, sizeof(ClockRate), 1, DataFile);
	fwrite(&Range, sizeof(Range), 1, DataFile);
	fwrite(&Slope, sizeof(Slope), 1, DataFile);
	fwrite(&NumberOfPoints, sizeof(NumberOfPoints), 1, DataFile);


	DisableDMA(ADDMAChannel1);           // Disable DMA channel in CPU.
	DisableDMA(ADDMAChannel2);           // Disable DMA channel in CPU.
	SetADDMA6430(ADDMAChannel1, ADDMAChannel2);  // Program the board for dual DMA.
	SetDMAController(ADDMAChannel1, MODE_REGISTER, DMAPage[0], DMAPageOffset[0], NumberofBytes);  // Set DMA Controller.
	SetDMAController(ADDMAChannel2, MODE_REGISTER, DMAPage[1], DMAPageOffset[1], NumberofBytes);  // Set DMA Controller.

	SetIRQ16430(5, IRQ_CHANNEL);        // Set Board IRQ1 Source = DMA Done.
													// Set IRQ Channel.
	ClearIRQ16430();							// Clear IRQ on DM6430.
	InitHostIT(NewISR,IRQ_CHANNEL);     // Set the Interrupt Service Routine.
	ClearADFIFO6430();                  // Clear FIFO.
	EnableDMA(ADDMAChannel1);           // Enable DMA in CPU.
	EnableDMA(ADDMAChannel2);           // Enable DMA in CPU.

	getch();
	gotoxy(1, 25); cprintf("Press enter key to stop. . .   ");

	StartConversion6430();              // Start the measurement.

	while (!kbhit()){
		if (Error == 1){                 // Check error flag.
			cprintf("Buffer Overflow %d",Transfers);
			goto exiterror;
		}
		if (Test != Transfers){				// If interrupted, write to disk.
			Busy = 1;							// Set busy flag.
			if (i==0){
				fwrite(DMAPtr2, sizeof(int), NumberOfPoints, DataFile);
			}
			else{
				fwrite(DMAPtr1, sizeof(int), NumberOfPoints, DataFile);
			}
			Test ++;								// Increment "Test" variable.
			gotoxy(45,8); cprintf("%d",Transfers);
			Busy = 0;							// Reset busy flag.
		}
	}
	getch();
exiterror:

	gotoxy(1, 25); cprintf("Press enter key to graph. . .   ");
	DisableDMA(ADDMAChannel1);           // Disable DMA channel in CPU.
	DisableDMA(ADDMAChannel2);           // Disable DMA channel in CPU.
	ClearADDMADone6430();                // Clear DMA done flag on board.
	RestoreHostIT(IRQ_CHANNEL);          // Restores the IT vector and disable.
	SetIRQ16430(0,0);				          // Disable board IRQ.
	fclose(DataFile);                    // Close Data file.
	freedmabuffer(DMAPtr1);              // free DMA Buffer 1.
	freedmabuffer(DMAPtr2);              // free DMA Buffer 2.
	getch();
	vgraph("DUALDMA.DAT");               // Graph data.
	clrscr();                            // Clear screen.
	return 0;
} //main

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -