基于MC9S12XS128控制器实现温度检测 - 图文

更新时间:2023-12-08 03:09:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

《单片机原理及应用》课程实验

题目:温度检测系统

姓名:ly 学号: 指导老师:任勇 学院:通信工程学院 班级:2011级电子信息实验班

2014年6月17日

一:实验内容

本次实验基于MC9S12XS128控制器实现温度检测,系统由微控制器、温度传感器、霍尔器件及其外围电路组成。要求DS18B20芯片进行温度检测,用霍尔器件进行开关检测。检测的结果通过SCI协议上传PC。

二:芯片信息及实验原理

DS18B20:温度传感器的种类众多,在应用与高精度、高可靠性的场合时DALLAS(达拉斯)公司生产的DS18B20温度传感器当仁不让。超小的体积,超低的硬件开消,抗干扰能力强,精度高,附加功能强,使得DS18B20更受欢迎。对于我们普通的电子爱好者来说,DS18B20的优势更是我们学习单片机技术和开发温度相关的小产品的不二选择。了解其工作原理和应用可以拓宽您对单片机开发的思路。

DS18B20工作原理及应用:DS18B20的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。其一个工作周期可分为两个部分,即温度检测和数据处理。在讲解其工作流程之前我们有必要了解18B20的内部存储器资源。18B20共有三种形态的存储器资源,它们分别是:

ROM 只读存储器,用于存放DS18B20ID编码,其前8位是单线系列编码(DS18B20的编码是19H),后面48位是芯片唯一的序列号,最后8位是以上56的位的CRC码(冗余校验)。数据在出产时设置不由用户更改。DS18B20共64位ROM。

RAM 数据暂存器,用于内部计算和数据存取,数据在掉电后丢失,DS18B20共9个字节RAM,每个字节为8位。第1、2个字节是温度转换后的数据值信息,第3、4个字节是用户EEPROM(常用于温度报警值储存)的镜像。在上电复位时其值将被刷新。第5个字节则是用户第3个EEPROM的镜像。第6、7、8个字节为计数寄存器,是为了让用户得到更高的温度分辨率而设计的,同样也是内部温度转换、计算的暂存单元。第9个字节为前8个字节的CRC码。EEPROM非易失

性记忆体,用于存放长期需要保存的数据,上下限温度报警值和校验数据,DS18B20共3位EEPROM,并在RAM都存在镜像,以方便用户操作。 DS18B20详细引脚功能描述: 序号 名称 引脚功能描述 1 2 3

GND DQ VDD

地信号

数据输入/输出引脚。开漏单总线接口引脚。当被用着在寄生电源下,也可以向器件提供电源。

可选择的VDD引脚。当工作于寄生电源时,此引脚必须接地。

由于DS18B20采用的是1-Wire总线协议方式,即在一根数据线实现数据的双向传输,而对AT89S51单片机来说,硬件上并不支持单总线协议,因此,我们必须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。

由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。该协议定义了几种信号的时序:初始化时序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。数据和命令的传输都是低位在先。

DS18B20的复位时序:

DS18B20的读时序

对于DS18B20的读时序分为读0时序和读1时序两个过程。

DS18B20的读时隙是从主机把单总线拉低之后,在15秒之内就得释放单总线,以让DS18B20把数据传输到单总线上。DS18B20在完成一个读时序过程,至少需要60us才能完成。

DS18B20的写时序

对于DS18B20的写时序仍然分为写0时序和写1时序两个过程。

DS18B20写0时序和写1时序的要求不同,当要写0时序时,单总线要被拉低至少60us,保证DS18B20能够在15us到45us之间能够正确地采样IO总线上的“0”电平,当要写1时序时,单总线被拉低之后,在15us之内就得释放单总线。

