Linux开发项目(四)

2021/6/16 7:25:35

本文主要是介绍Linux开发项目(四),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

ZigBee技术的使用

上一篇文章介绍了上位机服务器环境的搭建,这一篇重点在于下位机的使用。本次硬件使用的是TI公司的CC2530,软件用IAR开发编程并且涉及到了TI开发的ZigBee协议栈Z-Stack的使用。

一、ZigBee相关知识

具体操作之前,简单了解一下协议栈的架构。在Z-Stack使用过程中程序的编写一般都在应用层App目录下的SampleApp.c中。
在这里插入图片描述
此外,在ZigBee网络中,每个ZigBee节点按功能的强弱划分为:全功能设备FFD和精简功能设备RFD,RFD节点为网络中存在数最多的端设备,而FFD节点可以担任路由器或是协调器的角色。
在这里插入图片描述
本次设计会用到一个协调器和两个终端,做到多点数据的采集。

二、具体操作

1. 串口配置

因为考虑到上位机和协调器之间的串口通信,需要先配置串口信息。在硬件层(HAL)的Target\CC2530EB\Drivers目录下的hal_uart.c文件中,包含了串口驱动程序的各种接口函数,只需要调用相应的函数就可以实现串口通信的功能,而对于串口的初始化函数需要在串口、监控测试层(MT)中查看,此目录下的MT_UART.c文件中,找到MT_UartInit()串口初始化函数,其中又关于波特率BaudRate的描述:

uartConfig.baudRate             = MT_UART_DEFAULT_BAUDRATE;

右键找到定义,将默认波特率大小改为9600bps:

#define	MT_UART_DEFAULT_BAUDRATE		HAL_UART_BR_9600

接着需要将默认开启的串口流控关闭:

#define	MT_UART_DEFAULT_OVERFLOW       FALSE

最后,根据相关函数在预编译设置里开启所需的串口,其中P1对应串口0。
在这里插入图片描述
然后需要在APP目录下的SampleApp.c文件中的SampleApp_Init()函数里加入:

  MT_UartInit();                  	//串口初始化
  MT_UartRegisterTaskID(task_id); 	//注册串口任务

之后使用HalUARTWrite()函数完成串口信息的写入。

2. DHT11温湿度数据收发

将事先编写好的DHT11的头文件和c文件加入App目录下,之后在SampleApp.c文件中的SampleApp_Init()函数里加入:

  P0SEL &= 0x7f;                  //P0_7配置成通用io
  P0DIR |= 0x02;                  //让P0.1为为输出 

以及在SampleApp_SendPeriodicMessage()函数里编写所需的内容,这里加入了当湿度大于60%时开启风扇的功能。

byte temp[5],humi[6];
  char dispT[20],dispH[20];
  Delay_ms(500);
  DHT11();             //获取温湿度
  Delay_ms(500);
  //将温湿度的转换成字符串 
  temp[0] = wendu_shi+0x30;
  temp[1] = wendu_ge+0x30;
  temp[2] = ' ';
  temp[3] = 'C';
  temp[4] = '\0';

  humi[0] = shidu_shi+0x30;
  humi[1] = shidu_ge+0x30;
  humi[2] = ' ';
  humi[3] = 'R';
  humi[4] = 'H';
  humi[5] = '\0';
  
  
  if((shidu_ge>0)&(shidu_shi>5))
  {
	P0_1=1;			//开启电机
  }
  else{
    P0_1=0;
  }
  
  osal_memcpy(dispT, "Temperature:", 12);
  osal_memcpy(&dispT[12], temp, 5);
  HalLcdWriteString(dispT, HAL_LCD_LINE_3);	//  LCD第三行显示

  osal_memcpy(dispH, "Humidity:", 9);
  osal_memcpy(&dispH[9], humi, 6);
  HalLcdWriteString(dispH, HAL_LCD_LINE_4);     // LCD第四行显示   
  
  //仅发送湿度的两位数据
  if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
                       SAMPLEAPP_PERIODIC_CLUSTERID,
                       2,
                       humi,
                       &SampleApp_TransID,
                       AF_DISCV_ROUTE,
                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }

这样就完成了终端的温湿度数据的LCD显示并且能够发送湿度数据,接下来配置协调器。同样在SampleApp.c文件中,找到SampleApp_MessageMSGCB()函数,修改为:

uint16 flashTime;

  switch ( pkt->clusterId )
  {
    case SAMPLEAPP_P2P_CLUSTERID:
      break;    
      
    case SAMPLEAPP_PERIODIC_CLUSTERID:
       HalUARTWrite(0, pkt->cmd.Data, pkt->cmd.DataLength); //输出接收到的数据
      break;

    case SAMPLEAPP_FLASH_CLUSTERID:
      break;
  }

因为考虑到后续多个节点的加入,所以使用了组播通信,这样协调器便完成了将接收到的数据写入串口的功能。

3. DS18B20温度数据收发

这里将第二个终端设计为温度采集的功能,也可以换为其他传感模块,采集不同的环境数据,例如烟雾传感和光敏电阻传感。
具体操作:将DS18B20相关文件加入App目录中,此时需要配置另一个终端。在IAR界面中依次点击Project–Edit Configurations…–New,加入EndDeviceEB-2,Based on已有的终端配置,之后在App目录里添加已经编写好的第二个终端函数(可以按照SampleApp.c文件修改,重命名以区分)。最后在Workspace栏下选择新建的终端EndDeviceEB-2,在App目录中,右键SampleApp.c文件,点击Options,勾上Exclude from build,之后Rebuild All完成编译过程。

 byte temp[6],data;
    char dispT[20];
    data = ReadDs18B20();             //获取温湿度
      //将温湿度的转换成字符串 
    temp[0] = data/10+48;
    temp[1] = data%10+48;
    temp[2] = ' ';
    temp[3] = 'C';
    temp[4] = '\0'; 

    
  if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
                       SAMPLEAPP_PERIODIC_CLUSTERID,
                       2,
                       temp,
                       &SampleApp_TransID,
                       AF_DISCV_ROUTE,
                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
  {
  }
  else
  {
    // Error occurred in request to send.
  }
4. 测试

将对应程序下载至ZigBee设备后,将协调器通过USB转TLL模块连接至电脑(或者连接至树莓派,后续介绍),打开串口调试助手,比对LCD屏显示结果观察数据。
在这里插入图片描述
在这里插入图片描述

三、程序附录

DHT11.c

#include <ioCC2530.h>
#include "OnBoard.h"

typedef unsigned char uchar;
typedef unsigned int  uint;

#define DATA_PIN P0_7

void Delay_us(void);
void Delay_10us(void);
void Delay_ms(uint Time);
void COM(void);
void DHT11(void);

//温湿度定义
uchar ucharFLAG,uchartemp;
uchar shidu_shi,shidu_ge,wendu_shi,wendu_ge=4;
uchar ucharT_data_H,ucharT_data_L,ucharRH_data_H,ucharRH_data_L,ucharcheckdata;
uchar ucharT_data_H_temp,ucharT_data_L_temp,ucharRH_data_H_temp,ucharRH_data_L_temp,ucharcheckdata_temp;
uchar ucharcomdata;

//延时函数
void Delay_us(void) //1 us延时
{
    MicroWait(1);   
}

void Delay_10us(void) //10 us延时
{
   MicroWait(12);
}

void Delay_ms(uint Time)//n ms延时
{
  unsigned char i;
  while(Time--)
  {
    for(i=0;i<100;i++)
     Delay_10us();
  }
}

//温湿度传感
void COM(void)    // 温湿写入
{     
    uchar i;         
    for(i=0;i<8;i++)    
    {
        ucharFLAG=2; 
        while((!DATA_PIN)&&ucharFLAG++);
        Delay_10us();
        Delay_10us();
        Delay_10us();
        uchartemp=0;
        if(DATA_PIN)uchartemp=1;
        ucharFLAG=2;
        while((DATA_PIN)&&ucharFLAG++);   
        if(ucharFLAG==1)break;    
        ucharcomdata<<=1;
        ucharcomdata|=uchartemp; 
    }    
}

void DHT11(void)   //温湿传感启动
{
    DATA_PIN=0;
    Delay_ms(20);  //>18MS
    DATA_PIN=1; 
    P0DIR &= ~0x80; //重新配置IO口方向
    Delay_10us();
    Delay_10us();                        
    Delay_10us();
    Delay_10us();  
    if(!DATA_PIN) 
    {
        ucharFLAG=2; 
        while((!DATA_PIN)&&ucharFLAG++);
        ucharFLAG=2;
        while((DATA_PIN)&&ucharFLAG++); 
        COM();
        ucharRH_data_H_temp=ucharcomdata;
        COM();
        ucharRH_data_L_temp=ucharcomdata;
        COM();
        ucharT_data_H_temp=ucharcomdata;
        COM();
        ucharT_data_L_temp=ucharcomdata;
        COM();
        ucharcheckdata_temp=ucharcomdata;
        DATA_PIN=1; 
        uchartemp=(ucharT_data_H_temp+ucharT_data_L_temp+ucharRH_data_H_temp+ucharRH_data_L_temp);
        if(uchartemp==ucharcheckdata_temp)
        {
            ucharRH_data_H=ucharRH_data_H_temp;
            ucharRH_data_L=ucharRH_data_L_temp;
            ucharT_data_H=ucharT_data_H_temp;
            ucharT_data_L=ucharT_data_L_temp;
            ucharcheckdata=ucharcheckdata_temp;
        }
        wendu_shi=ucharT_data_H/10; 
        wendu_ge=ucharT_data_H%10;
        
        shidu_shi=ucharRH_data_H/10; 
        shidu_ge=ucharRH_data_H%10;        
    } 
    else //没用成功读取,返回0
    {
        wendu_shi=0; 
        wendu_ge=0;
        
        shidu_shi=0; 
        shidu_ge=0;  
    } 
    
    P0DIR |= 0x80; //IO口需要重新配置 
}

DHT11.h

#ifndef __DHT11_H__
#define __DHT11_H__

#define uchar unsigned char
extern void Delay_ms(unsigned int xms);	//延时函数
extern void COM(void);                  // 温湿写入
extern void DHT11(void);                //温湿传感启动

extern uchar temp[2]; 
extern uchar temp1[5];
extern uchar humidity[2];
extern uchar humidity1[9];
extern uchar shidu_shi,shidu_ge,wendu_shi,wendu_ge;

#endif

DS18B20.c

#include"iocc2530.h"
#include"OnBoard.h"
#include "ds18b20.h" 

#define Ds18b20IO P0_7       //温度传感器引脚


void Ds18b20Delay(unsigned int k);
void Ds18b20InputInitial(void);
void Ds18b20OutputInitial(void);
unsigned char Ds18b20Initial(void);
void Ds18b20Write(unsigned char infor);
unsigned char Ds18b20Read(void);


//时钟频率为32M
void Ds18b20Delay(unsigned int k)
{
  while (k--)
  {
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");   
  }
}

void Ds18b20InputInitial(void)//设置端口为输入
{
    P0DIR &= 0x7f;
}

void Ds18b20OutputInitial(void)//设置端口为输出
{
    P0DIR |= 0x80;
}

