基于ZigBee的无线传输(患者监护系统)

视频链接:基于zigbee的无线传输(患者监护系统)_哔哩哔哩_bilibili

可以通过视频更加清晰地了解项目。

程序不完善,但是基本可以完成无线传输的目的。

1.项目要求:

跟着步骤一步一步来,基本可以完成此次项目,所用程序全部开源。项目总体要求为利用Arduino采集两个传感器的数据,通过Arduino的串口发送给终端(就是其中一个zigbee),然后终端利用无线传输发送给协调器。

1.1补充:

以下展示其主要目的为展示zigbee的无线传输,arduino采集的传感器数据可以通过我们自身去模拟,下面会有段落描述怎样模拟产生arduino产生的串口数据给终端zigbee。

2.项目所用硬件模块:

 

1.两台zigbee模块,一台充当协调器(收集数据),一台充当终端(发送数据)。

 

2.一个arduino模块用来采集传感器信息,主要利用arduino上的IIC模块,其实不用arduino也可以,我们可以采用其他的的硬件模块采集传感器数据或者就用zigbee。补充一下:在模拟的时候,我们完全可以不采用arduino采集的数据,可以通过串口助手给终端发数据。

3.所用的传感器型号为:MX30205和MAX30102。

心率传感器部分的接线:

VIN- 3.3V

SDA-SDA

SCL-SCL

GND-GND

人体温度传感器部分的接线:

VCC- 3.3V

SDA-SDA

SCL-SCL

OS-GND(模块的中断引脚,任意)

A2-GND

A1-VCC

A0-GND

 

 

3.arduino程序

#include <Wire.h>
#include "Protocentral_MAX30205.h"
#include "MAX30105.h"
#include "heartRate.h"

MAX30205 tempSensor; //体温传感器
MAX30105 particleSensor; //心率传感器

byte SendPack[3]={0x00,0x00,0x00}; //串口发送协议帧缓存,首尾字节为帧头和帧尾,有效数据分别为体温、心率
int timer1_counter;

const byte RATE_SIZE = 4; //定义多少次心率数据取平均值
byte rates[RATE_SIZE]; //用于存放心率数据
byte rateSpot = 0;
long lastBeat = 0; //存储上次心跳发生的时间

float beatsPerMinute;
int beatAvg;

void setup() 
{
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(9600);
  tempSensor.begin();   //初始化体温传感器为连续模式
  
  // 初始化心率传感器
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
    while (1);
  }
  particleSensor.setup(); //使用默认设置来配置心率传感器
  particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED

  //配置定时器,用于串口定时发送数据包
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
 // timer1_counter = 65536-(62500*0.5);  //0.5s 定时器中断
  timer1_counter = 34286;  //预加载timer1 65536-16Mhz/256/2Hz
  TCNT1 = timer1_counter;
  TCCR1B |= (1 << CS12);
  TIMSK1 |= (1<< TOIE1);
  interrupts();
}

void loop() 
{
//温度处理
  unsigned int temp = tempSensor.getTemperature()*100; // 读取温度值并放大100倍
  SendPack[0]=temp / 100; //更新体温值整数部分
  SendPack[1]=temp % 100; //更新体温值小数部分

//心率处理 
  long irValue = particleSensor.getIR();
  if ((checkForBeat(irValue) == true)&&(irValue > 50000)) //检测到一次心跳
  {
    long delta = millis() - lastBeat;
    lastBeat = millis();
    beatsPerMinute = 60 / (delta / 1000.0); //根据两次心跳时间差来计算心率值
    if (beatsPerMinute < 255 && beatsPerMinute > 40) //小于40BPM或大于255BPM视为无效
    {
      rates[rateSpot++] = (byte)beatsPerMinute; //将心跳数据存入缓存以便求平均
      rateSpot %= RATE_SIZE; //循环存储
      beatAvg = 0;
      for (byte x = 0 ; x < RATE_SIZE ; x++)  //计算平均心率
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
      if(beatAvg<40) //小于40BPM视为无效
         beatAvg = 0;
    }
    if(beatsPerMinute < 40)
      beatsPerMinute=0;
  }
  else if(irValue < 50000)
  {
    beatsPerMinute=0;
    beatAvg = 0;
  }
  SendPack[2]=beatAvg; //更新心跳值
}

//定时器中断服务函数
ISR(TIMER1_OVF_vect) 
{
  TCNT1 = timer1_counter;
  for(char i=0;i<3;i++) //通过串口将协议帧发送出去
  {
    Serial.write(SendPack[i]);
  }
}

4.终端程序

#include <iocc2530.h>

#define LED1 P1_0
#define LED2 P1_1
#define LED3 P0_4
#define KEY1 P0_1
#define SENDVAL 5

unsigned char RX0_Buffer[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};    //UART0接收缓冲
unsigned char DataGet_Flag = 0;   //串口0接收到协议帧标志
unsigned char ReceiveData = 0;
unsigned char ReceiveIndex = 0;

char SendPacket[]={0x0E,0x61,0x88,0x00,0x07,0x20,0xEF,0xBE,0x20,0x50,0x00,0x00,0x00,'\r','\n'};
void ConfigGPIO(void);
void Init32M(void);
void halRfInit(void);
void RFSend(char *pstr,char len);
void Uart0_Cfg(void);
void Uart0_PrintASCII(unsigned char c);	

void DelayMS(unsigned int ms)
{
  unsigned int i,j;

  for (i=0; i<ms; i++)
  for (j=0; j<605; j++);
}

void main()
{
  char backup = 1;
  ConfigGPIO();
  Init32M();
  halRfInit();
  Uart0_Cfg();
  SHORT_ADDR0=0x50;
  SHORT_ADDR1=0x20;//设置本模块地址  设置本模块的网络地址0x2050
  for(;;)
  {
      DelayMS(1010);
      SendPacket[10] = RX0_Buffer[0];
      SendPacket[11] = RX0_Buffer[1];
      SendPacket[12] = RX0_Buffer[2];
      RFSend(SendPacket,15);
      Uart0_PrintASCII(RX0_Buffer[0]);
      Uart0_PrintASCII(RX0_Buffer[1]);
      Uart0_PrintASCII(RX0_Buffer[2]);
      Uart0_PrintASCII(SendPacket[10]);
      Uart0_PrintASCII(SendPacket[11]);
      Uart0_PrintASCII(SendPacket[12]);
  }
}


void Uart0_PrintASCII(unsigned char c)		
{ 
    UTX0IF = 0;   
    U0DBUF = c;   
    while(UTX0IF==0);   
    UTX0IF = 0;   
}

void Init32M(void)
{
   SLEEPCMD &=0xFB;//1111 1011 开启2个高频时钟源
   while(0==(SLEEPSTA & 0x40));// 0100 0000 等待32M稳定
   DelayMS(1);
   CLKCONCMD &=0xF8;//1111 1000 不分频输出
   CLKCONCMD &=0XBF;//1011 1111 设置32M作为系统主时钟
   while(CLKCONSTA & 0x40); //0100 0000 等待32M成功成为当前系统主时钟
}

void ConfigGPIO(void)
{
  P1SEL &= ~0x03;
  P0SEL &= ~0x10;
  P1DIR |= 0x03;
  P0DIR |= 0x10;
  
  P0SEL &= ~0x02;
  P0DIR &= ~0x02;
  P0INP &= ~0x02;
}

void halRfInit(void)
{
    EA=0;
    FRMCTRL0 |= 0x60;

    // Recommended RX settings  
    TXFILTCFG = 0x09;
    AGCCTRL1 = 0x15;
    FSCAL1 = 0x00;
    
    // enable RXPKTDONE interrupt  
    RFIRQM0 |= 0x40;//把射频接收中断打开
    // enable general RF interrupts
    IEN2 |= 0x01;
    
    FREQCTRL =(11+(25-11)*5);//(MIN_CHANNEL + (channel - MIN_CHANNEL) * CHANNEL_SPACING);   
                     //设置载波为2475M
    PAN_ID0=0x07;
    PAN_ID1=0x20; //0x2007   
    //halRfRxInterruptConfig(basicRfRxFrmDoneIsr);    
    RFST = 0xEC;//清接收缓冲器
    RFST = 0xE3;//开启接收使能 
    EA=1;    
}

void RFSend(char *pstr,char len)
{
  char i;
    RFST = 0xEC; //确保接收是空的
    RFST = 0xE3; //清接收标志位
    while (FSMSTAT1 & 0x22);//等待射频发送准备好
    RFST = 0xEE;//确保发送队列是空
    RFIRQF1 &= ~0x02;//清发送标志位
    for(i=0;i<len;i++)
    {
       RFD=pstr[i];
    }
    
    RFST = 0xE9; 
    while(!(RFIRQF1 & 0x02) );
    RFIRQF1 = ~0x02;
}

void Uart0_Cfg()
{
  PERCFG&=~0x01;   //有2个备用位置,0使用备用位置1;1使用备用位置2
  P0SEL |= 0x0C;   //P0_2 RXD P0_3 TXD 外设功能 0000 1100
 
  U0CSR |= 0xC0;  //串口接收使能  1100 0000 工作UART模式+允许接受
  U0UCR |= 0x00;  //无奇偶校验,1位停止位
 
  U0GCR |= 0x08;  
  U0BAUD = 0x3b;  //波特率:9600bps  
 
  IEN0 |= 0X04;     //开串口接收中断 'URX0IE = 1',也可以写成 URX0IE=1;
  EA=1;
}

#pragma vector=URX0_VECTOR
__interrupt void URX0_IRQ(void)
{  
    URX0IF=0;
    if(ReceiveIndex == 3)
    {
      ReceiveIndex = 0;
    }
    RX0_Buffer[ReceiveIndex++] = U0DBUF; 
}

#pragma vector=RF_VECTOR
__interrupt void RF_IRQ(void)
{
    EA=0;
    if( RFIRQF0 & 0x40 )
    {            
        RFIRQF0&= ~0x40;   
    }
    S1CON= 0;                 
    RFST = 0xEC;//清接收缓冲器
    RFST = 0xE3;//开启接收使能 
    EA=1;
}

5.协调器程序

#include <iocc2530.h>
#include "stdio.h"
#include "string.h"

#define LED1 P1_0
#define LED2 P1_1
#define LED3 P0_4
#define KEY1 P0_1
#define SENDVAL 5

void ConfigGPIO(void);
void Init32M(void);
void ConfigGPIO(void);
void Uart0_Cfg();
void Uart0SendByte(char SendByte);
void halRfInit(void);
void Uart0_Printf(unsigned char *p);	

char RF_RecData[3] = {0, 0, 0};
double Temperature=0.0; 
unsigned char HeartRate=0; 

__near_func int putchar(int c)
{
  UTX0IF = 0;
  U0DBUF = (char)c;
  while(U0DBUF == 0);
  return c;
}

void DelayMS(unsigned int ms)
{
  unsigned int i,j;

  for (i=0; i<ms; i++)
  for (j=0; j<605; j++);
}

void main()
{
  char buf[100];
  int repleacedatatemphigh;
  int repleacedatatemplow;
  int repleacedataheart;
  ConfigGPIO();
  Init32M();
  halRfInit();
  Uart0_Cfg();
  SHORT_ADDR0=0xEF;
  SHORT_ADDR1=0xBE;//设置本模块地址  0xBEEF
  for(;;)
  {
    DelayMS(1200);
    Uart0_Printf("temp: ");
    repleacedatatemphigh = RF_RecData[0];
    sprintf(buf, "%d",repleacedatatemphigh);
    Uart0_Printf(buf);
    Uart0_Printf(".");
    
    repleacedatatemplow = RF_RecData[1];
    sprintf(buf, "%d",repleacedatatemplow);
    Uart0_Printf(buf);
    Uart0_Printf("\r\n");
    
    Uart0_Printf("heart: ");
    repleacedataheart = RF_RecData[2];
    sprintf(buf, "%d",repleacedataheart);
    Uart0_Printf(buf);
    Uart0_Printf("\r\n");
    
  }
}

void Init32M(void)
{
   SLEEPCMD &=0xFB;//1111 1011 开启2个高频时钟源
   while(0==(SLEEPSTA & 0x40));// 0100 0000 等待32M稳定
   DelayMS(1);
   CLKCONCMD &=0xF8;//1111 1000 不分频输出
   CLKCONCMD &=0XBF;//1011 1111 设置32M作为系统主时钟
   while(CLKCONSTA & 0x40); //0100 0000 等待32M成功成为当前系统主时钟
}

void ConfigGPIO(void)
{
  P1SEL &= ~0x03;
  P0SEL &= ~0x10;
  P1DIR |= 0x03;
  P0DIR |= 0x10;
  
  P0SEL &= ~0x02;
  P0DIR &= ~0x02;
  P0INP &= ~0x02;
}

void Uart0_Cfg()
{
   PERCFG &=0xFE;
   P0SEL  |=0x0C;
   U0CSR |=0xC0;
   U0UCR =0; 
   U0GCR =11;
   U0BAUD =216;
   
   IEN0 |=0x04; 
   EA=1;
}

void Uart0_Printf(unsigned char *p)				//发送字符串
{	
    while(*p)
    {
        U0DBUF=*(p++);
        while(UTX0IF == 0);
        UTX0IF = 0;
    }   
}

void Uart0SendByte(char SendByte)
{
    U0DBUF=SendByte;  //把我们收到的数据通过串口再返回发出去
    while(UTX0IF==0);
    UTX0IF=0;
}

void halRfInit(void)
{
    EA=0;
    FRMCTRL0 |= 0x60;

    // Recommended RX settings  
    TXFILTCFG = 0x09;
    AGCCTRL1 = 0x15;
    FSCAL1 = 0x00;
    // enable RXPKTDONE interrupt  
    RFIRQM0 |= 0x40;
    // enable general RF interrupts
    IEN2 |= 0x01;
    
    FREQCTRL =(11+(25-11)*5);//(MIN_CHANNEL + (channel - MIN_CHANNEL) * CHANNEL_SPACING);    
    PAN_ID0=0x07;
    PAN_ID1=0x20;    
//halRfRxInterruptConfig(basicRfRxFrmDoneIsr);    
    RFST = 0xEC;//清接收缓冲器
    RFST = 0xE3;//开启接收使能 
    EA=1;    
}

void RevRFProc()
{
 static char len;
 static int  ch;
 static char Alllen;
 static char index = 0;
    len=ch=0;
    RFIRQM0 &= ~0x40;
    IEN2 &= ~0x01;
    EA=1;
 
    len=RFD;
    //len=0x0C 12
    Alllen=len;
    while (len>0) 
    {
        ch=RFD;
        if(3==len)
        {
           
        }
        if((len>=3)&&(Alllen-len>=9))
        {
          if(index == 3)
            index = 0;
          RF_RecData[index++] = ch;
          //Uart0SendByte(ch);
        }
        len--;
     }     
    EA=0;
    // enable RXPKTDONE interrupt
    RFIRQM0 |= 0x40;
    // enable general RF interrupts
    IEN2 |= 0x01;        
}

#pragma vector=RF_VECTOR
__interrupt void RF_IRQ(void)
{
    EA=0;
    if( RFIRQF0 & 0x40 )
    {
        
        RevRFProc();
             
        RFIRQF0&= ~0x40;   // Clear RXPKTDONE interrupt
    }
    S1CON= 0;                   // Clear general RF interrupt flag
    RFST = 0xEC;//清接收缓冲器
    RFST = 0xE3;//开启接收使能 
    EA=1;
}

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值