嵌入式安防监控项目——ZigBee学习

目录

一、ZigBee引入

二、开发环境搭建

三、协议栈系统工作原理

三、串口实验

四、GPIO操作

五、协议栈之无线数据透传

六、项目整合


一、ZigBee引入

是一种低速短距离传输的无线局域网协议

 

他的大小还没一元硬币大,他的速度最大只有250kb/s

二、开发环境搭建

 安装IAR写代码,安装协议栈支持使用

工程放到这个协议栈的路径下才能使用

选择协调器

打开这个.s文件

/*******************************************************************************
 *
 * Workaround for missing ?V1,?V2,... when linking. This is normally caused
 * by using an older version of cstartup (pre 8.30) in your project.
 * 
 * Add this file to your project.
 *
 * Copyright 2013 IAR Systems. All rights reserved.
 *
 ******************************************************************************/

;----------------------------------------------------------------;
; Virtual registers                         ;
; =================                         ;
; Below is some segment needed for the IAR ICC C/EC++ compiler   ;
;                                 ;
; BREG  : A segment for 8 bit registers for use by the compiler. ;
;         ?B0 is the first register.                             ;
; VREG  : Segment that holds up to 32 virtual registers for      ;
;         use by the compiler. ?V0 is the first register.        ;
; PSP   : Segment containing the PDATA stack pointer (?PSP)      ;
; XSP   : Segment containing the XDATA stack pointer (?XSP)      ;
;                                  ;
;----------------------------------------------------------------;
;----------------------------------------------------------------;

    PROGRAM VIRTUAL_REGISTERS
    PUBLIC  ?B0
    PUBLIC  ?V0
    PUBLIC  ?V1
    PUBLIC  ?V2
    PUBLIC  ?V3
    PUBLIC  ?V4
    PUBLIC  ?V5
    PUBLIC  ?V6
    PUBLIC  ?V7
    PUBLIC  ?V8
    PUBLIC  ?V9
    PUBLIC  ?V10
    PUBLIC  ?V11
    PUBLIC  ?V12
    PUBLIC  ?V13
    PUBLIC  ?V14
    PUBLIC  ?V15
    PUBLIC  ?V16
    PUBLIC  ?V17
    PUBLIC  ?V18
    PUBLIC  ?V19
    PUBLIC  ?V20
    PUBLIC  ?V21
    PUBLIC  ?V22
    PUBLIC  ?V23
    PUBLIC  ?V24
    PUBLIC  ?V25
    PUBLIC  ?V26
    PUBLIC  ?V27
    PUBLIC  ?V28
    PUBLIC  ?V29
    PUBLIC  ?V30
    PUBLIC  ?V31
    PUBLIC  ?PSP
    PUBLIC  ?XSP
    RSEG    BREG:BIT:NOROOT
?B0:
    DS      8

      RSEG    VREG:DATA:NOROOT
?V0:
    DS      1
?V1:
    DS      1
?V2:
    DS      1
?V3:
    DS      1
?V4:
    DS      1
?V5:
    DS      1
?V6:
    DS      1
?V7:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V7
?V8:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V8
?V9:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V9
?V10:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V10
?V11:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V11
?V12:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V12
?V13:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V13
?V14:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V14
?V15:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V15
?V16:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V16
?V17:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V17
?V18:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V18
?V19:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V19
?V20:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V20
?V21:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V21
?V22:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V22
?V23:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V23
?V24:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V24
?V25:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V25
?V26:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V26
?V27:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V27
?V28:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V28
?V29:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V29
?V30:
    DS      1

      RSEG    VREG:DATA:NOROOT
      REQUIRE ?V30
?V31:
    DS      1

    RSEG    PSP:DATA:NOROOT
    EXTERN  ?RESET_PSP
    REQUIRE    ?RESET_PSP
?PSP:
    DS      1

    RSEG    XSP:DATA:NOROOT
    EXTERN  ?RESET_XSP
    REQUIRE    ?RESET_XSP
?XSP:
    DS      2

    ENDMOD ; VIRTUAL_REGISTERS

    END

 添加到文件末尾并删除end

现在就没有错误了

烧入不了

 没安驱动

关闭流控,更改波特率

 

虽然乱码但是通了

三、协议栈系统工作原理

zigbee网络协议结构 

 zigbee对象:协调器(组网)、路由器(转发消息)、终端(具体干什么)。前面两个也可干终端的活,zigbee只在软件上区分,硬件上这三个都一样。

 

他们共同开发了SDK 

协议栈是协议的具体实现形式,通俗点来理解就是协议栈是协议和用户之间的一个缺口,开发人员通过使用协议栈来使用这个协议的,进而实现无线数据收发。 

hal是硬件接口,mac就是mac层,mt是串口、osal是操作系统

SDK中开源的代码都在components里

Documents里面都是文档,有哪些API参数是什么。有什么作用

projects是自己的工程

tools是工具 

 我们国家是半开源的,做成了一些库给我们使用

安全层内是一些机密算法,调制解调。

 OSAL是zigbee的一个操作系统

三、串口实验

复制一份然后改名

打开后弹出界面选是

 

选择协调器 

 

编译一下有个错误

 把这个改成8

我们在他的应用层做开发具体就是这个文件

 这些外设也由协议栈为我们写好了

 在task_id的处理函数中case的选项都是宏

把这个宏注释掉这样串口就不会打印乱码

 

void MT_UartProcessZToolData ( uint8 port, uint8 event )
{
 uint8 i = 0;
 uint8 rx_buf[MT_UART_DEFAULT_MAX_RX_BUFF], rx_len = 0;
 (void)event;
  while (Hal_UART_RxBufLen(port)){   //循环将 DMA 中接收到的串口数据读出来,并放入缓冲区 rx_buf;
        HalUARTRead(port, &rx_buf[rx_len], 1);
        rx_len++;
    }
    if (rx_len != 0) {          //确保缓冲区中有数据;
        pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof( mtOSALSerialData_t ) + rx_len + 1);//为消息分配内存空间;
        pMsg->hdr.event = CMD_SERIAL_MSG;       //指定了消息的类型,将串口数据复制到消息的数据区,数据的格式为:数据长度+数据
        pMsg->msg = (uint8*)(pMsg + 1);
        pMsg->msg[0] = rx_len;
        for (i = 0; i < rx_len; i++){
          pMsg->msg[i + 1] = rx_buf[i];
        }
    osal_msg_send( App_TaskID, (byte *)pMsg );//将消息发送给指定 task_id 的任务。
    }
}

 把这个又长又不好用的回调函数给注释掉

换成这个函数

 这样就可以给他发送了

四、GPIO操作

依旧是复制一份这个然后改名叫风扇

 

选择终端然后operation里改成8

把前面串口的移植过来,不过那些协议栈文件不用改因为他们是共用的

 

PxSEL //决定IO⼝功能, 1表示⽚上外设,0表示普通IO⼝ PxDIR //决定输⼊还是输出, 1表示输出, 0表示输⼊

PxINP //决定是上下拉模式还是三态

注意:P2INP这个特殊寄存器,它的低四位是控制P2⼝上拉模式还是下拉模式,⽽⾼三位7,6,5是对应控制P2-P0的GPIO端⼝具体是上拉还是下拉

void FanConrtol( uint8 * pkt)
{
  P1DIR |= (1<<3);
  //消息--->pkt
  //解析消息 strncmp  00--->打开风扇   11--->关闭风扇
  if(strncmp(pkt,"00",2) == 0)//完全相等返回值为0
  {
    P1_3 = 0;
    HalUARTWrite ( 0 ,"fan open!\n", sizeof("fan open!\n"));
    //低电平打开风扇
  }else{
    P1_3 = 1;
    HalUARTWrite ( 0 ,"fan close!\n", sizeof("fan close!\n"));   
  }
}

写一个风扇控制程序加到任务控制中

五、协议栈之无线数据透传

这次选择协调器 

void UartWireless(uint8 * msg)
{
  //调用发送APP
  AF_DataRequest( &SampleApp_Flash_DstAddr,//填写目的地址+端口号
                       &SampleApp_epDesc,//源(答复和确认)终端的一个描述
                       SAMPLEAPP_FLASH_CLUSTERID,//簇ID             
                       strlen(msg),             //发送长度
                       msg,                  //发送缓冲区的第一个buf
                       &SampleApp_TransID,      //任务ID号
                       AF_DISCV_ROUTE,          //有效位掩码
                       AF_DEFAULT_RADIUS );      //传输跳转数

}

写完这个再切换成终端完成风扇功能

 

 

这些注释掉,我们不需要定时发送

复制一份改成协调器,不使用风扇功能

六、项目整合

