stm32f103与2.4寸TFT可触液晶屏实现的数字示波器

一、移植文件

将 queue.c 、 queue.h两个文件添加到过程文件夹下

1.1 queue.c

#include "queue.h"
#include "key.h"

float queue1[MAXSIZE];
float queue2[MAXSIZE];
extern int lowfflag;
extern int key_par;

int Getmaxi(float *queue)
{
	int max = 0;
	int i;
	for (i = 1; i < MAXSIZE; i++)
	{
		if (queue[i] > queue[max])
		{
			max = i;
		}
	}
	return max;
}


int Getmini(float *queue)
{
	int min = 0;
	int i;
	for (i = 1; i < MAXSIZE; i++)
	{
		if (queue[i] < queue[min])
		{
			min = i;
		}
	}
	return min;
}



int countnum(float *queue)
{
	float tempuse;
	int i;
	int pos;
	int sum = 0;

	if (queue[0] > 0)
		tempuse = 1;
	else
		tempuse = -1;

	for (i = 1; i < MAXSIZE; i++)
	{
		if (tempuse*queue[i] < 0) //记下第一个异号的数据下标 并退出循环
		{
			pos = i;
			sum++;
			break;
		}
	}

	for (; pos < MAXSIZE; pos++)
	{
		if (tempuse*queue[pos] < 0)
		{
			sum++;
		}
		else
		{
			return sum;
		}
	}
	return -1;
}


void show_f(void)
{
#define xpos 254
	int ypos;
	float f1 = f1 = (50 / (countnum(queue1) * 2 * 0.0225096))*14.5031 - 2.6832;
	float f2 = f2 = (50 / (countnum(queue2) * 2 * 0.0225096))*14.5031 - 2.6832;
	GUI_SetFont(&GUI_Font20_ASCII);
	GUI_SetColor(GUI_YELLOW);
	ypos = 80;
	GUI_DispStringAt("f1:", xpos, ypos);

	ypos += 20;
	GUI_GotoXY(xpos, ypos);					//移动光标 显示频率
	if (lowfflag==1||lowfflag==3) f1 /= 14;
	if (f1 > 0)
		GUI_DispFloat(f1, 6);

	ypos = 200;
	GUI_DispStringAt("f2:", xpos, ypos);

	ypos += 20;
	GUI_GotoXY(xpos, ypos);					//移动光标 显示频率
	if (lowfflag==2||lowfflag==3) f2 /= 14;
	if (f2 > 0)
		GUI_DispFloat(f2, 6);
}


void show_maxmin(float max, float min, int adorder)
{
#define xpos 254
	int ypos = 0;
	GUI_SetFont(&GUI_Font20_ASCII);
	GUI_SetColor(GUI_YELLOW);
	if (adorder == 1)
	{
		ypos = 0;
		GUI_DispStringAt("min1:", xpos, ypos);

		ypos += 20;
		GUI_GotoXY(xpos, ypos);					//移动光标 显示最小值
		if (min < 0)
			GUI_DispFloat((min), 6);
		else
			GUI_DispFloat((min), 5);

		ypos += 20;
		GUI_DispStringAt("max1:", xpos, ypos);
		ypos += 20;
		GUI_GotoXY(xpos, ypos);					//移动光标 显示最大值
		if (max < 0)
			GUI_DispFloat((max), 6);
		else
			GUI_DispFloat((max), 5);
	}
	else
	{
		ypos = 120;
		GUI_DispStringAt("min2:", xpos, ypos);

		ypos += 20;
		GUI_GotoXY(xpos, ypos);					//移动光标 显示最小值
		if (min < 0)
			GUI_DispFloat((min), 6);
		else
			GUI_DispFloat((min), 5);

		ypos += 20;
		GUI_DispStringAt("max2:", xpos, ypos);
		ypos += 20;
		GUI_GotoXY(xpos, ypos);					//移动光标 显示最大值
		if (max < 0)
			GUI_DispFloat((max), 6);
		else
			GUI_DispFloat((max), 5);
	}
}


void draw_grid()//画网格
{
	int m_wid = 1;
	int i;
	GUI_SetColor(GUI_YELLOW);
	for (i = 0; i <= 10; i++)
	{
		if (i <= 8)
			GUI_DrawLine(0 + m_wid, i * 29 + m_wid, 251, i * 29 + m_wid);
		GUI_DrawLine(i * 25 + m_wid, 0 + m_wid, i * 25 + m_wid, 233);
	}
}



