📄 dmastrm.c
字号:
/***************************************************************************
FILE NAME: DMASTRM.C
FILE DESCRIPTION: DMASTRM (Direct Memory Acces with the PC's DMA chip)
Sample program that demonstrates how to use DMA transfer.
This program stores acquired data into a buffer at a designated rate
using DMA transfers. When the requested number of samples have been
transferred to the buffer, the data will be graphed on the screen.
PROJECT NAME: DMASTRM (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 ADDMAChannel 7 // DMA Channel.
#define IRQ_CHANNEL 10 // IRQ Channel.
// To set DMA Mode Register
#define MODE_REGISTER (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
ClearADDMADone6430();
if(i==0){
i = 1;
SetDMAController(ADDMAChannel, MODE_REGISTER, DMAPage[i], DMAPageOffset[i], NumberofBytes); // Set DMA Controller.
}
else{
i = 0;
SetDMAController(ADDMAChannel, MODE_REGISTER, DMAPage[i], DMAPageOffset[i], NumberofBytes); // Set DMA Controller.
}
EnableDMA(ADDMAChannel); // Enable DMA.
Transfers++;
ClearIRQ16430(); // Clear IRQ on DM6430.
EndOfIT(IRQ_CHANNEL); // VERY IMPORTANT !!!
}
/***************************************************************************
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;
double Actual_PACER_RATE;
clrscr();
NumberofBytes = (long)(DMA_BUF_SIZE) * 2L;
// Allocating first memory buffer for DMA.
DMAPtr1 = allocdmabuffer(NumberofBytes, ADDMAChannel, &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, ADDMAChannel, &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("DMASTRM.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);
SetADDMA6430(ADDMAChannel, 0); // Program the board for DMA.
SetDMAController(ADDMAChannel, MODE_REGISTER, DMAPage[0], DMAPageOffset[0], NumberofBytes); // Set DMA Controller.
SetIRQ16430(5, IRQ_CHANNEL); // Set Board IRQ1 Source = DMA Done.
ClearIRQ16430(); // Clear IRQ on DM6430.
InitHostIT(NewISR,IRQ_CHANNEL); // Set the Interrupt Service Routine.
// Set IRQ Channel.
ClearADFIFO6430(); // Clear FIFO.
EnableDMA(ADDMAChannel); // 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(ADDMAChannel); // 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("DMASTRM.DAT"); // Graph data.
clrscr(); // Clear screen.
return 0;
} //main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -