信号发生与测量装置

硬件

STM32F407ZGT6

4638fb894313473eab660f625cd8246e.png

信号的产生

1.AD9833 产生信号

        AD9833介绍

        AD9833 是一款低功耗、可编程的、基于DDS 技术的波形发生器芯片,能够产生正弦
波、三角波和方波并从一个端口输出。正弦波输出频率约可达10MHz,三角波输出频率约可达2MHz,方波输出频率约可达100kHz。输出频率和相位可通过程序修改。

        工作电压2.3V~5.5V,默认使用+5V。

        AD9833 通过一个三线式串行接口写入数据(时钟速率max=40MHz)。

a2cd001e7fa4416aba2e9bb73c902391.png

AD9833使用

引脚连接:

AD9833单片机IO口模式
SDATAPG10OUTPUT
SCLKPD5OUTPUT
FSYNCPD3OUTPUT

配置IO口:

ddff8cd306a34229b420d3f5cce7489c.png

 添加驱动文件,头文件路径:

d819656636214274b05f854a3ff53681.png

 编写代码:

        当IO口引脚的 User Label(宏定义)不同时,需要相应地修改驱动文件。

/* mian.c */

#include "ad9833.h"

bsp_InitAD9833();    // 初始化ad9833
AD9833_SelectWave(2);	// 设置波形;0矩形波,1三角波,2正弦波,3无输出
AD9833_SetFreq(1000);	// 设置频率,单位HZ

2.DAC+TIM+DMA 产生信号

(104条消息) STM32cubemx教程 DAC+TIM+DMA_stm32 定时器dma dac cubemx_四臂西瓜的博客-CSDN博客

信号的测量

1.ADS8688 测量信号

ADS8688介绍

        ADS8688是8通道ADC模块。基于16位逐次逼近ADC。模拟SPI通信。

        5V供电。

328b2d85d8464edfada6c71596287517.png

ADS8688使用

ADS8688单片机IO口模式
CSPB3OUTPUT
RSTPB6OUTPUT
DAISYPA12OUTPUT
SDOPG8INPUT
CLKPG6OUTPUT
SDIPC8OUTPUT

e3035e545c7949f6a6e659c7a25591fd.png

编写代码:

        当IO口引脚的 User Label(宏定义)不同时,需要相应地修改驱动文件。

ADS8688手动采集

/* main.c */
#include "ads8688.h"


/* main */
uint16_t value[9];

ADS8688_Init(CH0_EN|CH1_EN|CH2_EN|CH3_EN|CH4_EN|CH5_EN|CH6_EN|CH7_EN);//ADS8688初始化

//设置通道输入范围
Set_CH_Range(CHIR_0,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_1,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_2,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_3,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_4,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_5,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_6,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_7,ADS8688_IR_N2_5V);


MAN_CH_Mode(MAN_CH_0);    // 手动模式选择通道
value[0]=Get_MAN_CH_Mode_Data();    // 读取通道数据,ADC值

// 读取通道数据,电压值,单位mv
value[0]=(Get_MAN_CH_Mode_Data()-32768)*CONST_N2_5V_LSB_mV;

ADS8688自动采集

/* main.c */
#include "ads8688.h"


/* main */
uint16_t value[8];

ADS8688_Init(CH0_EN|CH1_EN|CH2_EN|CH3_EN|CH4_EN|CH5_EN|CH6_EN|CH7_EN); // ADS8688初始化

// 设置通道输入范围
Set_CH_Range(CHIR_0,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_1,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_2,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_3,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_4,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_5,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_6,ADS8688_IR_N2_5V);
Set_CH_Range(CHIR_7,ADS8688_IR_N2_5V);

AUTO_RST_Mode();//进入自动扫描模式

// 自动扫描模式,自动扫描并转换8通道。数据存在value数组中,ADC值
Get_AUTO_RST_Mode_Data(value,8);

2.ADC+TIM+DMA 测量信号

(104条消息) STM32HAL ADC+TIM+DMA采集交流信号 基于cubemx_cubemx adc dma tim_四臂西瓜的博客-CSDN博客

配置ADC和DMA

        ADC配置为外部触发 ; 开启 DMA,DMA配置为normal模式。

e12c6c97a10141df879cba251507637d.png

 开启DMA

