收藏 分销(赏)

基于WIFI模块和单片机的无线数据传输附代码DOC.doc

上传人:天**** 文档编号:2991829 上传时间:2024-06-12 格式:DOC 页数:31 大小:1.82MB 下载积分:12 金币
下载 相关 举报
基于WIFI模块和单片机的无线数据传输附代码DOC.doc_第1页
第1页 / 共31页
基于WIFI模块和单片机的无线数据传输附代码DOC.doc_第2页
第2页 / 共31页


点击查看更多>>
资源描述
南京工业大学 计算机科学与技术学院 Project3课程设计 2014-2015学年第二学期 班 级: 浦电子1203 组员姓名: 组员学号: 指导老师:武晓光,胡方强,包亚萍 袁建华,毛钱萍 2015年7月8日 目 录 第一章 阶段任务 第二章 基于WIFI模块的无线数据传输的原理 1.1 时钟模块 1.2 最小单片机系统的原理 1.3 温度传感器DS18B20 1.4 串口 1.5 WIFI模块 第三章 基于WIFI模块的无线数据传输的实现   2.1 WIFI模块设置 2.2 串口部分设置 2.3 调试与运行过程 第四章 程序与框图 第五章 小结 第一章 阶段任务: 第一阶段 (1天)1、了解课程所给的WIFI模块,并详细研读其说明书 2、复习单片机知识 (2天)1、了解温湿度传感器模块,并设计其硬件模块 2、了解lcd1602显示模块,并设计其硬件模块 (2天)1、设计整合电路:5v转3.3v电路 2、串口通讯电路 第二阶段 (4天) 1、链接并完成整体电路图的设计,并检查 2、焊接电路并调试。 第三阶段 (3天)1、根据设计的硬件模块设计程序 (1):温湿度传感器模块 (2):串口通讯模块 (3):WIFI传输与接收模块 (4):显示电路模块 (3天)2、将设计好的模块程序烧录到单片机内,调试 第四阶段:2天 (2天)写报告 第二章 基于WIFI模块的无线数据传输的原理 1.1时钟DS1302模块: 电路原理图:DS1302与单片机的连接也仅需要3条线:CE引脚、SCLK串行时钟引脚、I/O串行数据引脚,Vcc2为备用电源,外接32.768kHz晶振,为芯片提供计时脉冲。 读写时序说明:DS1302是SPI总线驱动方式。它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位( 0位)开始。同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。数据读写时序如图 1.2单片机最小系统的原理: 说明 复位电路:由电容串联电阻构成,由图并结合"电容电压不能突变"的性质,可以知道,当系统一上电,RST脚将会出现高电平,并且,这个高电平持续的时间由电路的RC值来决定.典型的51单片机当RST脚的高电平持续两个机器周期以上就将复位,所以,适当组合RC的取值就可以保证可靠的复位. 晶振电路:典型的晶振取11.0592MHz(因为可以准确地得到9600波特率和19200波特率,用于有串口通讯的场合)/12MHz(产生精确的uS级时歇,方便定时操作) 单片机:一片AT89S51/52或其他51系列兼容单片机 特别注意:对于31脚(EA/Vpp),当接高电平时,单片机在复位后从内部ROM的0000H开始执行;当接低电平时,复位后直接从外部ROM的0000H开始执行. 1.3温度传感器DS18B20的原理(连接到单片机最小系统,并将温度发送给WIFI模块): 3.1.1 DS18B20性能特点 (1) 独特的单线接口方式,只需一个接口引脚即可通信; (2) 每一个DS18B20都有一个唯一的64位ROM序列码; (3) 在使用中不需要任何外围元件; (4) 可用数据线供电,电压范围:+3.0V-+5.5 V; (5) 测温范围:-55℃ -+125℃,在-10℃-+85℃范围内精度为+0.5℃,分辨率为0.0625℃; (6) 通过编程可实现9-12位的数字读数方式。温度转换成12位数字信号所需时间最长为750ms,而在9位分辩模式工作时仅需93.75ms; (7) 用户可自设定非易失性的报警上下限值; (8) 告警搜索命令可识别和定位那些超过报警限值的DS18B20; (9) 多个DS18B20可以并联在惟一的三线上,实现多点测温; (10)电源极性接反时,DS18B20不会因发热而烧毁,但不能正常工作; 3.1.2 DS18B20内部存储器及温度数据格式 对于DS18B20内部存储器结构(如图3.1),它包括一个暂存RAM和一个非易失性电可擦除EERAM,后者存放报警上下限TH、TL。当改变TH、T L中的值时,数据首先被写进暂存器的第二、三字节中,主机可再读出其中内容进行验证。如果正确,当主机发送复制暂存器命令,暂存器的第二、三字节将被复制到TH、TL中,这样处理有利于确保该数据在单总线上传输的完整性[7]。 暂存器结构 EERAM结构 温度低字节 (BYTE0) 温度高字节 (BYTE1) 上限报警温度TH(BYTE2) 下限报警温度TL(BYTE3) 结构寄存器 (BYTE4) 保留 (BYTE5) 保留 (BYTE6) 保留 (BYTE7) CRC ( BYTE8) TH TL 结构寄存器 图3.1 DS18B20结构框图 暂存存储器作用是在单线通信时确保数据的完整性,它由8字节组成,头两个字节表示测得的温度读数。以12位转化为例说明温度高低字节存放形式(温度的存储形式如表3.1)及计算:12位转化后得到的12位数据,存储在18B20的两个高低8位的RAM中,二进制中的前面5位是符号位。如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1,再乘于0.0625才能得到实际温度[8]。 表3.1 温度的存储形式 高8位 S S S S S 26 25 24 低8位 23 22 21 20 2-1 2-2 2-3 2-4 S=1时表示温度为负,S=0时表示温度为正,其余低位以二进制补码形式表示,最低位为1时表示0.0625℃ 。温度/数字对应关系如表3.2所示。 表3.2 DS18B20温度/数字对应关系表 温度(℃) 输出的二进制码 对应的十六进制码 +125 0000 0111 1101 0000 07D0H +85 0000 0101 0101 0000 0550H +25.0625 0000 0001 1001 0001 0191H +10.125 0000 0000 1010 0010 00A2H +0.5 0000 0000 0000 1000 0008H 0 0000 0000 0000 0000 0000H -0.5 1111 1111 1111 1000 FFF8H -10.125 1111 1111 0110 1110 FF5EH -25.0625 1111 1110 0110 1111 FF6FH -55 1111 1100 1001 0000 FC90H DS18B20有六条控制命令,如表3.3所示: 表3.3 控制命令 指    令 约定代码 操      作    说      明 温度转换 44H 启动DS18B20进行温度转换 读暂存器 BEH 读暂存器9个字节内容 写暂存器 4EH 将数据写入暂存器的TH、TL字节 复制暂存器 48H 把暂存器的TH、TL字节写到E2RAM中 重新调E2RAM B8H 把E2RAM中的TH、TL字节写到暂存器TH、TL字节 读电源供电方式 B4H 启动DS18B20发送电源供电方式的信号给主CPU 3.1.3 DS18B20操作命令及时序特性 DS18B20对读写的数据位有着严格的时序要求,它是在一根I/O线上读写数据的。同时,DS18B20为了保证各位数据传输的正确性和完整性,它有着严格的通信协议。DS18B20每一步操作都要遵循严格的工作时序和通信协议,如主机控制DS18B20完成温度转换这一过程,根据DS18B20的通讯协议,须经三个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作 。该协议定义了几种信号的时序:初始化时序、读时序、写时序。所有时序都是将主机作为主设备,单总线器件作为从设备。而每一次命令和数据的传输都是从主机主动启动写时序开始的,如果要单总线器件送回数据,在进行写命令后,主机需启动读时序完成数据的接收。另外,数据和命令的传输都是低位在先[9]。 (1)DS18B20的复位时序 主机控制DS18B20完成任何操作之前必须先初始化,即主机发一复位脉冲(最短为480µs的低电平),接着主机释放总线进入接收状态,DS18B20在检测到I/0引脚上的上升沿之后,等待15~60µs,然后发出存在脉冲(60~240)µs的低电平。如图3.2所示。 (2)DS18B20的读时序 DS18B20的读时序分为读0时序和读1时序两个过程。DS18B20的读时序是从主机把单总线拉低后,在15秒之内就得释放单总线,从而让DS18B20把数据传输到单总线上。DS18B20完成一个读时序的过程,至少需要60µs。如图3.3所示。 图3.2 DS18B20的复位时序 图3.3 DS18B20的读时序 (3)DS18B20的写时序 DS18B20的写时序同读时序一样,仍然分为写0时序和写1时序两个过程。 DS18B20写0时序和写1时序的要求不同,当要写0时序时,单总线要被拉低至少60µs,保证DS18B20能够在15µs到45µs之间能正确地采样I/O总线上的“0”电平,当要写1时序时,单总线被拉低之后,在15µs之内就得释放单总线。如图3.4所示。 图3.4 DS18B20的写时序 由DS18B20的通讯协议得知,主机控制DS18B20完成温度转换的过程必须经过三个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,从而对DS18B20进行预定的操作。复位要求主CPU将数据线下拉500µs,然后释放,DS18B20收到信号后等待16~60µs左右,然后发出60~240µs的存在低脉冲,主CPU收到此信号表示复位成功。 1.4串口部分(让WIFI与电脑,单片机进行通讯) 串口原理图: 80C51串行口的结构图: 80C51串行口的工作方式 : 方式1 方式1是10位数据的异步通信口。TXD为数据发送引脚,RXD为数据接收引脚,传送一帧数据的格式如图所示。其中1位起始位,8位数据位,1位停止位。 1、 方式1输出 方式1输入 用软件置REN为1时,接收器以所选择波特率的16倍速率采样RXD引脚电平,检测到RXD引脚输入电平发生负跳变时,则说明起始位有效,将其移入输入移位寄存器,并开始接收这一帧信息的其余位。接收过程中,数据从输入移位寄存器右边移入,起始位移至输入移位寄存器最左边时,控制电路进行最后一次移位。当RI=0,且SM2=0(或接收到的停止位为1)时,将接收到的9位数据的前8位数据装入接收SBUF,第9位(停止位)进入RB8,并置RI=1,向CPU请求中断 始位1位,数据9位(含1位附加的第9位,发送时为SCON中的TB8,接收时为RB8),停止位1位,一帧数据为11位。方式2的波特率固定为晶振频率的1/64或1/32,方式3的波特率由定时器T1的溢出率决定。 1.5WIFI模块: 使用接口: 1 电源接口 系统采用标准电源插座,外径5.5mm内径2.1mm的标准尺寸,内正外负,输入电压范围5~48V,电流350mA 2 指示灯 ID 名称 描述 1 Power 设备供电后亮 2 Ready 内部Linux系统启动完成后亮 3 Link 网络连接建立后亮 4 RXD 本设备的串口收到数据闪烁 5 TXD 本设备通过串口向外发送数据时闪烁 2.3 RS232接口 设备的串口为公口(针),RS232 电平(可以直接连电脑串口的电平),引脚顺序与计算机的COM 口保持一致,与电脑连接时需要用交叉线(2-3 交叉,7-8 交叉,5-5 直连,7-8 可以不接但是一定不能直连电脑,否则可能导致工作不正常),一共有6 根线有定义,其余悬空。 序号 名称      描述  2 RXD   设备数据接收引脚 3 TXD   设备数据发送引脚 5 GND   信号地 8  RTS   请求发送 8    CTS   清除发送 9    VCC 默认未使用,PCB 上有个焊盘跳线,需要时可以将它与设备的电源输入正极连接,用于给串口传感器供电或者外部通过串口线给设备供电。 第三章 基于WiFi模块的无线传输的实现 2.1 WIFI模块的设置 2.2串口部分设置 2.3调试: 运行过程: 单片机首先运行,然后对DS18B20和DS1302,LCD1602进行初始化,接着对DS18B20和DS1302进行写设置,读取温度和时间,单片机处理数据,将其在LCD1602上显示,单片机进行串口初始化并通过串口程序将温度和时间准备好,等到串口接收到相应的信号,在发送数据。在程序内检测温度,若温度超过设定的值(值可通过终端修改),将发出报警信号。蜂鸣器报警,待温度下降后(可通过终端打开降温系统),蜂鸣器关闭。 第五章 程序与框图 程序: #include<reg52.h> #include<string.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int sbit DQ=P2^0; sbit lcden=P3^4; sbit lcdrs=P3^5; sbit dula=P2^6; sbit wela=P2^7; //sbit led=P1^0; sbit sclk=P1^4; //时钟信号线 sbit io=P1^5; //信号线 sbit ce=P1^6; //片选,也是RST sbit buzz=P2^3; sbit ledle=P2^5; unsigned int temp,temp1,temp2,temper,xs,flag,a,s,cc; unsigned char j; uchar code day[]="1234567"; uchar shi,fen,miao,nian,yue,ri; uchar cdflag; uchar code number[]="0123456789"; sbit ACC0 = ACC^0; //定义寄存器ACC的零位 sbit ACC7 = ACC^7; void delay1(unsigned int m) { unsigned int i,j; for(i=m;i>0;i--) for(j=110;j>0;j--); } void delay(unsigned int m) { while(m--); } /************************DS18B20程序**********************************************/ void Init_DS18B20() { unsigned char x=0; DQ=1; delay(8); DQ=0; delay(80); DQ=1; delay(4); x=DQ; delay(20); } uchar ReadOneChar() { unsigned char i=0; unsigned char dat=0; for(i=8;i>0;i--) { DQ=0; dat>>=1; DQ=1; if(DQ) dat|=0x80; delay(4); } return(dat); } void WriteOneChar(unsigned char dat) { unsigned char i=0; for(i=8;i>0;i--) { DQ=0; DQ=dat&0x01; delay(5); DQ=1; dat>>=1; } } void duwendu() { unsigned char a=0; unsigned char b=0; Init_DS18B20(); WriteOneChar(0xcc); WriteOneChar(0x44); delay(5); Init_DS18B20(); WriteOneChar(0xcc); WriteOneChar(0xbe); delay(5); a=ReadOneChar(); b=ReadOneChar(); temp1=(b<<4)&0x7f; //去除高四位,即正负位 temp1+=(a&0xf0)>>4; //个位 temp2=a&0x0f; //小数 temp=((b*256+a)>>4); //整数 xs=temp2*0.0625*10; temper=temp+xs; } /****************************************lcd程序******************************************************************/ void write_com(uchar com) { lcdrs=0; P0=com; delay(5); lcden=1; delay(5); lcden=0; } void write_data(uchar date) { lcdrs=1; P0=date; delay(5); lcden=1; delay(5); lcden=0; } /******************************************************************** 串口初始化 *********************************/ void ckinit() { TMOD=0x20;//设置定时器1为工作方式2 TH1=0xfa; TL1=0xfa; TR1=1; REN=1; //允许串行接收 SM0=0; SM1=1; //工作方式1 // SCON=0x50; PCON=0x80; //波特率加倍 EA=1; ES=1; } /****************************************************************************************************** LCD1602初始化 *****************************************************************************/ void lcdinit() { dula=0; wela=0; ledle=0; lcden=0; write_com(0x38); write_com(0x0e); write_com(0x06); write_com(0x01); write_com(0x80+0x10); } /*************************************** ************* 温度显示 *********************************/ void display() { write_com(0x80+0x40); //write_data(number[temper/100]); write_data(number[temp/10]); write_data(number[temp%10]); write_data('.'); write_data(number[xs%10]); write_data('C'); } void fas(unsigned char dat) { ES=0; //串口中断允许位 SBUF=dat; while(!TI); TI=0; ES=1; } /******************************************************************** 发送字符串函数 *********************************/ void fss(unsigned char *str) { uchar b,i; b=strlen(str); for(i=0;i<b;i++) { fas(*str); str++; } } /******************************************************************** DS1302写字节程序 *********************************/ void write_ds1302_byte(uchar add) //DS1302写一个字节数据 { uchar i; ACC = add; for(i=8; i>0; i--) { io = ACC0; //就是把最低位的数据传输给IO sclk = 1; //时钟拉高读走数据 sclk = 0; //时钟拉低允许数据变化 ACC = ACC >> 1; //把ACC右移一位,然后又把最低的一位传送过去 } } /******************************************************************** DS1302读字节 *********************************/ uchar read_ds1302_byte() //读DS1302一个字节 { uchar i; for(i=8; i>0; i--) { ACC = ACC >>1; //特别说明,读回来的数据是从最低位到最高位。 ACC7 = io; //把读回来的数据存到ACC寄存器的最高位,然后在移到最低位 sclk = 1; sclk = 0; } return ACC; } /******************************************************************** DS1302写地址数据 *********************************/ void write_ds1302(uchar add, uchar dat)//写任意地址,任意数据 { ce=0; //根据时序图编写 sclk=0; ce=1; //片选打开 write_ds1302_byte(add); write_ds1302_byte(dat); io=0; //释放总线 sclk=0; //时钟释放 ce=0; //片选关闭 } /******************************************************************** DS1302读地址数据 返回值:时间 *********************************/ uchar read_ds1302(uchar add) //读任意地址数据 { uchar temp; ce=0; sclk=0; ce=1; //片选打开 write_ds1302_byte(add); temp=read_ds1302_byte(); sclk=0; //时钟释放 io=0; //释放总线 ce=0; //片选关闭 return temp; } /****************************************************************************************************** ************* 时间显示函数 *********************************/ void dis_sj() { uchar th,tl; nian=read_ds1302(0x8d); //年寄存器 yue=read_ds1302(0x89); //月寄存器 ri=read_ds1302(0x87); //日寄存器 write_com(0x80+0x08); //设置时位置 th=nian>>4; write_data(number[th]); //刷新年高位 tl=nian&0x0f; write_data(number[tl]); //刷新年低位 write_data('-'); th=yue>>4; write_data(number[th]); tl=yue&0x0f; write_data(number[tl]); write_data('-'); th=ri>>4; write_data(number[th]); tl=ri&0x0f; write_data(number[tl]); shi=read_ds1302(0x85); //时寄存器 fen=read_ds1302(0x83); //分寄存器 miao=read_ds1302(0x81); //秒寄存器 write_com(0x80+0x48); th=shi>>4; write_data(number[th]); //刷新时高位 tl=shi&0x0f; write_data(number[tl]); //刷新时低位 write_data(':'); th=fen>>4; write_data(number[th]); tl=fen&0x0f; write_data(number[tl]); write_data(':'); th=miao>>4; write_data(number[th]); tl=miao&0x0f; write_data(number[tl]); } void fssj() { uchar th,tl; th=nian>>4; fas(number[th]); tl=nian&0x0f; fas(number[tl]); fas('-'); th=yue>>4; fas(number[th]); tl=yue&0x0f; fas(number[tl]); fas('-'); th=ri>>4; fas(number[th]); tl=ri&0x0f; fas(number[tl]); fss(" "); th=shi>>4; fas(number[th]); tl=shi&0x0f; fas(number[tl]); fas(':'); th=fen>>4; fas(number[th]); tl=fen&0x0f; fas(number[tl]); fas(':'); th=miao>>4; fas(number[th]); tl=miao&0x0f; fas(number[tl]); fss(" "); fss("Temp: "); } void main() { ckinit(); lcdinit(); cc=30; duwendu(); delay1(1000); while(1) { duwendu(); dis_sj(); duwendu(); display(); if(flag==1) { if(a=='1') { fssj(); fas(number[temp/10]); fas(number[temp%10]); fas('.'); fas(number[xs%10]); fas(' '); fas('C'); } if(a=='2') { fas(number[cc/10]); fas(number[cc%10]); fas(' '); fas('C'); } if(a=='3') { cc++; } if(a=='4') { cc--; } if(a=='5') { P1=0xff; ledle=1; P1=0xfe; delay1(5); ledle=0; } if(a=='6') { P1=0xff; ledle=1; delay1(5); ledle=0; } flag=0; } if(temp>=cc) { buzz=0; fssj(); fas(number[temp/10]); fas(number[temp%10]); fas('.'); fas(number[xs%10]); fas(' '); fas('C'); fas(' '); fss("warnning"); delay1(2000); if(a=='3') { cc++; } if(a=='4') { cc--; } } else { buzz=1; } } } void ser() interrupt 4 { RI=0; //接收标志位 flag=1; a=SBUF; //接收的数据 } 框图: 第四章 小结 在这次课程设计中,有些部分的功能能够顺利的实现,但也有部分代码无法实现其功能。首先出现的问题是温度报警功能。因为DS18B20初始化结束后默认温度为85度,单片机读取此温度后将直接进入报警程序,这点是不合理的。为了避免初始温度的影响,我在初始化程序后,WHILE大循环前加一段代码,首先是读温度,此时温度为85度,然后延时一段时间,在进入大循环,紧接着读温度,此时的温度就为正常温度,单片机正常工作。然后还有一个问题,就是在通过串口发送一些报警字符时需要一个一个发送,这会使程序繁琐,减弱程序的可读性,这时就需要一函数来发送字符串。然而这段函数需要用到指针和字符串中的一些函数库,介于这方面我很少使用,所以对此没有太好的方法。经过半天的学习,我重温了C语言基础,运用STRLEN()函数完成了这函数的设计。
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 学术论文 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服