霍尔器件44E:霍尔器件是一种磁传感器,是半导体材料制成的一种薄片,它是一种磁敏感器件,当它处于磁场中时,会产生电动势。在垂直磁场平面方向上施加外磁场、在沿平面上加外电场,则使电子在磁场中运动,结果在器件的的两个侧面之间产生霍尔电势,霍尔电势的大小和外磁场以及电流大小成正比。用它们可以检测磁场及其变化,可在各种与磁场有关的场合中使用。霍尔器件以霍尔效应为其工作基础。

霍尔器件具有许多优点,它们的结构牢固,体积小,重量轻,寿命长,安装方便,功耗小,频率高(可达1MHz),耐震动,不怕灰尘、油污、水汽及盐雾等的污染或腐蚀。

霍尔线性器件的精度高、线性度好;霍尔开关器件无触点、无磨损、输出波形清晰、无抖动、无回跳、位置重复精度高(可达μm级)。取用了各种补偿和保护措施的霍尔器件的工作温度范围宽,可达-55℃~150℃。

按照霍尔器件的功能可将它们分为: 霍尔线性器件和霍尔开关器件 。前者输出模拟量,后者输出数字量。 按被检测的对象的性质可将它们的应用分为:直接应用和间接应用。前者是直接检测出受检测对象本身的磁场或磁特性,后者是检测受检对象上人为设置的磁场,用这个磁场来作被检测的信息的载体,通过它,将许多非电、非磁的物理量例如力、力矩、压力、应力、位置、位移、速度、加速度、角度、角速度、转数、转速以及工作状态发生变化的时间等,转变成电量来进行检测和控制。

采用44E型霍尔开关器件,引脚1接电源(电压4.5V~24V),引脚2接地线,引脚3接为数字信号输出端接单片机。

三:硬件连接

DS18B20引脚芯片: 1、 GND为电源地

2、 DQ为数字信号输入/输出端

3、 VDD为外接供电电源输入端(在寄生电源接线方式时接地)。

在核心板上的接线方式为,DQ接J1中的PP7口,VDD和GND分别接J2的地线和电源线。

霍尔器件44E引脚芯片:

1、 引脚1接电源。 2、 引脚2接地线。

3、 引脚3接为数字信号输出端接单片机。

在核心板上的接线方式为:我们设置用核心板上的PB0口来检测霍尔开关的输入,核心板上PBO口接的是LED1,因此可以用LED1灯的亮灭来显示是否有霍尔开关的输入。

四:功能介绍

温度检测: 当显示“温度检测就绪”时,温度检测开始,这时将会在PC机的串口助手中显示当前摄氏温度,每隔一段时间检测一次。

霍尔开关控制暂停:霍尔器件控制温度检测的暂停与开始,当用磁体靠近霍尔芯片时,指示灯LED1亮,温度检测暂停,并在串口助手中显示“温度检测暂停”,当拿开磁体时,温度检测继续。

温度报警:当温度大于32摄氏度时(为方便观看现象暂时设置为32度的警戒线),LED2将会点亮,以报警提醒温度过高。

五:实验结果

系统上电检测开始。DS18B20检测到的温度被上传至PC显示,可以看到每隔一定时延将会显示一次当前温度。之后用磁铁靠近霍尔器件,则温度检测暂停,并且显示“温度检测暂停”。移开磁铁温度检测继续。按下PIT中断键可以进行PIT中断复位,之后温度检测将重新开始。实验结果如下:

附 程序代码 main.c

#include /* common defines and macros */ #include \ /* derivative-specific definitions */

#include \ #include \ #include

uint8_t AK; //正、负温度标标识 uint8_t T_DS18B20 = 0; uint8_t T_ASCII_H = 0; uint8_t T_ASCII_L = 0; uint8_t m; byte HALL; uint8_t Temp2;

uint8_t Udisp[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char readyCode[]=\温度检测就绪\\n\就绪码 char arr[]=\现在的温度是:\ char arr1[3];

char arr2[]=\温度检测暂停\\n\

char arr3[]; char arrC[]=\℃\\n\ //温度单位字符串

//MCU初始化 void MCUInit(void) {

CLKSEL &= 0x7f; PLLCTL &= 0xbf;

SYNR = 0x01; REFDV = 0x03; POSTDIV = 0x00; PLLCTL |= (1<<6);

while ((CRGFLG&0x08) == 0x00); CLKSEL |= (1<<7); ECLKCTL_NECLK = 1; IRQCR &= 0xbf; COPCTL = 0x00; DDRB=0x02; PORTB=0x02; }

