基于ARM7的电压监测报警系统.docx
《基于ARM7的电压监测报警系统.docx》由会员分享,可在线阅读,更多相关《基于ARM7的电压监测报警系统.docx(24页珍藏版)》请在冰豆网上搜索。
基于ARM7的电压监测报警系统
《嵌入式系统设计导论》
课程设计
题目:
基于ARM7的电压监测报警系统
学院
班级
学号
姓名
二〇一三年四月
基于ARM7的电压监测报警系统
摘要
本系统采用LPC2138系列的ARM硬件、WS-1型电位器、液晶屏LM016L、按键、蜂鸣器、虚拟终端和上位机等组成,系统可实现在液晶屏实时显示电压的功能,并将电压数据串口通信传递给上位机,通过按键可调节阈值电压,系统除基本数字电压表功能外,还具有电压超限时声光报警等功能。
在设计中我们应用具有丰富的硬件资源的ARM7开发板。
本设计采用电位器实现对电压信号的采集,利用LPC2138内部的ADC模块将转换后的电压传送给LCD液晶显示,虚拟终端再将数据传递给上位机,同时按键可调节阈值电压,当当前电压超过阈值电压时,报警通过蜂鸣器鸣叫和LED灯亮来提示。
本文详细介绍了AD采样、与PC机的串口通信、液晶屏显示等部分,具有较强的实用性和推广性。
关键词:
LPC2138;上位机;LM016L液晶屏;电压超限报警;
一、设计目的
1.通过本课程设计,熟悉嵌入式系统开发方法和流程。
2.能结合课堂所学自主设计实现一个简单的监测报警系统。
3.进一步学会应用定时器、A/D、显示等模块功能
二、设计要求
1.能利用学过的A/D转换、定时器、按键等模块,实现温度(可用DS18B20传感器)或电压(可用滑动电阻)的检测、显示、阈值设置,以及超过阈值能声光报警。
2.将温度/电压数据通过串行通信(UART)发送到PC上位机显示,由上位机可显示实时监测数据、历史曲线,并可发送控制命令给ARM实现报警或关闭加热源/电源。
注:
上位机软件程序可用VB、VC++做界面,也可简单地通过“串口调试软件”显示。
三、系统总体方案
3.1总体方案设计
利用ARM7控制芯片、LCD液晶屏、LED、电位器、虚拟终端等分别实现;
(1)通过电位器的移动来调节应采集的电压信号的大小;
(2)通过液晶显示当前电压值和阈值及其大小关系;
(3)通过蜂鸣器和LED灯实现超限报警;
(4)虚拟终端将实时电压显示出来,并通过串口物理端口将数据传递给上位
机。
图1设计方案总体框图
系统初始化后,通过调节电位器来调节采集电压信号的大小,通过LCD上显示当前电压值和阈值,通过按键实现电压阈值设定,如果采集的电压值超过设定的阈值电压,蜂鸣器会鸣叫且LED等亮提示电压超限,起到报警的作用。
3.2ARM7LPC2138
EasyARM2131开发板是广州周立功公司设计的EasyARM系列开发套件之一,采用了PHILIPS公司基于ARM7TDMI-S核、单电源供电、LQFP64封装的LPC2131,具有JTAG仿真调试、ISP编程等功能。
开发板上提供了一些键盘、LED、蜂鸣器等常用功能部件,还具有RS232接口电路、I2C存储器电路。
另外,用户也可以更换兼容的CPU进行仿真调试,如LPC2132、LPC2138、LPC2142等。
灵活的跳线组合(开发板内使用的所有I/O均可断开连接),还有用户I/O接口,极大地方便了用户进行32位ARM嵌入式系统的开发实验。
EasyARM2131实验板功能特点:
*完全自主设计的软硬件、拥有自主版权的JTAG仿真技术;
*支持ADS1.2集成开发环境及其PHILIPS所有型号ARM微控制器的仿真与开发;
*采用“主板+CPUPACK适配器+SD卡适配器(标准配置)+多种可选配置适配器”
*的形式构成EasyARM2131开发套件,标准配置的CPUPACK主芯片为
LPC2131FBD;
*板上的功能部件与CPU之间,可以使用跳线器选择连接;
*全面支持9种型号的64PIN小管脚ARM7微控制器:
-LPC213x(LPC2131/2132/2134/2136/2138)
-内置USB接口的LPC214x(LPC2142/2144/2146/2148)
*多种免费商业化软件包及其详细的开发文档:
*移植μC/OS-II到ARM7软件包
四、硬件设计
4.1AD采样模块设计
左图为电压信号调节电路,如图所示,电源电压Vcc=3.3V,故测量范围为(0~3.3V),电位器RV2=1K,信号采集端接到ARM7芯片P0.27口,通过调节电位器改变采集P0.2口的电压值,送至芯片内部AIN0(AD转换器)进行A/D转换。
A/D没有独立的参考电压引脚,A/D的参考电压与供电电压连接在一起即3.3V,假定从ADDR寄存器中读取到的10位A/D转换结果为VALUE,则对应的时间电压为:
图2信号采集电路图
4.2LCD液晶屏显示设计
LCD液晶屏显示电路如图4-2所示。
该液晶可实现显示当前电压值和信号显示时间,具体控制和实现方法如下:
(1)ARM7的P1.16-P1.23口连接液晶屏的DBO-DB7,控制对液晶屏并行数据
读和写;
(2)ARM7的P1.24口连接液晶屏的RS口,控制并行的指令/数据选择信号;
(3)ARM7的P1.25口连接液晶屏的R/W口,控制并行的读写选择信号;
(4)ARM7的P1.26口连接液晶屏的EN口,控制并行的使能信号;
图3LCD液晶屏电路图
4.2.1LCD内部的11条指令
序号
指令
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
1
清显示
0
0
0
0
0
0
0
0
0
1
2
光标返回
0
0
0
0
0
0
0
0
1
*
3
置输入模式
0
0
0
0
0
0
0
1
I/D
S
4
显示开/关控制
0
0
0
0
0
0
1
D
C
B
5
光标或字符移位
0
0
0
0
0
1
S/C
R/L
*
*
6
置功能
0
0
0
0
1
DL
N
F
*
*
7
置字符发生存贮器地址
0
0
0
1
字符发生存贮器地址
8
置数据存贮器地址
0
0
1
显示数据存贮器地址
9
读忙标志或地址
0
1
BF
计数器地址
10
写数到CGRAM或DDRAM)
1
0
要写的数据内容
11
从CGRAM或DDRAM读数
1
1
读出的数据内容
表1LCD内部指令表
指令1:
清显示,指令码01H,光标复位到地址00H位置。
指令2:
光标复位,光标返回到地址00H。
指令3:
光标和显示模式设置I/D:
光标移动方向,高电平左移,低电平右移S:
屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效。
指令4:
显示开关控制。
D:
控制整体显示的开与关,高电平表示开显示,低电平表示关显示C:
控制光标的开与关,高电平表示有光标,低电平表示无光标B:
控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:
光标或显示移位S/C:
高电平时移动显示的文字,低电平时移动光标。
指令6:
功能设置命令DL:
高电平时为4位总线,低电平时为8位总线N:
低电平时为单行显示,高电平时双行显示F:
低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
指令7:
字符发生器RAM地址设置。
指令8:
DDRAM地址设置。
指令9:
读忙信号和光标地址BF:
为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10:
写数据。
指令11:
读数据。
液晶显示部分的程序可根据上表进行编写,本文中如果电压超过设定值w,则显示屏上显示当前电压且大于设定电压,否则,显示当前电压且小于设定电压,清晰的看出当前电压情况。
4.3按键调节电路
按键SWI和按键SWI1分别接到芯片的P0.26、P0.30口,当按键SWI按下时,P0.26口的变为低电压,当程序检测到IO0PIN的改变,阈值电压w=w+200;
同理,当按键SWI1按下时,阈值电压w=w-200;
同时液晶屏上会显示此时电压>阈值电压,或此时电压<阈值电压,液晶屏会同步更新阈值电压,虚拟终端和上位机也会实时显示当前电压值。
图4按键调节电路图
4.4蜂鸣器和LED报警电路
LED灯和蜂鸣器电路分别接芯片的P1.28和P1.29口,当经过AD转换的电压u超出设定的阈值电压w时,程序拉高了ARM芯片的P1.28、P1.29口,使NPN管导通,蜂鸣器开始鸣叫,LED灯亮报警,同理如果电压值低于阀值电压,NPN管截止,则蜂鸣器不鸣叫。
图5蜂鸣器电路图
4.5串口通信(UART)电路
串口通信电路如下图,串口物理端口(COMPIM)的RXD接芯片的P0.1口,TXD接芯片的P0.0口,即UART0口,电压信息可实时显示在虚拟终端上,且可通过VSPD将虚拟终端与串口调试软件连接起来,将信息显示在串口调试软件上。
图6串口通信电路
五、系统的软件设计
5.1系统主流程图
图5-1为系统主流程图,主流程图具体介绍如下:
(1)系统初始化包括对AD转换模块进行初始化、液晶屏初始化,串口通信
初始化、设定GPIO、设定电压阈值W等;
(2)ADC模块电压转换,转换之后显示当前检测到的电压并赋值给U,同时
串口通信传递给串口调试软件;
(3)检测按键1是否按下,如果按下,则阈值电压w增加200,同理,如
果按键2按下,则阈值电压减小200;
(4)将检测到的电压值U与电压阈值W进行比较,如果U>W,则蜂鸣器鸣叫
报警,否则蜂鸣器不鸣叫。
(5)循环执行
(2)~(4)。
图7系统主流程图
5.2液晶显示功能模块
图5-2为液晶显示功能模块流程图;
图8液晶显示功能模块流程图
5.2.11602LCD的一般初始化(复位)过程
延时15mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
以后每次写指令、读/写数据操作均需要检测忙信号
写指令38H:
显示模式设置
写指令08H:
显示关闭
写指令01H:
显示清屏
写指令06H:
显示光标移动设置
写指令0CH:
显示开及光标设置
5.3串口通信模块
串口通信模块的流程图如下:
图9串口通信流程图
5.3.1串口通信的基本步骤
(1)选择串口UART0;
(2)设置UART0的工作模式为:
8位字符长度,1个停止位,无奇偶校验,使能除数锁存寄存器
(3)确定除数锁存寄存器高8位和低8位的数据;
(4)串口通信还需锁相环(PLL)来实现输出信号频率对输入信号频率的跟踪,PLL主要由下面这3个寄存器来控制状态:
①PLLCON寄存器:
控制PLL是否进行连接,这个连接需要在向PLLFEED发送正确的信息(馈送序列)的时候才生效,且PLLCON必须在PLL开始连接之前就设置好,否则会造成系统不可预知的错误。
②PLLCFG寄存器:
这个寄存器是用来设置倍频系数M和分频系数N的,这两个值决定了倍频和分频的频率。
③PLLFEED:
向此寄存器以连续的VPB总线周期写入0xAA,Ox55,即馈送序列,在正确的序列被写入PLLFEED之后,PLLCON,PLLCFG才生效,PLL电路才能正确的连接到电路中。
(5)UART0查询方式发送字节数据。
5.4AD转换模块
AD转换模块的流程图如下:
图10AD转换流程图
使用ADC模块时,先要将测量通道引脚设置为AINx功能,然后通过ADCR寄存器设置ADC的工作模式、ADC转换通道、CLKDIV时钟分频值,并启动ADC转换。
可以通过查询或中断的方式等待ADC转换完毕,转换数据保存在ADDR寄存器中。
6、设计结果演示
图10系统总体仿真图
由图可看出当前电压和阈值电压,也可直接通过LED灯看出电压是否超过阈值,按键的按下能及时反映在液晶屏上阈值大小的变化。
图11虚拟终端的电压显示图
图12串口调试软件接收数据图
七、设计体会
回顾此次ARM课程设计,我感触颇多,最深刻的体会是:
事情只有做了那你才能知道是什么结果,开始觉得程序很难懂,每次编都有好多错误,很多垂头丧气的时候都想要放弃,可是最终都放下情绪坚持了下来,因为我坚信:
付出终会有收获,同时也懂得了理论与实践相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实际编程相结合起来,才能充分运用和体会所学知识。
我在设计中遇到了许多问题,同时也发现了自己的不足之处,比如:
不够耐心,部分程序思路不清等,在今后的学习中我会慢慢改正。
最后,很感激老师的指导,我会继续努力的!
附:
系统总程序
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#defineuint8unsignedchar
#defineuint32unsignedint
#defineuint16unsignedint
#defineFpclk11059200//晶振频率
#defineUART_BPS9600
#defineLED(1<<28)
#defineBEE(1<<29)
#defineSWI(1<<30)
#defineSWI1(1<<26)
#definers(1<<24)
#definerw(1<<25)
#defineen(1<<26)
uint32ADC_data,u,i,w;
uchar*q;charstr[20];
chardis[5];
voiddelay(unsignedinta)//延迟函数
{
while(--a!
=0)
for(i=0;i<500;i++);
}
voidUART0_Ini(void)//初始化串口0
{
uint16Fdiv;
U0LCR=0x83;
Fdiv=(Fpclk/16)/UART_BPS;
U0DLM=Fdiv/256;
U0DLL=Fdiv%256;
U0LCR=0x03;
}
voidlcd_init(void)//液晶屏初始化
{
IO1CLR=IO1CLR|rs;
IO1CLR=IO1CLR|rw;
IO1CLR=IO1CLR|0x00ff0000;//D1~D7先清零
IO1SET=IO1SET|0x00380000;//再送数(置功能双行显示)
IO1SET=IO1SET|en;
IO1CLR=IO1CLR|en;
delay(5);
IO1CLR=IO1CLR|rs;//全部清零
IO1CLR=IO1CLR|rw;
IO1CLR=IO1CLR|0x00ff0000;//先清零
IO1SET=IO1SET|0x00060000;//再送数(置输入模式)
IO1SET=IO1SET|en;
IO1CLR=IO1CLR|en;
delay(5);
IO1CLR=IO1CLR|rs;//全部清零
IO1CLR=IO1CLR|rw;
IO1CLR=IO1CLR|0x00ff0000;//先清零
IO1SET=IO1SET|0x000c0000;//再送数(显示开关控制)
IO1SET=IO1SET|en;
IO1CLR=IO1CLR|en;
delay(5);
}
voidlcd_printf(char*s,longtemp_data)//液晶屏显示
{
if(temp_data<0){
temp_data=-temp_data;
*s='-';
}
else*s='';
*++s=temp_data/1000+0x30;
*++s=temp_data%1000/100+0x30;
temp_data=temp_data%100;//取余运算
*++s=temp_data/10+0x30;
temp_data=temp_data%10;//取余运算
*++s=temp_data+0x30;
}
voidAdd(longdat)
{dat=dat<<16;
delay(5);
IO1CLR=IO1CLR|rs;//全部清零
IO1CLR=IO1CLR|rw;
IO1CLR=IO1CLR|0x00ff0000;//先清零
IO1SET=IO1SET|dat;//再送数(DDRAM地址设置)
IO1SET=IO1SET|en;
IO1CLR=IO1CLR|en;
}
voidWrDat(longdat)
{
dat=dat<<16;
delay(5);
IO1SET=IO1SET|rs;
IO1CLR=IO1CLR|rw;
IO1CLR=IO1CLR|0x00ff0000;//先清零
IO1SET=IO1SET|dat;//再送数(置功能)
IO1SET=IO1SET|en;
IO1CLR=IO1CLR|en;
}
voidUART0_SendByte(uint8data)//向串口发送字节数据,并等待数据发送完毕
{
U0THR=data;
while((U0LSR&0x40)==0);
}
voidUART0_SendStr(uint8const*str)//向串口发送字符串
{
while
(1)
{if(*str=='\0')break;
UART0_SendByte(*str++);
}
}
voidadcwork()//读取AD转换结果
{
while(ADDR&0x800000000==0);//等待转换结束
ADC_data=ADDR;
ADC_data=(ADC_data>>6)&0x3ff;//处理转换值
u=(long)ADC_data*3300/1024;//得到实际电压
if((IO0PIN&SWI)==0)//阈值调节
w=w+200;
if((IO0PIN&SWI1)==0)
w=w-200;
if(u>w)//报警显示
{IO1SET=IO1SET|LED;
IO1SET=IO1SET|BEE;
Add(0x89);
WrDat(62);
Add(0x8a);
WrDat(119);}
else
{IO1CLR=IO1CLR|LED;
IO1CLR=IO1CLR|BEE;
Add(0x89);
WrDat(60);
Add(0x8a);
WrDat(119);
}
delay(100);
Add(0x83);
WrDat(u/1000+0x30);
Add(0x84);
WrDat(u%1000/100+0x30);
Add(0x85);
WrDat(u%1000%100/10+0x30);
Add(0x86);
WrDat(u%1000%100%10+0x30);
Add(0x87);
WrDat(109);
Add(0x88);
WrDat(86);
Add(0x8b);
WrDat(0x3d);
Add(0x8c);
WrDat(w/1000+0x30);
Add(0x8d);
WrDat(w%1000/100+0x30);
Add(0x8e);
WrDat(w%1000%100/10+0x30);
Add(0x8f);
WrDat(w%1000%100%10+0x30);
lcd_printf(dis,u);
}
intmain()//主函数
{
PINSEL1=0x00000000;
PINSEL0=0x00000000;//设置所有管脚连接GPIO
PINSEL2=0x00000000;
PINSEL0|=5;//P0.0为TxD0,P0.1为RxD0
UART0_Ini();//串口初始化
delay(100);
lcd_init();
PINSEL1=0X00400000;
IO1DIR=IO1DIR|0xffffffff;//引脚均设为输出状态
w=2800;
//----------------------------------------对于串口要加入
VPBDIV=2;
PLLCFG=
(1)|(0<<5);
PLLCON=3;//设置激活并连接PLL
PLLFEED=0xaa;//发送PLL馈送序列,执行激活和连接动作
PLLFEED=0x55;
//----------------------------------------
while
(1)
{
PINSEL1=0x00400000;
ADCR=(1<<0)|((Fpclk/1000000-1)<<8)|(0<<16)|(0<<17)|(1<<21)|(0<<22)|(1<<24)|(0<<27);
delay(10);
ADC_data=ADDR;
adcwork();
UART0_SendStr("Thecurrentvoltageis");
UART0_SendByte((u/1000)+'0');
UART0_SendByte((u%1000/100)+'0');
UART0_SendByte((u%1000%100/10)+'0');
UART0_SendByte((u%1000%100%10)+'0');
UART0_SendStr("mV\r\n");
delay(10);
}
}