寒假小项目—基于stm32g0的迷你示波器
在寒假期间前后一个多星期边学边做的一个小示波器,花了点时间测试和完善功能,后面学了点C#,试着写了个上位机,但是没有写波形显示界面。
标签
嵌入式系统
青小冘
更新2021-03-03
2625

实现功能:

  1. Mic和Ain通道示波功能,有三个可调参数,能够调整采样速度和横纵轴的放大。
  2. Aux的波形输出,能够调整波形的类型(用定时器实现的方波和三角波)、频率和占空比。
  3. 配套上位机实现串口与单片机的通信,实现了简单的几个命令。


未完成内容:

  1. 首先未完成的是傅里叶变换功能,主要是ram空间问题。将CubeIDE仅生成adc的LL库,然后采样并参考jack的FFT库,利用FFT的计算函数进行运算,也会出现RAM不够的问题。希望有大佬能点拨点拨。
  2. 由于没有外围电路,所以没有实现波形输出正弦波(之前看到论坛上的方案是模拟函数,但是示波器测试了一下,并不是正弦波,不知道该怎么处理)
  3. 上位机没有实现波形显示功能。C#是现学的,adc方面可能存在上位机serialPort读取速率和缓存的问题,就没有搞下去。不过可以用开源的串口调试助手Vofa+,它自带了数据的波形显示。

