基于uCOS-II的UDP网络编程

基于uCOS-II的UDP网络编程

---------------------------------------------------------

Author             :tiger-john
WebSite            :blog.csdn.net/tigerjb

Email               :jibo.tiger@gmail.com

开发环境         硬件环境:LPC2200

                            操作系统:UC/OS-II操作系统

                            编译环境:ADS1.2

Update-Time   : 2011年2月21日星期一

Tiger声明:本人鄙视直接复制本人文章而不加出处的个人或团体,

但不排斥别人转载tiger-john的文章,只是请您注明出处并和本人

联系或留言给我。3Q

---------------------------------------------------------

一.    基于UCOS-II操作系统的UDP网络编程

1.UDP网络编程的组成部分

Ø  启动任务:负责UDP的初始化,创建通信工具和轮训检测是否有数据报到来。

Ø  UDP数据处理任务:负责UDP报文的处理

Ø  UDP服务例程:实现数据的收发。

二.    启动任务

1. 启动任务的功能

l  负责初始化UDP。

l  创建UDP数据处理处理任务和UDP服务例程。

l  轮训检测是否有数据到来。

2.UDP初始化由那及部分组成

 

 

1>初始化网络端口地址

通过调用SetNetPort()函数来设置主机IP地址网关地址,子网掩码和主机物理地址。

SetNetPort();

2>初始化RTL8019芯片

通过调用InitNic()函数初始化RTL9019以太网芯片对RTL8019芯片的工作寄存器进行设置。

InitNic(0);

3>初始化ARP函数

通过调用Initial_arp()函数初始化ARP。

Initial_arp();

4>初始化UDP

通过调用Udp_Initial函数初始化UDP。

Udp_Initial();

3.启动任务程序