//ds18b20初始化  初始化成功返回0x00,失败返回0x01
unsigned char Ds18b20Initial(void)
{
    unsigned char Status = 0x00;
    unsigned int CONT_1 = 0;
    unsigned char Flag_1 = 1;
    Ds18b20OutputInitial();
    Ds18b20IO = 1;      //DQ复位
    Ds18b20Delay(260);  //稍做延时
    Ds18b20IO = 0;      //单片机将DQ拉低
    Ds18b20Delay(750);  //精确延时 大于 480us 小于960us
    Ds18b20IO = 1;      //拉高总线
    Ds18b20InputInitial();//设置IO输入
    while((Ds18b20IO != 0)&&(Flag_1 == 1))//等待ds18b20响应,具有防止超时功能
    {                                      //等待约60ms左右
        CONT_1++;
        Ds18b20Delay(10);
        if(CONT_1 > 8000)Flag_1 = 0;
        Status = Ds18b20IO;
    }
    Ds18b20OutputInitial();
    Ds18b20IO = 1;
    Ds18b20Delay(100);
    return Status;       //返回初始化状态
}

void Ds18b20Write(unsigned char infor)
{
    unsigned int i;
    Ds18b20OutputInitial();
    for(i=0;i<8;i++)
    {
        if((infor & 0x01))
        {
            Ds18b20IO = 0;
            Ds18b20Delay(6);
            Ds18b20IO = 1;
            Ds18b20Delay(50);
        }
        else
        {
            Ds18b20IO = 0;
            Ds18b20Delay(50);
            Ds18b20IO = 1;
            Ds18b20Delay(6);
        }
        infor >>= 1;
    }
}

unsigned char Ds18b20Read(void)
{
    unsigned char Value = 0x00;
    unsigned int i;
    Ds18b20OutputInitial();
    Ds18b20IO = 1;
    Ds18b20Delay(10);
    for(i=0;i<8;i++)
    {
        Value >>= 1; 
        Ds18b20OutputInitial();
        Ds18b20IO = 0;// 给脉冲信号
        Ds18b20Delay(3);
        Ds18b20IO = 1;// 给脉冲信号
        Ds18b20Delay(3);
        Ds18b20InputInitial();
        if(Ds18b20IO == 1) Value |= 0x80;
        Ds18b20Delay(15);
    } 
    return Value;
}

//温度读取函数
unsigned char ReadDs18B20(void) 
{
    unsigned char V1,V2;   //定义高低8位 缓冲
    unsigned char temp;    //定义温度缓冲寄存器
    
    Ds18b20Initial();
    Ds18b20Write(0xcc);    // 跳过读序号列号的操作
    Ds18b20Write(0x44);    // 启动温度转换
    
    Ds18b20Initial();
    Ds18b20Write(0xcc);    //跳过读序号列号的操作 
    Ds18b20Write(0xbe);    //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
    
    V1 = Ds18b20Read();    //低位
    V2 = Ds18b20Read();    //高位
    temp = ((V1 >> 4)+((V2 & 0x07)*16)); //转换数据 

    return temp;
}

//温度读取函数 带1位小数位
float floatReadDs18B20(void) 
{
    unsigned char V1,V2;   //定义高低8位 缓冲
    unsigned int temp;     //定义温度缓冲寄存器
    float fValue;
    Ds18b20Initial();
    Ds18b20Write(0xcc);    // 跳过读序号列号的操作
    Ds18b20Write(0x44);    // 启动温度转换
    
    Ds18b20Initial();
    Ds18b20Write(0xcc);    //跳过读序号列号的操作 
    Ds18b20Write(0xbe);    //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
    
    V1 = Ds18b20Read();    //低位
    V2 = Ds18b20Read();    //高位
    //temp = ((V1 >> 4)+((V2 & 0x07)*16)); //转换数据 
    temp=V2*0xFF+V1;
    fValue = temp*0.0625;
    
    return fValue;
}

DS18B20.h

#ifndef __DS18B20_H__
#define __DS18B20_H__

extern unsigned char Ds18b20Initial(void);
extern unsigned char ReadDs18B20(void);
extern float floatReadDs18B20(void);
#endif


这篇关于Linux开发项目(四)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程