因为我们的板子上没有串口助手所以需要自己实现一个,Linux中有一切皆文件的思想,所以我们插入USB串口后会生成一个ttyUSB0的文件直接操作它就行。

#ifndef __LINUX_UART_H_
#define __LINUX_UART_H_

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <termios.h>
#include <string.h>
#include "data_global.h"

extern int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits);
extern int open_port(char *com_port);
extern void USB_UART_Config(char* path, int baud_rate);

#endif
#include "linuxuart.h"

int set_com_config(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
	struct termios new_cfg, old_cfg;
	int speed;
	/*保存原有串口配置*/
	if (tcgetattr(fd, &old_cfg) != 0){
		perror("tcgetattr");
		return -1;
	}

	new_cfg =old_cfg;

	/*配置为原始模式*/
	cfmakeraw(&new_cfg);
	new_cfg.c_cflag &= ~CSIZE;

	/*设置波特率*/
	switch (baud_rate)
	{
		case 2400:{
					  speed = B2400;
					  break; 
				  }
		case 4800:{
					  speed = B4800;
					  break;
				  }
		case 9600:{
					  speed = B9600;
					  break;
				  }
		case 19200:{
					   speed = B19200;
					   break;
				   }
		case 38400:{
					   speed = B38400;
					   break;
				   }

		default:
		case 115000:{
						speed = B115200;
						break;
					}
	}

	cfsetispeed(&new_cfg, speed);
	cfsetospeed(&new_cfg, speed);

	/*设置数据位*/
	switch (data_bits)
	{
		case 7:{
				   new_cfg.c_cflag |= CS7;
				   break;
			   }   
		default:	
		case 8:{
				   new_cfg.c_cflag |= CS8;
				   break;
			   }
	}

	/*设置奇偶校验位*/
	switch (parity)
	{
		default:
		case 'n':
		case 'N':{
					 new_cfg.c_cflag &= ~PARENB;
					 new_cfg.c_iflag &= ~INPCK;
					 break;
				 }
		case 'o':
		case 'O':{
					 new_cfg.c_cflag |= (PARODD |PARENB);
					 new_cfg.c_iflag |= INPCK;
					 break;
				 }
		case 'e':
		case 'E':{
					 new_cfg.c_cflag |= PARENB;
					 new_cfg.c_cflag &= ~PARODD;
					 new_cfg.c_iflag |= INPCK;
					 break;
				 }
		case 's':
		case 'S':{
					 new_cfg.c_cflag &= ~PARENB;
					 new_cfg.c_cflag &= ~CSTOPB;
					 break;
				 }
	}

	/*设置停止位*/
	switch (stop_bits)
	{
		default:
		case 1:{
				   new_cfg.c_cflag &= ~CSTOPB;
				   break;
			   }   	
		case 2:{
				   new_cfg.c_cflag |= CSTOPB;
				   break;
			   }
	}

	/*设置等待时间和最小接收字符*/
	new_cfg.c_cc[VTIME] = 0;
	new_cfg.c_cc[VMIN] = 1;
	tcflush(fd, TCIFLUSH);
	if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0)
	{
		perror("tcsetattr");
		return -1;
	}

	return 0;
}


int open_port(char *com_port)
{
	int fd;

	/*打开串口*/
	fd = open(com_port, O_RDWR|O_NOCTTY|O_NDELAY);
	if (fd < 0){
		perror("open serial port");
		return -1;
	}

	/*恢复串口阻塞状态*/
	if (fcntl(fd, F_SETFL, 0) < 0){
		perror("fcntl F_SETFL\n");
	}

	/*判断是否为终端设备*/
	if (isatty(fd) == 0){
		perror("This is not a terminal device");
	}

	return fd;
}


/*--------------------CH340Ƥ׃---------------------------*/
void USB_UART_Config(char* path, int baud_rate)
{
	int fd;
	fd = open_port(path);
	if(fd < 0){
		printf("open %s failed\n",path);
		return ;
	}
	if (set_com_config(fd, baud_rate, 8, 'N', 1) < 0)
	{
		perror("set_com_config");
		return ;
	}
	close(fd);
	return ;
}

 讲个笑话,我大二做大数据课设的时候,用python写的串口读取显示函数只用一行

加上tcp通信和功能处理都不会超过20行代码,C写项目最明显的特征就是写的多,最终结果的体积却是最小的,因为你写了一堆可能也就几K,但是你用python写一句话可能就得30MB,所以嵌入式还是选C。

 

 

这三个是串口常用接口

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇努力学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值