/********************************************************************

** Function name:       TASK0

** Descriptions:        创建任务TASK1(udp数据处理任务)、TASK2(udp服务例程),分配信号量

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/

void Task0(void *pdata) 

{

    UBYTE iii;

    #if OS_CRITICAL_METHOD == 3                         

    OS_CPU_SR  cpu_sr;

       #endif

       TargetInit();         

       OSTaskCreate(Task1,(void *)0, &TaskStk1[1000 - 1],3);

       OSTaskCreate(Task2,(void *)0, &TaskStk2[1000 - 1],4);

       UDP_INIT();

    SetNetPort();

       InitNic(0);                   //RTL8019芯片初始化,在global.c中定义

       Initial_arp();

      Udp_Initial();

  while(1)

  {

             

              OSTimeDly(4);

              do

              {

 

               iii=Rec_Packet();//监控是否有数据到来

 

             

              }

              while(iii!=0);

    }

}

 

三.    UDP服务例程序任务

1.     UDP服务例程任务的功能:

Ø  创建套接字

Ø  绑定本地IP和端口与套接字相连

Ø  实现数据的接发

2..UDP服务例程有那几部分组成

3.UDP服务例程中所用到的API函数接口:

A.socket()函数

1)应用程序在使用套接口通信前,必须要拥有一个套接口,使用socket()函数给应用程序创建一个套接口。

2)函数socket()的原型

SOCKET * socket(uint16 af,uint16 type,uint16 protocol)
该函数功能是从SOCKET pool中分配一个SOCKET插口,供应用程序使用。

其参数说明如下:
1>参数af:表示要使用的协议地址族。

Ø  PF_INET:

Ø  AF_INET:

在zlg_socket.h中定义:

#define PF_INET       0

#define AF_INET      1

2>参数type:描述套接口的类型

Ø  SOCK_STREAM:对应TCP协议

Ø  SOCK_DGRAM:对应UDP协议

在zlg_socket.h中定义:

#define SOCK_STREAM 0

#define SOCK_DGRAM  1

3>参数protocol:分配SOCKET协议的类型。

SOCKET协议的类型:

Ø  TCP_PROTOCOL:表示应用TCP协议和上面的type要一致。

Ø  UDP_PROTOCOL:表示应用UDP协议和上面的type要一致。

在zlg_socket.h中定义:

#define TCP_PROTOCOL            0

#define UDP_PROTOCOL     1

4>返回值:函数执行成功,返回SOCKET*指针指向的一个SOCKET,失败返回NULL。

3)程序实例:

s=*socket( 0,SOCK_DGRAM, UDP_PROTOCOL);

B.bind()函数

1)当socket()函数创建一个套接口后,需要将该套接口与该主机上提供服务的某端口联系在一起。

2)函数bind()的原型

 int  bind(SOCKET * s,struct  sockaddr * name,uint 16 namelen)

本函数功能是将IP地址和端口绑定到一个SOCKET 指针* sock指向的s。

其参数说明如下:

1>SOCKET  * s:指向被绑定的SOCKET,它是socket()函数调用成功时返回的值。

2>struct sockaddr * name:是一个与指定协议有关的地址结构指针,存储了套接口的地址信息。

struct  sockaddr{

                 uint16      sin_family;

                 uint8        sin_addr[4];

                 uint16      sin_port;

      };  

3> namelen:表示地址参数的(name)的长度。

4>返回值:成功返回值为0。

3)程序实例:

iii=bind((SOCKET*)&s,(struct sockaddr*)&clientaddr,sizeof(clientaddr));

C.sendto()函数

1)对于无连接的套接口,使用sendto()函数来发送一个数据报文。

2)函数sendto()的原型

uint16 sendto(SOCKET s,uint8 *buff,uint16 len,int flags,struct sockaddr  *to,uint16  tolen)

向指定SOCKET *sock插口发送数据,由UDP使用。

其参数说明如下:
1>SOCKET      s:本地套接字。

2> uint8 * buff:待发送数据的缓冲区。

3>uint16  len:指明buf缓冲区中要发送的数据长度。

4>int flags:调用方式

5>struct  sockaddr  * to:指明发送数据的目的套接口地址。

6>uint16  tolen:  to所指的地址长度。

7>返回值:为发送数据的字节数。

3)程序实例:

sendto(s,rec_buffer,10,0, (struct sockaddr*)&servaddr, sizeof(servaddr) );

D.recvfrom()函数

1)对于无连接的套接口,通过recvfrom()函数从套接口上接收一个数据报文,并报存发送数据的源地址。

2)函数recvfrom()的原型

uint16 recvfrom(SOCKET *s,uint8 *buff,uint16 len,int flags,struct sockaddr * from,uint16 *fromlen)

函数的参数说明如下:

1> SOCKET  s :标识一个套接口的描述字。

2>uint8  * buf:接收数据的缓冲区。

3>uint16  len:接收数据缓冲区的长度。

4> int   flags :调用操作方式。

5>struct  sockaddr  *from: 指明接收数据的目的套接口地址。

6>uint16       *fromlen:  指向from缓冲区的长度值

7>返回值:为已读取的字节数。

3)程序实例:

recvfrom(s,rev_buffer,100,0,(struct sockaddr*)&serveraddr,&iii);

E.closesocket()函数

1)一个套接口不再使用时一定要关闭这个套接口,以释放与该套接口关联的所有资源,包括等候处理的数据。

2)函数closesocket()函数的原型

int closesocket( SOCKET s )

函数参数说明如下:

1>  SOCKET  s:表示即将被关闭的套接口。

3)程序的实例:

closesocket(s )

4.UDP服务例程的程序:

/********************************************************************

** Function name:       TASK2

** Descriptions:        UDP服务例程,实现数据的收发

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/

void Task2(void *pdata)

{

 

 uint8 rec_buffer[10];

 uint8 add[20]={"Hello tiger-john!"};

 SOCKET      s;

 int send_coute;

 int rec_coute;

 uint16 iii;

 struct sockaddr servaddr,clientaddr;

 PINSEL1&=0xfffffcff;     //P0.20定以为GPIO是具体情况而定

       OSTimeDly(60);

       servaddr.sin_family=0;

       servaddr.sin_addr[1]=168;

       servaddr.sin_addr[2]=0;

       servaddr.sin_addr[3]=55;

       servaddr.sin_port=1025; 

    OSTimeDly(60);

    s=*socket( 0,SOCK_DGRAM, UDP_PROTOCOL);

    clientaddr.sin_family=0;

       clientaddr.sin_addr[0]=192;

       clientaddr.sin_addr[1]=168;

       clientaddr.sin_addr[2]=0;

       clientaddr.sin_addr[3]=174;

       clientaddr.sin_port=1025; 

       iii=bind( (SOCKET * )&s, (struct sockaddr*)&clientaddr,sizeof(clientaddr));

   while(1)

       {   

         rec_coute = recvfrom(s,rec_buffer,10,0,(struct sockaddr *)&servaddr,&iii);

              if(rec_coute > 0)

              {

                     if(rec_buffer[0] == 'A')

                     {

                            //如果接收到的数据首字母是A,则把接收到的数据直接返回

                            send_coute = sendto(s,rec_buffer,rec_coute,0, (struct sockaddr*)&servaddr, sizeof(servaddr) );

              }

              else

              {

                    //否则发送"tiger-john"给上位机

                    send_coute = sendto(s,add,20,0,(struct sockaddr *)&servaddr,sizeof(servaddr));

              }

          

        }

     }  

}

四.完整程序

情景:接收上位机发送的数据,若上位机发送数据的首字母为A时将接收到的数据再发送给上位机,否则发送tiger-john给上位机。

/****************************Copyright(c)*******************************

**                                   西安邮电学院

**                                   graduate school

**                                                                  XNMS实验室

**                                  Author:冀博

**                                                                  Time:2011年2月21日

**                                 http://blog.csdn.net/tigerjb

**

**--------------FileInfo-------------------------------------------------------------------------------

****************************Copyright(c)******************************/

 

