嵌入式课程设计_第1页
嵌入式课程设计_第2页
嵌入式课程设计_第3页
嵌入式课程设计_第4页
嵌入式课程设计_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

-.z.-----总结资料嵌入式课程设计学院:计算机与通信工程学院专业:物联网工程班级:物联1501:王强**:41501602实验日期:2017年12月25日实验名称:嵌入式课程设计实验目的:以STC89开发板为硬件平台,开发温度采集、动态数码管显示、按键响应、与PC串口通讯的综合程序,实现以下功能:1〕PC上的串口调试助手通过串口给STC89开发板发送"GetTemp〞命令。2〕STC89开发板从串口接收到"GetTemp〞命令后启动温度传感器DS18B20的测温程序获取当前温度,测试完成时将所测得温度数据显示在动态数码管上。(动态数码管在温度获取之前应该显示"FFFFFFFF〞,只有在获取温度后才显示温度值)3〕动态数码管显示出温度数据后,请通过按键触发STC89开发板通过串口回送步骤2所测的温度数据给PC上串口调试助手,同时恢复动态数码管显示为"FFFFFFFF〞。为保证每个同学的实验都独立完成,要求回送的数据包含自己的**,即如果你的**是20150809,当前温度值是19.6摄氏度,则在PC上的串口调试助手应该显示:20150809:19.6°C。硬件电路说明:1〕STC89处理器管脚和晶振电路2〕独立按键独立按键一共5个,分别连接在单片机的P3.0到P3.4口。去抖动的方式,我们采用软件延时的方法。过程如下:先设置IO口为高电平〔一般上电默认就为高〕,读取IO口电平确认是否有按键按下,如有IO电平为低电平后,延时几个ms,再读取该IO电平,如果任然为低电平,说明对应按键按下,执行相应按键的程序。3〕DS18B20温度传感器局部DS18B20内部的低温度系数振荡器是一个振荡频率随温度变化很小的振荡器,为计数器1提供一频率稳定的计数脉冲。高温度系数振荡器是一个振荡频率对温度很敏感的振荡器,为计数器2提供一个频率随温度变化的计数脉冲。初始时,温度存放器被预置成-55℃,每当计数器1从预置数开场减计数到0时,温度存放器中存放的温度值就增加1℃,这个过程重复进展,直到计数器2计数到0时便停顿。初始时,计数器1预置的是与-55℃相对应的一个预置值。以后计数器1每一个循环的预置数都由斜率累加器提供。为了补偿振荡器温度特性的非线性性,斜率累加器提供的预置数也随温度相应变化。计数器1的预置数也就是在给定温度处使温度存放器存放值增加1℃计数器所需要的计数个数。DS18B20内部的比拟器以四舍五入的量化方式确定温度存放器的最低有效位。在计数器2停顿计数后,比拟器将计数器1中的计数剩余值转换为温度值后与0.25℃进展比拟,假设低于0.25℃,温度存放器的最低位就置0;假设高于0.25℃,最低位就置1;假设高于0.75℃时,温度存放器的最低位就进位然后置0。这样,经过比拟后所得的温度存放器的值就是最终读取的温度值了,其最后位代表0.5℃,四舍五入最大量化误差为±1/2LSB,即0.25℃。温度存放器中的温度值以9位数据格式表示,最高位为符号位,其余8位以二进制补码形式表示温度值。测温完毕时,这9位数据转存到暂存存储器的前两个字节中,符号位占用第一字节,8位温度数据占据第二字节。DS18B20测量温度时使用特有的温度测量技术。DS18B20内部的低温度系数振荡器能产生稳定的频率信号;同样的,高温度系数振荡器则将被测温度转换成频率信号。当计数门翻开时,DS18B20进展计数,计数门开通时间由高温度系数振荡器决定。芯片内部还有斜率累加器,可对频率的非线性度加以补偿。测量结果存入温度存放器中。一般情况下的温度值应该为9位,但因符号位扩展成高8位,所以最后以16位补码形式读出。电路图及管脚如下:4〕串口通信串行通信是将数据字节分成一位一位的形式在一条传输线上逐个地传送,此时只需要一条数据线,外加一条公共信号地线和假设干控制信号线。因为一次只能传送一位,所以对于一个字节的数据,至少要分S位才能传送完毕。串行通信的必要过程是:发送时,要把并行数据变成串行数据发送到线路上去,接收时,要把串行信号再变成并行数据,这样才能被计算机及其他设备处理。在串行通信中,收、发双方对发送或接收数据的速率要有约定。通过编程可对单片机串行口设定为4种工作方式,其中方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T1的溢出率来决定。串行口的4种工作方式对应三种波特率。由于输入的移位时钟的来源不同,所以各种方式的波特率计算公式也不一样,以下是4种方式波特率的计算公式。开发板的电路图如下列图5〕动态数码管显示数码管的显示原理是靠点亮内部的发光二极管来发光,下面就来我们讲解一个数码管是如何亮起来的。数码管内部电路如下列图所示,从右图可看出,一位数码管的引脚是10个,显示一个8字需要7个小段,另外还有一个小数点,所以其内部一共有8个小的发光二极管,最后还有一个公共端,生产商为了封装统一,单位数码管都封装10个引脚,其中第3和第8引脚是连接在一起的。而它们的公共端又可分为共阳极和共阴极,中间图为共阴极内部原理图,右图为共阳极内部原理图。上图展出了常用的两种数码管的引脚排列和内部构造。总所周知,点亮发光二极管就是要给予它足够大的正向压降。所以点亮数码管其实也就是给它内部相应的发光二极管正向压降。如上图左〔一共a、b、c、d、e、f、g、DP八段〕,如果要显示"1〞则要点亮b、c两段LED;显示"A〞则点亮a、b、c、e、f、g这六段LED;动态显示是多个数码管,交替显示,利用人的视觉暂停作用使人看到多个数码管同时显示的效果。完整程序代码:主程序文件main.c:-.z.#include"temp.h" //引用temp.h头文件,包括一些有关温度传感器的函数#include"reg51.h" //引用reg51.h头文件,说明引脚地址#defineGPIO_DIGP0 //将P0端口定义为GPIO_DIG#defineGPIO_LEDP2 //将P2端口定义为GPIO_LEDsbitLSA=P2^2; //位选,P2^2定义为LSAsbitLSB=P2^3; //同上位选定义变量sbitLSC=P2^4; //同上位选定义变量sbitK3=P3^2; //位选,P3^2定义为K3按键unsignedintdisp[8]={0*71,0*71,0*71,0*71,0*71,0*71,0*71,0*71}; //显示FFFFFFFFunsignedcharcodeDIG_CODE[10]={0*3f,0*06,0*5b,0*4f,0*66,0*6d,0*7d,0*07,0*7f,0*6f};//0、1、2、3、4、5、6、7、8、9的显示码unsignedcharcheck1[7]={'0','0','0','0','0','0','0'}; //用来存放串口通信传送字符unsignedcharcheck2[7]={'G','e','t','T','e','m','p'}; //用来比拟串口通信传送字符unsignedcharmessage[17]={'4','1','5','0','1','6','0','2',':','0','0','0','0','0','0','0','0'};//显示**为41501602:unsignedcharDisplayData[8]; //用来存放要显示的8位数的值unsignedcharKeyValue=0; //是否按下独立按键的标志位voidDigDisplay(); //动态数码管显示函数voidUsartConfiguration(); //串口设置函数voidLcdDisplay(int); //数码管显示读取到的温度voidIntConfiguration(); //设置外部中断voidDelay(unsignedintn); //延时函数voidTimer0Configuration(); //定时器初始设置voidCheckMessage(charm); //逐字检查串口通信字符是否正确unsignedintflag=0; //数码管显示标志位unsignedintj=0; //用于CheckMessage逐字检查发送字符unsignedcharNum=0; //动态数码管位选/*******************************************************************************主函数模块*******************************************************************************/voidmain() //主函数{ unsignedinti; IntConfiguration(); //初始化外部中断设置UsartConfiguration(); //初始化串口设置Timer0Configuration(); //初始化定时器设置while(1) { if(flag==1) //当flag为1时数码管直接显示当前温度 {LcdDisplay(Ds18b20ReadTemp()); //调用温度传感器函数并在数码管显示温度 }if(flag==0) //当flag为0时数码管显示FFFFFFFF { for(i=0;i<8;i++) //循环给disp[]数组赋值 {disp[i]=0*71; //disp[i]赋值 } } }}/*******************************************************************************独立按键模块*******************************************************************************/voidIntConfiguration() //设置外部中断{//设置INT0 IT0=1; //跳变沿触发方式〔下降沿〕E*0=1; //翻开INT0的中断允许。//设置INT1 IT1=1; //跳变沿触发方式为下降沿E*1=1; //翻开INT1的中断允许EA=1; //翻开总中断}voidDelay(unsignedintn)//延时50us误差0us {unsignedchara,b; for(;n>0;n--) { for(b=1;b>0;b--)for(a=22;a>0;a--); }}voidInt0() interrupt0 //外部中断0的中断函数K3按键中断{ unsignedintk=0; Delay(1); //延时消抖if(K3==0) //如果K3按键被按下的话,动态数码管就显示FFFFFFFF { KeyValue=1; flag=0; for(k=0;k<17;k++) //逐字将message[]字符数组中字符送入SBUF { SBUF=message[k]; //将接收到的数据放入到发送存放器while(!TI); //等待发送数据完成TI=0; //去除发送完成标志位 }if(k==17) //如果message数组发送完毕就归零准备下一次 {k=0; } } else KeyValue=0; //K3按键没被按下的时候就一直保持当前状态,显示当前温度}/*******************************************************************************串口通信模块*******************************************************************************/voidUsartConfiguration() //串口设置{SCON=0*50; //设置为工作方式1 TMOD=0*20; //设置计数器工作方式2,也就是自动重装模式PCON=0*80; //波特率加倍TH1=0*F3; //计数器初始值设置,注意波特率是4800的TL1=0*F3; ES=1; //翻开接收中断EA=1; //翻开总中断TR1=1; //翻开计数器}voidUsart()interrupt4 //串口中断{unsignedcharreceiveData; receiveData=SBUF; //出去接收到的数据RI=0; //去除接收中断标志位CheckMessage(receiveData); //判断发送字节是否正确}voidCheckMessage(charm) //逐字检查串口通信字符是否正确{check1[j]=m; //将串口接收到的字符一位一位的赋给check1[] if(check1[j]!=check2[j]) //按位逐字检查发送字符是否符合要求{ flag=-1; //不符合直接退出} if(j==6) //符合时改变显示标志位,数码管显示当前温度{ flag=1; } j++; //按位检查}/*******************************************************************************动态数码管模块*******************************************************************************/voidDigDisplay()interrupt1 //动态数码管显示{//定时器在工作方式二会自动重装初,所以不用在赋值。TH0=0*9c; //给定时器赋初值,定时1ms TL0=0*00; GPIO_DIG=0; //消隐switch(Num) //位选,选择点亮的数码管, {case(7): LSA=0;LSB=0;LSC=0;break;//显示第7位case(6): LSA=1;LSB=0;LSC=0;break;//显示第6位case(5): LSA=0;LSB=1;LSC=0;break;//显示第5位case(4): LSA=1;LSB=1;LSC=0;break;//显示第4位case(3): LSA=0;LSB=0;LSC=1;break;//显示第3位case(2): LSA=1;LSB=0;LSC=1;break;//显示第2位case(1): LSA=0;LSB=1;LSC=1;break;//显示第1位case(0): LSA=1;LSB=1;LSC=1;break;//显示第0位 }GPIO_DIG=disp[Num]; //发送段码Num++; //动态数码管从0到7循环点亮if(Num>7) Num=0;}voidTimer0Configuration() //定时器初始设置{TMOD=0*20; //选择为定时器模式,工作方式2,仅用TR*翻开启动。TH0=0*9C; //给定时器赋初值,定时100us TL0=0*9C; ET0=1; //翻开定时器0中断允许EA=1; //翻开总中断TR0=1; //翻开定时器}/*******************************************************************************温度传感器DS18B20模块*******************************************************************************/voidLcdDisplay(inttemp) //数码管显示读取到的温度{ unsignedchardatas[]={0,0,0,0,0};//定义数组floattp; if(temp<0) //当温度值为负数 { disp[2]=0*40; //如果温度值为负数的时候,disp[2]数码管显示负号- //因为读取的温度是实际温度的补码,所以减1,再取反求出原码temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就//算由".5,还是在小数点后面。 } else { disp[2]=0; //如果温度不是负数,就置零tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量//如果温度是正的则,则正数的原码就是补码它本身temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就//算加上0.5,还是在小数点后面。 }message[9]=(temp/10000)+'0'; //具体温度的百位message[10]=(temp%10000/1000)+'0'; //具体温度的十位message[11]=(temp%1000/100)+'0'; //具体温度的个位message[12]='.'; //小数点字符message[13]=(temp%100/10)+'0'; //具体温度的十分位message[14]=(temp%10)+'0'; //具体温度的千分位message[15]='o'; //message[15]和[16]字符串代表°C摄氏度符号message[16]='C';disp[0]=0; //disp[0]和disp[1]直接置零disp[1]=0;disp[3]=DIG_CODE[temp/10000]; //数码管显示具体温度的百位disp[4]=DIG_CODE[temp%10000/1000]; //数码管显示具体温度的十位disp[5]=DIG_CODE[temp%1000/100]|0*80; //数码管显示具体温度的个位//共阴接法,数码管为高电平驱动,且小数点的段接在IO的bit7,所以用|0*80来点亮小数点disp[6]=DIG_CODE[temp%100/10]; //数码管显示具体温度的十分位disp[7]=DIG_CODE[temp%10]; //数码管显示具体温度的千分位}-.z.温度传感器temp.c:-.z.#include"temp.h"/********************************************************************************函数名:Delay1ms*函数功能:延时函数*输入:无*输出 :无*******************************************************************************/voidDelay1ms(unsignedinty){ unsignedint*; for(y;y>0;y--) for(*=110;*>0;*--);}/********************************************************************************函数名:Ds18b20Init*函数功能:初始化*输入:无*输出 :初始化成功返回1,失败返回0*******************************************************************************/unsignedcharDs18b20Init(){ unsignedinti; DSPORT=0; //将总线拉低480us~960us i=70; while(i--);//延时642us DSPORT=1; //然后拉高总线,如果DS18B20做出反响会将在15us~60us后总线拉低i=0; while(DSPORT) //等待DS18B20拉低总线 {i++; if(i>5000)//等待>5MS return0;//初始化失败 }return1;//初始化成功}/********************************************************************************函数名:Ds18b20WriteByte*函数功能:向18B20写入一个字节*输入:*输出 :无*******************************************************************************/voidDs18b20WriteByte(unsignedchardat){ unsignedinti,j; for(j=0;j<8;j++) { DSPORT=0; //每写入一位数据之前先把总线拉低1us i++; DSPORT=dat&0*01;//然后写入一个数据,从最低位开场i=6; while(i--);//延时68us,持续时间最少60us DSPORT=1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值dat>>=1; }}/********************************************************************************函数名:Ds18b20ReadByte*函数功能:读取一个字节*输入:*输出 :无*******************************************************************************/unsignedcharDs18b20ReadByte(){ unsignedcharbyte,bi; unsignedinti,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线i++; i++;//延时6us等待数据稳定bi=DSPORT; //读取数据,从最低位开场读取/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/ byte=(byte>>1)|(bi<<7); i=4; //读取完之后等待48us再接着读取下一个数while(i--); } returnbyte;}/********************************************************************************函数名:Ds18b20ChangTemp*函数功能:让18b20开场转换温度*输入:*输出 :无*******************************************************************************/voidDs18b20ChangTemp(){ Ds18b20Init(); Delay1ms(1); Ds18b20Writ

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论