STM32简易示波器

第一次写博客,也是想分享一下自己的心得体会。本人大三,因为准备比赛的缘故,需要做一个示波器,因为不是想做一个成品,所以只是实现了基本功能,后续的话也不会再用这个,更多的是体会过程。此文章主要是给像我这样的初学者一个参考,当时做的时候看到了很多大佬的成品,感觉一上来看一些很完美的代码看不太懂,所以想自己写一个东西。这东西是和同学一起做的,他用另一块单片机进行AD采样,通过串口发送给STM32,然后从寄存器中读出来数据(关于32的AD采集内容可以去看其他大佬的文章)。当时有事没要来他的代码,这里主要说一下有关通信和显示的部分。一块单片机能完成的事情为什么要用两块?文章最后会给出说明。废话不多说,开始进入正题。

1.串口通讯部分

串口设置的一般步骤可以总结为如下几个步骤:

  1. 串口时钟使能, GPIO 时钟使能
  2. 串口复位
  3. GPIO 端口模式设置
  4. 串口参数初始化
  5. 开启中断并且初始化 NVIC(如果需要开启中断才需要这个步骤)
  6. 使能串口
  7. 编写中断处理函数

查看手册得知, 配置全双工的串口 1,那么 TX(PA9)管脚需要配置为推挽复用输出, RX(PA10)管脚配置为浮空输入或者带上拉输入。 模式配置参考下面表格:

在这里插入图片描述串口的GPIO 端口模式设置和初始化都是一些套路性的东西,比较重要的是中断处理函数的编写,这里代码我是参考原子来的,感觉原子哥写的很巧妙:

u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大字节数
//接收状态
//bit15 接收完成标志
//bit13 接收到的有效字节长度
u16 USART_RX_STA=0;       //接受状态标志

因为TFT屏幕用的是ILI9328型号,分辨率240*320,所以在usart.h里把最大字节数定义为260,可以一次性从USART_RX_BUF[ ]中读260个值送入显示。这里我适当修改了原子的中断服务程序:

void USART1_IRQHandler(void)                 //串口1中断服务程序
 {
	 u8 Res;
	#if SYSTEM_SUPPORT_OS   //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	   OSIntEnter();    
	#endif
	 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
	  {
	  Res =USART_ReceiveData(USART1); //读取接收到的数据
	  
	  if((USART_RX_STA&0x8000)==0)//接收未完成
	   {
	      if(USART_RX_STA<USART_REC_LEN)  //还可以接收数据    
	      {
	          USART_RX_BUF[USART_RX_STA++]=Res;  //记录接收到的值 
	       }else 
	         {
	            USART_RX_STA|=1<<15;     //强制标记接收完成,可以看成0x8000
	         }     
	       } 
	    }
	#if SYSTEM_SUPPORT_OS  //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	   OSIntExit();              
	#endif
} 

原子的程序是接收到回车符视为一次接受完成,考虑到这样会降低通信的效率,所以我把它改成了接收到260个字符视为一次完成。这一段代码好好看看,写的特别好,有些地方也不是很好懂。

/*****************************串口接收***********************************/                                                                                       
  if(USART_RX_STA&0x8000)
  {        
   len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
   for(t=0;t<len;t++)
   {
    USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
    while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
   }
   USART_RX_STA=0;
  }
/*************************************************************************/  

我们发送一个数据到串口USART_RX_BUF[ ]中(数据就可以从这个寄存器中取了),之后,要检测这个数据是否已经被发送完成了。 USART_FLAG_TC 是宏定义的数据发送完成标识符。

2.TFT显示部分

首先,在工程中加入和TFTLCD相关的.c文件和.h文件,基本的GPIO定义就不说了。当时做的时候遇到了一个难题,就是如何让LCD横屏显示,如果你是原子的屏,改一个参数就OK了,但我的屏文件里的代码只有一些基本的,胡乱改了好多东西,显示的都是乱码,当时心里是崩溃的,实在是不想放弃,后来硬着头皮查了下LCD和扫描有关的寄存器,终于算是成功了。

1.显存控制方式 (AM、I/D0、I/D1)

在这里插入图片描述

2.扫描线控制方式(R01h)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
上面说的有点晦涩难懂,简单来说就是修改01h,03h,60h的控制指令。而Write_Cmd_Data0x_ _,0x _ _ )就是分别写入指令和数据,实际上是这一个函数调用了两个函数,简化了代码。

Write_Cmd_Data(0x0001,0x0000);   //set SS and SM bit //设置扫描方向  
Write_Cmd_Data(0x0003,0x1038);   //set Entry Mode  //设置进入模式  
Write_Cmd_Data(0x0060,0xA700); // Gate Scan Line

void LCD_SetPos(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1)
{
     Write_Cmd_Data(0x50,y0);  // Horizontal GRAM Start Address
     Write_Cmd_Data(0x51,y1);  // Horizontal GRAM End Address
     Write_Cmd_Data(0x52,x0);  // Vertical GRAM Start Address
     Write_Cmd_Data(0x53,x1);  // Vertical GRAM Start Address
     Write_Cmd_Data(0x20,y0);  // GRAM horizontal Address
     Write_Cmd_Data(0x21,x0);  // GRAM Vertical Address
     Write_Cmd(0x00,0x22);    // 0x0022,Start to Write Data to GRAM 
}

下面是我总结的表格:

LCD 扫描指令1LCD扫描指令2
0x01, 0x00000x01, 0x0100
0x03, 0x10380x03, 0x1030
0x60, 0xA7000x60, 0x2700

把0x20和0x21后面的参数互相调一下,上面的带代码已经调过了。
不同型号的屏的修改方式不同,不同人写的代码,这几个函数的写法也不同,大家可以自己修改尝试一下,大概有8种可能的显示方式(因为有些组合是乱码)。

接下来就是从USART_RX_BUF[ ]中取数据的程序,

for(n=0;n<260;n++) //从串口寄存器中取
  {
        adc1[n]=USART_RX_BUF[n];
  }
  for(n=0;n<260;n++) 
  {
        adc[n]=16*(adc1[n])+adc1[n+1]+120;
  }

这里多加了一个adc1[ ]数组作为过渡,不写这个的话不知道为什么取出来的数莫名其妙的变得特别大,后来把这几个寄存器中的值都显示出来计算分析了一下找到了问题所在。因为我接收到的数值是十六进制的,所以在取高位时乘了16。刚开始认为得到的值是ASCII码,应该减去**‘0’**才是真值,但那样写了不对,所以就删掉了。在接收数据之前,可以先自己用串口调试助手调试一下,给大家看一下我调试的结果:
在这里插入图片描述
右边的频率和峰值什么的参数,本来是想加的,但时间不允许了,就把它糊弄过去了,要加的话,只需让发送方周期性的发送这些信息(例如每发260个点发一次)。波形还是挺漂亮的!

3.示波器最终效果(半成品)

在这里插入图片描述
采样的波形把网格线刷掉了,时间原因就没有去掉,之前从网上看到过,是一篇LCD的“或关系”显示的文章,有想完善的朋友可以完善一下。出现了波形失真是因为当时用信号发生器时忘了加直流偏移量,一般要加到峰峰值的一半以上,AD采样的芯片采不到真正的0,忘加直流偏移量可能会烧芯片,幸好我们的没烧。这里说明一下为什么要用通信的方法,单片机外设接的多了必然会影响速度,而且采样到的波形会有很多毛刺,所以真正显示的波形以后要改成自己生成的所谓的“完美波形”,串口发送的也不再是一系列的点,而是波形的信息。
当然还有一点更重要的,提供的单片机的型号是STM32F103C8T6,端口实在是少得可怜,插上TFT屏之后ADC端口就用不了了,改端口的话还要自己插线,麻烦得很,就偷了个懒。

代码在下面的链接里,大家可以自行下载:
STM32简易示波器
https://download.csdn.net/download/qq_42628795/10926556

如果觉得还不错的话,求个点赞啊!!!

  • 72
    点赞
  • 209
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
STM32简易示波器是一种基于STM32单片机的简单示波器,用于测量和显示电压信号的波形。它通过采集输入信号的模拟电压,并在液晶显示屏上实时显示相应的波形图。 STM32简易示波器具有以下主要特点: 1. 高精度: STM32单片机采用高精度的模数转换器(ADC),可以准确地将输入信号的模拟电压转换为数字信号。 2. 快速采样率: STM32单片机的高速时钟和优化的固件编程,使得示波器具有较高的采样率,可以准确地捕捉和显示快速变化的波形。 3. 多通道显示: STM32简易示波器具有多个输入通道,并可以在液晶显示屏上同时显示多个波形图,方便用户在测量中进行比较和分析。 4. 可调参数: 示例波形的时间和电压尺度可以通过用户界面进行调整,以适应不同的测量需求。用户可以根据实际情况选择合适的尺度,以获得更清晰的波形显示。 5. 数据记录: 示波器具有数据记录功能,可以将测量的波形数据保存在存储设备中,以便后续分析和处理。 6. 用户友好界面: STM32简易示波器具有易于操作的用户界面,用户可以通过按钮和旋钮进行参数调整和功能选择。 由于STM32简易示波器采用的是单片机设计,有一定的硬件和软件限制,因此它的功能和性能相对较简单。但对于一般的电子爱好者和学生来说,它已经具备了基本的测量和显示功能,能够满足日常的电路调试和实验需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值