Osciloscopio simple casero

De hecho, quería usar un osciloscopio cuando estaba clasificando los componentes disponibles, pero no tenía uno, así que pensé en fabricar uno yo mismo para satisfacer mis necesidades simples.

Después de la prueba, la forma de onda de 10Khz e inferior se puede mostrar normalmente, puede ir al final del artículo para ver el efecto primero. No se han probado frecuencias más altas. La desventaja es: solo se puede medir el voltaje positivo, 0-3.3. En general, es suficiente medir la salida de onda PWM de la placa de desarrollo al depurar el motor.

====>>> Resumen del artículo (con código resumen) <<<====

1. Preparación de hardware

  1. Puntual atom STM32F103 Mini placa de desarrollo, el control principal STM32F103RCT6.
  2. Pantalla LCD de 2,8 pulgadas a juego.

Otras placas de desarrollo también están bien, siempre que puedan controlar esta pantalla.
Para la placa de desarrollo de Puzhong, mi página de inicio también tiene el mismo tutorial del controlador de pantalla LCD, que puede reemplazar directamente el trasplante.

2. Planificación de software

Sección de Monitoreo del Osciloscopio

  1. El temporizador activa el ADC con regularidad;
  2. ADC monitorea los cambios de voltaje;
  3. Datos de transferencia DMA Datos ADC.

Parte de la pantalla:

  1. pantalla LCD para visualización;

3. Configuración de hardware

3.1 Crear un proyecto

Seleccione el maestro STM32F103RCT6;

Configurar la interfaz de depuración
inserte la descripción de la imagen aquí
Configurar el reloj externo
inserte la descripción de la imagen aquí
Configurar
inserte la descripción de la imagen aquí
los ajustes del proyecto del árbol del reloj
inserte la descripción de la imagen aquí

3.2 Configuración LCD

Si es perezoso, puede tomar directamente el proyecto de software que simula la interfaz 8080 para controlar la pantalla LCD (hay un artículo en la parte superior de la página de inicio). Omita los pasos anteriores y los pasos de esta sección.

Debido a que la pantalla LCD ocupa muchos pines y está fijada en la placa de desarrollo, y ADC y similares, todos tienen opciones, así que configure esto primero.

Aquí se utiliza la placa de desarrollo STM32F103 Mini atom puntual, que está impulsada por el protocolo de comunicación 8080 de simulación de software.

Ya se ha mencionado la configuración de la pantalla LCD, por lo que no la repetiré aquí. Consulte la pantalla LCD de la unidad de puerto paralelo 8080 de simulación de software que forma parte del artículo anterior.

====>>> Configuración LCD aquí<<<====

En la figura se muestra la distribución de huellas después de completar la configuración.

inserte la descripción de la imagen aquí
Luego agregue el archivo del controlador LCD. Primero pruebe si la pantalla LCD se puede manejar normalmente. Por la misma razón, consulte el artículo mencionado anteriormente.

inserte la descripción de la imagen aquí

Si es perezoso, puede tomar directamente el proyecto de software que simula la interfaz 8080 para controlar la pantalla LCD (hay un artículo en la parte superior de la página de inicio). Omita los pasos anteriores y los pasos de esta sección.

Con la pantalla LCD funcionando, comience a configurar el resto.

3.3 Configuración del temporizador

Debido a que es necesario asegurarse de que el intervalo de tiempo utilizado por el ADC sea el mismo cada vez, no es posible realizar un muestreo cíclico en while(1).

En el "Manual de referencia en chino STM32", puede ver el siguiente contenido.
inserte la descripción de la imagen aquí
Es decir, se puede usar un temporizador para activar el muestreo ADC.

Por lo tanto, configure de la siguiente manera.
inserte la descripción de la imagen aquí

Todos los temporizadores están colgados en APB1 y APB2, y la frecuencia del reloj es la misma, ambos son de 72 MHz.
Aquí 分频系数为 36-1, la frecuencia después de la división de frecuencia es 72Mhz / 36 = 2Mhzy el valor de conteo es 100, es decir, 20000se genera una interrupción cada segundo.

Es decir, el ADC se activa 20 000 veces por segundo. En otras palabras, la frecuencia de muestreo del ADC es 20000HZ.

3.4 Configuración del ADC

Simplemente elija un canal ADC.

  1. Para establecer la alineación de datos, generalmente elija la alineación correcta directamente.
  2. No es necesario configurar el escaneo y el ciclo.
  3. Establecer como disparador de evento externo del temporizador 3.
  4. Establecer el período de adopción.
  5. Configure DMA, desde periféricos hasta memoria.
    inserte la descripción de la imagen aquí

DMA necesita transferir datos cíclicamente.

