📄 dac1_fgen1.c
字号:
//-----------------------------------------------------------------------------
// DAC1_fgen1.c
//-----------------------------------------------------------------------------
//
// AUTH: BW,FB
// DATE: 2 OCT 01
//
// Target: C8051F02x
// Tool chain: KEIL C51
//
// Description:
// Example source code which outputs waveforms on DAC1. DAC1's output is
// scheduled to update at a rate determined by the constant
// <SAMPLE_RATE_DAC>, managed and timed by Timer4.
//
// Implements a 256-entry full-cycle sine table of 16-bit precision. Other
// waveforms supported are square, triangle, and saw tooth.
//
// The output frequency is determined by a 16-bit phase adder.
// At each DAC update cycle, the phase adder value is added to a running
// phase accumulator, <phase_accumulator>, the upper bits of which are used
// to access the sine lookup table.
//
// The program is controlled through UART using HyperTerminal running on a
// PC. All commands are two characters in length and have optional
// frequency and amplitude arguments. Note that the amplitude parameter
// cannot be specified unless the frequency is also specified.
//
// Command Format:
//
// XX [frequency] [amplitude]
//
// where XX denotes the command
//
// Command List:
//
// SQ - Square Wave
// SI - Sine Wave
// TR - Triangle Wave
// SA - Saw Tooth Wave
// OF - Output OFF
// ?? - Help
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f020.h> // SFR declarations
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F02x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 TMR3RL = 0x92; // Timer3 reload value
sfr16 TMR3 = 0x94; // Timer3 counter
sfr16 ADC0 = 0xbe; // ADC0 data
sfr16 ADC0GT = 0xc4; // ADC0 greater than window
sfr16 ADC0LT = 0xc6; // ADC0 less than window
sfr16 RCAP2 = 0xca; // Timer2 capture/reload
sfr16 T2 = 0xcc; // Timer2
sfr16 RCAP4 = 0xe4; // Timer4 capture/reload
sfr16 T4 = 0xf4; // Timer4
sfr16 DAC0 = 0xd2; // DAC0 data
sfr16 DAC1 = 0xd5; // DAC1 data
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void main (void);
void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void Timer4_Init (int counts);
void Timer4_ISR (void);
long pow(int x, int y);
void Print_Command_List(void);
void Sine(void);
void Square(void);
void Triangle(void);
void Saw(void);
void Off(void);
void Help(void);
void Error(void);
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 22118400 // SYSCLK frequency in Hz
#define BAUDRATE 9600 // Baud rate of UART in bps
#define SAMPLE_RATE_DAC 80000L // DAC sampling rate in Hz
#define PHASE_PRECISION 65536 // range of phase accumulator
#define command_length 2 // command length is 2 characters
#define command_size 3 // command size is 3 bytes
typedef struct Command_Table_Type { // when a command is entered, it is
char command[command_size]; // compared to the command field of
void (*function_ptr)(void); // of the table. If there is a match
}Command_Table_Type; // then the the function located at
// function_ptr will be executed
typedef enum Waveform { // the different possible output
SQUARE, // waveforms
SINE,
TRIANGLE,
SAW,
OFF
}Waveform;
typedef union lng { // access a long variable as two
long Long; // 16-bit integer values
int Int[2];
} lng;
//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
unsigned long frequency = 1000; // frequency of output in Hz,
// defaults to 1000 Hz
unsigned int phase_add = 1000 * PHASE_PRECISION / SAMPLE_RATE_DAC;
unsigned int amplitude = 100 * 655; // 655 is a scaling factor
// see the Timer 4 ISR
Waveform output_waveform = OFF;
char input_str[16]= "";
#define num_commands 6
Command_Table_Type code function_table[num_commands + 1] = {
{"SQ", Square},
{"SI", Sine},
{"TR", Triangle},
{"SA", Saw},
{"OF", Off},
{"??", Help},
{"", Error}
};
// a full cycle, 16-bit, 2's complement sine wave lookup table
int code SINE_TABLE[256] = {
0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2,
0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6,
0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504,
0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3,
0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6,
0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d,
0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c,
0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24,
0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4,
0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de,
0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b,
0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324,
0x0000, 0xfcdc, 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e,
0xe708, 0xe3f5, 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef,
0xcf05, 0xcc22, 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86,
0xb8e4, 0xb64c, 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be,
0xa57e, 0xa34c, 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a,
0x9593, 0x93dc, 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc,
0x89bf, 0x8894, 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d,
0x8276, 0x81e3, 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a,
0x8000, 0x800a, 0x8028, 0x8059, 0x809e, 0x80f7, 0x8163, 0x81e3,
0x8276, 0x831d, 0x83d7, 0x84a3, 0x8583, 0x8676, 0x877c, 0x8894,
0x89bf, 0x8afc, 0x8c4b, 0x8dab, 0x8f1e, 0x90a1, 0x9236, 0x93dc,
0x9593, 0x975a, 0x9931, 0x9b18, 0x9d0e, 0x9f14, 0xa129, 0xa34c,
0xa57e, 0xa7be, 0xaa0b, 0xac65, 0xaecd, 0xb141, 0xb3c1, 0xb64c,
0xb8e4, 0xbb86, 0xbe32, 0xc0e9, 0xc3aa, 0xc674, 0xc946, 0xcc22,
0xcf05, 0xd1ef, 0xd4e1, 0xd7da, 0xdad8, 0xdddd, 0xe0e7, 0xe3f5,
0xe708, 0xea1e, 0xed38, 0xf055, 0xf375, 0xf696, 0xf9b9, 0xfcdc,
};
code char string0[] = "\n\n*** OUTPUT IS NOW A ";
code char string1[] = "\n\n----------------------------------\n\n";
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void) {
char i; // counting variable
char* arg_ptr1; // pointers to command line parameters
char* arg_ptr2;
long temp_frequency; // used to hold the values input from the
int temp_amplitude; // keyboard while they are error checked
int printed_amplitude = 100; // a separate copy of amplitude because
// temp_amplitude is written over
void (*f)(void); // function pointer used to call the proper
// function from the command table
WDTCN = 0xde; // Disable watchdog timer
WDTCN = 0xad;
SYSCLK_Init ();
PORT_Init ();
// initializations for wave generation
REF0CN = 0x03; // enable internal VREF generator
DAC1CN = 0x97; // enable DAC1 in left-justified mode
Timer4_Init(SYSCLK/SAMPLE_RATE_DAC);
// using Timer4 as update scheduler
// initialize T4 to update DAC1
// after (SYSCLK cycles)/sample have
// passed.
// initialization for command input
UART0_Init ();
EA = 1; // Enable global interrupts
Print_Command_List();
while(1){
// get user input
printf ("ENTER A COMMAND:>");
gets(input_str,sizeof(input_str)); // wait for input
input_str[0] = toupper(input_str[0]); // convert the two characters
input_str[1] = toupper(input_str[1]); // in the command to uppercase
// Parse the command
for (i = 0; i < num_commands; i++){
// strncmp() returns 0 if the first two arguments are the same string
// set <i> for the command that matched
if (0 == strncmp(input_str, function_table[i].command, command_length)){
arg_ptr1 = strchr (input_str, ' ');
arg_ptr1++; // point to the frequency
arg_ptr2 = strchr(arg_ptr1, ' ');
arg_ptr2++; // point to amplitude
temp_frequency = atol(arg_ptr1);
temp_amplitude = atol(arg_ptr2);
// check to make sure entered frequency is valid
if (temp_frequency) {
frequency = temp_frequency;
} else {
printf("\n** Frequency will not change\n");
}
// check to make sure entered amplitude is valid
if ((temp_amplitude > 0) && (temp_amplitude <=100)){
// multiply by 655 to be divided by 65535 (16-bit shift) in the
// ISR; this is an optimization to reduce the number of
// instructions executed in the ISR
amplitude = temp_amplitude * 655;
printed_amplitude = temp_amplitude;
} else {
printf("\n** Amplitude will not change\n");
}
printf("\nFREQUENCY: %ld Hz", frequency);
printf("\nAMPLITUDE: %d %% of VREF/2", printed_amplitude);
EA = 0; // Disable Interrupts to avoid
// contention between the ISR
// and the following code.
// set the frequency
phase_add = frequency * PHASE_PRECISION / SAMPLE_RATE_DAC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -