📄 waves.c
字号:
/***************************************************************************
FILE NAME: WAVES.C
FILE DESCRIPTION: WAVES (Waveform Generator)
Sample program that demonstrates how to generate and send waveforms
to the analog output using interrupts.
This program generates waveforms on the analog output.
The program works by creating a lookup table that contains a digitized
version of a selected waveform (square, sine, ramp). The user timer
is configured to generate interrupts at precise intervals. Every time
an interrupt occurs a value is read from the lookup table and written
to the analog output, the index into the lookup table is incremented and
if it exceeds the length of the waveform it is reset to the beggining of
the table. This cycle repeats until a key is struck on the keyboard.
Users who are interested in using their DACs to generate waveforms should
examine the procedure used for building the lookup table. This procedures
allow the user to specify the maximum and minimum values as well as the
number of complete waveforms per second (rate) to be generated. For
square wave generation, the user can also specify the duty cycle (% high).
For further details see the comments just prior to the BuildSquareWave
part of the procedure.
PROJECT NAME: WAVES (Part of DM6430 DOS Driver)
DRIVER VERSION: 1.1
COMPILER: Borland C++ 3.1
TARGET: Real-Mode DOS
Copyright 2003 RTD Embedded Technologies
***************************************************************************/
#include <conio.h>
#include <dos.h>
#include <math.h>
#include "drvr6430.h"
#include "dio5812.h"
#include "pcutil.h"
/***************************************************************************
Defines
Change these constants to alter the program parameters.
****************************************************************************/
#define BASE_ADDRESS 768 // Base address of DM6430.
#define IRQ_CHANNEL 10 // Interrupt channel.
#define DAC_SLOPE (65536.0/20.0) // Number Bits divided by DAC Range.
#define DAC_OFFSET 0 // Offset of the output line signal.
#define RATE 1000 // Clock rate in 'Hz'.
#define SQUARE_WAVE 1 // For BuildWaveForm().
#define SINE_WAVE 2
#define RAMP_WAVE 3
#define PI 3.14159
// Global definitions
//--------------------
typedef struct WaveStructure // Structure for waves
{
int WaveLength;
int WaveArray[5000];
};
struct WaveStructure WaveForm; // Store built wave
unsigned int WCnt; // Wave counter
/***************************************************************************
NewISR()
The NewISR() function is called whenever an interrupt is generated on the
specified IRQ. It outputs a value from the wave array to the DAC then
increments the index WI. If WI exceeds the size of the wave array it
is reset to zero.
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
{
LoadDAC6430(WaveForm.WaveArray[WCnt]); // Send analog output data
if (++WCnt >= WaveForm.WaveLength){ // If wave data ends it sets
WCnt = 0; // the wave counter to 0 again
}
ClearIRQ16430(); // Clear IRQ on DM6430.
EndOfIT(IRQ_CHANNEL); // VERY IMPORTANT !!!
// 'End of Interrupt' command.
} //NewISR
/*****************************************************************************
BuildWaveForm()
The BuildWaveForm() function builds DAC lookup table. The type of the wave-
form depends on the 'WaveType' variable. For maximum efficiency, a digitized
version of a waveform is calculated once at the beginning of the program and
stored in an array.
*****************************************************************************/
void BuildWaveForm( struct WaveStructure *Wave, unsigned int WaveType,
float High, float Low, float WaveRate, int OnDuty)
// 'Wave' points to the data structure to fill.
// 'WaveType' determines the type of the waveform: Square, Sine or Ramp.
// 'High' is the maximum values of the waveform in [V].
// 'Low' is the minimum values of the waveform in [V].
// 'WaveRate' defines the frequency of the waveform in [Hz].
// 'OnDuty' defines the percent of square wave when it is high.
{
int i, j;
unsigned int DigitalHigh;
unsigned int DigitalLow;
gotoxy(10, 12);
switch (WaveType) {
case SQUARE_WAVE: {
cprintf("Building square waveform, please be patient.");
DigitalHigh = (High * DAC_SLOPE) + DAC_OFFSET;
DigitalLow = (Low * DAC_SLOPE) + DAC_OFFSET;
Wave->WaveLength = RATE / WaveRate;
j = Wave->WaveLength * (OnDuty / 100.0);
for (i = 0; i < j; i++) // Generating the High level
Wave->WaveArray[i] = DigitalHigh;
for (i = j; i < Wave->WaveLength; i++) // Generating the Low level
Wave->WaveArray[i] = DigitalLow;
break;
} //case: BuildSquareWave
case SINE_WAVE: {
unsigned int WaveOffset; // Offset of the sine wave
unsigned int PeakHeight; // Amplitude of the sine wave
cprintf("Building sine waveform, please be patient.");
PeakHeight = ( fabs(High - Low) / 2) * DAC_SLOPE;
WaveOffset = ( fabs(High + Low) / 2) * DAC_SLOPE + DAC_OFFSET;
Wave->WaveLength = RATE / WaveRate;
for (i = 0; i < Wave->WaveLength; i++) { // Building waveform
Wave->WaveArray[i] = PeakHeight *
sin((i * 2 * PI) / Wave->WaveLength) +
WaveOffset;
} //for
break;
} //case: BuildSineWave
case RAMP_WAVE: {
unsigned int PeakToPeak; // Size of Ramp
cprintf("Building ramp waveform, please be patient.");
DigitalHigh = ( High * DAC_SLOPE) + DAC_OFFSET;
DigitalLow = ( Low * DAC_SLOPE) + DAC_OFFSET;
PeakToPeak = DigitalHigh - DigitalLow;
Wave->WaveLength = RATE / WaveRate;
for (i = 0; i < Wave->WaveLength; i++) // Build a single ramp
Wave->WaveArray[i] = DigitalLow + i *
(PeakToPeak / Wave->WaveLength);
break;
} //case: BuildRampWave
} //switch
gotoxy(1,12); clreol();
} //BuildWaveForm
/***************************************************************************
SetProgramScreen()
The SetProgramScreen() function initializes the screen.
****************************************************************************/
void SetProgramScreen(void)
{
clrscr();
// Print header and footer.
gotoxy( 1, 1); cprintf(TitleString6430());
gotoxy(40, 1); cprintf("Generating Waveforms on Analog Output");
gotoxy( 1,25); cprintf("Press any key to exit. . .");
window(1, 3, 80, 23);
gotoxy(15, 8); cprintf("Output DAC Channel : ");
} //SetProgramScreen
int main(void)
{
float ActualRate0; // Actual clock rate returned from timer 0.
SetProgramScreen();
BuildWaveForm(&WaveForm, // Stores wave
SINE_WAVE, // Type (Square/Sine/Ramp)
5.0, -5.0, // Max and min values in [V]
10, // Frequency in [Hz]
50); // Percentage of High (only for Square)
WCnt = 0; // Clear wave counter.
SetBaseAddress(BASE_ADDRESS); // Set board base address.
InitBoard6430(); // Initialize board.
ActualRate0 = SetUserClock6430(0, 8000000.0, 20000.0); // Initialize User Clock0.
SetUserClock6430(1, ActualRate0, RATE); // Initialize User Clock1.
SetIRQ16430(13,IRQ_CHANNEL); // Set Board IRQ1 Source User TC out 1
// Set IRQ Channel
InitHostIT(NewISR,IRQ_CHANNEL); // Set the Interrupt Service Routine
// and enable the appropriate IRQ
// channel.
ClearIRQ16430(); // Clear IRQ on DM6430.
while ( !kbhit() ) { // Run until any key pressed.
gotoxy(37, 8); cprintf("%8d ", WaveForm.WaveArray[WCnt]);
// Display the current wave data.
} //while
getch(); // Get the pressed character.
SetIRQ16430(13,0); // Disable board interrupt.
RestoreHostIT(IRQ_CHANNEL); // Restores the IT vector and disable
// the appropriate IRQ channel.
DoneTimer6430(); // Reset timer.
window(1,1,80,25); // Reset original screen coordinates,
clrscr(); // and clear the screen.
return 0;
} //main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -