基于STM32的简易数字电子示波器项目

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

示波器是电子工程师必不可少的工具,按照信号的不同分为模拟示波器以及数字示波器两种,模拟示波器采用模拟电路和电子枪,通过电子束打在屏幕上显示波形,而数字示波器采用数字电路和数字存储技术,将波形数字化并显示出来。

简介

实验硬件:STM32F103C8T6核心板、1.8寸TFTLCD显示屏(ST7735S)、PCB板;

成品展示:

一、示波器的应用?

示波器是用来观测和分析电信号的仪器,广泛应用于电子、通信、计算机等领域。在计算机科学中,示波器主要有以下应用:

1. 故障排除:示波器可以用于调试和排除电路中的故障。通过观察电路中的信号波形,可以确定信号是否正确、是否存在干扰或损坏等问题,从而定位和解决故障。

2. 时序分析:示波器可以用来观察和分析电子系统中的时序关系,比如时钟信号、数据传输的时机等。通过对时序关系的分析,可以找到系统中的时序问题,并进行优化和改进。

3. 数据分析:示波器可以捕获和分析数据信号的波形和特征。在计算机网络中,可以用示波器来观察和分析数据包的传输情况,包括传输速率、时延、丢包率等。在存储系统中,可以用示波器来观察和分析磁盘读写操作的波形,包括读写速率、延迟等。

4. 性能评估:示波器可以用来评估计算机系统的性能。通过捕获和分析系统中的信号波形,可以确定系统的响应时间、吞吐量、资源利用率等性能指标,从而进行性能分析和优化。

总之,示波器在计算机科学中广泛应用于故障排除、时序分析、数据分析和性能评估等方面,帮助工程师和研究人员更好地理解和改进电子系统的工作原理和性能。

二、原理分析

1.硬件部分

数字示波器是一种用于显示电信号波形的仪器,主要由模拟前端处理电路、电源电路、单片机电路、人机交互电路等电路组成。

(1)模拟前端处理电路:负责将输入的检测模拟信号进行处理后给单片机进行识别,具体电路包括了交直流耦合选择电路、电压衰减电路、信号处理电路以及频率检测电路,是整个电路的核心。

(2)电源电路:负责给运放提供正负电源以及系统供电,是保障电路正常运行的基础;

(3)单片机电路:给系统提供控制核心,负责对输入信号的采集与处理输出工作;

(4)人机交互电路:用于控制示波器功能,包括按键、旋钮、LED灯、显示屏以及其它输入输出接口,为示波器功能的开发提供基础。

2.软件部分

(1)ADC部分

  ADC是一种用于将模拟信号转换为数字信号的模拟数字转换器。STM32F103 系列最少都拥有 2 个 ADC,我们的C8T6刚好是2个ADC,STM32 的 ADC 最大的转换速率为 1Mhz,也就是转换时间为 1us。

(2)PWM部分

PWMPulse-width modulation)是脉冲宽度调制的缩写。脉冲宽度调制是一种模拟信号电平数字编码方法。

PWM是脉冲宽度调制,具有两个非常重要的参数:频率和占空比。

  • 频率:PWM的频率是整个周期的倒数。
  • 占空比:占空比是指一个周期内高电平所占的比例。

注意:定时器通道输出默认是关闭的,若没打开通道仅使能定时器,会发现没有任何效果,则PWM输出无效。

(3)TFTLCD显示

TFT屏主要的构成包括:背光源、导光板、扩散膜、棱镜膜、配向膜、液晶材料、薄膜晶体管等。该实验使用的是ST7735驱动芯片,引脚接口为四线SPI通信方式。

一般使用TFT屏幕驱动,都需要有以下几个步骤:

    • 配置TFT屏幕引脚GPIO&时钟
    • 配置SPI驱动引脚&时钟
    • 配置SPI通信参数
    • 使能SPI
    • 编写SPI发送数据函数
    • 编写TFT屏幕发送数据函数
    • 编写TFT屏幕发送命令函数
    • 编写TFT屏幕设置起始地址函数
    • 编写TFT屏幕初始化函数

同时,不建议大家自己编写初始化部分代码,十分繁琐且容易出现问题,可以和店家或者网上自己寻找。

代码部分

#include "tft_init.h"
#include "tft.h"
#include "delay.h"
/*
*   函数内容:初始化SPI0引脚
*   函数参数:无
*   返回值:无
*/
static void Init_SPI0_GPIO(void)
{
  //SPI句柄
  SPI_InitTypeDef SPI_InitStructure;
  //GPIO句柄
	GPIO_InitTypeDef GPIO_InitStructure;
  /* 使能SPI时钟 */
	RCC_APB2PeriphClockCmd ( RCC_APB2Periph_SPI1, ENABLE );
  /* 使能端口时钟 */
	RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA, ENABLE );
  /* 使能端口时钟 */
	RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOB, ENABLE );
  /* 使能复用时钟 */
	RCC_APB2PeriphClockCmd ( RCC_APB2Periph_AFIO, ENABLE );
  
  /************引脚配置*************/
  
	GPIO_InitStructure.GPIO_Pin = TFT_SPI_CS_PIN;  //SPI_NSS-CS
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(TFT_SPI_CS_PORT, &GPIO_InitStructure);
	TFT_CS_HIGH();//拉高CS电平
  
	GPIO_InitStructure.GPIO_Pin = TFT_SPI_SCK_PIN;		//SPI_SCK
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(TFT_SPI_SCK_PORT, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin =  TFT_SPI_MISO_PIN;		//SPI_MISO
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(TFT_SPI_MISO_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = TFT_SPI_MOSI_PIN;        //SPI_MOSI
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(TFT_SPI_MOSI_PORT, &GPIO_InitStructure);


  /* SPI 模式配置 */
  SPI_Cmd(TFT_SPIx, DISABLE);	 //必须先禁用,才能改变MODE
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//单线发送
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主机模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8bit数据位宽
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//时钟级性高
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//时钟触发模式第二边沿
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//软件触发片选
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//分频
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
  SPI_InitStructure.SPI_CRCPolynomial = 7;//数据校验
  SPI_Init(TFT_SPIx , &SPI_InitStructure);

  /* 使能 SPI  */
  SPI_Cmd(TFT_SPIx , ENABLE);

}

/*
*   函数内容:SPI0发送数据
*   函数参数:无
*   返回值:无
*/
static void SPI0_Write(uint8_t TxData)
{
    //等待发送缓冲区空闲
    while(SPI_I2S_GetFlagStatus(TFT_SPIx,SPI_I2S_FLAG_TXE)==RESET);
    TFT_SPIx->DR=TxData; //通过外设SPIx发送一个byte  数据
    TFT_SPIx->SR&=(1<<0);
//  //经试验发现单线模式下在发送数据时不能使用SPI_I2S_FLAG_TXE来判断发送完成,
//  //只能使用SPI_I2S_FLAG_BSY标志来判断设备是否空闲。
//    while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_BSY)== SET){}
}

/*
*   函数内容:初始化REST和BLK引脚
*   函数参数:无
*   返回值:无
*/
static void TFT_GPIO_Init(void)
{
  //GPIO初始化句柄
	GPIO_InitTypeDef GPIO_InitStructure;  
  
  //配置REST接口
  RCC_APB2PeriphClockCmd(REST_GPIO_CLK,ENABLE);
  GPIO_InitStructure.GPIO_Pin = REST_GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(REST_GPIO_PORT, &GPIO_InitStructure);
  
  //配置TFT_BLK
  RCC_APB2PeriphClockCmd(BLK_GPIO_CLK,ENABLE);
  GPIO_InitStructure.GPIO_Pin = BLK_GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(BLK_GPIO_PORT, &GPIO_InitStructure);
  
  //配置TFT_DC
  RCC_APB2PeriphClockCmd(DC_GPIO_CLK,ENABLE);
  GPIO_InitStructure.GPIO_Pin = DC_GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(DC_GPIO_PORT, &GPIO_InitStructure);
}

/*
*   函数内容:TFT发送单个字节数据
*   函数参数:无
*   返回值:无
*/
void TFT_WR_DATA8(uint8_t data)
{
    SPI_TFT_CS_LOW();   //拉低片选信号
    
    SPI0_Write(data);
    
    SPI_TFT_CS_HIGH();     //拉高片选信号
}

/*
*   函数内容:TFT发送2个字节数据
*   函数参数:无
*   返回值:无
*/
void TFT_WR_DATA(uint16_t data)
{
    SPI_TFT_CS_LOW();   //拉低片选信号
    
    SPI0_Write(data>>4);
    
    SPI0_Write(data);
    
    SPI_TFT_CS_HIGH();     //拉高片选信号
}

/*
*   函数内容:TFT发送命令数据
*   函数参数:无
*   返回值:无
*/
void TFT_WR_REG(uint8_t reg)
{
    SPI_TFT_CS_LOW();   //拉低片选信号
    TFT_DC_LOW();       //拉低片选信号
    
    SPI0_Write(reg);
    
    TFT_DC_HIGH();     //拉高命令信号
    TFT_DC_HIGH();;     //拉高片选信号
}


void TFT_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
	if(USE_HORIZONTAL==0)
	{
		TFT_WR_REG(0x2a);//列地址设置
		TFT_WR_DATA(x1+2);
		TFT_WR_DATA(x2+2);
		TFT_WR_REG(0x2b);//行地址设置
		TFT_WR_DATA(y1+1);
		TFT_WR_DATA(y2+1);
		TFT_WR_REG(0x2c);//储存器写
	}
	else if(USE_HORIZONTAL==1)
	{
		TFT_WR_REG(0x2a);//列地址设置
		TFT_WR_DATA(x1+2);
		TFT_WR_DATA(x2+2);
		TFT_WR_REG(0x2b);//行地址设置
		TFT_WR_DATA(y1+1);
		TFT_WR_DATA(y2+1);
		TFT_WR_REG(0x2c);//储存器写
	}
	else if(USE_HORIZONTAL==2)
	{
		TFT_WR_REG(0x2a);//列地址设置
		TFT_WR_DATA(x1);
		TFT_WR_DATA(x2);
		TFT_WR_REG(0x2b);//行地址设置
		TFT_WR_DATA(y1);
		TFT_WR_DATA(y2);
		TFT_WR_REG(0x2c);//储存器写
	}
	else
	{
		TFT_WR_REG(0x2a);//列地址设置
		TFT_WR_DATA(x1);
		TFT_WR_DATA(x2);
		TFT_WR_REG(0x2b);//行地址设置
		TFT_WR_DATA(y1);
		TFT_WR_DATA(y2);
		TFT_WR_REG(0x2c);//储存器写
	}
}

void TFT_Init(void)
{
    TFT_GPIO_Init();
    Init_SPI0_GPIO();
    
    TFT_REST_LOW();   //复位
    delay_ms(100);
    TFT_REST_HIGH();     //
    delay_ms(50);
    
    TFT_BLK_HIGH();     //打开背光
    delay_ms(100);
	//************* Start Initial Sequence **********//
	TFT_WR_REG(0x11); //Sleep out 
	delay_ms(120);              //Delay 120ms 
	TFT_CS_LOW();
	//------------------------------------ST7735S Frame Rate-----------------------------------------// 
	TFT_WR_REG(0xB1); 
	TFT_WR_DATA8(0x01); 
	TFT_WR_DATA8(0x2C); 
	TFT_WR_DATA8(0x2D);
	
	TFT_WR_REG(0xB2); 
	TFT_WR_DATA8(0x01);
	TFT_WR_DATA8(0x2C); 
	TFT_WR_DATA8(0x2D); 
	
	TFT_WR_REG(0xB3); 
	TFT_WR_DATA8(0x01);
	TFT_WR_DATA8(0x2C); 
	TFT_WR_DATA8(0x2D); 
	TFT_WR_DATA8(0x01);
	TFT_WR_DATA8(0x2C); 
	TFT_WR_DATA8(0x2D); 
	//------------------------------------End ST7735S Frame Rate---------------------------------// 
	TFT_WR_REG(0xB4); //Dot inversion 
	TFT_WR_DATA8(0x07); 
	//------------------------------------ST7735S Power Sequence---------------------------------// 
	TFT_WR_REG(0xC0); 
	TFT_WR_DATA8(0xA2); 
	TFT_WR_DATA8(0x02); 
	TFT_WR_DATA8(0x84); 
	TFT_WR_REG(0xC1); 
	TFT_WR_DATA8(0XC5);
	
	TFT_WR_REG(0xC2); 
	TFT_WR_DATA8(0x0A); 
	TFT_WR_DATA8(0x00); 
	
	TFT_WR_REG(0xC3); 
	TFT_WR_DATA8(0x8A); 
	TFT_WR_DATA8(0x2A); 
	TFT_WR_REG(0xC4); 
	TFT_WR_DATA8(0x8A); 
	TFT_WR_DATA8(0xEE); 
	//---------------------------------End ST7735S Power Sequence-------------------------------------// 
	TFT_WR_REG(0xC5); //VCOM 
	TFT_WR_DATA8(0x0E); 
	
	TFT_WR_REG(0x36); //MX, MY, RGB mode 
	TFT_WR_DATA8(0x70);
  
	//------------------------------------ST7735S Gamma Sequence---------------------------------// 
	TFT_WR_REG(0xE0); 
	TFT_WR_DATA8(0x0F); 
	TFT_WR_DATA8(0x1A); 
	TFT_WR_DATA8(0x0F); 
	TFT_WR_DATA8(0x18); 
	TFT_WR_DATA8(0x2F); 
	TFT_WR_DATA8(0x28); 
	TFT_WR_DATA8(0x20); 
	TFT_WR_DATA8(0x22); 
	TFT_WR_DATA8(0x1F); 
	TFT_WR_DATA8(0x1B); 
	TFT_WR_DATA8(0x23); 
	TFT_WR_DATA8(0x37); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x07); 
	TFT_WR_DATA8(0x02); 
	TFT_WR_DATA8(0x10); 
	
	TFT_WR_REG(0xE1); 
	TFT_WR_DATA8(0x0F); 
	TFT_WR_DATA8(0x1B); 
	TFT_WR_DATA8(0x0F); 
	TFT_WR_DATA8(0x17); 
	TFT_WR_DATA8(0x33); 
	TFT_WR_DATA8(0x2C); 
	TFT_WR_DATA8(0x29); 
	TFT_WR_DATA8(0x2E); 
	TFT_WR_DATA8(0x30); 
	TFT_WR_DATA8(0x30); 
	TFT_WR_DATA8(0x39); 
	TFT_WR_DATA8(0x3F); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x07); 
	TFT_WR_DATA8(0x03); 
	TFT_WR_DATA8(0x10);
	
  TFT_WR_REG(0x2A); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x7F);
	
  TFT_WR_REG(0x2B); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x00); 
	TFT_WR_DATA8(0x9F);	
	
  TFT_WR_REG(0xF0); 
	TFT_WR_DATA8(0x01); 
	TFT_WR_REG(0xF6); 
	TFT_WR_DATA8(0x00); 
	//------------------------------------End ST7735S Gamma Sequence-----------------------------// 
	TFT_WR_REG(0x3A); //65k mode 
	TFT_WR_DATA8(0x05); 
	
	TFT_WR_REG(0x29); //Display on   
}


最后

工程资源来源于嘉立创训练营,对其进行了部分改动(毕竟要适合于自己的板子)

 链接:https://pan.baidu.com/s/1B8Zj6ZBQJvG4gFpFvUhydA 
提取码:32fk 
 

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-03-27 10:54:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-27 10:54:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-27 10:54:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-27 10:54:01       20 阅读

热门阅读

  1. 微信小程序对于回调函数异步API的优化

    2024-03-27 10:54:01       18 阅读
  2. 深度学习调参指南

    2024-03-27 10:54:01       16 阅读
  3. 什么是软件工程?如何应用软件工程原则?

    2024-03-27 10:54:01       17 阅读
  4. 卸载docker

    2024-03-27 10:54:01       13 阅读
  5. linux - rm命令删除文件到垃圾箱

    2024-03-27 10:54:01       15 阅读
  6. 决策树学习-计算数据集的信息熵

    2024-03-27 10:54:01       18 阅读
  7. c# 执行动态编译的方法

    2024-03-27 10:54:01       19 阅读
  8. C语言动态分配数组

    2024-03-27 10:54:01       18 阅读
  9. rust - 动态构造文件名字符串

    2024-03-27 10:54:01       19 阅读
  10. elementui的tree默认高亮显示无效的问题

    2024-03-27 10:54:01       19 阅读
  11. @JsonFormat(pattern = “yyyy-MM-dd“) 年月日用法

    2024-03-27 10:54:01       16 阅读