float getWID(float max, float min, int key_par)
{
	float WID;//获取垂直分辨率
	float avg;

	if (key_par == 1)
	{
		WID = 0.1;
	}
	else if (key_par == 2)
	{
		WID = 1.0;
	}
	else if (key_par == 0)
	{
		avg = (max + min) / 2;
		max -= avg;
		min -= avg;
		if (max > -min)
			WID = max / 4;
		else
			WID = -min / 4;
	}
	return WID;
}


void mod1queue1(float max1, float min1)
{
	float avg1 = (max1 + min1) / 2;
	int i;
	for (i = 0; i < MAXSIZE; i++)
	{
		queue1[i] -= avg1;
	}
}

void mod1queue2(float max2, float min2)
{
	float avg2 = (max2 + min2) / 2;
	int i;
	for (i = 0; i < MAXSIZE; i++)
	{
		queue2[i] -= avg2;
	}
}


void mod2queue1(float max1, float min1)
{
	float avg1 = (max1 + min1) / 2;
	int i;
	for (i = 0; i < MAXSIZE; i++)
	{
		queue1[i] += avg1;
	}
}


void mod2queue2(float max2, float min2)
{
	float avg2 = (max2 + min2) / 2;
	int i;
	for (i = 0; i < MAXSIZE; i++)
	{
		queue2[i] += avg2;
	}
}


void shouparam(float max1, float min1, float max2, float min2)
{

	show_maxmin(max1, min1, 1);
	show_maxmin(max2, min2, 2);

	if (max1 >= 0 && min1 >= 0)
		mod1queue1(max1, min1);
	if (max2 >= 0 && min2 >= 0)
		mod1queue2(max2, min2);

	show_f();

	if (max1 >= 0 && min1 >= 0)
		mod2queue1(max1, min1);
	if (max2 >= 0 && min2 >= 0)
		mod2queue2(max2, min2);
}


void Clear(int num, int step, int x)
{
	GUI_SetBkColor(GUI_BLACK);
	if (num == 0)
	{
		GUI_ClearRect(x, 0, x + step, 240);	//第一列矩形
	}
	else if (num == 1)
	{
		GUI_ClearRect(x, 0, x + step, 240);	//第二列矩形
	}
	else if (num == 2)
	{
		GUI_ClearRect(250, 0, 280, 240);	//第二列矩形
	}
	draw_grid();//画网格
}


void draw()
{
	float ybef1, ynow1;//相邻两个要连线的点的纵坐标
	float ybef2, ynow2;//相邻两个要连线的点的纵坐标
	int i = 0;//循环遍历时 开始的位置 队头
	int x = 0;//开始作图的起始横坐标
	int step = 250 / (int)MAXSIZE;  //相邻两个采样点X坐标差距
	vu8 key = 0;//作为按键输入的返回值
	float WID;//获取垂直分辨率

	float max1 = queue1[Getmaxi(queue1)];//数组1中最大值
	float min1 = queue1[Getmini(queue1)];//数组1中最小值
	float max2 = queue2[Getmaxi(queue2)];//数组2中最大值
	float min2 = queue2[Getmini(queue2)];//数组2中最小值

	shouparam(max1, min1, max2, min2);//显示频率和极值

	Clear(0, step, x);//第一个黑色矩形的绘制
	for (i = 0; i < MAXSIZE - 1;)
	{
		Clear(1, step, x + step);//第二个黑色矩形的绘制

		WID = getWID(max1, min1, key_par);
		if (key_par == 0)//如果是autoset档位则使其尽量铺满屏幕
		{
			ybef1 = 117 - (queue1[i] - (max1 + min1) / 2) / WID * 29;
			ynow1 = 117 - (queue1[i + 1] - (max1 + min1) / 2) / WID * 29;
		}
		else
		{
			ybef1 = 117 - queue1[i] / WID * 29;
			ynow1 = 117 - queue1[i + 1] / WID * 29;
		}
		if (ybef1 <= 2) ybef1 = 2;//修改坐标 使其显示在屏幕网格范围内
		if (ynow1 <= 2) ynow1 = 2;
		if (ybef1 >= 233) ybef1 = 233;
		if (ynow1 >= 233) ynow1 = 233;


		WID = getWID(max2, min2, key_par);
		if (key_par == 0)//如果是autoset档位则使其尽量铺满屏幕
		{
			ybef2 = 117 - (queue2[i] - (max2 + min2) / 2) / WID * 29;
			ynow2 = 117 - (queue2[i + 1] - (max2 + min2) / 2) / WID * 29;
		}
		else
		{
			ybef2 = 117 - queue2[i] / WID * 29;
			ynow2 = 117 - queue2[i + 1] / WID * 29;
		}
		if (ybef2 <= 2) ybef2 = 2;//修改坐标 使其显示在屏幕网格范围内
		if (ynow2 <= 2) ynow2 = 2;
		if (ybef2 >= 233) ybef2 = 233;
		if (ynow2 >= 233) ynow2 = 233;


		GUI_SetColor(GUI_WHITE);		//ch1画白线
		GUI_DrawLine(x, ybef1, (x + step), ynow1);
		GUI_SetColor(GUI_BLUE);		 //ch2画蓝线向下移动一个像素 加以区分
		GUI_DrawLine(x, ybef2 + 1, (x + step), ynow2 + 1);

		x += step;

		//按键实现锁存、改变采样频率、改变图像纵向每格电压大小
		key = KEY_Scan(0);	//得到键值
		if (key)
		{
			switch (key)
			{
			case KEY1_PRES://改变采样速率
				lowfflag = (1 + lowfflag)%4;//0(初始采样速率) 1(只降低一通道采样速率) 2(只降低二通道采样速率) 3(降低一、二通道采样速率)循环
				break;

			case WKUP_PRES://设置电压档位
				key_par = (key_par + 1) % 3;//0(auto) 1(0.1V) 2(1V)循环
				break;

			case KEY0_PRES://实现图像静止
				while (1)
				{
					key = KEY_Scan(0);	//得到键值
					if (key)
					{
						switch (key)
						{
						case KEY0_PRES://再按一下KEY0_PRES则 跳出此while 进行i++和下一步作图
							goto B;
						}
					}
				}
				break;
			}
		}
		//实现结束

	B:	i++;

	}
}