实现过程:

   上手前先去研究研究了jack的开源程序以及一些优秀的stm32示波器开源项目,有了大体的实现思路。由于是初次上手CubeIDE,对于cube的一些特性还不是很熟悉,只能边用边学。通过直播课,了解到LL库的优势,便尝试使用LL库,这也是一个新的知识。整个项目中都是在不断尝试新知识,不断摸索。

  • oled驱动是直接找的别人已经开源的驱动,然后自己调整了下引脚初始化,加上了上部和下部的刷新函数,将示波界面的参数和波形分成两个区域进行单独的刷新,提高屏幕的稳定性和刷新速度。
    //更新oled上部显存
    void OLED_Refresh_12(void)
    {
    	uint8_t i,n;
    	for(i=0;i<2;i++)
    	{
    	   OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
    	   OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
    	   OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
    	   for(n=0;n<128;n++)
    		 OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
        }
    }
    
    //更新oled下部显存
    void OLED_Refresh_345678(void)
    {
    	uint8_t i,n;
    	for(i=2;i<8;i++)
    	{
    	   OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
    	   OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
    	   OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
    	   for(n=0;n<128;n++)
    		 OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
        }
    }​
  • 按键检测采用常规的中断方式,用于交互界面,进入功能界面后连按两次ok键退出到初使界面。存在的一点问题是连按的时候,中断会进入多次,可以在中断之后加一个几十ms延迟解决这个问题。
  • 串口使用了USART2,重定义printf到USART2,同时开启接收中断用于接收上位机的数据。中断中读取寄存器中的一个字节,根据该数据进行不同的功能选择,与自己写的上位机相匹配。
    void USART2_IRQHandler(void)
    {
      /* USER CODE BEGIN USART2_IRQn 0 */
    
    	if(LL_USART_IsActiveFlag_RXNE(USART2))
    	{
    		data=LL_USART_ReceiveData8(USART2);
    		switch(data)
    		{
    		case 0:
    			Fun_Flag=1;
    			break;
    		case 1:
    			Fun_Flag=0;
    			Fun_Value=1;
    			break;
    		case 2:
    			Fun_Flag=0;
    			Fun_Value=2;
    			break;
    		case 3:
    			Fun_Flag=0;
    			Fun_Value=3;
    			break;
    		case 4:
    			Fun_Flag=0;
    			Fun_Value=4;
    			break;
    		case 5:
    			Fun_Flag=0;
    			Fun_Value=5;
    			break;
    		case 6:
    			Fun_Flag=0;
    			Fun_Value=6;
    			break;
    		default:break;
    
    		}
    
    		LL_USART_TransmitData8(USART2, data);
    	}
      /* USER CODE END USART2_IRQn 0 */
      /* USER CODE BEGIN USART2_IRQn 1 */
    
      /* USER CODE END USART2_IRQn 1 */
    }​
  • 定时器部分,使用的LL库中没有us级延迟,故用TIM1设置了一个us的延迟函数用于adc的采样速度设置。还初使话了TIM2为PWM输出模式,用于生成方波。
    void TIM1_uDelay(uint16_t us)
    {
    	__HAL_TIM_SetCounter(&htim1, 0);//htim1
    
    	__HAL_TIM_ENABLE(&htim1);
    
    	while(__HAL_TIM_GetCounter(&htim1) < (64 * us));//计数频率64MHz,64次即1us
    	/* Disable the Peripheral */
    	__HAL_TIM_DISABLE(&htim1);
    }​
  • adc初使话为了单次转换,并且没有使用DMA传输数据(不用DMA的话,单次转换应该满足需要了),通过设置延迟时间来进行规律性的adc采样转换,保存到缓存数组中进行处理。在oled上显示了采样速度,横轴纵轴的倍率,实现波形的放大缩小。
    //波形读取/显示函数
    void Draw_BoXing(void)
    {
    	uint8_t t;
    	uint8_t x;
    	//根据参数a,b自动调整横纵轴
    	for(t=1,x=1;t<(100/oscilldev.b)-1;t++,x+=oscilldev.b)
    	{
    		OLED_DrawLine_1(x,62-(double)(oscilldev.buffer[t])/4095/oscilldev.a*45,x+oscilldev.b,62-(double)(oscilldev.buffer[t+1])/4095/oscilldev.a*45);
    	}
    	//补画尾巴
    	OLED_DrawLine_1(x,62-(double)(oscilldev.buffer[t])/4095/oscilldev.a*45,100,62-(double)(oscilldev.buffer[t])/4095/oscilldev.a*45);
    }​

    /波形显示函数
    void DrawOscillogram(uint8_t ch)//画波形图
    {
    	uint8_t t;
    
    	if(oscilldev.flag == 0)//判断是否采集完
    	{
    		oscilldev.flag = 1;
    
    	  //for(t=4;t<124;t++)
    		for(t=1;t<(100/oscilldev.b);t++)//存储AD数值
    		{
    			oscilldev.buffer[t] =Get_Adc(ch);
    			//printf("%f\r\n",((float)(oscilldev.buffer[t])/4095*3.3));
    			if(oscilldev.tim==10000)	LL_mDelay(10);//改变AD取样间隔
    			else	TIM1_uDelay(oscilldev.tim);
    		}
    
    		OLED_Clear();
    		Draw_BianKuang();
    		Draw_GeZi();
    		Draw_BoXing();
    		OLED_Refresh_345678();//单刷新波形区域,不刷新上部
    		//OLED_Refresh();
    		LL_mDelay(50);
    
    		oscilldev.flag = 0;
    	}
    	else ;
    
    	//功能选择函数
    	if(KEY_Value != 254)
    	{
    		if(KEY_Value==L_Value)//对menu值的操作,进行选择移动
    		{
    			if(menu>1)menu--;
    
    		}
    		if(KEY_Value==R_Value)
    		{
    			if(menu<3)menu++;
    		}
    		if(KEY_Value==U_Value)//根据menu进行不同的操作赋值
    		{
    			if(menu==1)
    			{
    				if(oscilldev.tim>10)oscilldev.tim/=10;
    				else if(oscilldev.tim==10)oscilldev.tim=1;
    			}
    			if(menu==2)
    			{
    				if(oscilldev.a<1)oscilldev.a+=0.2;
    			}
    			if(menu==3)
    			{
    				if(oscilldev.b==2)oscilldev.b=4;
    				if(oscilldev.b==1)oscilldev.b=2;
    			}
    		}
    		if(KEY_Value==D_Value)
    		{
    			if(menu == 1)
    			{
    				if(oscilldev.tim<10000)oscilldev.tim*=10;
    			}
    			if(menu == 2)
    			{
    				if(oscilldev.a>0.6)oscilldev.a-=0.2;
    			}
    			if(menu == 3)
    			{
    				if(oscilldev.b==2)oscilldev.b=1;
    				if(oscilldev.b==4)oscilldev.b=2;
    			}
    		}
    		if(KEY_Value==OK_Value)//连按两次ok返回功能选择界面
    		{
    			KEY_Value=254;
    			LL_mDelay(1000);
    			if(KEY_Value==OK_Value)
    			{
    				Fun_Flag=1;
    				OLED_Clear();
    				OLED_ShowString(10, 4, "wait...", 16, 1);
    				OLED_Refresh();
    				LL_mDelay(1000);
    
    			}
    
    		}
    		Draw_CanShu();
    		OLED_Refresh_12();//单刷新上部,不刷新波形区域
    		//OLED_Refresh();
    		KEY_Value=254;
    	}
    }​
  • 上位机部分采用C#开发,功能比较简单,通过几个按钮,给单片机发送指定的字节,实现功能转换。
    上位机

源码下载:

 程序:链接:https://pan.baidu.com/s/1KAOS7wciKGL8-cRCQ7MC1A
          提取码:zodq

二进制烧录文件:链接:https://pan.baidu.com/s/1ILy_WQ7AM_6rrDV0ijLVyw
                       提取码:ppap

上位机:链接:https://pan.baidu.com/s/19Lot_To_gIyktd0X4Ukk3w
            提取码:d02r

附件下载
stm32g0_scope_V1.4发布.7z
程序主要源码,main中while仅留下了Mic示波函数
stm32g0_scope_V0.bin
二进制烧录文件
Mini_ScopeV0.7z
上位机程序源码,有可直接运行的exe
团队介绍
南京信息工程大学 电子信息类(3)班
团队成员
沈佳杰
长望学院
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号