inserte la descripción de la imagen aquí
Después de configurar el ADC, también se debe cambiar el reloj del ADC. Antes de configurar el ADC, este lugar es gris. Se puede cambiar ahora y no debe exceder los 14 Mhz después de la configuración.
inserte la descripción de la imagen aquí

3.5 Configuración de teclas

Para ajustar la visualización del osciloscopio, hay una perilla en el osciloscopio serio, que aquí se reemplaza por botones, y una placa de desarrollo funciona en conjunto.

Hay tres botones en la placa de desarrollo. WK_UP, KEY0, KEY1. El diagrama esquemático es el siguiente, y estos tres botones están configurados como interrupciones.

  • WK_UP: Interrupción de flanco ascendente, desplegable;
  • KEY0: Interrupción de borde descendente, pull-up;
  • KEY1: Interrupción de borde descendente, pull-up;

inserte la descripción de la imagen aquí

A lo que se debe prestar atención es a la prioridad de la interrupción clave y la interrupción DMA (la prioridad de interrupción relacionada con DMA siempre debe depurarse durante mucho tiempo... No entiendo, estoy cansado, compensaré la investigación y estudiar en otro día).

inserte la descripción de la imagen aquí

3.6 Configuración de luces indicadoras

Finalmente, configure una luz indicadora para dar un recordatorio, deje que el LED se encienda antes de que se actualicen los datos, y apáguelo después de que se actualice la forma de onda, y luego enciéndalo nuevamente cuando se adquieran los datos la próxima vez. . .

Hay dos diagramas esquemáticos en la placa de desarrollo, solo use uno aquí, elija LED0.
inserte la descripción de la imagen aquí

Configúralo como una salida push-pull, las demás no son importantes.

En este punto, todas las configuraciones se han ido, simplemente regenere el proyecto.

Cabe señalar que debido a que el código se regenera, si el archivo de origen y el archivo de encabezado de la pantalla LCD anterior desaparecen, debe agregar el archivo de origen y la ruta del archivo de encabezado nuevamente.

4. Código de programa

4.1 Código de interfaz gráfica de usuario

Planifique primero la interfaz de la pantalla LCD y empaquete el código del controlador LCD para facilitar el dibujo.

Echemos un vistazo al efecto final primero. El efecto de cuadrícula ya no debe cambiarse, y un texto estático que no necesita actualizarse se coloca en la función void setBackGroundText(void);y finalmente vuelve a cambiar de acuerdo con el diseño.

inserte la descripción de la imagen aquí

Cree una carpeta más dentro de la carpeta, cree icodey archive dentro de la carpeta . Y agregue el archivo fuente y el archivo de encabezado al proyecto en keil.GUIGUIgui.cgui.h

gui.h

#ifndef __GUI_H
#define __GUI_H

/*
	author:Haozi
	
	Author URI:https://blog.csdn.net/weixin_46253745
	
	Describe:对 LCD 的驱动文件进行了包装,方便绘制GUI
*/

#include "stdint.h"		// uint16_t 定义

void drawLineWithColor(uint16_t startX, uint16_t startY, uint16_t endX, uint16_t endY, uint16_t color);
void drawStringWithColor(uint16_t startX, uint16_t startY, uint16_t width, uint8_t *p, uint16_t color);
void setBackGroundColor(void);
void drawNetwork(void);
void setBackGroundText(void);

#endif

gui.c

#include "gui.h"
#include "stdint.h"		// uint16_t 定义
#include "lcd.h"

/*
	author:Haozi
	
	Author URI:https://blog.csdn.net/weixin_46253745
	
	Describe:对 LCD 的驱动文件进行了包装,方便绘制GUI
*/


/* ===================================================== */
// 描述:画线函数
// 参数:
//		起始和结束的x y坐标。
//		color:线的颜色
// 返回值:
/* ===================================================== */
void drawLineWithColor(uint16_t startX, uint16_t startY, uint16_t endX, uint16_t endY, uint16_t color)
{
    
    
	POINT_COLOR = color;
	LCD_DrawLine(startX, startY, endX, endY);
}


/* ===================================================== */
// 描述:显示字符串函数
// 参数:
//		startX、startY:起始的x y坐标。
//		width:			区域宽度。
//		p:				字符串地址。
//		color:			线的颜色
// 返回值:
/* ===================================================== */
void drawStringWithColor(uint16_t startX, uint16_t startY, uint16_t width, uint8_t *p, uint16_t color)
{
    
    
    POINT_COLOR = color;
	// 字符区域大小 和 字体大小 直接定死了
    LCD_ShowString(startX, startY, width, 16, 16, p);
}

