资源描述
目 录
第1章 系统设计分析 1
1.1 系统设计要求 1
1.2 任务和实现的功能 1
1.3 主要性能指标 1
1.4 方案的论证 1
1.5 采集电压电路的选择 1
第2章 硬件的设计 2
2.1 电源电路 2
2.2 电压采集电路 2
2.3 温度显示电路 3
2.3.1 74 HC595具有的特点 3
2.3.2 74HC595管脚图 4
2.3.3 数码显示管原理 5
2.4 M0介绍 6
2.4.1 A/D及数据采集处理 7
第3章 软件设计 9
3.1 软件实现功能 9
3.2 软件设计 9
第4章 功能测试及结果分析 10
4.1 硬件调试分析 10
4.2 测试结果分析 10
4.3 温度报警实物图 10
第5章 设计心得 11
参考文献 12
附录 13
附录一:元器件明细表 13
附录二:PT1000温度与电阻的关系 13
附录三:硬件电路原理图 14
附录四:参考程序 15
附录五:实物图 24
24
第1章 系统设计分析
1.1 系统设计要求
1、 以单片机、CPLD/FPGA、ARM、DSP等为核心器件,组成一个单片机数据采集系统;
2、 温度范围为0~150°C,测量精度为1°C;
3、 被测温度通过4位LED数码管显示;
4、 温度下限为80°C,上限为90°C,超过上下限温度具有报警功能。根据项目的具体要求,经过阅读思考,可对题目的具体任务、功能、技指等作出如下分析。
1.2 任务和实现的功能
实际上项目的任务就是要设计一个温度采集系统,系统的功能是用户可以随意设定某一温度,当前温度超过一定范围时可以报警,温度回到正常值停止报警,并且可动态显示当前的温度。
在控制部分,要求系统跟随动态设定的温度而报警,题目并未规定报警反应时间长短,但显然报警要快。
1.3 主要性能指标
1、温度范围为0~200°C,测量精度为1°C,可以估算到0.1°C;
2、被测温度通过前4位LED数码管显示,后4位LED数码管显示动态设定的报警温度;
3、自己可以通过键盘显示板设置报警温度;
1.4 方案的论证
经过对题目进行深入的分析和思考,可将整个系统分为以下几个部分:模拟温度传感器、A/D转换、ARM、数码显示 、温度报警部分组成 。系统框图如下(图1.1)。
数码显示
模拟温度传感器 A/D转换 ARM
温度报警
图1.1 系统结构框图
1.5 采集电压电路的选择
1、 采用差动放大原理
运放LM324正反相放大器,利用差动放大原理,对于纯粹的单向放大电路,这是足够的。但是设计匹配相关电阻以及采集后电阻及温度的关系稍显麻烦,并且电路供电是3.3V不太需要放大。
2、 简单分压电路采集
本次采用的温度传感器PT1000在0~100°C之间温度与电阻成十分良好的线性关系,故很适合采用分压原理进行测量,能够很精确的反应出温度的变化,并且电路简单。本次设计电路故采用分压原理设计。
第2章 硬件的设计
2.1 电源电路
本次项目用直流5V、3.3V稳压电源,M0工作电压在3.3V而实际电压为3.29V可以满足要求。
具体电路如下(图2.1):
图2.1 电源电路图
2.2 电压采集电路
本次采用的是分压原理采集电压,故电路很简单,如下所示(图2.2):
图2.2 电压采集电路
由于这个电路输出的是电压信号,不能直接被ARM利用,因此需经过一个A/D转换器,将电压信号转换为数字量。A/D转换器有很多类型,需要根据精度和转换速度来进行选择。本设计可采用最常用的A/D芯片之一AD0809的应用电路。也可直接选用M0上的A/D转换器,这样可以省去A/D电路的制作,简化了电路,提高了可靠性。值得注意的是ARM系列的微处理器A/D的值要小于3.3V。
2.3 温度显示电路
本次设计使用的键盘显示板主要采用74HC595芯片和数码显示管。显示电路图(图2.3)
图2.3 键盘显示板的电路图
2.3.1 74 HC595具有的特点
74HC595是一款漏极开路输出的CMOS移位寄存器,输出端口为可控的三态输出端,亦能串行输出下一级级联芯片。
1、 高速移位时钟频率Fmax>25MHz;
2、 标准串行(SPI)接口;
3、 CMOS串行输出,可用于多个设备的级联;
4、 低功耗:Ta=25℃时,Icc=4uA(MAX);
2.3.2 74HC595管脚图
图2.4 74HC595的管脚图
下面是74HC595管脚列表:
表1: 74HC595管脚列表
管脚编号
管脚名
说明
1、2、3、4、5、6、7、15
QA—QH
三态输出管脚
8
GND
电源地
9
SQH
串行数据输出管脚
10
SCLK
移位寄存器清零端
11
SCK
数据输入时钟线
12
RCK
输出存储器锁存时钟线
13
OE
输出使能
14
SI
数据线
15
VCC
电源端
输入输出管脚图(图2.5):
图2.5 输入输出管脚图
表2: 74HC595真值表
输入管脚
输出管脚
SI
SCK
SCLR
RCK
OE
X
X
X
X
H
QA—QH输出高阻
X
X
X
X
L
QA—QH输出有效值
X
X
L
X
X
移位寄存器清零
L
上沿
H
X
X
移位寄存器存储L
H
上沿
H
X
X
移位寄存器存储H
X
下沿
H
X
X
移位寄存器状态保持
X
X
X
上沿
X
输出存储器锁存移位寄存器中的状态值
X
X
X
下沿
X
输出存储器状态保持
2.3.3 数码显示管原理
我们最常用的是七段式和八段式LED数码管,八段比七段多了一个小数点,其他的基本相同。所谓的八段就是指数码管里有八个小LED发光二极管,通过控制不同的LED的亮灭来显示出不同的字形。数码管又分为共阴极和共阳极两种类型,其实共阴极就是将八个LED的阴极连在一起,让其接地,这样给任何一个LED的另一端高电平,它便能点亮。而共阳极就是将八个LED的阳极连在一起。其原理图(图2.6)如下。
图2.6 数码显示管的电路与结构图
其中引脚图的两个COM端连在一起,是公共端,共阴数码管要将其接地,共阳数码管将其接正5或3.3伏电源。一个八段数码管称为一位,多个数码管并列在一起可构成多位数码管,它们的段选线(即a,b,c,d,e,f,g,dp)连在一起,而各自的公共端称为位选线。显示时,都从段选线送入字符编码,而选中哪个位选线,那个数码管便会被点亮。数码管的8段,对应一个字节的8位,a对应最低位,dp对应最高位。所以如果想让数码管显示数字0,那么共阴数码管的字符编码为00111111,即0x3f;共阳数码管的字符编码为11000000,即0xc0。可以看出两个编码的各位正好相反。如下表(表3)所示。
表3:数码管显示数字对应的段码表
共阳极数码显示管
共阴极数码显示管
十进制
十六进制位码
十进制
十六进制位码
十进制
十六进制位码
十进制
十六进制位码
0
0xc0
8
0x80
0
0x3f
8
0x7f
1
0xf9
9
0x90
1
0x06
9
0x6f
2
0xa4
a
0x88
2
0x5b
a
0x77
3
0xb0
b
0x83
3
0x4f
b
0x7c
4
0x99
c
0xc6
4
0x66
c
0x39
5
0x92
d
0xa1
5
0x6d
d
0x5e
6
0x82
e
0x86
6
0x7d
e
0x79
7
0xf8
f
0x8e
7
0x07
f
0x71
2.4 M0介绍
LPC1100系列Cortex-M0微控制器是为嵌入式系统应用而设计的高性能、低功耗的32位微处理器。它是市场上低价最低的32位微控制器解决方案,其价值和易用性比现有的8/16位微控制器更胜一筹。该控制器性能卓越、简单易用、功耗低,更重要的是它能显著降低所有8/16位应用的代码长度。
LPC1100系列Cortex-M0微控制器的主频时钟高达50MHz,拥有高性能的运算控制能力,每秒可执行4500多万条指令,支持睡眠、深度睡眠和深度掉电3种低功耗模式。同时它拥有丰富的外围组件:高达32KB片内Flash程序存储器、8KB片内SRAM、一路(FM+)、一路RS-485/EIA-485UART、两路SSP、4个通用定时器以及多达42个通用I/O口。
LPC1100系列Cortex-M0微控制器主要包括以下主要模块:AD转换器、I2C、SPI、SSP、UART、定时器、功率控制等模块组成。内部结构图如下所示(图2.7)
图2.7 Cortex-M0内部结构图
Cortex-M0内核特性如下:
1、系统选项
Cortex-M0内核集成了嵌套向量中断控制器(NVIC),支持多达32个中断;
集成了系统节拍定时器;
2、调试选项
集成了JTAG调试接口;
集成串行调试接口,支持两个观察点和四个中断断点;
2.4.1 A/D及数据采集处理
LPC1100系列Cortex-M0微控制器A/D转换器的基本时钟由APB时钟提供。A/D转换器包含一个可编程的分频器,它可以将APB时钟调整为逐次逼近转换所需的时钟(最大可达4.5MHz,并且完全满足精度要求的转换需要11个这样的时钟)。
1、 ADC转换时钟分频值计算:
其中:Fadclk为所要设置的ADC时钟,其值不能大于4.5MHz。
2、 A/D转换值计算:
LPC1100系列Cortex-M0内部ADC转换精度是10bit,因此当通道0的结果寄存器AD0DR0中保存的准换值为时,则转换结果的计算方法如下:
由于本次采用的是3.3V作为基准参考电压源,则LPC1100系列Cortex-M0A/D转换器的最小分辨率LSB的如下:
(mv)
在一次转换中,A/D转换器能够区分的最小电压为3.22mv;
在本次设计中我们知道PT1000基本变化范围时1000~1300Ω左右,所以选择1000Ω电阻来分压(实际测量是996Ω),电源提供的是3.3.v(实际测量是3296mv);
故可以得出相关准换公式 :
PT1000电阻值与温度的关系:
Res=1000+3.9T
故得温度与电压的关系:
T=(C)
通过这个公式可以很简单明了的表示出电压与温度的关系。
第3章 软件设计
3.1 软件实现功能
1、 对温度的采集并显示当前的温度及用户设定的报警温度。
2、 对当前温度的实时监控。
3、 用户可以通过按键修改报警温度。
4、 系统的复位。
3.2 软件设计
首先运行程序,对定时器、GPIO、SPI、A/D等部分功能引脚及其功能初始化设置。起初设定的报警温度是40C。当进入主程序,首先进行检测是否有按键按下,若有键按下则修改报警温度,在这个程序中共设置了五个按键,其中两个按键分别加1ºC、10ºC(case1、case3),另外两个按键分别减1ºC、10ºC(case2、case4),还设置了一个还原键恢复到40ºC(case7)。之后把A/D采样的电压进行程序计算得出实时温度,每完整采集转换一次温度便与设置的报警温度进行比较,如果大于设置的温度则进行报警。同时实时采集当前的温度与报警温度比较,如果温度低于报警温度则停止报警,否则继续报警直到温度低于报警温度或是通过按键提高报警温度,这样循环下去。
主程序流程图(图3.1)所示,实现对报警温度值的设定、执行、显示实时温度及对温度的实时监测。
图3.1 软件流程图
第4章 功能测试及结果分析
使用的主要仪器仪表:PC机;数字万用表(DT-9205B,GDM-8245);可跟踪直流稳压电源。
4.1 硬件调试分析
1、 受热时受热不均与,导致测量的误差有点大。
2、 采集电压没有加滤波电容会导致A/D采样的不精确,因为之中会含有高次谐波,加上滤波电容之后就可以解决这个问题。
4.2 测试结果分析
1、 由实际测量可知,系统性能基本上达到了所要求的指标。能够实时跟踪温度并报警,测温精度能够达到1ºC,能够估算到0.1ºC,达到比较好的精度。
2、 在测温中,影响系统性能的因素非常多。最关键的是温度传感器本身的物理性质。由于传感器受热不均,因此温度传感器难免会有迟滞。
4.3 温度报警实物图
见附录五。
第5章 设计心得
从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习ARM更是如此,程序只有在经常的写与读的过程中才能提高,这就是我在这次课程设计中的最大收获。
本课题在选题及进行过程中得到了张振利的悉心指导。制作过程中,张老师多次帮助我分析思路,开拓视角,在我遇到困难想放弃的时候给予我最大的支持和鼓励。张老师老师严谨求实的治学态度,踏实坚韧的工作精神,将使我终生受益,再多华丽的言语也显苍白。在此,谨向张老师致以诚挚的谢意!
在课程设计接近结束之时,在我整个设计过程中,我还要特别感谢我们实验室的庄河文及张广双同学,在设计中我们合作的很愉快,当我们遇到困难的时候我们一起去探讨和研究,一起去战胜它,大家也一起分享排除问题和困难后的喜悦。 可以说我的设计和论文能够顺利的完成并不是我个人的努力可以做到的,离开师的悉心指导,离开同学们的帮助,单就我一人的努力是很难完成的。非常感谢在设计与论文撰写过程中帮助过我的老师和同学们!
在此我表示真诚的感谢!
参考文献
[1]《深入浅出ARM7——LPC213x/214x》上册,周立功等著,北京:北京航天航空大学出版社,2006.1
[2]《模拟电子技术基础》,童诗白,华成英著,北京:高等教育出版社,2000.
[3]《数字电子技术基础》,阎石著,北京:高等教育出版社,2005.
[4]《晶体管电路设计》,铃木雅臣著,周南生译,北京“科学出版时,2005.
[5]《C程序设计》,谭浩强著,北京:清华大学出版社,2005.
附录
附录一:元器件明细表
序号
器件名称
规格
数量
1
M0芯片
1片
2
键盘显示板
1个
3
电容
0.1u/10u
各2个
4
电阻
1K
2个
5
发光二极管
Red/Green
各1个
附录二:PT1000温度与电阻的关系
附录三:硬件电路原理图
外围电路采集电压图 报警显示电路
TinyM0开发板原理图
键盘显示板电路图
附录四:参考程序
/**--------------File Info---------------------------------------------------------------------------------
** File name: main.c
** Last modified Date: 2010-02-04
** Last Version: V1.0
** Descriptions: The main() function example template
**
**--------------------------------------------------------------------------------------------------------
** Created by: Lanwuqiang
** Created date: 2010-02-05
** Version: V1.0
** Descriptions: 添加用户应用程序
**
**--------------------------------------------------------------------------------------------------------
** Modified by: ZhangNingbo
** Modified date: 2010-02-25
** Version: V1.0
** Descriptions: SPI0主机示例程序
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
**
** Rechecked by:
*********************************************************************************************************/
#include "..\config.h"
/*********************************************************************************************************
宏定义
*********************************************************************************************************/
#define BEEP (1ul << 7)
#define BEEPOFF() GPIO2DATA |= BEEP /* 蜂鸣器关 */
#define BEEPON() GPIO2DATA &= ~BEEP /* 蜂鸣器开 */
#define key 1<<5
uint8 data[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //段码表
uint8 selectable[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //位码
uint8 i=0;
uint8 T=0;
uint8 buf[8]={0}; //存分解数据
unsigned char tem_pnt;
unsigned char tem_num;
uint8 tem_sign;
uint8 whichkeydown=0;
uint8 T0FLAG=0;
uint32 display1=40;
uint32 temperuture=0;
uint32 MAX=0;
void CONVBIT(uint32 num1,uint32 num2)
{
buf[0] = num1%10; //个位
buf[1] = num1%100/10; //十位,强制转换
buf[2] = num1%1000/100; //百位
buf[3] = num1%10000/1000; //
buf[4] = num2%10; //个位
buf[5] = num2%100/10; //十位,强制转换
buf[6] = num2%1000/100; //百位
buf[7] = num2%10000/1000; //
}
/*********************************************************************************************************
** Function name: myDelay
** Descriptions: 软件延时
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void myDelay (INT32U ulTime)
{
INT32U i;
i = 0;
while (ulTime--) {
for (i = 0; i < 5000; i++);
}
}
/*********************************************************************************************************
** Function name: SSP_GetByte()
** Descriptions: 接受数据。
** input parameters: data 待发送的数据
** output parameters: 返回值为读取的数据
** Returned value: 无
*********************************************************************************************************/
uint8 SPP_GetByte (void)
{
while ((SSP0SR & 0x01) == 0) {
}
return(SSP0DR);
}
/*********************************************************************************************************
** Function name: SSP_SendData()
** Descriptions: SSP接口向SPI总线发送数据。
** input parameters: data 待发送的数据
** output parameters: 返回值为读取的数据
** Returned value: 无
*********************************************************************************************************/
uint8 SSP_SendData(uint8 data)
{
SSP0DR = data;
while ((SSP0SR & 0x01) == 0) { /* 等待TFE置位,即发送FIFO空 */
}
return(SSP0DR);
}
/*********************************************************************************************************
** Function name: timer1Isr
** Descriptions: 32位定时器1中断
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void timer32B1Isr(void)
{
MAX+=1;
if(MAX%20==0)
CONVBIT(display1,temperuture);
if(i==5)
{
SSP_SendData(data[buf[i]]|(0x80)); /* 发送显示数据 */
}
else{
SSP_SendData(data[buf[i]]); /* 发送显示数据 */
}
while((SSP0SR & (1<<0))==0);
SSP_SendData(selectable[i]);
while((SSP0SR & (1<<0))==0);
if((GPIO3DATA&(key))!=0) //无键
{
if (whichkeydown == i)
{
switch(whichkeydown)
{
case 0:
{
display1=display1+1;
T=1;
}break;
case 1:
{
display1=display1-1;
}break;
case 2:
{
display1=display1+10;
}break;
case 3:
{
display1=display1-10;
}break;
case 7:
{
display1=40;
}break;
}
whichkeydown=0x09;
}
}
else if((GPIO3DATA&(key))==0) //有键按下
{
myDelay(1); //防抖
if((GPIO3DATA&(key))==0); //确认有建按下
{
whichkeydown = i; //扫描哪个键按下
}
}
i=(i+1)%8; //位码循环
TMR32B1IR =0x01; /* 清除中断标志 */
}
/*********************************************************************************************************
** Function name: timer16B1Init
** Descriptions: 32位定时器1初始化函数
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void timer32B1Init(void)
{
SYSAHBCLKCTRL |= (1ul << 10);
TMR32B1IR = 0;
TMR32B1PR = 0;
TMR32B1MCR=3;
TMR32B1MR0=FAHBCLK/400;
zyIsrSet(NVIC_TIMER32B1, (unsigned long)timer32B1Isr, PRIO_ONE);
/* 设置外部中断并使能 */
TMR32B1TCR = 0x01; /* 启动定时器 */
}
/*********************************************************************************************************
** Function name: ADCInit
** Descriptions: ADC初始化
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void ADCInit( void )
{
PDRUNCFG &= ~(0x01 << 4); /* ADC模块上电 */
SYSAHBCLKCTRL |= (0x01 << 13); /* 使能ADC模块时钟 */
IOCON_PIO0_11 &= ~0xBF; /* 配置PIO0_11为模拟输入模式 */
IOCON_PIO0_11 |= 0x02; /* PIO0_11模拟输入通道0 */
AD0CR = ( 0x01 << 0 ) | /* SEL=1,选择ADC0 */
((FAHBCLK / 1000000 - 1) << 8 ) /* 转换时钟1MHz */
( 0 << 16 ) | /* 软件控制转换操作 */
( 0 << 17 ) | /* 使用11 clocks转换 */
( 0 << 24 ) | /* ADC转换停止 */
( 0 << 27 );
展开阅读全文