当前位置:首页 > 文章中心 > 正文内容

基于单片机stm32的迷你示波器 - 单片机 嵌入式 物联网(含代码)

dgx6669个月前 (03-23)文章中心33


基于stm32的迷你示波器

  • 难度系数:4分
  • 工作量:4分
  • 创新点:3分

1 简介

在一些简单的电子电路设计中,无需使用到高性能且体积庞大的台式示波器。因此,本项目为体积小巧的USB虚拟示波器。在设计过程中,在考虑了成本问题的基础上,尽量实现标准示波器的各项功能,充分发挥芯片性能。参数和特点如下:

  • 采样率2MSa/S
  • 测量范围±10V
  • 交流耦合和直流耦合模式
  • 输入阻抗约为1MΩ/100pF
  • 最大100倍程控增益
  • 电压测量精度2%
  • 支持一键自动功能
  • 支持FFT模式
  • 在快速模式下屏幕刷新率可达20FPS

2 主要器件

  • STM32G030主控芯片
  • XC6902N331稳压芯片
  • 1117线性稳压芯片
  • NCS20072运放芯片
  • CD4053模拟开关
  • CH340串口转USB芯片

3 实现效果





4 设计原理

4.1 硬件部分

总体说明
硬件主要包括将测量信号转换至单片机AD可以采集的模拟信号转换部分、单片机电路USB串口数字电路部分和±3.3V电源部分。


信号转换电路

信号首先经过680KΩ和220KΩ电阻电容构成的衰减电路,使得±10V的信号转化至运放可以处理的±2.5V范围,后一级电压跟随器使得示波器的输入阻抗为900KΩ/90pF。

由单刀双掷开关控制是否经过RC高通滤波器,以实现交直流耦合切换。此处使用继电器是一个更好的方案,但模拟开关CD4053的价格显然更为合适。

两个同相比例放大器构成类似于级联的形式,由模拟开关控制是否进行放大。第一级放大倍数为5倍,第二级放大倍数接近于20倍。从而可以实现放大倍数为1倍、5倍、20倍、100倍的不同增益。相比较由一个运放构成的改变反馈电阻的程控放大电路,该电路对于频率较高的小信号有更好的放大能力。

后续经过电压抬升电路,将正负电压信号转换成单片机AD可以采集的信号,最终的信号将叠加在1.5V直流量上。比较器的正比较端也接入1.5V直流信号,比较器输出端即为同频率的脉冲信号。加入比较器的主要作用是获取波形的频率值,以更快的实现一键自动功能。

此外,图中所用的LM358通用运放在实际调试中改成了性能更好的NCS20072运放。可能由于LM358的压摆率太低,导致在频率超过10KHz时就会出现奇怪的失真波形。
主要原理图



4.2 软件部分

软件包括STM32单片机部分和LabVIEW上位机部分。单片机主要实现串口接收指令、AD采集、波形数据转换和串口发送波形数据的功能。采用STM32Cube预先配置各项参数,在Keil中进一步编程。

单片机参数配置

配置ADC触发方式为定时器触发,这样可以更精准的控制采样间隔。由DMA控制器将波形数据保存至数组,并设置DMA为非循环模式。

配置串口波特率为256000(没有采用常用的115200,因为只有在该波特率下才能够实现20FPS的刷新率)。开启接收中断。由DMA控制串口发送数据,这样在发送串口数据时,不会影响主程序的运行,从而可以提高刷新速度。

在频率测量中,配置定时器为输入捕获模式,将定时器从模式设置为复位,触发源为TI1FP1。由DMA控制器将每次脉冲信号来临时,将定时器的计数值保存至数组。另外,比较器的输出端含有高频脉冲噪声,需要配置定时器输入通道滤波器。

单片机波形采集程序

串口波形数据格式为< time00640fre00100amp0dc>的形式。其中AD触发定时器的计数值Time,最大65535;输入捕获定时器的计数值Fre,最大65535;程控放大器的放大倍数Amp,最大值3;耦合方式用DC和AC表示。

波形采集过程如下。



上位机程序