//PIT初始化 void InitPIT(void)

{

PITCFLMT=0x00; PITTF=0x01; PITMUX=0x00; PITMTLD0=99; PITLD0=39999; PITINTE=0x01; PITCE=0x01; PITCFLMT=0x80; }

//ms延时程序

void delayms(int ms) {

int ii,jj;

if (ms<1) ms=1; for(ii=0;ii

for(jj=0;jj<2670;jj++); //8MHz--1ms }

//主函数

void main(void) {

//禁止总中断

DISABLE_INTERRUPTS;

//1. 芯片初始化

MCUInit();

InitPIT();

//2. DS18B20初始化 m=Init_18B20();

SCI0_Init();

ENABLE_INTERRUPTS;

SCI0_SendString(readyCode);

//总循环 for(;;) {

//(1)读取温度 AK = Get_T_AK();

//T_DS18B20 = read_DS18B20_Temp(); //获取温度正负标识 T_DS18B20=Get_temp();

if(HALL) {

Temp2=T_DS18B20; //获取温度数值 //arr3=arrC;

arr1[0]= Udisp[Temp2/10]; arr1[1]= Udisp[Temp2]; arr1[2]= '\\0'; SCI0_SendString(arr);

SCI0_SendString(arr1); //发送一个字符串 SCI0_SendString(arrC);

if(T_DS18B20>0x20) {

PORTB=0xFD; } else {

PORTB=0x02; } } else {

SCI0_SendString(arr2); while(!HALL); }

delayms(50); } }

//PIT中断

#pragma CODE_SEG NON_BANKED interrupt 66 void PIT0_ISR() {

PITTF=0x01;

HALL=PORTAB_PB0; }

DS18B20.h

#include \

//DS18B20初始化及数据发送宏定义

#define DQ_1() {DDRP |= 0x80;PTP_PTP7 = 1;}

#define DQ_0() {DDRP |= 0x80;PTP_PTP7 = 0;} #define DQ_IN() DDRP &= 0x7F #define DQ PTP_PTP7

//函数定义

uint8_t Init_18B20(void);

uint8_t Init_18B20(); //写命令函数

uint8_t Read_18B20(void); //写命令函数 uint8_t Get_T_AK(void); //写命令函数

uint8_t Get_temp(void); //写命令函数 void Delay_us( int time ); //写命令函数 void Write_18B20(uint8_t wdata); //写命令函数 void ReadTemp(); //写命令函数 void Convert_Temp(); //写命令函数 uint8_t read_DS18B20_Temp(void);

DS18B20.c

#include \ /* derivative-specific definitions */ #include \

//全局变量定义

uint8_t Temp[2] = {0,0}; //存放读出温度的高位和低位

void Delay_us( int time ) {

volatile uint16_t i ;

for( i = 0; i < time; i ++ ) {

asm nop ; } }

