首页 51单片机应用开发范例大全(光盘)代码12

51单片机应用开发范例大全(光盘)代码12

举报
开通vip

51单片机应用开发范例大全(光盘)代码12【实例86】总线接口的软件实现 /*引脚定义和相关头文件包含*/ #include sbit I2C_SDA = P1^0; sbit I2C_SCL = P1^1; (1)函数void delay() 在C51中使用nop指令,实现一段时间的延时,程序代码如下: void delay( void ) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } (2)函数void i2...

51单片机应用开发范例大全(光盘)代码12
【实例86】总线接口的软件实现 /*引脚定义和相关头文件包含*/ #include sbit I2C_SDA = P1^0; sbit I2C_SCL = P1^1; (1)函数void delay() 在C51中使用nop指令,实现一段时间的延时,程序代码如下: void delay( void ) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } (2)函数void i2c_start() void i2c_start( void ) { I2C_SDA = 1; I2C_SCL = 1; delay(); I2C_SDA = 0; delay(); I2C_SCL = 0; } (3)函数void i2c_stop() void i2c_stop( void ) { I2C_SDA = 0; I2C_SCL = 1; delay(); I2C_SDA = 1; delay(); I2C_SCL = 0; } (4)函数void i2c_ ack () void i2c_ack( void ) { I2C_SDA = 0; I2C_SCL = 1; delay(); I2C_SDA = 1; I2C_SCL = 0; } (5)void i2c_send_byte() /*输入参数: c */ void i2c_send_byte( unsigned char c ) { unsigned char i; for( i=8;i>0;i--) { if( c & 0x80 ) I2C_SDA = 1; else I2C_SDA = 0; I2C_SCL = 1; delay(); I2C_SCL = 0; c = c<<1; } I2C_SDA = 1; /*释放数据线,准备接收应答信号*/ I2C_SCL = 1; delay(); while(!(0 == I2C_SDA /*等待应答信号*/ && 1 == I2C_SCL) ) ; } (6)函数unsigned char i2c_recv_byte() /*输入参数: c */ /*返回数值:从 总线上读取的数据*/ unsigned char i2c_recv_byte( void ) { unsigned char i; unsigned char r; I2C_SDA = 1; for( i=8;i>0;i--) { r = r<<1; /*左移补0*/ I2C_SCL = 1; delay(); if( I2C_SDA ) r = r | 0x01 ; /*当数据线为高时,数据位为1*/ I2C_SCL = 0; } return r; } 【实例87】SPI总线接口的软件实现 程序中端口宏定义如下: #include #include #define WREN 0x06 /*设置写使能锁存器*/ #define WRDI 0x04 /*复位写使用锁存器*/ #define RSDR 0x05 /*读状态寄存器*/ #define WRSR 0x01 /*写状态寄存器(看门狗和块锁)*/ #define READ 0x03 /*/读操作指令 0000 A8 011*/ #define WRITE 0x02 /*写操作指令 0000 A8 010*/ #define WIP 0x01 /*状态寄存器中写操作是否忙*/ /*各引脚定义*/ sbit X5045_SO = P1^1; sbit X5045_SI = P1^6; sbit X5045_SCK= P1^4; sbit X5045_CS = P1^2; (1)函数void write_byte() /*入口:byte,要写入的8位数据*/ void write_byte( unsigned char byte ) { unsigned char i; unsigned char tmp; for(i=0;i<8;i++) { X5045_SCK = 0; tmp = byte & 0x80; if( tmp == 0x80) /*与0X80比较判断最高数据位是否为1*/ { X5045_SI=1; _nop_(); } else { X5045_SI=0; _nop_(); } X5045_SCK = 1; byte = byte<<1; } } (2)函数unsigned char read_byte() /*返回值:从X5045中读取的8位数据*/ unsigned char read_byte( void ) /*读数据,一次8位*/ { unsigned char i; unsigned char byte=0; for(i=8;i>0;i--) { byte = byte<<1; /*先读出的是高位*/ X5045_SCK = 1; _nop_(); _nop_(); X5045_SCK = 0; _nop_(); _nop_(); byte = byte|(unsigned char) X5045_SO; } return ( byte ); } (3)函数void x5045_start()和void x5045_stop() void x5045_start( void ) { X5045_CS = 1; _nop_(); _nop_(); X5045_SCK= 0; _nop_(); _nop_(); X5045_CS = 0; _nop_(); _nop_(); } void x5045_end( void ) { X5045_SCK = 0; _nop_(); _nop_(); X5045_CS = 1; _nop_(); _nop_(); } (4)函数unsigned char x5045_read_status() unsigned char x5045_read_status( void ) { unsigned char tmp ; x5045_start(); write_byte( RSDR ); tmp = read_byte( ); x5045_end(); return tmp; } (5)函数void x5045_write_status() void x5045_write_status( unsigned char status ) { unsigned char tmp ; /*写操作之前先使能写操作*/ x5045_start(); write_byte( WREN ); x5045_end(); /*写入状态寄存器*/ x5045_start(); write_byte( WRSR ); write_byte( status ); x5045_end(); /*检查写操作是否完成*/ do { x5045_start(); write_byte( RSDR ); /*RSDR read status regesiter*/ tmp = read_byte(); x5045_end(); } while( tmp & WIP ) ; } (6)函数unsigned char read_addr_data() /*函数入口:addr,要读取数据的地址*/ unsigned char read_addr_data( unsigned int addr ) { unsigned char addr_tmp,tmp; unsigned char read_cmd ; if( addr > 255 ) read_cmd = READ|0X08; /*如果超出了一页,则名字字节A8为1*/ else read_cmd = READ; addr_tmp = (unsigned char) (addr&0xff ) ; x5045_start(); write_byte( read_cmd ); write_byte( addr_tmp ); tmp = read_byte(); x5045_end(); return tmp; } (7)函数void write_addr_data() /*入口地址:addr,要写入数据的地址*/ void write_addr_data( unsigned int addr,unsigned char edata ) { unsigned char tmp,addr_tmp; unsigned char cmd_tmp; /*写使能操作*/ x5045_start(); write_byte( WREN ); x5045_end(); /*地址和写操作指令调节*/ if( addr >255 ) cmd_tmp = WRITE | 0x08; else cmd_tmp = WRITE; addr_tmp = (unsigned char )( addr & 0xff ); /*向指定地址写入数据*/ x5045_start(); write_byte( cmd_tmp ); write_byte( addr_tmp ); write_byte( edata ); x5045_end(); /*检查写操作是否完成*/ do { x5045_start(); write_byte( RSDR ); tmp = read_byte(); x5045_end(); } while( tmp & WIP ) ; } (8)函数void reset_wdt() void reset_wdt( void ) { X5045_CS = 0; _nop_(); _nop_(); X5045_CS = 1; nop_(); _nop_(); } 【实例88】1-WIRE总线接口的软件实现 (1)函数void _1wire_init() /*包含头文件*/ #include #include /*引脚定义*/ sbit DQ = P1^2; /*函数名称:单总线初始化*/ void init( void ) { unsigned char i; DQ = 1; DQ = 0; for( i = 200;i>0;i--) _nop_(); /*延时约600μs*/ DQ = 1; for( i = 10;i>0;i--) _nop_(); /*延时约30μs */ while( DQ==1 ); for( i = 100;i>0;i--) _nop_(); /*延时约300μs*/ DQ = 1; } (2)函数void write_bit_1() void write_bit_1(void) { unsigned char i; DQ = 1; DQ = 0; for( i = 25;i>0;i--) _nop_(); /*延时约90μs */ DQ = 1; } (3)函数void write_bit_0() void write_bit_0(void) { unsigned char i; DQ = 1; DQ = 0; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); DQ = 1; for( i = 25;i>0;i--) _nop_(); /* 延时约90μs */ } (4)另外仔细观察1-WIRE总线的写时序图,可将写“1”和写“0”合为一个函数。 void write_bit( bit D ) { unsigned char i; DQ = 1; DQ = 0; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); DQ = D for( i = 25;i>0;i--) _nop_(); /*延时约90us */ DQ = 1; } (5)函数bit read_bit() bit read_bit( void ) { unsigned char i; DQ = 0; for( i=0;i<5;i++)_nop_(); if( DQ == 1 ) { return 1; } else { return 0; } } (6)函数void write_byte() void write_byte( unsigend char byte) { unsigned char i; unsigned char tmp; tmp = byte&0x01 for( i=0;i<8;i++) { tmp = byte>>i; /*将要写的数据字节右移i位*/ tmp &= 0x01; /*得到数据字节的第i位*/ write_bit( (bit)tmp ); } } (7)函数unsigned char read_byte() unsigned char read_byte( void ) { unsigned char i; unsigned char tmp; . tmp = 0; /*将返回值初始化为0*/ for(i=0;i<8;i++) { if( read_bit() ) /*如果当前读取的数据位为1*/ { tmp = tmp | (0x01< sbit rst=P3^5; /*单片机与RTL8019AS复位线的接口*/ /*其他程序代码*/ rst=1; /*RTL8019AS复位线高电平时复位*/ etherdev_delay_ms(100); /*延时一段时间*/ rst=0; 选择寄存器组的一段程序: #define reg00 xdata[0x0800] /*其他程序代码*/ void page( unsigned char page_no ) { unsigned char temp; temp=reg00; temp=temp&0x3B ; /*0011 1011*/ page_no = page_no <<6; temp=temp | page_no; reg00=temp; } 寄存器的设置情况: #define reg00 xdata[0x8000] #define reg01 xdata[0x8001] /*其他程序代码*/ #define reg1f xdata[0x801f] bit etherdev_init(void) { unsigned char tmp=0; rst=1; /*复位RTL8019*/ etherdev_delay_ms(100); rst=0; reg00=0x21; /*0010 0001 CR /*选择页0的寄存器,芯片停止运行,因为还/*没有初始化*/ page(0); /*可以不加*/ reg01=0x4c; /*Pstart,接收缓冲区首地址*/ reg02=0x50; /*Pstop 50H*/ reg03=0x4c; /*BNRY, 读页指针*/ reg04=0x40; /*TPSR,发送缓冲区首地址*/ reg0a=0x00; /*RBCR0 远程dma字节数低位*/ reg0b=0x00; /*RBCR1 远程dma字节数高位*/ reg0c=0xcc; /*RCR 接收配置寄存器 1100 1100*/ reg0d=0xe0; /*TCR 传输配置寄存器 1110 0000*/ reg0e=0xc8; /*DCR 数据配置寄存器 8位数据dma 1100 1000*/ reg0f=0x00; /*IMR屏蔽所有中断*/ page(1); /*选择页1的寄存器*/ reg07=0x4c; /*CURR与??相等就会停止接收??*/ reg08=0x00; /*MAR0 reg09=0x41; /*MAR1 reg0a=0x00; /*MAR2 reg0b=0x00; /*MAR3 reg0c=0x00; /*MAR4 reg0d=0x00; /*MAR5*/ reg0e=0x00; /*MAR6*/ reg0f=0x00; /*MAR7*/ /*写入MAC地址*/ reg01=ETHADDR0; /* reg02=ETHADDR1; /* reg03=ETHADDR2; /* reg04=ETHADDR3; /* reg05=ETHADDR4; /* reg06=ETHADDR5; /* page(0); reg00=0x22; /*CR 0010 0010选择页0寄存器,芯片执行命令*/ reg07=0xff; /*ISR*/ TR0 = 0; /*以下为时钟脉冲初始化部分*/ TMOD &= 0xF0; TMOD |= 0x01; TH0 = ETH_T0_RELOAD >> 8; TL0 = ETH_T0_RELOAD; TR0 = 1; ET0 = 1; EA = 1; return 1; } RTL8019发送数据包程序代码如下: void etherdev_send(void) /*发送数据包程序部分*/ { unsigned int i; unsigned char *ptr; /*指针指向 的数据缓冲区*/ ptr = _buf; page(0); reg00=RD2 | STA; /*终止DMA操作*/ while( reg00 & TXP) continue; /*查询数据是否已经发送完?*/ reg07|=RDC; /*清除ISR中远程DMA操作完成标志*/ reg08=0x00; /*RSAR0*/ reg09=ETH_TX_PAGE_START; /* RSAR1 设置远程DMA操作地址*/ reg0a=(unsigned char)( _len & 0xFF); /* RBCR0远程dma字节数低位reg0b=(unsigned char)( _len >> 8 )*/ /* RBCR1远程dma字节数高位*/ reg00=RD1 | STA; /*CR启动远程DMA写命令*/ for(i = 0; i < _len; i++) { /*单片机向RTL8019远程DMA写数据*/ if(i == 40 + _LLH_LEN) { ptr = (unsigned char *) _appdata; } reg10=*ptr++; /* RDMA远程DMA端口,即8019接收数据的端口,*/ } /*每写完一字节,自动加1*/ while(!(reg07 & RDC)) continue; /*查询远程DMA是否完成?*/ reg00= RD2 | STA; /*CR终止远程DMA操作*/ reg04=ETH_TX_PAGE_START; /* TPSR设置发送缓冲区首地址*/ if( _len < ETH_MIN_PACKET_LEN) { /*以太网包的最小长度为60字节*/ _len = ETH_MIN_PACKET_LEN; } reg05=(unsigned char)( _len & 0xFF); /*TBCR0发送数据包字节数*/ reg06=(unsigned char)( _len >> 8); /*TBCR1 高低字节*/ reg00= 0x3E; //RD2 | TXP | STA; /*CR 启动发送命令*/ return; } (1)函数unsigned int etherdev_read() unsigned int etherdev_read(void) { unsigned int bytes_read; /* tick_count时钟滴答设置为0.5s,若读数据等待时间超过0.5s,则返回*/ while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue; tick_count = 0; return bytes_read; } (2)函数static unsigned int etherdev_poll() static unsigned int etherdev_poll(void) { unsigned int len = 0; unsigned char tmp; /* 检查接收缓冲区是否有数据*/ if(reg07 & PRX) { /*PRX置位,表明数据包被正确接收*/ if( reg07 & OVW) { /*检查缓冲区是否溢出*/ bit retransmit = 0; /*若缓冲区溢出,则丢弃缓冲区的所有数据包,我们无法保证溢出后*/ /*缓冲区的数据不受影响变化*/ reg00=RD2 | STP; /* 终止当前DMA操作*/ reg0a=0x00; /*复位远程数据计数器 低位*/ reg0b=0x00; /*复位远程数据计数器 高位*/ /*当接收缓冲区发生溢出后,从缓冲区中读取一些数据而使其 /*不再处于溢出状态时,RST会被置位*/ while(!(reg07 & RST)) continue; if(reg00 & TXP) { /*检测当前是否仍在传输数据*/ if(!((reg07 & PTX) || (reg07 & TXE))) { /*若无错误,则重发数据包*/ retransmit = 1; } } reg0d=LB0; /* TCR, LB0) */ reg00= RD2 | STA; /*重新让RTL8019开始工作*/ reg03=ETH_RX_PAGE_START; /*再重初始化BNRY*/ page(1); reg07=ETH_RX_PAGE_START; /*再重初始化CURR */ page(0); reg07=PRX | OVW; /*清除接收缓冲区溢出标志*/ reg0d=0x00; /* TCR配置接收配置寄存器为正常工作状态*/ if(retransmit) { reg00=0x3e; /*CR, RD2 | TXP | STA,重发数据包*/ } } else { /*接收缓冲区未溢出,读取数据包到 _buf缓冲区中*/ unsigned int i; unsigned char next_rx_packet; unsigned char current; reg07=RDC; /*ISR, RDC清除远程DMA完成标志位*/ reg08=0x00; /* RSAR0设置远程DMA开始地址*/ reg09=reg03; /*RSAR1=BNRY reg0a=0x04; /*RBCR0, 0x04设置远程DMA操作字节数,注意以太网帧头部4字节*/ reg0b=0x00; /*RBCR1, 0x00 reg00=RD0 | STA; /* CR, RD0 | STA tmp=reg10; /* RDMA,远程DMA读取第一个字节,为接收状态,不需要,注意*/ /*RTL8019接收数据包前4个字节并不是真正的以太网帧头,而是*/ /*接收状态(8BIT),下页指针(8BIT),以太网包长度(16Bit)*/ next_rx_packet =reg10; /* RDMA,第二个字节为下一帧数据的指针*/ len = reg10; /*RDMA,存储包的长度*/ len += (reg10<<8); /* RDMA << 8*/; len -= 4; /*减去尾部CRC校验4字节*/ while(!(reg07 & RDC)) continue; /*等待远程DMA操作完成*/ reg00=RD2 | STA; /* CR 终止DMA操作*/ if(len <= _BUFSIZE) { /*检查数据包的长度*/ reg07=RDC; /* ISR, RDC清除远程DMA操作完成标志*/ reg08=0x04; /* RSAR0,设置远程DMA操作地址,前部分程序中并没有将*/ /*整个数据包//读入,只是读取接收数据包的前4个字节。*/ reg09=reg03; *RSAR1=BNRY,BNRY中为 CURR /*根据上文读取的数据包的长度设置远程DMA操作字节数寄存器*/ reg0a=(unsigned char)(len & 0xFF); * RBCR0*/ reg0b=(unsigned char)(len >> 8); * RBCR1*/ reg00=RD0 | STA; /*etherdev_reg_write(CR, RD0 | STA) 读取数据包到 _buf中*/ for(i = 0; i < len; i++) { *( _buf + i) = reg10; /* read RDMA*/ } while(!(reg07 & RDC)) continue; /*等待操作完成*/ reg00= RD2 | STA; /*CR 远程DMA操作完成后终止*/ } else { /*若数据包的长度太长, _buf将容纳不下丢弃此数据包len = 0 */ } reg03=next_rx_packet; /* BNRY=next_rx_packet,下页指针调整*/ page(1); current = reg07; /* 读取CURR指针*/ page(0); if(next_rx_packet == current) { /* 检测上次接收的数据包是否已经被读走*/ reg07=PRX; /*ISR, PRX 清除数据包被正确接收标志位*/ } } } return len; /*返回读取数据包的长度,数据已在 _buf中,若len=0,表明无数据*/ } 【实例92】单片机控制GPRS传输 函数send_gprs_data()实现发送指定长度数据的功能,本例中程序实现过程如下: unsigned char send_gprs_data( unsigned char *send_data_p, /* 要发送数据的指针 */ unsigned int send_data_len /* 发送数据的长度*/ ) { /* ASCII 码形式存放的发送数据长度 */ unsigned char sd_len_asc[4]; /* 将要发送数据长度(16进制)转换为ASCII码形式 */ if( send_data_len <9 ) { sd_len_asc[0]=send_data_len +0x30; sd_len_asc_l =1; } else if( send_data_len <99 ) { sd_len_asc[0] = (send_data_len%10) + 0x30 ; sd_len_asc[1] = (send_data_len/10) + 0x30 ; sd_len_asc_l = 2; } else if( send_data_len <999 ) { sd_len_asc[0] = (send_data_len/100) + 0x30; sd_len_asc[1] = (send_data_len%100)/10 + 0x30; sd_len_asc[2] = (send_data_len%10 ) + 0x30; sd_len_asc_l = 3; } else { sd_len_asc_l = 0; } /* AT命令发送要发送数据的长度 */ seri_send("AT+CIPSEND=",11); seri_send(&sd_len_asc[0],sd_len_asc_l); seri_send('\d',1); /* 判断是否返回 " > " */ if( (seri_poll('>',1)==FALSE )|| (seri_poll('>',1)==TIME_OUT) ) { return AT_CIPSEND_ERR; } seri_send( send_data_p,send_data_len); /* 发送数据*/ seri_send('\d',1); if((seri_poll("SEND OK",7)==FALSE )|| (seri_poll("SEND OK",7)==TIME_OUT) ) { /* 检查发送是否成功 */ return SEND_ERR; } return GPRS_DATA_SEND_OK; } 函数recv_gprs_data()主要完成对串行口接收数据简单处理的功能,seri_poll()函数的功能是在一段时间内查询串行口上是否有数据的功能。本例中程序如下: unsigned char recv_gprs_data( void ) { GPRS_DATA_HDR *gprs_data_p; if( (seri_poll(NULL,0)==0)|| (seri_poll(NULL,0)==TIME_OUT)) /* 检查有无数据接收到 */ { return NO_GPRS_DATA; } gprs_data_p = (GPRS_DATA_HDR *)&seri_recv_buf[0]; if( gprs_data_p->mask!=GPRS_DATA_SYN) /* 检查数据接收的开始字符是否和法 */ { clr_seri_buf(); return NO_MATCH_SYN; } gprs_recv_c ++; if( (gprs_recv_c> 6 )&& (gprs_recv_c<512)&& ( seri_recv_buf[ gprs_recv_c ] == FIN ) /* 检查结束字符 */ ) { return GPRS_RECV_FRAME_OK; /* 数据长度在GPRS_DATA_HDR结构中定义 */ } else if( seri_recv_buf[gprs_recv_c>512] { clr_seri_buf(); return GPRS_FRAME_ERR; } else { return GPRS_RECVING; } } 程序中定义了数据的帧头格式,C语言中用结构体表示如下: typedef struct { unsigned char syn_chr; /* 起始字符*/ unsigned int data_len; /* 本数据帧长度*/ unsigned int chk_sum; /* 校验数据*/ unsigned char opt; /* 功能域等*/ unsigned char *data_p; /* 数据指针*/ } GPRS_DATA_FRAME; 【实例93】单片机实现TCP/IP协议 上文中的例子将d加上volatile关键字后,如下: #include unsigned char a,b,c; volatile unsigned char xdata d; void main( void) { x=0xaa; y=0xbb; z=0xcc; d=0xdd; while(1) { x=d; y=d; z=d; } } 重新编译得到的代码(部分未列出)如下: main: MOV x,#0AAH MOV y,#0BBH MOV z,#0CCH MOV DPTR,#d MOV A,#0DDH MOVX @DPTR,A ?C0001: MOV DPTR,#d MOVX A,@DPTR MOV x,A MOVX A,@DPTR MOV y,A MOVX A,@DPTR MOV z,A SJMP ?C0001 END uIP使用一结构体arp_hdr来表示ARP数据帧。 struct arp_hdr { struct uip_eth_hdr ethhdr; /*以太网头部*/ u16_t hwtype, /*硬件类型*/ protocol; /*协议类型*/ u8_t hwlen, /*硬件地址长度*/ protolen; /*协议地址长度*/ u16_t opcode; /*操作代码*/ struct uip_eth_addr shwaddr; /*发送方硬件地址MAC地址*/ u16_t sipaddr[2]; /*发送方IP地址*/ struct uip_eth_addr dhwaddr; /*接收方硬件地址MAC地址*/ u16_t dipaddr[2]; /*接收方IP地址*/ }; ethhdr:以太网头部。定义的结构体原型如下: struct uip_eth_hdr { struct uip_eth_addr dest; /*以太网目的地址 */ struct uip_eth_addr src; /*以太网源地址 */ u16_t type; /*数据帧类型*/ }; uIP并没有单独将IP帧拿出来进行单独处理,定义数据结构时直接将IP和TCP部分的头部放在一个结构体uip_tcpip_hdr中: typedef struct { /* IP 帧头*/ u8_t vhl, /*4位版本和4位首部长度*/ tos, /*8位服务类型*/ len[2], /*16位总长度*/ ipid[2], /*16位标识*/ ipoffset[2], /*3位标志和13位偏移*/ ttl, /*8位生存时间*/ proto; /*8位协议*/ u16_t ipchksum; /*16位首部校验和*/ u16_t srcipaddr[2], /*源IP地址*/ destipaddr[2]; /*目的IP地址*/ /* TCP帧头*/ u16_t srcport, /*16位源端口号*/ destport; /*16位目的端口号*/ u8_t seqno[4], /*32位序列号*/ ackno[4], /*32位确认序列号*/ tcpoffset, /*4位首部长度和保留位*/ flags, /*标志*/ wnd[2]; /*窗口大小*/ u16_t tcpchksum; /*16位校验和*/ u8_t urgp[2]; /*16位紧急指针*/ u8_t optdata[4]; /*选项数据*/ } uip_tcpip_hdr; 每一个元素的类型为struct uip_conn型,uip_conn结构体定义如下: struct uip_conn { u16_t ripaddr[2]; /*远程主机的IP地址*/ u16_t lport; /*本地TCP端口*/ u16_t rport; /*远程TCP端口*/ u8_t rcv_nxt[4]; /*期望收到的下一个顺序号*/ u8_t snd_nxt[4]; /*上次发送的顺序号*/ u16_t len; /*预先发送的数据长度*/ u16_t mss; /*本连接的最大报文大小*/ u16_t initialmss; /*本连接的初始最大报文大小*/ u8_t sa; /*重发数据超时计算状态变量*/ u8_t sv; /*重发数据超时计算状态变量*/ u8_t rto; /*重发数据超时*/ u8_t tcpstateflags; /*TCP状态标志*/ u8_t timer; /*重发数据定时器*/ u8_t nrtx; /*上次重发数据段的序号*/ /*应用程序数据状态 */ u8_t appstate[UIP_APPSTATE_SIZE]; }; uIP0.9版本中应用程序部分带了一个简单的WEB服务器和只读文件系统,实现了简单的CGI功能。 void httpd_appcall(void) { u8_t idata i; switch(uip_conn->lport) { case HTONS(80): /* 判断是不是请求80端口 */ hs = (struct httpd_state xdata *)(uip_conn->appstate); /* 得到当前的http状态 */ if(uip_connected()) { hs->state = HTTP_NOGET; hs->count = 0; return; } else if(uip_poll()) { if(hs->count++ >= 10) { uip_abort(); } return; } else if(uip_newdata() && hs->state == HTTP_NOGET) { if( uip_appdata[0] != ISO_G || /* 如果不是get请求,丢弃数据 */ uip_appdata[1] != ISO_E || uip_appdata[2] != ISO_T || uip_appdata[3] != ISO_space) { uip_abort(); return; } for(i = 4; i < 10; ++i) { if( uip_appdata[i] == ISO_space || uip_appdata[i] == ISO_cr || uip_appdata[i] == ISO_nl) { uip_appdata[i] = 0; break; } } if(uip_appdata[4] == ISO_slash && uip_appdata[5] == 0) { hs->script = NULL; hs->state = HTTP_FILE; hs->dataptr = web-12; hs->count = sizeof(web)+12; } } /*与else if(uip_newdata() && hs->state == HTTP_NOGET) */ if(hs->state != HTTP_FUNC) { if(uip_acked()) { /* 如果上次发送的数据已经被接收,继续发送剩余的数据*/ if( hs->count >= uip_conn->len) { hs->count -= uip_conn->len; hs->dataptr += uip_conn->len; } else { hs->count = 0; } if(hs->count == 0) { uip_close(); } } } if(hs->state != HTTP_FUNC && !uip_poll()) /* 发送数据 */ { uip_send(hs->dataptr, hs->count); } return; default: uip_abort(); break; } }
本文档为【51单片机应用开发范例大全(光盘)代码12】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_807289
暂无简介~
格式:doc
大小:139KB
软件:Word
页数:31
分类:互联网
上传时间:2018-09-05
浏览量:23