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

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

dgx6664个月前 (03-23)文章中心16


基于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的迷你示波器 - 单片机 嵌入式 物联网(含代码)” 的相关文章

新华社、人民日报、央视官方微信点赞,“菏泽好邻居”让全国人民羡慕

齐鲁网·闪电新闻5月5日讯 俗话说“远亲不如近邻”。邻里间的互动,有时候可谓非常有趣。近日,山东菏泽“致楼上邻居的一封信”在网上走红。‘一位热心又专业的邻居老王,写信对邻居练钢琴,提出了一些“指导意见”,指出了两首曲子中的错误,还附上了自己精心准备的乐谱。这封“钢琴指导”信张贴后,引来众多邻居留言。...

Auto CAD 2014 软件下载地址、注册机下载地址(附:Auto CAD 2014 安装教程)

从事在线培训十多年,每天都会有很多学员问到软件工具,相信看完这篇文章之后,对使初学的学员节约很多的时间。这里收集整理了几个常见的问题,未涉及到的问题,欢迎大家留言①学习室内设计,不知道如何下载软件---本文要讲的②下载好软件了,不会安装,不会破解---本文要讲的③软件卸载删除后,重装失败---点击》...

cad2014怎么转换成pdf?推荐这几款转换神器!

PDF是一种通用的文件格式,可以在不同的操作系统、不同版本的CAD软件和不同设备上打开和查看,还可以保持打印格式的一致性,避免在不同设备上打印时出现格式错误。这有助于提高文档的可读性和可理解性,确保打印的准确性和一致性。在进行建筑设计、工程制图等领域的工作时,将CAD转换为PDF是一种常见的做法。下...

CAD启动太慢了?只需一键关闭这些按钮,即可快速启动CAD

工作紧急时,CAD不给力怎么办?启动太慢了,每次启动都要等上好半天,真的超级忧伤... 别急,想要快速启动CAD其实是有诀窍的。你只要学会下面这几招即可快速启动你的CAD了,那么下面我们就一起来看看吧。一、关闭通讯中心和联机帮助中心想要快速启动CAD,只要关闭通讯中心和联机帮助中心就行了。那么通讯中...

CAD打印怎么设置黑白?一文教会你CAD打印黑白图纸

CAD设计过程中,为了区分图纸中各个图形对象使其看起来更加直观,方便二次编辑,通常会用不同颜色来标识不同的内容。但在CAD打印时并不需要将这些颜色全部打印出来,只需要黑白打印即可。那么,你知道CAD打印怎么设置黑白吗?本文小编就以浩辰CAD软件为例来给大家分享一下CAD打印怎么设置黑白吧!CAD打印...

cad2007圆形标记方法技巧 #cad2007

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