基于51单片机的单电源DDS函数信号发生器proteus仿真原理图PCB

功能:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶显示当前输出波形类型和频率
2.可通过按键调整输出波形类型和频率
3.可通过按键设置频率更改步进值
4.支持正弦波/方波/三角波/锯齿波输出,输出频率范围:10~100Hz
5.采用DC002作为电源接口可直接输入5V给整个系统供电

原理图:
在这里插入图片描述

PCB :
在这里插入图片描述

主程序:

#include <reg52.h> //包含头文件
#include <intrins.h>
#define uchar unsigned char //宏定义
#define uint unsigned int

sbit KEY_ADD = P2^1; //定义按键的接口
sbit KEY_SUB = P2^3;
sbit KEY_MODE = P2^2;
sbit KEY_SET = P2^0;

sbit LED_ZIGZAG = P3^2;
sbit LED_TRIANGLE = P3^3;
sbit LED_SQUARE = P3^5;
sbit LED_SINE = P3^4;

sbit LCD_RS = P3^6; //液晶控制位
sbit LCD_EN = P3^7;

char g_wave;
char g_cnt; //定义全局变量
int g_freq = 100; //*0.1Hz
int g_step = 1;
int g_stepDisp = 1;
uchar code g_table_num[] = "0123456789"; //定义显示的数组
uchar code g_table_str[] = "Freq:     Wave form:";
unsigned long T0CNT;
int T0RH;
int T0RL;
int g_mode;
unsigned char pwmValue = 50;
unsigned char outValue = 0;

//自定义字符
uchar code USER_CHAR[] = {
    0x0e, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x0e, 0x00, //正弦波	   0  1

    0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00,
    0x00, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, //矩形波	   2  3

    0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00, 0x00,
    0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, //三角波	   4  5

    0x00, 0x01, 0x03, 0x05, 0x09, 0x11, 0x00, 0x00, //锯齿波	   6
};
uchar code SINE_CHAR[64] = {
    135, 145, 158, 167, 176, 188, 199, 209, 218, 226, 234, 240, 245, 249, 252, 254, 254, 253, 251, 247, 243, 237, 230, 222, 213, 204, 193, 182, 170, 158,
    146, 133, 121, 108, 96, 84, 72, 61, 50, 41, 32, 24, 17, 11, 7, 3, 1, 0, 0, 2, 5, 9, 14, 20, 28, 36, 45, 55, 66, 78, 90, 102, 114, 128}; //正弦波取码

