基于STM32单片机的函数信号发生器原理图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/

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于STM32函数信号发生器是一种能够产生各种函数波形信号的设备。它采用STM32系列微控制器作为主控芯片,具有较高的计算速度和稳定性,可以通过编程控制产生不同的信号波形。 基于STM32函数信号发生器最基本的功能是产生正弦波、方波、三角波等常见的函数波形信号。通过设定参数,如频率、幅度和相位,可以产生不同频率和幅度的信号。此外,它还可以实现信号的频率调制和幅度调制,使产生的信号更加丰富和灵活。 在基于STM32函数信号发生器设计中,需要使用相关的软件开发工具,如Keil、IAR或CubeMX等,编写相应的代码实现信号波形的生成和调节。根据不同的需求,可以选择不同的函数生成算法,如直接数字合成(DDS)、查表法或快速傅立叶变换(FFT)等,来实现信号的产生和处理。 此外,基于STM32函数信号发生器还可以与外部设备进行通信,实现远程控制和数据传输。可以通过串口、以太网或无线通信等方式,与上位机或其他设备进行数据交互,使信号发生器具有更广泛的应用。 基于STM32函数信号发生器具有体积小、功耗低、价格较为实惠等优点,广泛应用于科研、教育和工程领域。它可以满足不同领域对于信号源的需求,为实验和研究提供便利,同时也为创新和技术发展提供了良好的基础。 ### 回答2: 基于STM32函数信号发生器是一种能够通过程序控制产生不同波形信号的设备。STM32是一款强大的32位微控制器系列,具有丰富的外设和高性能的处理能力,非常适合用来实现信号发生器的功能。 在该功能的实现过程中,首先需要使用STM32芯片的定时器模块来产生基准时钟信号。利用定时器的时钟源和分频器,可以得到一定频率的时钟脉冲信号。 然后,通过编程的方式,根据用户输入的参数,计算出每个时钟脉冲的幅值,并将其加载到DAC(数字模拟转换器)输出引脚上。DAC可以将数字信号转换为模拟信号,从而产生特定幅值的波形信号。 此外,为了实现不同的波形,还可以利用STM32的GPIO(通用输入输出)模块来产生不同的输出模式。例如,通过将GPIO配置为PWM(脉冲宽度调制)输出模式,可以产生方波信号。通过控制GPIO引脚输出高低电平并控制持续时间,也可以生成其他波形信号,如正弦波、三角波等。 最后,通过使用LCD显示模块,可以在屏幕上显示当前的波形类型、频率、幅值等参数。使用按钮或旋钮可以方便地调整这些参数。 总而言之,基于STM32函数信号发生器通过利用芯片强大的计算和控制能力,结合定时器、DAC、GPIO等功能模块,能够灵活地产生各种类型、不同频率和幅值的波形信号,为实验、测试等应用提供了便利。 ### 回答3: 基于STM32函数信号发生器是一种能够产生各种波形信号的设备。STM32是一种常用的嵌入式微控制器,具有高性能和丰富的外设资源,非常适合用于信号发生器的设计。 在实现函数信号发生器的过程中,我们首先需要基于STM32的开发平台搭建系统。通过使用STM32的GPIO(通用输入输出)和定时器,我们可以实现对外部电路的控制和时序控制。同时,我们可以使用STM32的ADC(模拟到数字转换器)模块,将外部输入信号进行采样,并通过定时器产生的中断来实现信号的输出控制。 在信号发生器的设计中,可以选择不同的波形生成算法,如正弦波、方波、三角波和锯齿波等。这些算法可以通过STM32的数学库函数来实现,或者使用查表法来获取波形的采样值。通过在固定的时间间隔内,按照采样值的顺序逐个输出,可以生成目标波形。 此外,我们还可以通过修改正弦波的频率、振幅和相位等参数,来实现更多种类的信号。通过更改定时器的时钟频率和参数设置,可以实现不同的输出频率。 在设计过程中,需要考虑到信号输出的精度和稳定性。通过使用STM32的时钟源和时钟校准功能,可以保证信号的输出精度。此外,合理选择电路的元件和阻抗匹配,可以减少信号的失真和干扰。 总之,基于STM32函数信号发生器具有灵活性和可定制性。通过合理的设计和编程,可以实现各种类型和频率的波形信号,并能满足不同领域的应用需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值