基于ARM7多通道仪表数据采集.docx
《基于ARM7多通道仪表数据采集.docx》由会员分享,可在线阅读,更多相关《基于ARM7多通道仪表数据采集.docx(26页珍藏版)》请在冰豆网上搜索。
![基于ARM7多通道仪表数据采集.docx](https://file1.bdocx.com/fileroot1/2023-1/30/f2ed65cd-30a0-4d6d-b4c5-97fc50e6d023/f2ed65cd-30a0-4d6d-b4c5-97fc50e6d0231.gif)
基于ARM7多通道仪表数据采集
《嵌入式系统与应用》
设计性实验报告
题目基于ARM7的多通道仪表数据采集实验
系别物理与电子工程学院
年级专业
班级]学号
学生姓名
指导教师
实验时间
引言1
第一章实验要求2
一、实验内容及目的2
二、实验设备及工具2
第二章正文3
一、实验分析3
二、系统设计3
三、代码分析8
第三章实验结果11
第四章实验总结12
参考文献13
附录14
引言
随着工业自动化与信息化的不断发展,数据采集已经成为了计算机与外部物理世界连接的桥梁。
数据采集系统广泛地应用于工业生产中设备工作状况的监测、控制领域中的闭环控制系统及仿真领域的半实物仿真系统。
传统的数据采集装置通常由单片机及采集卡组成,其采集通道数较少、单任务的软件结构及实时性差等不足之处已无法满足人们的需求。
ARM(AdvancedRISCMachines)是基于RSIC架构的数据宽为32位可嵌入操作系统的微处理器。
由于其体积小、价格低、可靠性高、低功耗等特点在工业自动化、国防、运输等领域得到了广泛的应用。
本次设计是基于ARM的多通道实时数据采集系统;该系统由下位机系统及上位机软件组成,下位机硬件主要基于ARM工控开发平台、数据采集板及模拟量输出板,采用μC/OSⅡ实时多任务操作系统,实现多通道数据的采集、数据存储及模拟量的输出,并将采集数据实时传送至上位计算机;上位机软件接收数据进行监控,图形化显示数据变化曲线,并控制下位机的模拟量输出功能;通过实验验证,下位机系统能够实现多通道数据的采集、存储及模拟量的输出,μC/OSⅡ操作系统完成多任务的实时调度,上位机软件成功进行模拟量数据的采集监控及数据变化的图形显示,整个系统具有良好的实时性。
第一章实验要求
一、实验内容及目的
采用多任务编程方法,每个任务监视一路AD转换,每一路AD的转换结果在液晶屏上用一个条形图的长短来表示,直观地显示每路模拟输入电压的大小。
可以通过文本框给每路AD设置警戒值,某路输入超出警戒线之后条形图中超出的部分会以闪动的方式显示。
并在数码管上对应的某通道的数值显示当超过警戒线数值时,数字闪烁显示。
在此基础上,利用实验箱中的数码管显示每一路的电压采样值,并能在超出警戒值的情况下闪烁显示,在LCD屏上对应条形图的顶部显示具体的电压值。
二、实验设备及工具
硬件:
ARM嵌入式开发平台、用于ARM7TDMI的JTAG仿真器、PC机Pentium100以上。
软件:
PC机操作系统Win98、Win2000或WinXP、ARMSDT2.51或ADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序。
第二章正文
一、实验分析
数据采集系统置于被监控的设备处,通过传感器对设备的电压或者电流信号进行采样、保持,并送入A/D转换器变成数字信号,然后将该信号送到FIFO中。
当FIFO中存放的数据到了一定数目时,由ARM7从FIFO中读出,然后通过ARM7的以太网接口送给上位机。
多路采集通道经过模拟开关后再进入A/D转换器。
CPLD是整个系统的控制核心,它控制采集通道的切换、A/D转换器的启/停、转换后的数据在FIFO中的存放地址发生器、产生中断请求以通知ARM7读取存放在FIFO中的数据等。
二、系统设计
1.编写OnKey()函数,响应键盘消息。
流程图如图1所示。
1)这里设置了两个文本框,用来输入通道编号和该通道的警戒值,在键盘消息响应函数里针对两个文本框分别作出处理,只处理回车键和取消键,其他键由控件本身处理。
程序里用变量EditNumber指示当前要编辑的文本框控件;用变量input指示该文本框控件是否处于输入编辑状态。
以此决定回车键应该执行的功能。
2)当文本框控件不是编辑状态时,回车将使其进入编辑状态,在程序里用SetWndCtrlFocus()函数将焦点转移到该控件并用SetTextCtrlEdit()函数设置为编辑状态;当文本框正处于编辑状态时,回车将使其退出编辑状态,并将要编辑的文本框切换到另一个文本框控件,取消键的处理和这种情况类似。
3)如果当前要编辑的文本框是警戒值输入框,在编辑状态中回车确定后,所输入的通道编号以及警戒值就会保存在数组WarnningData中,代码如下:
WarnningData[Unicode2Int(pChannelTextCtrl->text)]=Unicode2Int(pValueTextCtrl->text);
图1
2.编写绘图显示任务Display_Task,绘制文本框和条形图等,并实现文本框编辑过程中和超过警戒值后的动画显示,其流程图为图2所示。
图2
1)程序中用TextOut()函数显示文本框的提示信息,用数组edit记录两个文本框是否处于编辑状态,用变量IsEdit指示提示信息是否显示。
实际上,IsEdit这个变量在显示任务循环一次就改变一次状态,当IsEdit==1时将提示信息擦掉,否则保持显示不变。
这就是闪烁显示的原理,表示AD转换结果的条形图超出警戒值的部分的闪烁也是这样实现的,随着任务的循环隔次的改变状态。
2)和变量IsEdit的作用类似,warnning[x]是条形图闪烁的指示变量。
当某路AD转换的结果result_ADx大于对应通道的警戒值WarnningData[x]时,根据warnning[x]的值决定条形图的长度是和result_ADx对应还是和WarnningData[x]对应,这样看起来条形图的长度是变化的,效果就是超过警戒线的那部分在闪烁。
3)这里条形图实际上是一个实心矩形,用FillRect()函数填充。
5、编写4路AD采集任务ADx_Task。
1)使用GetADresult()函数即可得到某路AD输出的二进制代码。
由于处理器的8
路10位AD转换单元的最大输入电压是2.50V,所以实际电压值就是
result_ADx=GetADresult(x)*2.50/1024;
三、代码分析
(1)数码管显示及闪烁显示的代码
//0通道显示
ZLG7289_ENABLE();//使zlg7289占有同步串口
Delay(5);//延时
WriteSDIO(ZLG7289_CMD_DATA1|6);//数码管以方式1译码,第一个数码管亮
WriteSDIO(((int)(result_AD0))%10);//显示个位
Delay
(1);//延时
if((int)((result_AD0))>9)
{//键值大于9显示十位
WriteSDIO(ZLG7289_CMD_DATA1|7);//发送十位数据
WriteSDIO(((int)(result_AD0))/10);
Delay
(1);
WriteSDIO(ZLG7289_CMD_HIDE);//使一、二、三这三位数码管显示
WriteSDIO(0xff);
}
else
{//键值小于10不显示十位
WriteSDIO(ZLG7289_CMD_HIDE);//使个位数码管显示
WriteSDIO(0x7f);
}
a=0xff;
if(result_AD0>WarnningData[0])
a=0x3f;
Delay
(1);
WriteSDIO(ZLG7289_CMD_FLASH);//闪烁
WriteSDIO(a);
通道1、2、3和通道0一样只需将通道0中的输入值和警戒值改成对应通道的值就可以实现。
(2)在LCD屏条形图中超出部分闪烁显示的代码
if(result_AD0<=WarnningData[0])
{
FillRect(pdc,110,(int)(210-result_AD0*20/3.3),130,210,GRAPH_MODE_NORMAL,COLOR_BLACK);
}
else
{
if(warnning[0]==1)
{
FillRect(pdc,110,(int)(210-result_AD0*20/3.3),130,210,GRAPH_MODE_NORMAL,COLOR_BLACK);
warnning[0]=0;
}
else
{
warnning[0]=1;
FillRect(pdc,110,(int)(210-WarnningData[0]*20/3.3),130,210,GRAPH_MODE_NORMAL,COLOR_BLACK);
}
}
这是通道0的代码,通道1、2、3的代码与之像似,只要改变相应的输入值和警戒值即可。
(3)条形图顶端显示具体电压值的代码
Int2Unicode((int)(result_AD0),result_AD0_16);
TextOut(pdc,114,(int)(198-result_AD0*20/3.3),result_AD0_16,TRUE,FONTSIZE_SMALL);
相应的也只需改变对应通道的输入值和警戒值即可。
第三章实验结果
将生成的文件编辑下载到开发平台并运行,通过四个旋钮来改变相应通道的电压值,当输入的电压值超过警戒值时,对应的数码管显示的数值也会闪烁显示,同时在LCD屏上的条形图的超过部分也会闪烁,条形图的顶端会显示相应的电压值(数值与数码管显示的值相同)。
在LCD屏上设置了两个文本框,一个是控制的通道的,另一个是改变警戒值的。
可以通过改变通道来设置相应的警戒值。
当这两个文本的数值改变是数码的闪烁及LCD屏上条形图超出部分的闪烁将根据新的值来执行。
第四章实验总结
实验做到这里也差不多要结束了,这次实验总体来说还是有些难度的,实验的代码也是相当的长,验中要实现的现象也有好几个,先前做过几个也是关于ARM7的实验,然而前面几个实验的是比较基础的要实现的现象也就一两个,单个来说实验还是很好做的,不过当这些现象多了的同时还要一起实现的话实验就有些难度了,有困难干等着也解决不了,所以在第一次实验没成功之后,我和几个做同样实验的同学就讨论了一下。
在第一次实验结束回来后,我们几个同学就在网上找了相应的资料,再看了相关资料后终于有了明确的思考方向,再次去实验时就顺利多了,虽然在实验代码中还有些问题,不过在之后调试中都一一解决了。
最后实验也顺利完成了。
通过这次实验我懂得了许多,一个人的力量再大也有不够的时候,团结同学合力完成实验或是其他的事情往往能起到事半功倍的效果。
同时一个人的基础知识也是相当重要的,有了基础才能走得更远、飞得更高!
参考文献
[1]田泽.嵌入式系统开发与应用教程[M].北京:
北京航空航天大学出版社,2005.3
[2]周立功.ARM嵌入式系统基础教程[M].北京:
北京航空航天大学出版社,2005.
[3]吴明晖.基于ARM的嵌入式系统开发与应用[M].北京:
人民邮电出版社,2004.
[4]朱永宏,马梅方,梅杓春.《国外电子测量技术》.维普资讯网第2期,2008
附录
#include"..\ucos-ii\includes.h"/*uC/OSinterface*/
#include"..\ucos-ii\add\osaddition.h"
#include"..\inc\drv.h"
#include
#include"..\inc\drv\ad.h"
#include"uhal.h"
#include"zlg7289.h"
#include"44b.h"
#pragmaimport(__use_no_semihosting_swi)//ensurenofunctionsthatusesemihosting
#defineID_ChannelTextCtrl101
#defineID_ValueTextCtrl102
#defineDraw_Wnd_ID104
PTextCtrlpChannelTextCtrl,pValueTextCtrl;
floatresult_AD0,result_AD1,result_AD2,result_AD3;
intWarnningData[4]={26,26,26,26};
intedit[2]={0,0};
externintZlg7289SIOBand;
externintZlg7289SIOCtrl;
///******************任务定义***************///
OS_STKMain_Stack[STACKSIZE*8]={0,};//Main_Test_Task堆栈
voidMain_Task(void*Id);//Main_Test_Task
#defineMain_Task_Prio12
OS_STKDisplay_Task_Stack[STACKSIZE*8]={0,};//Main_Test_Task堆栈
voidDisplay_Task(void*Id);//Main_Test_Task
#defineDisplay_Task_Prio20
OS_STKAD0_Task_Stack[STACKSIZE*8]={0,};//Main_Test_Task堆栈
voidAD0_Task(void*Id);//Main_Test_Task
#defineAD0_Task_Prio21
OS_STKAD1_Task_Stack[STACKSIZE*8]={0,};//Main_Test_Task堆栈
voidAD1_Task(void*Id);//Main_Test_Task
#defineAD1_Task_Prio22
OS_STKAD2_Task_Stack[STACKSIZE*8]={0,};//Main_Test_Task堆栈
voidAD2_Task(void*Id);//Main_Test_Task
#defineAD2_Task_Prio23
OS_STKAD3_Task_Stack[STACKSIZE*8]={0,};//Main_Test_Task堆栈
voidAD3_Task(void*Id);//Main_Test_Task
#defineAD3_Task_Prio24
/**************已经定义的OS任务*************
tcp监控任务11
以太网物理层监控任务8
触摸屏任务9
键盘任务10
lcd刷新任务59
系统任务1
*****************************************************/
///*****************事件定义*****************///
OS_EVENT*Nand_Rw_Sem;//Nand_Flash读写控制权旗语
//andyoucanuseitasfolloeing:
//Nand_Rw_Sem=OSSemCreate
(1);//创建Nand-Flash读写控制权旗语,初值为1满足互斥条件//
//OSSemPend(Nand_Rw_Sem,0,&err);
//OSSemPost(Nand_Rw_Sem);
OS_EVENT*Uart_Rw_Sem;//Uart读写控制权旗语
//andyoucanuseitasfolloeing:
//Uart_Rw_Sem=OSSemCreate
(1);//创建Uart读写控制权旗语,初值为1满足互斥条件//
//OSSemPend(Uart_Rw_Sem,0,&err);
//OSSemPost(Uart_Rw_Sem);
//////////////////////////////////////////////////////////
voidinitOSGUI()//初始化操作系统的图形界面
{
initOSMessage();
initOSList();
initOSDC();
initOSCtrl();
initOSFile();
}
/////////////////////////////////////////////////////
//Mainfunction.//
////////////////////////////////////////////////////
intmain(void)
{
Uart_Printf("\nArmTargetInitOK.");
Zlg7289_Reset();//zlg7289复位
ARMTargetInit();//开发板初始化
OSInit();//操作系统初始化
uHALr_ResetMMU();//复位MMU
LCD_Init();//初始化LCD模块
LCD_printf("LCDinitializationisOK\n");//向液晶屏输出数据
LCD_printf("320x240TextMode\n");
initOSGUI();//初始化图形界面
LoadFont();//调Unicode字库
LoadConfigSys();//使用config.sys文件配置系统设置
LCD_printf("CreatetaskonuCOS-II...\n");
OSTaskCreate(Main_Task,(void*)0,(OS_STK*)&Main_Stack[STACKSIZE*8-1],Main_Task_Prio);//创建系统任务
OSTaskCreate(Display_Task,(void*)0,(OS_STK*)&Display_Task_Stack[STACKSIZE-1],Display_Task_Prio);//20
OSTaskCreate(AD0_Task,(void*)0,(OS_STK*)&AD0_Task_Stack[STACKSIZE-1],AD0_Task_Prio);
OSTaskCreate(AD1_Task,(void*)0,(OS_STK*)&AD1_Task_Stack[STACKSIZE-1],AD1_Task_Prio);
OSTaskCreate(AD2_Task,(void*)0,(OS_STK*)&AD2_Task_Stack[STACKSIZE-1],AD2_Task_Prio);
OSTaskCreate(AD3_Task,(void*)0,(OS_STK*)&AD3_Task_Stack[STACKSIZE-1],AD3_Task_Prio);
OSAddTask_Init();//创建系统附加任务
LCD_printf("StartinguCOS-II...\n");
LCD_printf("Enteringgraphmode...\n");
LCD_ChangeMode(DspGraMode);//变LCD显示模式为文本模式
InitRtc();//初始化系统时钟
Nand_Rw_Sem=OSSemCreate
(1);//创建Nand-Flash读写控制权旗语,初值为1满足互斥条件//
OSStart();//操作系统任务调度开始
//不会执行到这里
return0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//voidinit_ADdevice()
//{
//rADCPSR=20;
//rADCCON=ADCCON_SLEEP;
//}
U8onKey(intnkey,intfnkey)
{
staticBOOLEANinput=FALSE;
staticintEditNumber=1;
if(EditNumber==1)
{
switch(nkey)
{
case14:
//OK
if(!
input)
{
SetWndCtrlFocus(NULL,ID_ChannelTextCtrl);
pChannelTextCtrl->text[0]=0;//清空文本框
SetTextCtrlEdit(pChannelTextCtrl,TRUE);
DrawTextCtrl(pChannelTextCtrl);
input=TRUE;
edit[0]=1;
}
else
{
SetTextCtrlEdit(pChannelTextCtrl,FALSE);
DrawTextCtrl(pChannelTextCtrl);
input=FALSE;
edit[0]=0;
EditNumber=2;
}
returnTRUE;
case16:
//Cancel
SetTextCtrlEdit(pChannelTextCtrl,FALSE);
input=FALSE;
edit[0]=0;
EditNumber=2;
returnTRUE;
}
}
elseif(EditNumber==2)
{
switch(nkey)
{
case14:
//OK
if(!
input)
{
SetWndCtrlFocus(NULL,ID_ValueTextCtrl);
pValueTextCtrl->text[0]=0;//清空文本框
SetTextCtrlEdit(pValueTextCtrl,TRUE);
DrawTextCtrl(pValueTextCtrl);
input=TRUE;
edit[1]=1;
}
else
{
SetTextCtrlEdit(pValueTextCtrl,FALSE);
DrawTextCtrl(pValueTextCtrl);
input=FALSE;
edit[1]=0;
EditNumber=1;
WarnningData[Unicode2Int(pChannelTextCtrl->text)]=Unicode2Int(pValueTextCtrl->text);
}
returnTRUE;
case17:
//Cancel
SetTextCtrlEdit(pValueText