第45章 示波器设计—系统框架
本章节主要是对示波器的系统框架做一个简单的介绍,后面会推出示波器的详细设计分析。示波器的的源码注释已经很详细,对框架有个了解之后看源码即可。
45.1 ucos-iii任务分配
45.2 示波器核心任务
45.3 DAC实现方波的输出
45.4 ADC实现数据的采集
45.5 总结
45.1 uCOS-III任务分配
主要创建了如下6个用户任务:
l AppTaskStart----启动任务
l AppTaskGUIUpdate---界面截图任务
l AppTaskCOM----留待以后升级使用
l AppTaskUserIF---留在以后升级使用
l AppTaskGUI------emWin任务
l AppTaskGUIRefresh---Led闪烁任务
下面主要对启动任务,界面截图任务,emWin任务,Led闪烁任务做一个介绍。
45.1.1 AppTaskStart—启动任务
启动任务用于硬件驱动的初始化,系统滴答时钟的初始化以及触摸扫描和按键扫描,代码如下:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskStart
- * 功能说明: 这是一个启动任务,在多任务系统启动后,必须初始化滴答计数器(在BSP_Init中实现)
- * 形 参: p_arg 是在创建该任务时传递的形参
- * 返 回 值: 无
- 优 先 级: 2
- *********************************************************************************************************
- */
- static void AppTaskStart (void *p_arg)
- {
- OS_ERR err;
- uint8_t ucCount = 0;
-
- (void)p_arg;
- bsp_Init();
- CPU_Init();
- BSP_Tick_Init();
-
- #if OS_CFG_STAT_TASK_EN > 0u
- OSStatTaskCPUUsageInit(&err);
- #endif
-
- #ifdef CPU_CFG_INT_DIS_MEAS_EN
- CPU_IntDisMeasMaxCurReset();
- #endif
-
- AppObjCreate();
- AppTaskCreate();
- while (1)
- {
- /* 1ms一次触摸扫描 */
- TOUCH_Scan();
-
- /* 5ms一次按键检测 */
- ucCount++;
- if(ucCount == 5)
- {
- ucCount = 0;
- bsp_KeyScan();
- }
- BSP_OS_TimeDlyMs(1);
- }
- }
45.1.2 AppTaskGUIUpdate—界面截图任务
界面截图任务主要用于界面的截图并将图片以BMP格式保存到SD卡中。
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskGUIUpdate
- * 功能说明: 此任务主要实现截图功能.
- * 形 参: p_arg 是在创建该任务时传递的形参
- * 返 回 值: 无
- 优 先 级: 3
- *********************************************************************************************************
- */
- static void AppTaskGUIUpdate(void *p_arg)
- {
- OS_ERR err;
- uint8_t Pic_Name = 0;
- char buf[20];
- CPU_BOOLEAN SemFlag;
-
- (void)p_arg;
-
- while(1)
- {
- SemFlag = BSP_OS_SemWait(&SEM_SYNCH, 0);
-
- if(SemFlag == DEF_OK)
- {
- sprintf(buf,"0:/PicSave/%d.bmp",Pic_Name);
- OSSchedLock(&err);
-
- /* 如果SD卡中没有PicSave文件,会进行创建 */
- result = f_mkdir("0:/PicSave");
- /* 创建截图 */
- result = f_open(&file,buf, FA_WRITE|FA_CREATE_ALWAYS);
- /* 向SD卡绘制BMP图片 */
- GUI_BMP_Serialize(_WriteByte2File, &file);
-
- /* 创建完成后关闭file */
- result = f_close(&file);
-
- OSSchedUnlock(&err);
- Pic_Name++;
- }
- }
- }
45.1.3 AppTaskGUI—GUI任务
这个任务是示波器设计中最重要的任务,代码如下:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskGUI
- * 功能说明: GUI任务
- * 形 参:p_arg 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级:OS_CFG_PRIO_MAX - 4u
- *********************************************************************************************************
- */
- static void AppTaskGUI(void *p_arg)
- {
- (void)p_arg; /* 避免编译器告警 */
-
- while (1)
- {
- MainTask();
- }
- }
45.1.4 AppTaskGUIRefresh—Led闪烁任务
这个任务主要通过LED的闪烁来指示系统的运行,代码如下:
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskGUIRefresh
- * 功能说明: Led闪烁任务,表示系统运行
- * 形 参: p_arg 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: OS_CFG_PRIO_MAX - 5u
- *********************************************************************************************************
- */
- static void AppTaskGUIRefresh(void *p_arg)
- {
- (void)p_arg; /* 避免编译器告警 */
-
- while (1)
- {
- BSP_OS_TimeDlyMs(200);
- bsp_LedToggle(2);
- }
- }
45.1.5 其余任务
剩下的两个任务留着以后升级使用。
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskCom
- * 功能说明: 留待以后使用
- * 形 参:p_arg 是在创建该任务时传递的形参
- * 返 回 值: 无
- 优 先 级:3
- *********************************************************************************************************
- */
- static void AppTaskCOM(void *p_arg)
- {
- (void)p_arg;
-
- while(1)
- {
- /* 100s执行一次 */
- BSP_OS_TimeDlyMs(1000000);
- }
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: AppTaskUserIF
- * 功能说明: 留待以后使用。
- * 形 参: p_arg 是在创建该任务时传递的形参
- * 返 回 值: 无
- 优 先 级: 2
- *********************************************************************************************************
- */
- static void AppTaskUserIF(void *p_arg)
- {
- (void)p_arg; /* 避免编译器报警 */
-
- while (1)
- {
- /* 100s执行一次 */
- BSP_OS_TimeDlyMs(1000000);
- }
- }
45.2 示波器核心任务
emWin部分是示波器设计的核心任务,主要包括以下几个文件:

下面把这几个文件及其之间的关系做一个简单的说明。
45.2.1 MainTask.c—GUI主任务文件
这个文件是示波器代码的核心文件,这个文件里面几个函数的关系搞清楚了,示波器的整体设计也就搞清楚了。下面把这个文件里面的几个函数简单的梳理下:
l 函数void MainTask(void)
代码如下:
- /*
- *********************************************************************************************************
- * 函 数 名: MainTask
- * 功能说明: GUI主函数
- * 形 参:无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void MainTask(void)
- {
- /* 开启所有窗口使用内存设备 */
- WM_SetCreateFlags(WM_CF_MEMDEV);
- GUI_Init();
-
- /* 设置皮肤色 *************************************************************/
- PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
- FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX);
- PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);
- BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);
- CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX);
- DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX);
- SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX);
- SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX);
- HEADER_SetDefaultSkin(HEADER_SKIN_FLEX);
- RADIO_SetDefaultSkin(RADIO_SKIN_FLEX);
- MULTIPAGE_SetDefaultSkin(MULTIPAGE_SKIN_FLEX);
-
- /*
- * 设置桌面窗口的回调函数
- */
- WM_SetCallback(WM_HBKWIN, _cbBkWin);
-
- /* 初始化 DSO */
- DSO_Init(1);
-
- /* 波形显示和处理 */
- DSO_Graph();
- }
这个函数里面最主要的就是DSO_Init(1)函数和DSO_Graph()两个函数。
l 函数DSO_Graph
这个函数是示波器的主函数,示波器任何函数都是通过这个函数直接或者间接的进行调用。这个函数
主要有两个功能,一个是ADC数据的处理并在TFT上显示出来,另一个是按键消息的处理,详细大家看代码即可,代码注释已经比较详细。
l 函数 _Draw
这个函数通过函数GUI_MEMDEV_Draw进行调用的,主要是实现绘制波形和波形区的虚线方框。
l 函数_cbBkWin
桌面窗口的回调函数,主要是用于示波器界面右侧8个按钮的回调消息处理,用来打开8个按钮所对应的的对话框。
45.2.2 MainTask.h—所有DSO相关文件的头文件
这个文件是所以DSO相关文件的头文件,方便各个文件进行调用,代码如下:
- /*
- *********************************************************************************************************
- *
- * 模块名称 : GUI各个部分的总头文件
- * 文件名称 : MainTask.c
- * 版 本 : V1.0
- * 说 明 : GUI界面主函数
- * 修改记录 :
- * 版本号 日期 作者 说明
- * v1.0 2015-01-05 Eric2013 首发
- *
- * Copyright (C), 2015-2016, 安富莱电子 www.armfly.com
- *
- *********************************************************************************************************
- */
-
- #ifndef __MainTask_H
- #define __MainTask_H
-
- #include "stdlib.h"
- #include "GUI.h"
- #include "DIALOG.h"
- #include "WM.h"
- #include "BUTTON.h"
- #include "CHECKBOX.h"
- #include "DROPDOWN.h"
- #include "EDIT.h"
- #include "FRAMEWIN.h"
- #include "LISTBOX.h"
- #include "MULTIEDIT.h"
- #include "RADIO.h"
- #include "SLIDER.h"
- #include "TEXT.h"
- #include "PROGBAR.h"
- #include "SCROLLBAR.h"
- #include "LISTVIEW.h"
- #include "GRAPH.h"
- #include "MENU.h"
- #include "MULTIPAGE.h"
- #include "ICONVIEW.h"
- #include "TREEVIEW.h"
- #include "MESSAGEBOX.h"
-
- #include "ff.h"
- #include "diskio.h"
-
- #include "arm_math.h"
- #include "arm_const_structs.h"
-
- /*
- *********************************************************************************************************
- * 宏定义
- *********************************************************************************************************
- */
- #define LCD_YSIZE 480
- #define LCD_XSIZE 630
-
- /* 定义波形的显示界面区域 600*400 */
- #define DSOSCREEN_STARTX 40 /* 波形显示的X起始位置 */
- #define DSOSCREEN_STARTY 40 /* 波形显示的Y起始位置 */
- #define DSOSCREEN_ENDX 639 /* 波形显示的X结束位置 */
- #define DSOSCREEN_ENDY 439 /* 波形显示的Y结束位置 */
- #define DSOSCREEN_LENGTH 600 /* 波形显示的Y结束位置 */
-
- #define ATT_COUNT 10 /* 定义支持的10种幅值单位 */
-
- #define TIME_COUNT 21 /* 定义支持的21种采样率 */
-
- #define WM_TextUpDate WM_USER + 1 /* 自定义一个回调函数的消息,用于界面数据的更新 */
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- extern const char *g_AttText[]; /* 10种幅度单位 */
- extern const char *g_TimeTable[]; /* 采样率,从2Msps到1Ksps 对应的时基 */
- extern const char *g_MeasureTable[]; /* 示波器当前实际支持的测量值 */
- extern const uint16_t g_CursorUintTable[][2]; /* 测量游标数据显示格式 */
- extern const uint16_t g_AttTable[ATT_COUNT][2]; /* 采样率衰减倍数表 */
-
- extern GUI_RECT rClient; /* 用于显示示波器的logo */
- extern GUI_RECT rRunMode; /* 用于显示运行状态,运行和暂停 */
- extern GUI_RECT rTrigMode; /* 用于显示触发模式,自动触发和正常触发 */
- extern GUI_RECT rTrigValue; /* 用于显示自动和正常的触发数组 */
- extern GUI_RECT rButState; /* 当前按键需要调节的状态 */
- extern GUI_RECT rRefPos; /* 示波器最左侧波形参考的位置区域 */
- extern GUI_RECT rTrigPos; /* 6KB数据查询 */
-
- extern const GUI_POINT aPointsTrigBrowser[3]; /* 6k数据中,波形显示的起始位置 */
- extern const GUI_POINT aPointsTrig[7]; /* 波形显示区右侧边上触发值箭头 */
- extern const GUI_POINT aPoints[5]; /* 波形显示区左侧边上波形显示的参考位置 */
-
- extern uint8_t g_ucLineStyle; /* 默认是实线绘制波形 */
- extern int8_t Ch1AmpId; /* 从g_AttText中选择每个方格表示的幅值 */
- extern int8_t TimeBaseId; /* 选择相应采样率 */
-
- extern uint8_t g_ucMeasureFlag[30]; /* 示波器支持的30种测量值标志 */
-
- /* 存储平均值,峰峰值,频率,最小值和最大值的变量 */
- extern float32_t g_WaveMean;
- extern float32_t g_WavePkPk;
- extern float32_t g_WaveFreq;
- extern float32_t g_WaveMax;
- extern float32_t g_WaveMin;
-
- /* 用于水平测量和垂直测量游标,下面是初始化的默认值 */
- extern uint16_t g_usCursorStep;
- extern int16_t g_sCursorHA;
- extern int16_t g_sCursorHB;
- extern int16_t g_sCursorVA;
- extern int16_t g_sCursorVB;
- extern float32_t g_WaveCursorA;
- extern float32_t g_WaveCursorB;
-
- extern uint8_t hWinRunStopFlag; /* 0:表示运行,1:表示暂停 */
-
- extern uint16_t TriggerFlag; /* 0:用于自动触发,1,2:用于普通触发 */
-
- /* 用于水平测量和垂直测量游标 */
- extern uint16_t g_usTriPos;
- extern uint16_t g_usTriStep;
- extern int16_t g_usCurTriPos;
- extern int16_t g_usCurTriStep;
- extern float32_t g_ufTrigValue;
- extern uint16_t g_usTrigValue;
- extern uint32_t g_ulTrigTimeLine;
-
-
- extern uint16_t g_usRefPos; /* 左侧的参考位置,默认开机后是中间位置 */
- extern uint8_t hWinButStateFlag; /* 8种按键功能状态 */
- extern uint16_t g_usWaveBuf[1024*6]; /* 示波器缓存 */
- extern uint16_t g_usWaveBuf1[1024*6];
-
- extern uint8_t hWinCoursorFlag; /* 0:不显示测量窗口,1:显示测量窗口 */
- extern uint8_t g_ucFFTDispFlag; /* FFT波形显示,0:表示显示,1:表示不显示 */
- extern uint8_t g_ucFirFlter_Step100KHz; /* 0:表示不执行滤波,1:表示100KHz,2:表示200KHz,,以此类推 */
- extern uint8_t g_ucFirFlter_Step10KHz; /* 0:表示不执行滤波,1:表示10KHz, 2:表示20KHz,,以此类推 */
- extern uint8_t g_ucFirFlter_Step1KHz; /* 0:表示不执行滤波,1:表示1KHz, 2:表示2KHz,,以此类推 */
- extern uint8_t g_ucWaveRefreshFlag; /* 0:表示不执行波形区域的刷新,1:表示执行波形区域的刷新 */
- /*
- *********************************************************************************************************
- * fatfs
- *********************************************************************************************************
- */
- /* 供外部文件调用的fatfs变量 */
- extern FRESULT result;
- extern FIL file;
- extern FILINFO finfo;
- extern DIR DirInf;
- extern UINT bw;
- extern FATFS fs;
- extern FATFS fs_nand;
- extern FATFS fs_usb;
- extern char *_acBuffer2;
-
- /* BMP图片生成 */
- extern void _WriteByte2File(U8 Data, void * p);
-
- /* 用于BMP图片的显示 */
- uint8_t _ShowBMP(const char * sFilename);
-
- /*
- *********************************************************************************************************
- * 窗口句柄
- *********************************************************************************************************
- */
- extern WM_HWIN hWinAmp; /* 用于显示幅度的窗口 */
- extern WM_HWIN hWinStatus; /* 用于显示频率,平均值,峰峰值,最大值等信息 */
- extern WM_HWIN hWinScale; /* 用于显示采样率 */
-
- /* 8个按钮句柄 */
- extern BUTTON_Handle hButton0;
- extern BUTTON_Handle hButton1;
- extern BUTTON_Handle hButton2;
- extern BUTTON_Handle hButton3;
- extern BUTTON_Handle hButton4;
- extern BUTTON_Handle hButton5;
- extern BUTTON_Handle hButton6;
- extern BUTTON_Handle hButton7;
-
- /*
- *********************************************************************************************************
- * 供外部文件调用的函数
- *********************************************************************************************************
- */
- /* 创建幅度,时基和状态窗口 */
- extern WM_HWIN CreateWindowAmplitude(void);
- extern WM_HWIN CreateWindowScale(void);
- extern WM_HWIN CreateWindowStatus(void);
-
- /* 示波器界面初始化 */
- extern void DSO_Init(uint8_t ucCreateFlag);
-
- /* 按钮创建的对话框 */
- extern WM_HWIN DSO_CreateMeasureDlg(void);
- extern WM_HWIN DSO_CreateInspectorDlg(void);
- extern WM_HWIN DSO_CreateAcquireDlg(void);
- extern WM_HWIN DSO_CreateTrigerDlg(void);
- extern WM_HWIN DSO_CreateMathDlg(void);
- extern WM_HWIN DSO_CreateSettingsDlg(void);
- extern WM_HWIN DSO_CreateDacDlg(void);
- extern WM_HWIN DSO_CreateReturnDlg(void);
-
- /* 示波器界面绘制 */
- extern void DSO_DrawBakFrame(void);
- extern void DSO_DrawCursorH(void);
- extern void DSO_DrawCursorV(void);
-
- /* Fir 滤波 */
- extern void DSO_FirFilter_Step100KHz(void);
- extern void DSO_FirFilter_Step10KHz(void);
- extern void DSO_FirFilter_Step1KHz(void);
- #endif
-
- /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
45.2.3 App_SysFunction.c—界面截图
这个文件主要是示波器界面截图。实现截图的主要函数如下:
- /*
- *********************************************************************************************************
- * 函 数 名: _WriteByte2File()
- * 功能说明: 写文件到SD卡或者其他存储介质
- * 形 参:Data 要写的数据, p 指向FIL类型变量
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void _WriteByte2File(U8 Data, void * p)
- {
- result = f_write (p, &Data, 1, &bw);
- }
这个函数是被emWin函数GUI_BMP_Serialize所调用。
45.2.4 DSO_Init.c—初始化
这个文件里面的函数DSO_Init()主要是实现示波器整个界面的初始化,初始化内容如下:
- /*
- *********************************************************************************************************
- * 函 数 名: DSO_Init
- * 功能说明: 示波器主界面初始化
- * 形 参:ucCreateFlag 1:表示需要创建按键和窗口等。
- * 0:不需要创建。
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void DSO_Init(uint8_t ucCreateFlag)
- {
- char buf[10];
- uint32_t ulTrigPos;
-
-
- /* 第1步:刷新背景*********************************************************************/
- GUI_SetBkColor(0x905040);
- GUI_Clear();
-
- /* 第2步:显示基本的信息***************************************************************/
- GUI_SetColor(GUI_WHITE);
- GUI_SetFont(&GUI_Font8x16x1x2);
- GUI_DispStringInRect("Eric2013", &rClient, GUI_TA_HCENTER | GUI_TA_VCENTER);
-
- /* 按键K2 :设置波形显示运行或暂停 */
- if(hWinRunStopFlag == 0)
- {
- GUI_DispStringInRect("Run", &rRunMode, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else
- {
- GUI_DispStringInRect("Stop", &rRunMode, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
-
- /* 按键K3 :设置普通触发方式或自动触发 */
- if(TriggerFlag == 0)
- {
- GUI_DispStringInRect("Auto", &rTrigMode, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else
- {
- GUI_DispStringInRect("Trig", &rTrigMode, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
-
- /* 第3步:显示自动触发的触发电压**********************************************************/
- g_ufTrigValue = 240 - g_usTriPos;
- g_ufTrigValue = g_ufTrigValue * g_AttTable[Ch1AmpId][1] / 50000;
- sprintf(buf, "%5.3fV", g_ufTrigValue);
-
- GUI_DispStringInRect(buf, &rTrigValue, GUI_TA_HCENTER | GUI_TA_VCENTER);
-
- /* 显示上升沿触发的标志 */
- GUI_DrawHLine(rTrigValue.y1-10, rTrigValue.x0+10, rTrigValue.x0 + 19);
- GUI_DrawLine(rTrigValue.x0 + 19, rTrigValue.y1-10, rTrigValue.x0+30, rTrigValue.y0+8);
- GUI_DrawHLine(rTrigValue.y0+8, rTrigValue.x0+31, rTrigValue.x0 + 41);
-
- /* 第4步:设置摇杆按键的调节状态,并将其显示出来******************************************/
- if(hWinButStateFlag == 0)
- {
- GUI_DispStringInRect("ChangeSampleFreq", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 1)
- {
- GUI_DispStringInRect("ChangeAmplitude", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 2)
- {
- GUI_DispStringInRect("ChangeRefPos", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 3)
- {
- GUI_DispStringInRect("ChangeCursorVA", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 4)
- {
- GUI_DispStringInRect("ChangeCursorVB", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 5)
- {
- GUI_DispStringInRect("ChangeCursorHA", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 6)
- {
- GUI_DispStringInRect("ChangeCursorHB", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
- else if(hWinButStateFlag == 7)
- {
- GUI_DispStringInRect("ChangeTrigger", &rButState, GUI_TA_HCENTER | GUI_TA_VCENTER);
- }
-
- /* 第5步:实现波形的放缩***************************************************************/
- GUI_SetBkColor(GUI_BLACK);
- GUI_ClearRect(210, 6, 470, 33);
- GUI_SetColor(GUI_YELLOW);
- GUI_DrawHLine(20,220, 220+239);
- GUI_DrawHLine(21,220, 220+239);
-
- GUI_SetColor(0x0040f0);
-
- /* 自动触发模式 */
- if(TriggerFlag == 0)
- {
- ulTrigPos = (g_usCurTriStep + g_usCurTriPos) * 240;
- }
- /* 普通触发模式 */
- else
- {
- ulTrigPos = (2772 + g_usCurTriStep)*240;
- }
-
- /* 根据上面求得数据的触发位置来更新屏上的触发图标位置 */
- ulTrigPos = ulTrigPos / 6144;
- GUI_FillPolygon(&aPointsTrigBrowser[0], GUI_COUNTOF(aPointsTrigBrowser), ulTrigPos+220, 13);
-
- /* 记录专门的触发位置 */
- GUI_SetColor(GUI_RED);
- GUI_DrawPixel(326, 20);
- GUI_DrawPixel(326, 21);
-
- GUI_DrawPixel(327, 20);
- GUI_DrawPixel(327, 21);
-
- GUI_DrawPixel(328, 20);
- GUI_DrawPixel(328, 21);
-
- GUI_DrawPixel(329, 20);
- GUI_DrawPixel(329, 21);
-
- GUI_DrawPixel(330, 20);
- GUI_DrawPixel(330, 21);
-
- /* 第6步:波形显示区的边框*************************************************************/
- GUI_SetColor(0XEBCD9E);
- GUI_DrawRect(DSOSCREEN_STARTX - 1, /* Upper left X-position. */
- DSOSCREEN_STARTY - 1, /* Upper left Y-position. */
- DSOSCREEN_ENDX + 1, /* Lower right X-position. */
- DSOSCREEN_ENDY + 1); /* Lower right Y-position. */
-
- GUI_SetColor(0XB37F63);
- GUI_DrawRect(DSOSCREEN_STARTX - 2, /* Upper left X-position. */
- DSOSCREEN_STARTY - 2, /* Upper left Y-position. */
- DSOSCREEN_ENDX + 2, /* Lower right X-position. */
- DSOSCREEN_ENDY + 2); /* Lower right Y-position. */
-
- /* 根据需要是否需要重新创建按键和窗口 */
- if(ucCreateFlag == 1)
- {
- /* 第7步:创建状态窗口*************************************************************/
- hWinAmp = CreateWindowAmplitude();
- hWinStatus = CreateWindowStatus();
- hWinScale = CreateWindowScale();
-
- /*
- * 创建定时器,其功能是经过指定周期后,向指定窗口发送消息。
- * 该定时器与指定窗口相关联。
- */
- WM_CreateTimer(hWinStatus, /* 接受信息的窗口的句柄 */
- 0, /* 用户定义的Id。如果不对同一窗口使用多个定时器,此值可以设置为零。 */
- 500, /* 周期,此周期过后指定窗口应收到消息*/
- 0); /* 留待将来使用,应为0 */
-
-
- /* 第6步:创建需要的按钮*************************************************************/
- hButton0 = BUTTON_Create(670, 40, 100, 45, GUI_ID_BUTTON0, WM_CF_SHOW);
- BUTTON_SetText(hButton0, "Measure");
- BUTTON_SetFont(hButton0, &GUI_Font20B_ASCII);
-
- hButton1 = BUTTON_Create(670, 90, 100, 45, GUI_ID_BUTTON1, WM_CF_SHOW);
- BUTTON_SetText(hButton1, "Inspector");
- BUTTON_SetFont(hButton1, &GUI_Font20B_ASCII);
-
- hButton2 = BUTTON_Create(670, 140, 100, 45, GUI_ID_BUTTON2, WM_CF_SHOW);
- BUTTON_SetText(hButton2, "Acquire");
- BUTTON_SetFont(hButton2, &GUI_Font20B_ASCII);
-
- hButton3 = BUTTON_Create(670, 190, 100, 45, GUI_ID_BUTTON3, WM_CF_SHOW);
- BUTTON_SetText(hButton3, "Trigger");
- BUTTON_SetFont(hButton3, &GUI_Font20B_ASCII);
-
- hButton4 = BUTTON_Create(670, 240, 100, 45, GUI_ID_BUTTON4, WM_CF_SHOW);
- BUTTON_SetText(hButton4, "Math");
- BUTTON_SetFont(hButton4, &GUI_Font20B_ASCII);
-
- hButton5 = BUTTON_Create(670, 290, 100, 45, GUI_ID_BUTTON5, WM_CF_SHOW);
- BUTTON_SetText(hButton5, "Settings");
- BUTTON_SetFont(hButton5, &GUI_Font20B_ASCII);
-
- hButton6 = BUTTON_Create(670, 340, 100, 45, GUI_ID_BUTTON6, WM_CF_SHOW);
- BUTTON_SetText(hButton6, "DAC");
- BUTTON_SetFont(hButton6, &GUI_Font20B_ASCII);
-
- hButton7 = BUTTON_Create(670, 390, 100, 45, GUI_ID_BUTTON7, WM_CF_SHOW);
- BUTTON_SetText(hButton7, "Return");
- BUTTON_SetFont(hButton7, &GUI_Font20B_ASCII);
- }
-
- /* 第8步:显示参考坐标*************************************************************/
- GUI_SetColor(GUI_YELLOW);
- GUI_FillPolygon(&aPoints[0], GUI_COUNTOF(aPoints), 5, g_usRefPos);
-
- GUI_SetColor(GUI_BLACK);
- GUI_SetFont(&GUI_Font24_ASCII);
- GUI_SetTextMode(GUI_TEXTMODE_TRANS);
- GUI_DispCharAt('1', 10, g_usRefPos - 10);
- }
45.2.5 DSO_MeasureDlg.c—测量对话框
这个文件主要用创建如下对话框:

45.2.6 DSO_InspectorDlg.c—对话框
这个文件主要用创建如下对话框,此文件实现的对话框还未开发,留待以后升级使用:

45.2.7 DSO_AcquireDlg.c—对话框
这个文件主要用创建如下对话框,此文件实现的对话框还未开发,留待以后升级使用:

45.2.8 DSO_TriggerDlg.c—对话框
这个文件主要用创建如下对话框,此文件实现的对话框还未开发,留待以后升级使用:

45.2.9 DSO_MathDlg.c—Fir低通滤波器设置对话框
这个文件主要用于Fir低通滤波器的截止频率配置,创建对话框如下:

45.2.10 DSO_SettingsDlg.c—设置对话框
这个文件主要用于设置对话框的创建。

45.2.11 DSO_DacDlg.c—对话框
这个文件主要用创建如下对话框,此文件实现的对话框还未开发,留待以后升级使用:

45.2.12 DSO_ReturnDlg.c—对话框
这个文件主要用创建如下对话框,此文件实现的对话框还未开发,留待以后升级使用:

45.2.13 DSO_DrawBakFrame.c—绘制波形区的虚线方格
这个文件用于创建如下虚线方格(不包括波形显示):

45.2.14 DSO_DrawCursorH.c—水平测量游标
这个文件用于创建如下水平测量游标:

45.2.15 DSO_DrawCursorV.c—垂直测量游标
这个文件用于创建如下垂直测量游标:

45.2.16 DSO_AmplititudeWindow.c—幅值窗口
这个文件用于创建如下窗口:

45.2.17 DSO_ScaleWindow.c—时基窗口
这个文件用于创建如下窗口:

45.2.18 DSO_StatusWindow.c—测量值窗口
这个文件用于创建如下窗口:

45.2.19 DSO_FirFilter_Step1KHz—Fir低通滤波
45.2.20 DSO_FirFilter_Step10KHz—Fir低通滤波
45.2.21 DSO_FirFilter_Step100KHz—Fir低通滤波
上面的三项主要用于Fir低通滤波器的实现。
45.3 DAC实现方波的输出
DAC输出方波的配置要注意初始化的顺序,顺序错误了,方波是无法输出的,还有就是不用的MDK优化等级,DAC配置时的顺序也不一样,这个应该是DAC库的一个bug。
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_InitDAC
- * 功能说明: DAC初始化
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void bsp_InitDAC(void)
- {
- uint8_t i;
-
- /* 用缓存放一个周期的方波 */
- for(i =0; i < 32; i++)
- {
- g_usWaveBuff[i] = 0;
- }
-
- for(i =0; i < 32; i++)
- {
- g_usWaveBuff[i+32] = 2048;
- }
-
- /* MDK优化等级为1的时候,DAC初始化顺序,不同的优化等级,
- 不同的输出顺序容易操作DAC无法输出波形。
- 这个问题要引起大家的特别注意!。
- */
- DAC_Ch1_WaveConfig();
- DAC_GPIOConfig();
- TIM6_Config();
- }
45.4 ADC实现数据的采集
ADC的驱动主要注意两个问题,一个是ADC数据采集的关闭或者开启一定要保证同步,要不会出现采集数据的混乱,还有就是由于没有使用官方的3ADC快速交替采样,官方的快速交替采用使用定时器触发采集出的数据效果不好,抖动较大(特别是使用定时改变不同的采样频率时) 。现在采用的每个ADC都是用定时器单独的触发,并把触发数据分开,分成三等分,每个时刻实现一个ADC的触发。
- /*
- *********************************************************************************************************
- * 函 数 名: TIM1_Config
- * 功能说明: 配置定时器1,用于触发ADC1,ADC2和ADC3。
- * 当外部触发信号被选为ADC规则或注入转换时,只有它的上升沿可以启动转换。
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void TIM1_Config(void)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
-
- /* 使能定时器1 */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
-
- /* 先禁能再配置 */
- TIM_Cmd(TIM1, DISABLE);
-
- /*
- ********************************************************************************
- system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:
-
- HCLK = SYSCLK / 1 (AHB1Periph)
- PCLK2 = HCLK / 2 (APB2Periph)
- PCLK1 = HCLK / 4 (APB1Periph)
-
- 因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;
- 因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;
-
- APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13, TIM14
- APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
-
- TIM1 更新周期是 = TIM1CLK / (TIM_Period + 1)/(TIM_Prescaler + 1)
- ********************************************************************************
- */
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //初始化定时器1的寄存器为复位值
- TIM_TimeBaseStructure.TIM_Period = 168000000/g_SampleFreqTable[TimeBaseId][0] - 1; TIM_TimeBaseStructure.TIM_Prescaler = g_SampleFreqTable[TimeBaseId][1]-1; TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; //CR1->CKD时间分割值
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //CR1->CMS[1:0]和DIR定时器模式 向上计数
- TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
-
- /**************ADC1的触发***********************************************/
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //CCER 输出使能
- TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period/3; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //CCER输出极性设置
- TIM_OC1Init(TIM1, &TIM_OCInitStructure);
-
- /**************ADC2的触发***********************************************/
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period*2/3;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
- TIM_OC2Init(TIM1, &TIM_OCInitStructure);
-
- /**************ADC3的触发***********************************************/
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = TIM_TimeBaseStructure.TIM_Period-1;
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
- TIM_OC3Init(TIM1, &TIM_OCInitStructure);
- //TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); //CMR2 设置预装载使能 更新事件产生时写入有效
- //TIM_ARRPreloadConfig(TIM1, ENABLE); //CR1 设置ARR自动重装 更新事件产生时写入有效
- TIM_Cmd(TIM1, ENABLE);
-
- /* 使能PWM输出 */
- TIM_CtrlPWMOutputs(TIM1, ENABLE);
- }
下面是DMA的开启和关闭,一定要保证按照如下的顺序进行,且这些函数不能省略一个,要不重新开启DMA数据将无法再次传输。
- /*
- *********************************************************************************************************
- * 函 数 名: DMA_Open
- * 功能说明: 使能ADC1,ADC2,ADC3的DMA
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void ADC_DMA_Open(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
-
- /* DMA2 Stream1 channel1 配置用于ADC3 **************************************/
- DMA_DeInit(DMA2_Stream1);
- DMA_InitStructure.DMA_Channel = DMA_Channel_2;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
- DMA_InitStructure.DMA_BufferSize = 1024*10;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(DMA2_Stream1, &DMA_InitStructure);
- DMA_Cmd(DMA2_Stream1, ENABLE);
-
- /* DMA2 Stream2 channel1 配置用于ADC2 **************************************/
- DMA_DeInit(DMA2_Stream2); /* 在DMA的DMA_Mode_Normal模式,一定要使用这个函数,循环模式可以不用 */
- DMA_InitStructure.DMA_Channel = DMA_Channel_1;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC2_DR_ADDRESS;
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC2ConvertedValue;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
- DMA_InitStructure.DMA_BufferSize = 1024*10;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(DMA2_Stream2, &DMA_InitStructure);
- DMA_Cmd(DMA2_Stream2, ENABLE);
-
- /* DMA2 Stream0 channel0 配置用于ADC1 **************************************/
- DMA_DeInit(DMA2_Stream0);
- DMA_InitStructure.DMA_Channel = DMA_Channel_0;
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
- DMA_InitStructure.DMA_BufferSize = 1024*10;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(DMA2_Stream0, &DMA_InitStructure);
- DMA_Cmd(DMA2_Stream0, ENABLE);