1.2 queue.h

#include "2ddisplay.h"

int Getmini(float *queue);//获取数组最小值的下标
int Getmaxi(float *queue);//获取数组最大值的下标
int countnum(float *queue);//统计半个周期采样次数 用来求周期
void show_maxmin(float max,float min,int adorder);//显示极值
void show_f(void);//显示频率
void shouparam(float max1,float min1,float max2,float min2);//显示极值和频率
void mod1queue1(float max1,float min1);//一通道数据都为非负数时同时减去极值的平均值 以用来求取频率和显示
void mod1queue2(float max2,float min2);//二通道数据都为非负数时同时减去极值的平均值 以用来求取频率和显示
void mod2queue1(float max1,float min1);//一通道求取频率时同时减去极值的平均值后 再加上减去的值 
void mod2queue2(float max2,float min2);//二通道求取频率时同时减去极值的平均值后 再加上减去的值 
void draw_grid(void);//画网格
float getWID(float max,float min,int key_par);//获取垂直分辨率
void draw(void);//做出图像
void Clear(int num,int step,int x);//画黑色矩形实现部分区域的清屏 以达到扫描效果

#define MAXSIZE 250

二、程序调用

2.1 main.c中添加变量

int lowfflag=0;	
int key_par=0;
#define k1  (7.4923)
#define b1  (-14.1525)
#define k2  (6.3584)
#define b2  (-10.4536)
extern float queue1[MAXSIZE];
extern float queue2[MAXSIZE];

2.1修改EMWINDEMO任务

//EMWINDEMO任务
void emwindemo_task(void *p_arg)
{
	int i;
	int adcx1,adcx2;
	float v_res1,v_res2;
	GUI_SetBkColor(GUI_BLACK);		//设置背景颜色
  GUI_Clear();
	uart_init(115200);	 	//串口初始化为115200
 	Adc1_Init();		  		//板载ADC1初始化
	Adc2_Init();		  		//板载ADC2初始化
	KEY_Init();         	//初始化与按键连接的硬件接口
	
	 while(1)
	 {		 	
			for (i = 0; i < MAXSIZE; i++)
			{			
				adcx1 =	Get_Adc1(ADC_Channel_1);//PA1   ad1读出的数值 0-4095 
			  v_res1=(float)adcx1*(3.3/4096);	
				//v_res1=v_res1*k1+b1;  	if(v_res1<0) v_res1+=0.07;//pa1线性校正
				queue1[i]=v_res1;
				
				if(lowfflag==1||lowfflag==3) delay_us(400);
			}	
			
			for (i = 0; i < MAXSIZE; i++)
			{					
				adcx2 =	Get_Adc2(ADC_Channel_4);//PA4    ad读出的数值 0-4095
				v_res2=(float)adcx2*(3.3/4096);	
				//v_res2=v_res2*k2+b2;//pa2线性校正
				queue2[i]=v_res2;

				if(lowfflag==2||lowfflag==3) delay_us(400);
			}	
			draw();//做出曲线图像			
		}
}

三、硬件电路设计

板载ADC前硬件设计如下。可采集VPP为20V,频率为10-2kHz的交流信号。
stm32f103与2.4寸TFT可触液晶屏实现的数字示波器_第1张图片

你可能感兴趣的:(stm32)