DDS Function Generator Embedded C Code

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 4

Embedded C code

#include <avr/io.h> // Include AVR IO definitions


#include <stdint.h> // Include standard integer definitions
#include <stdlib.h> // Include standard library definitions
#include <util/delay.h> // Include delay utilities

// Define pins for DATA, SCLK, and FSYNC


#define DATA 3
#define CLK 5
#define FSYNC 2

// Declare a global variable to store the frequency


float _freq;

// Define an enumeration for different waveform modes


typedef enum mode
{
MODE_SINE, // Sine wave mode
MODE_SQUARE, // Square wave mode
MODE_TRIANGLE, // Triangle wave mode
} mode_t;

// Function to write 16-bit data to the AD9833


void AD_write16(uint16_t data)
{
PORTB &= ~(1<<FSYNC); // Pull FSYNC low to start communication
SPDR = (data>>8); // Send the high byte
while (!(SPSR & (1<<SPIF))) ; // Wait for transmission complete, checks
status of SPIF
SPDR = (data & 0xFF); // Send the low byte
while (!(SPSR & (1<<SPIF))) ; // Wait for transmission complete
PORTB |= (1<<FSYNC); // Pull FSYNC high to end communication
}

// Function to set the frequency of the AD9833


void AD_setFrequency(float freq)
{
_freq = freq; // Store the frequency in the global variable
uint32_t _regFreq = freq * 10.73742 + 0.5; // Calculate register value
for frequency
AD_write16(0x4000 | (uint16_t)(_regFreq & 0x3FFF)); // Write lower 14
bits of frequency
AD_write16(0x4000 | (uint16_t)((_regFreq >> 14) & 0x3FFF)); // Write
upper 14 bits of frequency
}

// Function to get the current frequency


const float AD_getFrequency()
{
return _freq; // Return the stored frequency
}

// Function to set the phase of the AD9833


void AD_setPhase(uint16_t phase)
{
uint32_t _regPhase = (51.2 * phase) / 45 + 0.5; // Calculate register
value for phase
Embedded C code
AD_write16(0xC000 | (uint16_t)(_regPhase & 0xFFF)); // Write phase
register
}

// Function to set the waveform mode of the AD9833


void AD_setMode(mode_t mode)
{
switch (mode)
{
case MODE_SINE:
AD_write16(0x2000); // Set to sine wave mode
break;
case MODE_SQUARE:
AD_write16(0x2028); // Set to square wave mode
break;
case MODE_TRIANGLE:
AD_write16(0x2002); // Set to triangle wave mode
break;
}
}

// Function to initialize the AD9833


void AD_init(void)
{
DDRB = (1<<DATA) | (1<<CLK) | (1<<FSYNC); // Set DATA, CLK, FSYNC as
outputs
PORTB &= ~(1<<CLK); // Set CLK low
PORTB |= (1<<FSYNC); // Set FSYNC high
SPCR = 0x59; // Set SPI control register
AD_write16(0x2100); // Reset AD9833
AD_setFrequency(1000); // Set initial frequency to 1000 Hz
AD_setPhase(0); // Set initial phase to 0
AD_write16(0x2000); // Set mode to sine wave
AD_setMode(MODE_SINE); // Set mode to sine wave
}

// Function to send a command to the LCD


void lcd_command(unsigned char cmnd)
{
PORTD = cmnd; // Send command to PORTD
PORTB &= ~(1<<PB0); // RS = 0 for command
PORTB |= (1<<PB1); // Enable pulse
_delay_us(1); // Delay
PORTB &= ~(1<<PB1); // Disable pulse
_delay_us(100); // Delay
}

// Function to send data to the LCD


void lcd_data(unsigned char data)
{
PORTD = data; // Send data to PORTD
PORTB |= (1<<PB0); // RS = 1 for data
PORTB |= (1<<PB1); // Enable pulse
_delay_us(1); // Delay
PORTB &= ~(1<<PB1); // Disable pulse
_delay_us(100); // Delay
}
Embedded C code

// Function to initialize the LCD


void lcd_init()
{
DDRD = 0xFF; // Set PORTD as output
DDRB |= 0x03; // Set PB0 and PB1 as output
PORTB &= ~(1<<PB1); // Set enable low
_delay_us(2000); // Delay for LCD to power up
lcd_command(0x38); // Function set: 8-bit, 2 line, 5x8 dots
lcd_command(0x0C); // Display on, cursor off
lcd_command(0x01); // Clear display
_delay_us(2000); // Delay for command to execute
}

// Function to print a string on the LCD


void lcd_print(char* StringPtr)
{
unsigned char i = 0;
while (StringPtr[i] != 0)
{
lcd_data(StringPtr[i]); // Send each character to LCD
i++;
}
}

// Main function
int main(void)
{
DDRC &= ~(0x38); // Set PC3, PC4, PC5 as input
AD_init(); // Initialize AD9833
lcd_init(); // Initialize LCD
_delay_ms(1000); // Delay for LCD to stabilize
int x = 0; // Mode switch variable
float freq_val = 0; // Variable to store frequency value
char str_temp[10]; // Temporary string buffer

while (1)
{
freq_val = AD_getFrequency(); // Get current frequency
if ((freq_val > 100) && (freq_val < 100000))
{
if (PINC & (1<<PC5)) // Check if PC5 is pressed
{
AD_setFrequency(freq_val + 100); // Increase frequency by 100
Hz
}
if (PINC & (1<<PC4)) // Check if PC4 is pressed
{
AD_setFrequency(freq_val - 100); // Decrease frequency by 100
Hz
}
}

lcd_command(0x02); // Move cursor to home position


_delay_ms(500); // Delay for stability
lcd_print("FREQ="); // Print "FREQ=" on LCD
dtostrf(freq_val, 10, 1, str_temp); // Convert frequency to string
Embedded C code
lcd_print(str_temp); // Print frequency value on LCD

if (PINC & (1<<PC3)) // Check if PC3 is pressed


{
x += 1; // Increment mode switch variable
switch (x)
{
case 1:
AD_setMode(MODE_TRIANGLE); // Set to triangle wave mode
lcd_command(0xC0); // Move to second line
lcd_print("TRIANGLEWAVE"); // Print "TRIANGLEWAVE" on LCD
break;
case 2:
AD_setMode(MODE_SINE); // Set to sine wave mode
lcd_command(0xC0); // Move to second line
lcd_print("SINE "); // Print "SINE" on LCD
break;
case 3:
AD_setMode(MODE_SQUARE); // Set to square wave mode
lcd_command(0xC0); // Move to second line
lcd_print("SQUARE "); // Print "SQUARE" on LCD
x = 0; // Reset mode switch variable
break;
}
}
}

return 0;
}

You might also like