#define          MSG_QUEUE_SIZE        20              

#define           TaskStkLengh          3000

 

OS_EVENT                *RecPackedFlag;             

OS_EVENT                *RecBufOverFlowFlag;    

OS_EVENT                *RecPingPackedFlag;

 

OS_STK                TaskStk0[TaskStkLengh];  

OS_STK              TaskStk1[1000];           

OS_STK              TaskStk2[1000];

 

void    Task0(void *pdata);               //Task0  任务0

void    Task1(void *pdata);         //Task1  任务1

void    Task2(void *pdata);         //Task2  任务2

 

 

/********************************************************************

** Function name:       UDP_INIT

** Descriptions:        初始化网络地址,RTL8019,ARP和UDP

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/

void UDP_INIT(void )

{

      

     SetNetPort();

       InitNic(0);                   //RTL8019芯片初始化,在global.c中定义

       Initial_arp();

      Udp_Initial();

}

 

 

/*********************************************************************

* Function name:       main()

** Descriptions:        创建任务TASK0任务

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/

int main (void)

{

    UBYTE iii;

    OSInit();                                         

    OSTaskCreate(Task0,(void *)0, &TaskStk0[TaskStkLengh - 1],2);

     RecPackedFlag=         OSSemCreate(0);

       RecBufOverFlowFlag=      OSSemCreate(0);

       RecPingPackedFlag=  OSSemCreate(0);

       SendFlag=            OSSemCreate(1);

       RecUdpQFlag=           OSQCreate(&RecUdpQ[0],Q_Max_Size);

    OSStart();                                          

}

/********************************************************************

** Function name:       TASK0

** Descriptions:        创建任务TASK1(udp数据处理任务)、TASK2(udp服务例程),分配信号量

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/

void Task0(void *pdata) 

{

    UBYTE iii;

    #if OS_CRITICAL_METHOD == 3                         

    OS_CPU_SR  cpu_sr;

       #endif

       TargetInit();         

       OSTaskCreate(Task1,(void *)0, &TaskStk1[1000 - 1],3);

       OSTaskCreate(Task2,(void *)0, &TaskStk2[1000 - 1],4);

       UDP_INIT();

    SetNetPort();

       InitNic(0);                   //RTL8019芯片初始化,在global.c中定义

       Initial_arp();

      Udp_Initial();

  while(1)

  {

             

              OSTimeDly(4);

              do

              {

 

               iii=Rec_Packet();//监控是否有数据到来

 

             

              }

              while(iii!=0);

    }

}

/*********************************************************************

* Function name:       TASK1

** Descriptions:        UDP数据处理任务

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/     

void Task1(void *pdata)

 

{

    void * UdpTemp;

       uint8 eer;   

    while (1)

    {

            UdpTemp=OSQPend(RecUdpQFlag,0,&eer);

              if(eer==OS_NO_ERR)

                     {

              Udp_Process((Rec_Ptr *)UdpTemp);

              eer=eer;

                     }

       

    }   

}

/********************************************************************

** Function name:       TASK2

** Descriptions:        UDP服务例程,实现数据的收发

** input parameters:    无

** output parameters:   无

** Returned value:      无

********************************************************************/

void Task2(void *pdata)