uint8_t Init_18B20(void) {

uint8_t Error;

//DISABLE_INTERRUPTS; //while(1) {

DQ_0();

Delay_us(500); //延时500us

DQ_1();

Delay_us(55); //延时55us

// }

PUCR=0xFF; DQ_IN();

if(DQ==1) {

Error = 1; //初始化失败 } else {

Error = 0; //初始化成功 DQ_1(); }

Delay_us(400); //延时400us return Error;

//ENABLE_INTERRUPTS ; }

void Write_18B20(uint8_t wdata) {

uint8_t i;

for(i = 0; i < 8;i++) {

DQ_0();

Delay_us(6); //延时6us if(wdata & 0X01) {

DQ_1(); } else {

DQ_0(); }

wdata >>= 1;

Delay_us(50); //延时50us DQ_1();

Delay_us(10); //延时10us } }

uint8_t Read_18B20(void) {

uint8_t i;

uint8_t temp = 0; for(i = 0;i < 8;i++) {

temp >>= 1; DQ_0();

Delay_us(2); //延时2us DQ_1();

Delay_us(4); //延时4us DQ_IN();

if(DQ==1) temp |= 0x80;

Delay_us(65); //延时65us }

return temp; } void ReadTemp(void) {

Temp[0] = Read_18B20(); //读低位 Temp[1] = Read_18B20(); //读高位 }

void Convert_Temp(void) {

uint8_t i; do {

i = Init_18B20(); //初始化 }

while(i);

Write_18B20(0xcc); //发送跳过读取产品ID号命令 Write_18B20(0x44); //发送温度转换命令

for(i = 20;i > 0;i--)

Delay_us(60000); //延时800ms以上 do {

i = Init_18B20(); //初始化 }

while(i);

Write_18B20(0xcc); //发送跳过读取产品ID号命令 Write_18B20(0xbe); //发送读ScratchPad命令 ReadTemp(); }

uint8_t Get_T_AK(void) {

uint8_t TH,TL,a;

Convert_Temp(); //转换温度 TL = Temp[0]; TH = Temp[1];

if((TH&0xf8)==0xf8) {

return a = 1; } else {

return a = 0; } }

uint8_t Get_temp(void)

{ uint8_t TH,TL,T,Tn; TL = Temp[0]; TH = Temp[1];

if((TH&0xf8)==0xf8) {

Tn =(TH<<4|TL>>4)&0x7f; //温度为负数 return T = 128 - Tn; } else

{

return T = (TH<<4|TL>>4); //温度为正数 } }

uint8_t read_DS18B20_Temp(void) //单子DS18B20操作 {

uint8_t err; uint8_t HALL=0; uint8_t Temp_L=0,Temp_H=0,Temp_18B20;

//rest_DS18B20();

err= Init_18B20(); //write_DS18B20(0xCC);//跳过ROM //write_DS18B20(0x44);//温度变换 Write_18B20(0xcc); //发送跳过读取产品ID号命令 Write_18B20(0x44); //发送读ScratchPad命令 //rest_DS18B20(); err= Init_18B20(); //write_DS18B20(0xCC); //write_DS18B20(0xBE);//读温度值 Write_18B20(0xcc); Write_18B20(0xBE); Temp_L=Read_18B20(); Delay_us(100); Temp_H=Read_18B20(); Temp_L>>=4;//去掉小数 Temp_H<<=4; Temp_18B20=Temp_H | Temp_L; if(Temp_18B20&0x80)//取出符号位 { HALL=0; } else HALL=1; return Temp_18B20; }

UART.h

#include \ /* derivative-specific definitions */

// 函数声明

void SCI0_Init(void);

void SCI0_SendByte(byte data); void SCI0_SendString(char arr[]); byte SCI0_ReceiveByte(void); void Delay_us(int time); void Delay_ms(int time);

UART.c

#include \ /* derivative-specific definitions */ #include \

// 变量定义

void SCI0_Init(void) //fBUS=8MHz {

// DISABLE_INTERRUPTS ;

SCI0BD=26; //波特率=fBUS/(16xSBR)=19200bps

SCI0CR1=0x00; //正常工作,8个数据位、无奇偶校验 SCI0CR2=0x2C; //接收满中断使能,发送允许,接收允许 // ENABLE_INTERRUPTS ; }

void SCI0_SendByte(byte data) {

while((SCI0SR1&0x80)!=0x80); SCI0DRL=data; }

void SCI0_SendString(char arr[]) {

int i=0;

while(arr[i]!='\\0') {

SCI0_SendByte(arr[i]); i++; } }

void Delay_ms(int time) {

int i,j;

for(i=0;i

for(j=0;j<800;j++) {

asm nop; } } }

//等待SCI是否可以发送 //SCI发送字节数据

本文来源:https://www.bwwdw.com/article/176t.html

Top