基于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.2 ARM7 LPC2138 EasyARM2131 开发板是广州周立功公司设计的 EasyARM 系列开发套件之一,采用 了 PHILIPS 公司基于 ARM7TDMI-S 核、 单电源供电、 LQFP64 封装的 LPC2131,具有 JTAG 仿真调试、 ISP 编程等功能。开发板上提供了一些键盘、 LED、蜂鸣器等常用功能部件, 还具有 RS232 接口电路、 I 2C存储器电路。 另外, 用户也可以更换兼容的 CPU进行仿真调试, 如 LPC2132、 LPC2138、 LPC2142 等。灵活的跳线组合(开发板内使用的所有 I/O 均可断开连接) ,还有用户 I/O 接 口,极大地方便了用户进行 32 位 ARM嵌入式系统的开发实验。EasyARM2131 实验板功能特点:* 完全自主设计的软硬件、拥有自主版权的 JTAG 仿真技术;* 支持 ADS1.2 集成开发环境及其 PHILIPS 所有型号 ARM 微控制器的仿真与开发;* 采用 “主板+ CPU PACK 适配器+ SD 卡适配器 (标准配置) +多种可选配置适配器”* 的 形 式构成 EasyARM2131 开发 套 件, 标 准 配置的 CPU PACK 主芯片为LPC2131FBD;* 板上的功能部件与 CPU 之间,可以使用跳线器选择连接;* 全面支持 9 种型号的 64 PIN 小管脚 ARM7 微控制器:- LPC213x( LPC2131/2132/2134/2136/2138)-内置 USB 接口的 LPC214x(LPC2142/2144/2146/2148) * 多种免费商业化软件包及其详细的开发文档:* 移植 μ C/OS- II 到 ARM7 软件包四、硬件设计4.1 AD 采样模块设计图 2 信号采集电路图4.2 LCD 液晶屏显示设计LCD液晶屏显示电路如图 4-2 所示。 该液晶可实现显示当前电压值和信号显示时间,具体控制和实现方法如下:左图为电压信号调节电路,如图所示,电源电压 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 ,则对应的时间电压为:VVALUEU 3.31024( 1) ARM7的 P1.16-P1.23 口连接液晶屏的 DBO-DB7, 控制对液晶屏并行数据读和写;( 2) ARM7的 P1.24 口连接液晶屏的 RS 口,控制并行的指令 /数据选择信号;( 3) ARM7的 P1.25 口连接液晶屏的 R/W 口,控制并行的读写选择信号;( 4) ARM7的 P1.26 口连接液晶屏的 EN 口,控制并行的使能信号;图 3 LCD 液晶屏电路图4.2.1 LCD 内部的 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 读出的数据内容表 1 LCD 内部指令表指令 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 按键调节电路图 4 按键调节电路图4.4 蜂鸣器和 LED报警电路按键 SWI 和按键 SWI1 分别接到芯片的P0.26、 P0.30 口, 当按键 SWI 按下时, P0.26口的变为低电压,当程序检测到 IO0PIN 的改变,阈值电压 w=w+200;同理,当按键 SWI1 按下时,阈值电压w=w-200;同时液晶屏上会显示此时电压 >阈值电压,或此时电压 W,则蜂鸣器鸣叫报警,否则蜂鸣器不鸣叫。( 5)循环执行( 2) ~( 4) 。图 7 系统主流程图5.2 液晶显示功能模块图 5-2 为液晶显示功能模块流程图;开始LCD初始化写命令到 LCD写数据到 LCD显示图 8 液晶显示功能模块流程图5.2.1 1602LCD 的一般初始化(复位)过程延时 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.4 AD 转换模块AD转换模块的流程图如下:图 10 AD 转换流程图使用 ADC 模块时,先要将测量通道引脚设置为 AINx 功能,然后通过 ADCR 寄存器设置 ADC 的工作模式、 ADC 转换通道、 CLKDIV 时钟分频值,并启动 ADC 转换。可以通过查询或中断的方式等待 ADC 转换完毕,转换数据保存在 ADDR 寄存器中。六、设计结果演示图 10 系统总体仿真图由图可看出当前电压和阈值电压, 也可直接通过 LED灯看出电压是否超过阈值,按键的按下能及时反映在液晶屏上阈值大小的变化。图 11 虚拟终端的电压显示图图 12 串口调试软件接收数据图七、设计体会回顾此次 ARM课程设计, 我感触颇多, 最深刻的体会是: 事情只有做了那你才能知道是什么结果, 开始觉得程序很难懂, 每次编都有好多错误, 很多垂头丧气的时候都想要放弃, 可是最终都放下情绪坚持了下来, 因为我坚信: 付出终会有收获, 同时也懂得了理论与实践相结合是很重要的, 只有理论知识是远远不够的, 只有把所学的理论知识与实际编程相结合起来, 才能充分运用和体会所学知识。我在设计中遇到了许多问题,同时也发现了自己的不足之处,比如:不够耐心,部分程序思路不清等,在今后的学习中我会慢慢改正。最后,很感激老师的指导,我会继续努力的!附:系统总程序#include#include #define uchar unsigned char #define uint unsigned int #define uint8 unsigned char #define uint32 unsigned int #define uint16 unsigned int #define Fpclk 11059200 //晶振频率#define UART_BPS 9600 #define LED (1>6) //处理转换值u=(long)ADC_data*3300/1024; //得到实际电压if((IO0PIN if((IO0PIN 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); } int main() //主函数{ 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(“The current voltage is “); 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); } }