{

 

 uint8 rec_buffer[10];

 uint8 add[20]={"Hello tiger-john!"};

 SOCKET      s;

 int send_coute;

 int rec_coute;

 uint16 iii;

 struct sockaddr servaddr,clientaddr;

 PINSEL1&=0xfffffcff;     //P0.20定以为GPIO是具体情况而定

       OSTimeDly(60);

       servaddr.sin_family=0;

       servaddr.sin_addr[1]=168;

       servaddr.sin_addr[2]=0;

       servaddr.sin_addr[3]=55;

       servaddr.sin_port=1025; 

    OSTimeDly(60);

    s=*socket( 0,SOCK_DGRAM, UDP_PROTOCOL);

    clientaddr.sin_family=0;

       clientaddr.sin_addr[0]=192;

       clientaddr.sin_addr[1]=168;

       clientaddr.sin_addr[2]=0;

       clientaddr.sin_addr[3]=174;

       clientaddr.sin_port=1025; 

       iii=bind( (SOCKET * )&s, (struct sockaddr*)&clientaddr,sizeof(clientaddr));

   while(1)

       {   

         rec_coute = recvfrom(s,rec_buffer,10,0,(struct sockaddr *)&servaddr,&iii);

              if(rec_coute > 0)

              {

                     if(rec_buffer[0] == 'A')

                     {

                            //如果接收到的数据首字母是A,则把接收到的数据直接返回

 send_coute = sendto(s,rec_buffer,rec_coute,0, (struct sockaddr*)&servaddr, sizeof(servaddr) );

              }

              else

              {

                    //否则发送"tiger-john"给上位机

    send_coute = sendto(s,add,20,0,(struct sockaddr *)&servaddr,sizeof(servaddr));

              }

          

        }

     }  

}

 

 转自:http://blog.csdn.net/tigerjibo/article/details/6195168
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于 ucos-ii 的 pid 温度控制系统代码主要包括任务创建、任务挂起和任务间通信等。 首先,我们需要创建三个任务:温度测量任务、PID控制任务和温度显示任务。 温度测量任务会周期性地读取温度传感器的数值,并将测得的温度值保存到一个全局变量中,以供PID控制任务使用。该任务创建函数可以使用UCOS-II提供的OSTaskCreate()函数。 PID控制任务会根据测得的温度值和目标温度值计算控制输出,并控制加热器的开关状态。该任务可以使用UCOS-II提供的OSTaskCreate()函数创建,并使用OSFlagPend()函数进行任务挂起。 温度显示任务会周期性地读取被控温度和当前实际温度,并将其显示在LCD屏幕上。该任务可以使用UCOS-II提供的OSTaskCreate()函数创建。 接下来,我们需要进行任务间的通信。PID控制任务可以通过全局变量来获取温度测量任务测得的温度值,并将计算得到的控制输出值写入到另一个全局变量中。温度显示任务可以通过读取全局变量来获取被控温度和当前实际温度的数值。 最后,在主函数中需要调用UCOS-II提供的OSInit()函数来初始化操作系统,调用OSTaskCreate()函数创建任务,并调用OSStart()函数来启动操作系统。 总结起来,基于UCOS-II的PID温度控制系统代码的关键步骤包括任务的创建、任务的挂起和任务间的通信。通过合理地利用UCOS-II提供的函数和数据结构,可以实现一个基本的PID温度控制系统。 ### 回答2: uCos-ii是嵌入式实时操作系统(RTOS),它提供了多任务处理、任务间通信、定时器和中断处理等功能,适用于嵌入式系统的开发。 PID温度控制系统是一个基于比例、积分和微分控制算法的温度调节系统。PID控制器通过比较设定值和实际值之间的差异来做出控制决策,并通过调整输出值来使差异减至最小。 在基于uCos-ii的PID温度控制系统代码中,可以按照以下步骤进行开发: 1. 首先,需要定义任务和任务优先级。例如,可以创建一个任务来采集温度传感器数据,另一个任务用于计算PID控制的输出值,最后一个任务用于控制执行器。 2. 然后,需要初始化uCos-ii系统和其他相关硬件设备,如温度传感器和执行器。这可以在主函数中完成。 3. 在采集温度传感器数据的任务中,获取实时温度值,并保存到一个变量中。 4. 在计算PID控制输出值的任务中,计算控制偏差,并应用PID算法来获得输出值。基于当前控制偏差、积分和微分参数以及历史数据,计算新的输出值。 5. 最后,在控制执行器的任务中,将计算得到的输出值发送给执行器,以控制温度。 需要注意的是,在任务之间进行通信和同步是很重要的。在uCos-ii中,可以使用消息队列、信号量或者事件标志等机制来实现任务间的通信与同步。 总的来说,基于uCos-ii的PID温度控制系统代码可以通过定义任务和任务优先级、初始化系统和硬件设备、采集温度、计算PID输出值和控制执行器等步骤来实现。这样可以实现一个实时、高效且稳定的温度调节系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值