基于51单片机的DDS函数信号发生器-矩阵键盘proteus仿真原理图PCB

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

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

PCB :
在这里插入图片描述

主程序:

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

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;

volatile unsigned char g_wave = 0;
char g_cnt = 0; //定义全局变量
int g_freq = 100; //*0.1Hz
int g_step = 10;
int g_stepDisp = 10;
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;
unsigned char g_keyValue;

//自定义显示字符
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(2);
    LCD_WriteData(3);
    LCD_WriteData(2);
    LCD_WriteData(3);
    LCD_WriteData(2);
    LCD_WriteData(3);
    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(2);
        LCD_WriteData(3);
        LCD_WriteData(2);
        LCD_WriteData(3);
        LCD_WriteData(2);
        LCD_WriteData(3);

    }
    if (g_wave == 1)
    {
        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 == 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 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 KeyScan() //矩阵按键程序
{
    static unsigned char keyIdle = 0;
    static unsigned char keyBuf;

    EA = 0;
    
    g_keyValue = 20; //按键值还原
    P2 = 0x0f;
    if ((P2 & 0x0f) != 0x0f) //按键按下
    {
        DelayMs(1); //按键消抖动
        if (((P2 & 0x0f) != 0x0f) && (keyIdle == 1))
        { //确认是按键按下
            keyIdle = 0;
            keyBuf = (P2 | 0xf0); //矩阵键盘扫描
            P2 = keyBuf;
            switch (P2)
            {
            case 0xee: //方波
                if (g_mode == 0)
                {
                    g_keyValue = 0;
                    g_wave = 0;
                    Display();
                    g_cnt = 0;
                }
                break; //得到按键值  
            case 0xed: //正弦波
                if (g_mode == 0)
                {
                    g_keyValue = 1;
                    g_wave = 1;
                    Display();
                    g_cnt = 0;
                }
                break; //得到按键值 
                
            case 0xeb: //三角波
                if (g_mode == 0)
                {
                    g_keyValue = 2;
                    g_wave = 2;
                    Display();
                    g_cnt = 0;
                }
                break; //得到按键值
            case 0xe7: //锯齿波
                if (g_mode == 0)
                {
                    g_keyValue = 3;
                    g_wave = 3;
                    Display();
                    g_cnt = 0;
                }
                break; //得到按键值

            case 0xdd: //步进减
                if (g_mode == 1)
                {
                    g_stepDisp--;
                    if (g_stepDisp <= 0)
                    {
                        g_stepDisp = 100;
                    }
                    DisplayStep();
                }
                break; //得到按键值
            case 0xdb: //步进加
                if (g_mode == 1)
                {
                    g_stepDisp++;
                    if (g_stepDisp >= 101)
                    {
                        g_stepDisp = 1;
                    }
                    DisplayStep();
                }
                break; //得到按键值    

            case 0xd7: //进入设置步进界面
                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();
                }
                break; //得到按键值   

            case 0xbb: //频率减
                if (g_mode == 0)
                {
                    g_freq -= g_step;
                    if (g_freq < 100)
                    {
                        g_freq = 1000;
                    }
                    T0CNT = 65536 - (144000 / g_freq) + 25;
                    T0RH = T0CNT / 256;
                    T0RL = T0CNT % 256;
                    Display();
                    g_cnt = 0;
                }
                break; //得到按键值
            case 0xb7: //频率加
                if (g_mode == 0)
                {
                    g_freq += g_step;
                    if (g_freq > 1000)
                    {
                        g_freq = 100;
                    }
                    T0CNT = 65536 - (144000 / g_freq) + 25;
                    T0RH = T0CNT / 256;
                    T0RL = T0CNT % 256;
                    Display();
                    g_cnt = 0;
                }
                break; //得到按键值 

            }
        }
        while (P2 != 0x0f)
            P2 = 0x0f;
    }
    else //按键松开
    {
        keyIdle = 1;
    }
    EA = 1;
}

void main() //主函数
{
    Init_LCD();
    T0CNT = 65536 - (144000 / g_freq) + 25; //11059200/12/64 = 144000
    T0RH = T0CNT / 256;
    T0RL = T0CNT % 256;
    Init_Timer();
    LED_ZIGZAG = 0;
    while (1)
    {
        if (g_wave == 0) //方波
        {
            P1 = SQUARE_CHAR[g_cnt];
            LED_SINE = 1;
            LED_SQUARE = 0;
            LED_TRIANGLE = 1;
            LED_ZIGZAG = 1;
        }
        else if (g_wave == 1) //正弦波
        {
            P1 = SINE_CHAR[g_cnt];
            LED_SINE = 0;
            LED_SQUARE = 1;
            LED_TRIANGLE = 1;
            LED_ZIGZAG = 1;
        }
        else if (g_wave == 2) //三角波
        {
            P1 = TRIANGLE_CHAR[g_cnt];
            LED_SINE = 1;
            LED_SQUARE = 1;
            LED_TRIANGLE = 0;
            LED_ZIGZAG = 1;
        }
        else if (g_wave == 3) //锯齿波
        {
            P1 = ZIGZAG_CHAR[g_cnt];
            LED_SINE = 1;
            LED_SQUARE = 1;
            LED_TRIANGLE = 1;
            LED_ZIGZAG = 0;
        }

        KeyScan();

    }
}

void T0_time() interrupt 1 //定时器
{
    TH0 = T0RH;
    TL0 = T0RL;
    g_cnt++;
    if (g_cnt >= 64)
    {
        g_cnt = 0;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值