99a2625c22aa4f62902ae22264983543.png

配置TIM

        开启定时器中断。定时器和触发ADC的定时器对应。

        通过设置 PSC 和 ARR 来设置ADC触发频率,即采样频率。

4dcde51293314b3f8debe7381ce49394.png

 PSC = 0

ARR = 时钟频率 / 采样频率

/* main.c */


/* 全局变量 */
uint16_t adc_buff[200];//存放ADC采集的数据

__IO uint8_t AdcConvEnd = 0;    // ADC采集完成标志


/* main */
HAL_TIM_Base_Start(&htim3);    //开启定时器3
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buff, 200); //让ADC1去采集200个数,存放到adc_buff数组里


/* while(1) */
if(1 == AdcConvEnd)    // ADC采集完成
{

}



/* stm32f4xx_it.c */

extern uint8_t AdcConvEnd;//引入外部变量


/* 
DMA中断服务函数
void DMA2_Stream0_IRQHandler(void)
*/
AdcConvEnd = 1;

信号的处理

1.ARM-DPS库

通过源码添加DSP库

1.工程目录下新建 DSP_LIB文件夹,引用DSP库文件

CUBEMX生成的代码,KEIL内的文件夹不能命名为 DSP_LIB,可以写成DSP

6d7895305d9a4ae1b0cc914039e5478d.png

8e35a235ec084a8a98e5bf0167f8ad43.png

2.添加头文件包含路径

f9491d6731a44ab7ba670270269b3355.png

3.添加全局宏定义

在 Define里设置全局宏定义

标准库,覆盖原来的:

STM32F40_41xxx,USE_STDPERIPH_DRIVER,ARM_MATH_CM4,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING

CUBEMX生成,在原来的基础上添加:       

,ARM_MATH_CM4,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING

DSP库的使用

FFT变换

FFT变换的原理的用途

        FFT(快速傅里叶变换)是一种用于将时域信号转换为频域信号的算法。它通过对时域信号进行傅里叶变换,将信号的频谱分解成不同频率的分量。

        FFT 可以用于频谱分析,滤波,数据分析。

FFT变换的实现

/* main.c */
#include "arm_math.h"
#include "arm_const_structs.h"

/* 全局变量 */
#define FFT_LENGTH		4096 		// FFT变换长度
float fft_inputbuf[FFT_LENGTH*2];	// FFT变换输入数组
float fft_outputbuf[FFT_LENGTH];	// FFT变换输出数组



/* main */
arm_cfft_radix4_instance_f32 scfft;
arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);//初始化scfft结构体,设定FFT相关参数

uint32_t MAXindex = 0;  // FFT输出最大值的数组下标
float32_t MaxValue = 0; // FFT输出最大值
uint32_t frequency = 0; // 频率

/* while(1) */
/* FFT变换输入数组赋值 */
for(int i=0; i<FFT_LENGTH; i++)
{
    // 实部电压值
    fft_inputbuf[2*i] = (float)ADC1_ConvertedValue[i] * 3.3 / 4096;

    // 虚部0
    fft_inputbuf[2*i+ 1] = 0;
}

arm_cfft_radix4_f32(&scfft,fft_inputbuf);	//FFT计算(基4)
arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);	//把运算结果复数求模得幅值 

/* 找出幅值最大的下标,第一个参数是起始地址,这里是[1],所以去掉了[0],即直流分量*/
arm_max_f32(&fft_outputbuf[1], FFT_LENGTH / 2, &MaxValue, &MAXindex);

/* 频率 = 最大幅值的数组下标 * 采样率 / FFT计算点数 */
frequency = (float32_t)MAXindex * (float32_t)SAM_FRE  / (float32_t) FFT_LENGTH; 

2.排序算法

快速排序

#include <stdio.h>
void bubble_sort(int arr[], int len) {
        int i, j, temp;
        for (i = 0; i < len - 1; i++)
                for (j = 0; j < len - 1 - i; j++)
                        if (arr[j] > arr[j + 1]) {
                                temp = arr[j];
                                arr[j] = arr[j + 1];
                                arr[j + 1] = temp;
                        }
}
int main() {
        int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
        int len = sizeof(arr) / sizeof(arr[0]);
        bubble_sort(arr, len);
        int i;
        for (i = 0; i < len; i++)
                printf("%d ", arr[i]);
        return 0;
}