上位机的主要工作是解析来自串口的字符串,处理波形、计算相关参数并显示。在单片机中不进行浮点运算,所有的波形数据均为AD采集的原始数据,为整数形式。而在上位机中,需要将这些整数转换成电压值。很显然,单片机AD值和输入电压值之间理论上成完全的线性关系,在上位机中需要跟据此线性关系求得实际电压值。在本作品中,有着4种程控增益,也就对应着4个函数关系。

5 部分核心代码

#include "main.h"
#include "adc.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "wave.h"
#include "msg.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_TIM1_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	my_UartInit(&UsartData);
	my_WaveInit(&WaveData);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		my_Wave(&WaveData);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_ADC;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

 /**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM14 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM14) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics ***** END OF FILE ****/

完整代码可进群免费领取。

嵌入式物联网的学习之路非常漫长,不少人因为学习路线不对或者学习内容不够专业而错失高薪offer。不过别担心,我为大家整理了一份150多G的学习资源,基本上涵盖了嵌入式物联网学习的所有内容。点击下方链接,0元领取学习资源,让你的学习之路更加顺畅!记得点赞、关注、收藏、转发哦!

点击这里找小助理0元领取:扫码进群领资料


扫描二维码推送至手机访问。

版权声明:本文由第六芝士网发布,如需转载请注明出处。

本文链接:http://www.dgx666.com/post/468.html

分享给朋友:

“基于单片机stm32的迷你示波器 - 单片机 嵌入式 物联网(含代码)” 的相关文章

CAD如何设置打印样式?简单3步!初学者必看

很多初学CAD的小伙伴对CAD的打印设置都不熟悉,其实CAD打印也有一定的技巧,掌握一些CAD的打印技巧,可以帮助我们省下不少时间呢!那么今天小编就来跟大家分享一期关于CAD的打印技巧,小伙伴们拿好小本本记下来哦!一、打印样式设置1、打印界面首先,我们打开CAD,在CAD界面中点击打印按钮,或这按快...

cad2007圆形标记方法技巧 #cad2007

大家好!很多小伙伴会问,在 cad 二零零七版当中,如果画了一个半径为一百的圆,画好后想给它做一个圆形标记该怎么去标记呢?1. 第一种方法可以点击标注,在标注里面,其实标注菜单里面有一个圆心标记,点击它,点了以后就会问选择圆弧或圆,这样一点之后就会自动给圆心做标记。如果觉得标记太小,可以输入缩放命令...

CAD快速测量面积与周长

这篇来教大家如何用CAD梦想画图快速测出规则图形与不规则图形的面积、首先这些图形都需要是封闭图形。操作工具操作系统:Windows10CAD软件:CAD梦想画图步骤1.首先我们画一个规则的矩形与一个用多边形绘制的不规则封闭图形,如下图动画所示:绘制图形2.然后点击功能菜单下的测量选项,系统会弹出“测...

桌面便签怎么设置提醒,哪个备忘录便签好?

  2024年终于开工了,第一天上班比较迷茫,不知道做什么比较好,这个时候如果有一款简单好用且可提醒的桌面便签软件该多好。那么,桌面便签怎么设置提醒,哪个备忘录便签好?  桌面便签怎么设置提醒,哪个备忘录便签好?功夫不负有心人,找了好多个终于找到了一款叫好用便签的电脑桌面便签软件,不仅设计简单,而且...

iPad 11和iPad Air 7上架:升级A16 / M3处理器,128GB起步

iPad A16 (第11代)屏幕配备 11英寸 2360x1640 分辨率 60Hz IPS面板,亮度 500 尼特,仅支持 Apple Pencil(USB-C)和 Apple Pencil(第一代)还是那非全贴合屏幕处理器从A14升级成了A16(4核 GPU),不支持苹果AI!注意:这颗A16...

恶意文件携带驱动人生数字签名,混淆视听执行后门

在现代数字化领域中,数字签名借助先进的加密技术,为文件和数据披上了一层坚固的“防护衣”,确保软件的完整性和来源的可靠性,极大地提升了软件的安全性。但是随着数字签名技术的广泛应用,一些安全检查也可能因此“放松警惕”,放过大部分带有数字签名的软件,为攻击者留下可乘之机。因为攻击者可以巧妙地利用数字签名,...