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

📄 dac1_fgen1.c

📁 用C8051F单片机的DAC作函数发生器
💻 C
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// 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 + -