/* ===================================================== */
// 描述:设置LCD背景。设置显示方向为横向;背景颜色为黑色。
// 参数:
// 返回值:
/* ===================================================== */
void setBackGroundColor(void)
{
    
    
	LCD_Display_Dir(1);		// 设置LCD显示方向为横向
	
	LCD_Clear(BLACK);		// 清空LCD,用黑色覆盖
	BACK_COLOR = BLACK;		// 背景颜色
	POINT_COLOR = YELLOW;	// 线的颜色
}

/* ===================================================== */
// 描述:显示字符串函数
// 参数:
//		startX、startY:起始的x y坐标。
//		width:			区域宽度。
//		p:				字符串地址。
//		color:			线的颜色
// 返回值:
/* ===================================================== */
void drawNetwork(void)
{
    
    
    uint16_t y = 0;
    uint16_t x = 0;
	
    for(x = 20; x < lcddev.width; x += 20)
    {
    
    
        for(y = 20; y < (lcddev.height - 20); y += 5)
        {
    
    
            LCD_Fast_DrawPoint(x, y, 0XAAAA);
        }
    }

    for(y = 20; y < (lcddev.height - 20); y += 20)
    {
    
    
        for(x = 0 ; x < lcddev.width ; x += 5)
        {
    
    
            LCD_Fast_DrawPoint(x, y, 0xAAAA);
        }
    }

	POINT_COLOR = 0X534c;
    drawLineWithColor(0, lcddev.height / 2, lcddev.width, lcddev.height / 2, POINT_COLOR);
    drawLineWithColor(lcddev.width / 2, 20, lcddev.width / 2, (lcddev.height - 20), POINT_COLOR);
    LCD_DrawRectangle(0, 20, lcddev.width, (lcddev.height - 20)); // 矩形
}

/* ===================================================== */
// 描述:设置背景上静态的文字
// 参数:
// 返回值:
/* ===================================================== */
void setBackGroundText(void)
{
    
    
	// 待定,最后根据布局再看吧。
}

Luego llámalo en la función principal para ver el efecto anterior.

// main函数上面
#include "lcd.h"
#include "gui.h"

	// main函数中
	
	// 1. 初始化LCD
	LCD_Init();

	// 2. 初始化 LCD 背景设置
	setBackGroundColor();	// 设置背景颜色
	drawNetwork();			// 绘制背景网络
	setBackGroundText();	// 设置背景静态文字

4.2 Adquisición y dibujo de tensión

Esta sección es la clave.

El método de adquisición del ADC está diseñado aquí y se muestra en la cuadrícula anterior.

Permítanme hablar sobre la idea primero, para que sea fácil de entender el código:
inserte la descripción de la imagen aquí
puede ver que, de acuerdo con esta idea, de hecho, el ADC no muestra continuamente el cambio de voltaje, sino que intercepta una sección a intervalos regulares. , intercepte de nuevo para evitar el impacto de la frecuencia de actualización de la pantalla LCD .

Cree una carpeta más dentro de la carpeta, cree icodey archive dentro de la carpeta . Y agregue el archivo fuente y el archivo de encabezado al proyecto en keil.OSCOSCosc.cosc.h

El código aquí es un poco largo, déjame decirte algunos puntos clave, todos los códigos están en el artículo superior de la página de inicio .

El código de inicialización es relativamente simple.

/* ===================================================== */
// 描述:示波器初始化
// 参数:
// 返回值:
/* ===================================================== */
void OSC_Init(void)
{
    
    
	// 初始化 示波器 背景设置
	setBackGroundColor();	// 设置背景颜色
	setBackGroundText();	// 设置背景静态文字
	
	// 1. adc校准
    HAL_ADCEx_Calibration_Start(&hadc1);
	// 2. 开启DMA传输
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&originalAdc, numOfCollect);
	// 3. 关掉传输一半中断
    __HAL_DMA_DISABLE_IT((&hadc1)->DMA_Handle, DMA_IT_HT);
	// 4. 设置ADC采样频率。并开始计时采样
    setAdcFrequency(numF);
    HAL_TIM_Base_Start(&htim3);
}

Código de interrupción DMA, esta sección es en realidad la clave en tiempo real, el código en el medio es un poco demasiado y se divide en varias funciones.

