基于STM32单片机的函数信号发生器原理图PCB

该博客介绍了一个基于STC89C52单片机的波形输出系统。系统通过LCD1602液晶显示波形类型和频率,可通过按键调整波形类型、频率及频率更改步进值,支持正弦波等四种波形输出,频率范围为10 - 100Hz,还给出了原理图、PCB、主程序及实物演示视频链接。

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

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

PCB:
在这里插入图片描述

主程序:

#define __MIAN_C
#include "main.h"
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "bsp_gpio.h"
#include "bsp_clkconfig.h"
#include "bsp_delay.h"
#include "bsp_lcd1602.h"
#include "bsp_key.h"
#include "bsp_dac0832.h"
#include "bsp_GeneralTim.h"

//自定义字符
unsigned char 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
};

unsigned char 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}; //正弦波取码

unsigned char 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}; //矩形波取码

unsigned char 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}; //三角波取码

unsigned char 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}; //锯齿波取码

// 局部变量,用于保存转换计算后的电压值
CreatByte Flag;
enum _MODE_DF_ dispMode;
char g_wave = 0;
char g_cnt; //定义全局变量
int g_freq = 100; //*0.1Hz
int g_step = 1;
int g_mode;
int g_stepDisp = 1;
unsigned char g_table_num[] = "0123456789"; //定义显示的数组
unsigned char g_table_str[] = "Freq:     Wave form:";
unsigned char pwmValue = 50;
unsigned char outValue = 0;
unsigned char dataBuf = 0;

int main(void)
{

    // 使用HSI,SYSCLK = 4M * RCC_PLLMul_x, x:[2,3,...16],最高是64MH
    HSI_SetSysClock(RCC_PLLMul_2); //使用内部8MHz晶振,并设置PLL输出为8MHz

    // 端口初始化
    GPIO_Config();
    GENERAL_TIM_Init();
    DelayMs(200);

    Key_GPIO_Config();
    DelayMs(200);

    LCD_GPIO_Init();
    DelayMs(200);
    Init_LCD();
    DelayMs(200);

    DAC0832_GPIO_Init();

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    TIM_TimeBaseStructure.TIM_Period = 156250 / g_freq;
    // 时钟预分频数
    TIM_TimeBaseStructure.TIM_Prescaler = GENERAL_TIM2_Prescaler;
    // 时钟分频因子 ,没用到不用管
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    // 计数器计数模式,设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    // 重复计数器的值,没用到不用管
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    // 初始化定时器
    TIM_TimeBaseInit(GENERAL_TIM2, &TIM_TimeBaseStructure);

    while (1)
    {
        if (g_mode == 0)
        {
            KeyScan();
            //Display();
        }

        ScanStep();

        switch (g_wave)
        {
        case 0:
            dataBuf = SQUARE_CHAR[g_cnt];
            dataBuf=(dataBuf<<4)|(dataBuf>>4);
            dataBuf=((dataBuf<<2)&0xcc)|((dataBuf>>2)&0x33);
            dataBuf=((dataBuf<<1)&0xaa)|((dataBuf>>1)&0x55);
            GPIO_Write(DAC0832_GPIO_PORT, (((unsigned int)dataBuf<<8) | (GPIO_ReadOutputData(DAC0832_GPIO_PORT) & (~DAC0832_GPIO_PIN))));
            LED_ZIGZAG_OFF;
            LED_SQUARE_ON;
            break;
        case 1:
            dataBuf = SINE_CHAR[g_cnt];
            dataBuf=(dataBuf<<4)|(dataBuf>>4);
            dataBuf=((dataBuf<<2)&0xcc)|((dataBuf>>2)&0x33);
            dataBuf=((dataBuf<<1)&0xaa)|((dataBuf>>1)&0x55);
            GPIO_Write(DAC0832_GPIO_PORT, (((unsigned int)dataBuf<<8) | (GPIO_ReadOutputData(DAC0832_GPIO_PORT) & (~DAC0832_GPIO_PIN))));
            LED_SQUARE_OFF;
            LED_SINE_ON;
            break;
        case 2:
            dataBuf = TRIANGLE_CHAR[g_cnt];
            dataBuf=(dataBuf<<4)|(dataBuf>>4);
            dataBuf=((dataBuf<<2)&0xcc)|((dataBuf>>2)&0x33);
            dataBuf=((dataBuf<<1)&0xaa)|((dataBuf>>1)&0x55);
            GPIO_Write(DAC0832_GPIO_PORT, (((unsigned int)dataBuf<<8) | (GPIO_ReadOutputData(DAC0832_GPIO_PORT) & (~DAC0832_GPIO_PIN))));
            LED_SINE_OFF;
            LED_TRIANGLE_ON;
            break;
        case 3:
            dataBuf = ZIGZAG_CHAR[g_cnt];
            dataBuf=(dataBuf<<4)|(dataBuf>>4);
            dataBuf=((dataBuf<<2)&0xcc)|((dataBuf>>2)&0x33);
            dataBuf=((dataBuf<<1)&0xaa)|((dataBuf>>1)&0x55);
            GPIO_Write(DAC0832_GPIO_PORT, (((unsigned int)dataBuf<<8) | (GPIO_ReadOutputData(DAC0832_GPIO_PORT) & (~DAC0832_GPIO_PIN))));
            LED_TRIANGLE_OFF;
            LED_ZIGZAG_ON;
            break;
        }
    }
}


void Display(void) //显示函数
{
    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_WriteCommand(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_WriteCommand(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_WriteCommand(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_WriteCommand(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_WriteCommand(0x80 + 10);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
        LCD_WriteData(6);
    }
}

void DisplayStep(void)
{
    u8 hundredbit, tenbit, unitbit;
    hundredbit = g_stepDisp / 100;
    tenbit = g_stepDisp % 100 / 10;
    unitbit = g_stepDisp % 100 % 10;
    LCD_WriteCommand(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(void)
{
    if (KEY_SET == 0)
    {
        DelayMs(5);
        if (KEY_SET == 0)
        {
            while (!KEY_SET)
                ;
            g_mode++;
            if (g_mode == 1)
            {
                LCD_WriteCommand(0x01);
                LCD_WriteCommand(0x80);
                DelayMs(1); //step value
                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(160);
            if (KEY_ADD == 0)
            {
                //while (!KEY_ADD);
                g_stepDisp++;
                if (g_stepDisp >= 101)
                {
                    g_stepDisp = 1;
                }
                DisplayStep();
            }
        }
        if (KEY_SUB == 0)
        {
            DelayMs(160);
            if (KEY_SUB == 0)
            {
                //while (!KEY_SUB);
                g_stepDisp--;
                if (g_stepDisp <= 0)
                {
                    g_stepDisp = 100;
                }
                DisplayStep();
            }
        }
    }
}
/*********************************************END OF FILE**********************/

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值