uchar code SQUARE_CHAR[64] = {
    255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //矩形波取码

uchar code TRIANGLE_CHAR[64] = {
    0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248,
    248, 240, 232, 224, 216, 208, 200, 192, 184, 176, 168, 160, 152, 144, 136, 128, 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0}; //三角波取码

uchar code ZIGZAG_CHAR[64] = {
    0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142,
    146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255}; //锯齿波取码

void DelayMs(uint t) //延时函数
{
    int i, j;
    for (i = t; i > 0; i--)
        for (j = 110; j > 0; j--)
            ;
}
void LCD_WriteCom(uchar com) //写命令函数
{
    LCD_RS = 0;
    P0 = com;
    DelayMs(1);
    LCD_EN = 1;
    DelayMs(1);
    LCD_EN = 0;
}

void LCD_WriteData(uchar dat) //写数据函数
{
    LCD_RS = 1;
    P0 = dat;
    DelayMs(1);
    LCD_EN = 1;
    DelayMs(1);
    LCD_EN = 0;
}

//自定义字符集
void LCD_RAM()
{
    uint i, j, k = 0, temp = 0x40;
    for (i = 0; i < 7; i++)
    {
        for (j = 0; j < 8; j++)
        {
            LCD_WriteCom(temp + j);
            LCD_WriteData(USER_CHAR[k]);
            k++;
        }
        temp = temp + 8;
    }
}

void Init_LCD() //初始化函数
{
    uchar i;
    LCD_EN = 0; //默认开始状态为关使能端,见时序图
    LCD_RAM();
    LCD_WriteCom(0x0f);
    LCD_WriteCom(0x38);       //显示模式设置,默认为0x38,不用变。
    LCD_WriteCom(0x01);       //显示清屏,将上次的内容清除,默认为0x01.
    LCD_WriteCom(0x0c);       //显示功能设置0x0f为开显示,显示光标,光标闪烁;0x0c为开显示,不显光标,光标不闪
    LCD_WriteCom(0x06);       //设置光标状态默认0x06,为读一个字符光标加1.
    LCD_WriteCom(0x80);       //设置初始化数据指针,是在读指令的操作里进行的
    for (i = 10; i < 20; i++) //显示初始化
    {
        LCD_WriteData(g_table_str[i]);
    }
    LCD_WriteCom(0x80 + 0x40);
    for (i = 0; i < 9; i++)
    {
        LCD_WriteData(g_table_str[i]);
    }
    LCD_WriteCom(0x80 + 10);
    LCD_WriteData(0);
    LCD_WriteData(1);
    LCD_WriteData(0);
    LCD_WriteData(1);
    LCD_WriteData(0);
    LCD_WriteData(1);
    LCD_WriteCom(0x80 + 0x40 + 0x09);
    LCD_WriteData(' ');
    LCD_WriteData('1');
    LCD_WriteData('0');
    LCD_WriteData('.');
    LCD_WriteData('0');
    LCD_WriteData('H');
    LCD_WriteData('z');
}
void Init_Timer() //时钟初始化
{
    TMOD = 0x01;
    TH0 = T0RH;
    TL0 = T0RL;
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}
void Display() //显示函数
{
    uchar kilobit, hundredbit, tenbit, unitbit;
    kilobit = g_freq / 1000;
    hundredbit = g_freq % 1000 / 100;
    tenbit = g_freq % 1000 % 100 / 10;
    unitbit = g_freq % 1000 % 100 % 10;
    LCD_WriteCom(0x80 + 0x40 + 0x09);

    if (kilobit == 0)
        LCD_WriteData(' ');
    else
        LCD_WriteData(g_table_num[kilobit]);
    if (kilobit == 0 && hundredbit == 0)
        LCD_WriteData(' ');
    else
        LCD_WriteData(g_table_num[hundredbit]);
    LCD_WriteData(g_table_num[tenbit]);
    LCD_WriteData('.');
    LCD_WriteData(g_table_num[unitbit]);
    LCD_WriteData('H');
    LCD_WriteData('z');
    if (g_wave == 0)
    {
        LCD_WriteCom(0x80 + 10);
        LCD_WriteData(0);
        LCD_WriteData(1);
        LCD_WriteData(0);
        LCD_WriteData(1);
        LCD_WriteData(0);
        LCD_WriteData(1);

    }
    if (g_wave == 1)
    {
        LCD_WriteCom(0x80 + 10);
        LCD_WriteData(2);
        LCD_WriteData(3);
        LCD_WriteData(2);
        LCD_WriteData(3);
        LCD_WriteData(2);
        LCD_WriteData(3);
    }

    if (g_wave == 2)
    {
        LCD_WriteCom(0x80 + 10);
        LCD_WriteData(4);
        LCD_WriteData(5);
        LCD_WriteData(4);
        LCD_WriteData(5);
        LCD_WriteData(4);
        LCD_WriteData(5);
    }
    if (g_wave == 3)
    {
        LCD_WriteCom(0x80 + 10);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
    }
}
void KeyScan() //键盘检测函数
{
    if (KEY_ADD == 0)
    {
        EA = 0;
        DelayMs(2);
        if (KEY_ADD == 0)
        {
            while (!KEY_ADD)
                ;
            g_freq += g_step;
            if (g_freq > 1000)
            {
                g_freq = 100;
            }
            Display();
            T0CNT = 65536 - (144000 / g_freq) + 25;
            T0RH = T0CNT / 256;
            T0RL = T0CNT % 256;
            EA = 1;
        }
    }
    if (KEY_SUB == 0)
    {

        DelayMs(5);
        if (KEY_SUB == 0)
        {
            EA = 0;
            while (!KEY_SUB)
                ;
            g_freq -= g_step;
            if (g_freq < 100)
            {
                g_freq = 1000;
            }
            Display();
            T0CNT = 65536 - (144000 / g_freq) + 25;
            T0RH = T0CNT / 256;
            T0RL = T0CNT % 256;
            EA = 1;
        }
    }
    if (KEY_MODE == 0)
    {
        DelayMs(5);
        if (KEY_MODE == 0)
        {
            EA = 0;
            while (!KEY_MODE)
                ;
            g_wave++;
            if (g_wave >= 4)
            {
                g_wave = 0;
            }
            Display();
            EA = 1;
        }
    }
}
void DisplayStep()
{
    uint hundredbit, tenbit, unitbit;
    hundredbit = g_stepDisp / 100;
    tenbit = g_stepDisp % 100 / 10;
    unitbit = g_stepDisp % 100 % 10;
    LCD_WriteCom(0x80 + 11);
    if (hundredbit == 0)
        LCD_WriteData(' ');
    else
        LCD_WriteData(g_table_num[hundredbit]);
    LCD_WriteData(g_table_num[tenbit]);
    LCD_WriteData('.');
    LCD_WriteData(g_table_num[unitbit]);
}
void ScanStep()
{
    if (KEY_SET == 0)
    {
        DelayMs(5);
        if (KEY_SET == 0)
        {
            while (!KEY_SET)
                ;
            g_mode++;
            if (g_mode == 1)
            {
                LCD_WriteCom(0x01);
                LCD_WriteCom(0x80);
                LCD_WriteData('S');
                DelayMs(1); //step value
                LCD_WriteData('t');
                DelayMs(1);
                LCD_WriteData('e');
                DelayMs(1);
                LCD_WriteData('p');
                DelayMs(1);
                LCD_WriteData(' ');
                DelayMs(1);
                LCD_WriteData('v');
                DelayMs(1);
                LCD_WriteData('a');
                DelayMs(1);
                LCD_WriteData('l');
                DelayMs(1);
                LCD_WriteData('u');
                DelayMs(1);
                LCD_WriteData('e');
                DelayMs(1);
                LCD_WriteData(':');
                DelayMs(1);
                g_stepDisp = g_step;

                DisplayStep();
            }
            if (g_mode == 2)
            {
                g_mode = 0;
                g_step = g_stepDisp;

                Init_LCD();
                Init_Timer();
                Display();
            }
        }
    }
    if (g_mode == 1)
    {
        if (KEY_ADD == 0)
        {
            DelayMs(5);
            if (KEY_ADD == 0)
            {
                while (!KEY_ADD)
                    ;
                g_stepDisp++;
                if (g_stepDisp >= 101)
                {
                    g_stepDisp = 1;
                }
                DisplayStep();
            }
        }
        if (KEY_SUB == 0)
        {
            DelayMs(5);
            if (KEY_SUB == 0)
            {
                while (!KEY_SUB)
                    ;
                g_stepDisp--;
                if (g_stepDisp <= 0)
                {
                    g_stepDisp = 100;
                }
                DisplayStep();
            }
        }
    }
}
void main() //主函数
{
    Init_LCD();
    T0CNT = 65536 - (144000 / g_freq) + 25;
    T0RH = T0CNT / 256;
    T0RL = T0CNT % 256;
    Init_Timer();
    LED_ZIGZAG = 0;
    while (1)
    {
        if (g_mode == 0)
        {
            KeyScan();
            // Display();
        }

        ScanStep();

        switch (g_wave)
        {
        case 0:
            P1 = SINE_CHAR[g_cnt];
            LED_ZIGZAG = 1;
            LED_SINE = 0;
            break;
        case 1:
            P1 = SQUARE_CHAR[g_cnt];
            // P1 = outValue;
            LED_SINE = 1;
            LED_SQUARE = 0;
            break;
        case 2:
            P1 = TRIANGLE_CHAR[g_cnt];
            LED_SQUARE = 1;
            LED_TRIANGLE = 0;
            break;
        case 3:
            P1 = ZIGZAG_CHAR[g_cnt];
            LED_TRIANGLE = 1;
            LED_ZIGZAG = 0;
            break;
        }
    }
}
void T0_time() interrupt 1 //定时器
{
    TH0 = T0RH;
    TL0 = T0RL;
    g_cnt++;
    if (g_cnt >= 64)
    {
        g_cnt = 0;
    }

    // if (g_cnt >= pwmValue)
    // {
    //     outValue = 255;
    // }
    // else
    // {
    //     outValue = 0;
    // }
}

仿真演示视频:
https://www.bilibili.com/video/BV1be411M7HE/

实物演示视频:
https://www.bilibili.com/video/BV1WN4y1K71W/

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值