/* ===================================================== */
// 描述:DMA传输回调函数,用于绘制获取的ADC波形并输出提示信息。
// 参数:
// 返回值:
// 注意:在绘制期间,会关闭定时器,停止触发ADC。
// 		可以看出,这里的逻辑是,
//		1. 打开定时器计时,定时器开始计数,可以触发中断;
//		2. 定时器触发中断,ADC获取连续的一段电压值;(在这里频率是可以设置的)
//		3. 关闭定时器计数,ADC停止转换;
//		4. 绘制刚刚获取的ADC波形,绘制完成之后,再次打开定时器。
// 		
//		简单来说,其实电压值并不是在连续转换。而是转换一段 停一会 再次转换一段。
/* ===================================================== */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    
    
	// 失能定时器3
    HAL_TIM_Base_MspDeInit(&htim3);

    if(oscState == 1)
    {
    
    
        // HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
        drawStringWithColor(240, 1, 120, "Running ", YELLOW);
		/*
			显示所有需要的内容
			1. 绘制背景网格
			2. 计算被测波形的频率;
			3. 将波形显示在屏幕上;
			4. 更新波形信息
		*/
		
		// 执行过程中 让LED亮
		HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
		
		drawNetwork();
		updateWaveFrequency();
		OSC_ShowWave();
		OSC_ShowInfo();
		
		// 刷新完成之后 灭掉LED
		HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
    }
    else
    {
    
    
        drawStringWithColor(240, 1, 120, "Stopping", RED);
    }
	
	// 使能定时器3
    HAL_TIM_Base_MspInit(&htim3);
}

La lógica de las cuatro funciones en el medio es la lógica del diagrama de flujo de arriba, así que no lo pondré aquí, puedes descargar el proyecto directamente. Todos los artículos adhesivos de la página de inicio del código tienen

4.3 Función principal

En la función principal, en realidad es muy simple, solo inicialice, y el resto se realiza en la función de devolución de llamada e interrupción.

#include "lcd,h"
#include "osc,h"

// 1. 初始化LCD
LCD_Init();
// 2. 初始化示波器(核心代码)
OSC_Init();
// 3. 设置运行标志位
oscState = 1;

4.4 Proyecto de prueba (opcional)

Encuentre otra placa de desarrollo y use un temporizador para generar ondas PWM para realizar pruebas.

Aquí utilizo tres temporizadores de otra placa de desarrollo para generar ondas PWM de 100 Hz, 1 Khz y 10 Khz respectivamente.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

En la función principal, encienda el temporizador, configure un ciclo de trabajo al azar y luego intente monitorearlo.

	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
	
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 4000);
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, 8000);
	
	__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 300);
	__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 500);

	__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 20);
	__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 60);

5. Instrucciones de uso y prueba

Conecte la GND de las dos placas de desarrollo juntas.
Conecte el pin de la placa de desarrollo de la señal de salida al pin PA1 de la placa de desarrollo del osciloscopio.

Función de la tecla:

  1. Mantenga presionada la tecla WK_UP para pausar la actualización/reinicio;
  2. Presione brevemente la tecla WK_UP para cambiar de modo, el modo seleccionado tendrá un cuadrado, si se selecciona el desplazamiento medio, las dos líneas medias se volverán blancas;
  3. KEY0, KEY1, en diferentes modos, aumentar o disminuir.

El significado de la siguiente información:

  1. max: el valor de voltaje máximo en esta pantalla;
  2. min: el valor de voltaje máximo en esta pantalla;
  3. dif: la diferencia entre el voltaje máximo y mínimo en esta pantalla;
  4. Hz: La frecuencia de la señal a medir.

El significado de la información anterior:

  1. Rango de voltaje de visualización de 1 V/2 V/4 V;
  2. 5ms: Indica el tiempo real correspondiente a un pequeño cuadrado (un cuadrado compuesto por puntos rojos);
  3. Símbolo [—|—]: el desplazamiento izquierdo y derecho de la forma de onda.
  4. Ejecutando / Parando: estado del osciloscopio.

Parpadeo del LED: encendido significa que está midiendo y mostrando; apagado significa que se ha actualizado en la pantalla LCD.

Efecto de vídeo: https://www.bilibili.com/video/BV1AP411M75M/

Resultados de la prueba de 1000 HZ
inserte la descripción de la imagen aquí
Resultados de la prueba de 10000 HZ
inserte la descripción de la imagen aquí
Resultados de la prueba de onda sinusoidal
inserte la descripción de la imagen aquí
Resultados de la prueba de onda triangular
inserte la descripción de la imagen aquí

El código está en la parte superior del artículo en la página de inicio, o puede hacer clic en un botón de seguir o me gusta, y puedo enviárselo directamente en un chat privado.


Agenda para el 22 de febrero de 2023.
Acabo de depurar la onda PWM del motor y quería ver qué pasaría si medía el voltaje de 12 V, así que lo toqué por un momento. . . Chip quemado. . .
-100.
¡No intente con alto voltaje! ! !

Supongo que te gusta

Origin blog.csdn.net/weixin_46253745/article/details/128065037
Recomendado
Clasificación