基于stm32的信号发生器(仅代码) 可输出正弦波 、三角波、矩形波,4.3寸lcd显示,可按键控制输出波形的频率,以及波形,输出峰峰值3.0V,频率范围5khz-40khz(这俩指标处于误差范围5%之内)理论上其他范围的频率也可以,需要自己改代码,怎么改我代码里有讲。

最近捣鼓了一个基于STM32的信号发生器,它能输出正弦波、三角波和矩形波,还配备4.3寸LCD显示,通过按键就能轻松控制输出波形的频率和类型,输出峰峰值稳定在3.0V,频率范围在5kHz - 40kHz(误差控制在5%以内),要是你有其他频率需求,改改代码也能实现,下面就给大家分享分享。

一、整体思路

整个系统主要由STM32主控芯片、LCD显示模块、按键模块以及波形输出模块构成。STM32负责生成不同波形的数据,通过DAC输出模拟信号,同时处理按键输入来调整波形和频率,LCD实时显示当前的波形和频率信息。

二、关键代码解析

1. 正弦波生成代码

// 定义正弦波数据数组
#define SINE_TABLE_SIZE 256
const uint16_t sineTable[SINE_TABLE_SIZE];

// 初始化正弦波表
void initSineTable(void) {
    for (uint16_t i = 0; i < SINE_TABLE_SIZE; i++) {
        sineTable[i] = (uint16_t)(1023 * (1 + sin(2 * PI * i / SINE_TABLE_SIZE)) / 2);
    }
}

// 输出正弦波
void outputSineWave(uint32_t frequency) {
    uint32_t period = SystemCoreClock / frequency;
    for (uint16_t i = 0; i < SINE_TABLE_SIZE; i++) {
        DAC_SetChannel1Data(DAC_Align_12b_R, sineTable[i]);
        for (volatile int j = 0; j < period / SINE_TABLE_SIZE; j++);
    }
}

这里先定义了一个正弦波表 sineTableinitSineTable 函数初始化这个表,通过三角函数计算每个点的值。outputSineWave 函数根据设定的频率,通过DAC输出正弦波数据,在每个数据点之间通过简单的延时来控制输出频率。

2. 三角波生成代码

// 输出三角波
void outputTriangleWave(uint32_t frequency) {
    uint32_t period = SystemCoreClock / frequency;
    uint16_t value = 0;
    uint8_t direction = 1;
    while (1) {
        if (direction) {
            value++;
            if (value >= 4095) {
                value = 4095;
                direction = 0;
            }
        } else {
            value--;
            if (value <= 0) {
                value = 0;
                direction = 1;
            }
        }
        DAC_SetChannel1Data(DAC_Align_12b_R, value);
        for (volatile int j = 0; j < period / 4096; j++);
    }
}

三角波生成采用了一个简单的计数器逻辑,direction 变量控制计数方向,当达到最大值或最小值时改变方向,然后通过DAC输出相应的数据,同样通过延时控制频率。

3. 矩形波生成代码

// 输出矩形波
void outputSquareWave(uint32_t frequency) {
    uint32_t period = SystemCoreClock / frequency;
    uint8_t value = 0;
    while (1) {
        value =!value;
        DAC_SetChannel1Data(DAC_Align_12b_R, value? 4095 : 0);
        for (volatile int j = 0; j < period / 2; j++);
    }
}

矩形波就更简单啦,通过一个 value 变量取反来控制DAC输出高电平和低电平,延时时间为周期的一半,这样就生成了占空比为50%的矩形波。

4. 按键处理代码

// 按键扫描
void keyScan(void) {
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) {
        // 按键1按下,切换波形
        currentWaveform = (currentWaveform + 1) % 3;
        while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0);
    }
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0) {
        // 按键2按下,增加频率
        if (currentFrequency < 40000) {
            currentFrequency += 5000;
        }
        while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0);
    }
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == 0) {
        // 按键3按下,降低频率
        if (currentFrequency > 5000) {
            currentFrequency -= 5000;
        }
        while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == 0);
    }
}

按键扫描函数通过检测GPIO口的电平状态来判断按键是否按下,分别实现了波形切换、频率增加和频率降低的功能。

5. LCD显示代码

// LCD初始化
void LCD_Init(void) {
    // 初始化LCD相关寄存器和引脚配置
    // 这里省略具体代码,一般涉及SPI或其他接口初始化
}

// 在LCD上显示波形和频率信息
void displayInfo(void) {
    char buffer[20];
    switch (currentWaveform) {
        case 0:
            sprintf(buffer, "Sine: %d Hz", currentFrequency);
            break;
        case 1:
            sprintf(buffer, "Triangle: %d Hz", currentFrequency);
            break;
        case 2:
            sprintf(buffer, "Square: %d Hz", currentFrequency);
            break;
    }
    LCD_SetCursor(0, 0);
    LCD_Puts(buffer);
}

LCD初始化函数完成LCD相关的初始化工作,displayInfo 函数根据当前的波形和频率信息,格式化字符串后显示在LCD上。

三、频率范围调整说明

如果需要调整频率范围,在上述代码中主要涉及到频率计算部分。例如,outputSineWaveoutputTriangleWaveoutputSquareWave 函数中的 period 计算依赖于 SystemCoreClock 和设定的频率 frequency。如果要拓展频率范围,除了修改 currentFrequency 的限制判断,还需要根据硬件性能合理调整 SystemCoreClock 以及延时部分,确保输出的频率在误差允许范围内。

基于stm32的信号发生器(仅代码) 可输出正弦波 、三角波、矩形波,4.3寸lcd显示,可按键控制输出波形的频率,以及波形,输出峰峰值3.0V,频率范围5khz-40khz(这俩指标处于误差范围5%之内)理论上其他范围的频率也可以,需要自己改代码,怎么改我代码里有讲。

通过这些代码,一个基于STM32的多功能信号发生器就基本实现啦,希望对大家有所帮助,一起享受硬件编程的乐趣!

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