信号的显示

1.串口屏显示

串口屏显示参数、文字用文本控件就行,显示波形用波形控件

淘晶驰资料中心 — 淘晶驰资料中心 1.1.0-2023-07-15 12:32:54 文档 (tjc1688.com)

配置单片机

配置 USART2 ,设置波特率,开启中断。

d01df8f1503c4cf49216d7b4ffd020c3.png

d39aa9995192476096284424b4d8df37.png

配置串口屏 

8814d9399ae44e068f3ae72277efd0d0.png

 设置串口屏波特率,与单片机相同。

a6942c0f5c7b434cb979fb73f201e1df.png

 添加字库

60caee7a99f94d0489e59be3f1c84ea2.png

添加控件

文本控件

内存占用设置为全局访问。

62010530a16b4790b84d5232c8021b5c.png

波形控件

内存占用设置为全局访问。

1e92864a457541a29adb536340199e03.png

/* main.c */
#include "string.h"
#include "stdio.h"

char temp[30];

/* 文本控件 objname = t0*/
sprintf(temp, "t0.txt=\"abc\"\xff\xff\xff");
HAL_UART_Transmit(&huart2, (uint8_t *)temp, strlen(temp), 1000);
  
/* 文本控件 objname = t1*/
sprintf(temp, "t1.txt=\"ww\"\xff\xff\xff");
HAL_UART_Transmit(&huart2, (uint8_t *)temp, strlen(temp), 1000);
  
/* 波形控件 objname = s0*/
  
// 发送要传输的数据量 数据量最多不超过1024个 ,数据取值范围[0, 255] 
sprintf(temp, "addt s0.id,0,100\xff\xff\xff");
HAL_UART_Transmit(&huart2, (uint8_t *)temp, strlen(temp), 1000);
HAL_Delay(100);

// 透传数据
for(int i=0; i<100; i++)
{
    sprintf(temp, "%c", i);
    HAL_UART_Transmit(&huart2, (uint8_t *)temp, strlen(temp), 1000);
}
// 发送透传结束指令
sprintf(temp, "\x01\xff\xff\xff");
HAL_UART_Transmit(&huart2, (uint8_t *)temp, strlen(temp), 1000);

HAL_Delay(1000);
// 清除波形控件s0的0通道数据,不能跨页面使用
sprintf(temp, "cle s0.id,0\xff\xff\xff");
HAL_UART_Transmit(&huart2, (uint8_t *)temp, strlen(temp), 1000);

2.蓝牙和上位机显示

配置蓝牙

蓝牙5V供电

20ab8a29f1a04b9fa6c923aeef826363.png

按住按钮上电,进入AT模式

搜索端口,获取模块信息。

修改模块信息:设备名称,连接密码,波特率。

更新模块信息。 

0562d5d80dd94577845293946ead2b51.png

配置单片机

配置 USART3 ,设置波特率,开启中断。

ed49fde9e89f4e419ab369af921427d8.png

5202b6a9937e41b4bce6273686cef927.png

导入蓝牙数据包文件

adc353ac55b04b45acadfd253915ac9e.png

 3ac1aee5758d40a8841a6218084e2348.png

添加头文件路径

 bacc5d1e132d4b39aa97c6f88ce7a339.png

 设置发送和接收数据包结构

bool byte short int float 五种类型

用 int 和 float 类型即可。

59e6e50d00294ca38b9406d04bf4999f.png

#include "Bluetooth.h"

TxPack txpack;//蓝牙发送数据包

/* 蓝牙数据包赋值 */
txpack.floats[0] = Thd;//THD

sendValuePack(&txpack);    // 发送蓝牙数据包

配置上位机

创建上位机工程

0c78ea631cad4edba6acbf271d925cd6.jpeg

 设置数据包格式

 2583ec7060644e3fa370b3be449d4f22.jpeg

 添加控件,显示参数用 文本 ; 显示波形用 Y-T一维波形。

024e6daa1a8443448e0b3f115c62b373.png

 选中控件后,连接数据

c4405bfa9b1c4a579a5735c5391c2c22.jpeg

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值