⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 straincollector.c

📁 51单片机实现接收桥梁健康监测数据的代码,主要测量桥梁挠度!!数据通过GPRS传送!
💻 C
📖 第 1 页 / 共 2 页
字号:
    send_char(MID);
    crc ^= MID;
	
    send_char(g_cmdData[CMDDLEN]);
    crc ^= g_cmdData[CMDDLEN];
	
    for (i=1; i<=g_cmdData[CMDDLEN]; i++)
    {
        send_char(g_cmdData[CMDDLEN+i]);
        crc ^= g_cmdData[CMDDLEN+i];
		
    }
    send_char(crc);
	delay10ms();
}

/******************************************
通过串口想管理器发送采集到的应变数据,
输入:g_cmdData, g_strainData, g_gaugeFlag。
*****************************************/
void send_data()
{
    uchar i=0, mark=1, crc = 0, j=0;
    g_sendcmdData[CMD] = 0x11;
    g_sendcmdData[CMDDLEN] = 0;
    for(i=0; i<8; i++)
    {
        if(g_strainflag & mark)
            g_sendcmdData[CMDDLEN] += 6;
        mark <<= 1;
    }
    
    mark = 1;
//	SBUF = STARTFLAG;
    send_char(STARTFLAG);
    crc ^= STARTFLAG;
    send_char(g_sendcmdData[CMD]);
    crc ^= g_sendcmdData[CMD];
    send_char(TID);
    crc ^= TID;
    send_char(MID);
    crc ^= MID;
    send_char(g_sendcmdData[CMDDLEN]);
    crc ^= g_sendcmdData[CMDDLEN];
    for(i=0; i<8; i++)
    {
        if(g_strainflag & mark)
        {
            send_char(i);
            for(j=0; j<5; j++)
            {
                send_char(g_strainData[i][j]);
                crc ^= g_strainData[i][j];
            }
        }
        mark <<= 1;
    }
    send_char(crc);
	delay10ms();
}
/******************************************
方波产生函数

*****************************************/
void SW_Gen(uchar th, uchar tl)
{
    P1_7 =! P1_7;
    flag++;
    TH0 = th;
    TL0 = tl;
	
}

void set_timeout(uchar msec)
{
    //   关闭定时器1
	TR1 = 0;				//启动T0
	ET1 = 0;				//允许定时器0中断
	
    // 50ms
    //TH1 = 0x3C;
    //TL1 = 0xB0;
    SET50MS1();
    g_totimes = msec;
    BTIMEOUT = 0;

    //  启动定时器1
    TR1 = 1;
    ET1 = 1;
}


/******************************************
设置工作的Timeout时间
1. 设置定时器1的Timeout时间。
2. 启动定时器1
*****************************************/
void set_50ms(uchar times)
{
    //   关闭定时器1
	TR1 = 0;				//启动T0
	ET1 = 0;				//允许定时器0中断
	
    // 50ms
    //TH1 = 0x3C;
    //TL1 = 0xB0;
    SET50MS1();
    g_totimes = times;

   //  启动定时器1
    TR1 = 1;
    ET1 = 1;
}

/******************************************
设置工作的Timeout时间
1. 设置定时器1的Timeout时间。
2. 启动定时器1
*****************************************/
void update_timeout()
{
    //   关闭定时器1
	TR1 = 0;				//启动T0
	ET1 = 0;				//允许定时器0中断
	
    // 50ms
    //TH1 = 0x3C;
    //TL1 = 0xB0;
    SET50MS1();

    if (BSLPFLG)
    {   //  设置在浅休眠状态下的Timeout时间:0.5s
        g_totimes = 10;
    }
    else
    {
        //  设置在工作状态下的Timeout时间:2s?
        g_totimes = 40;
    }
	
    //  启动定时器1
    TR1 = 1;
    ET1 = 1;
}
/******************************************
设置休眠时间并进入休眠状态
*****************************************/
void shallow_sleep()
{
    //  关闭无线通信电源
    P3_7 = 1;
    //  关闭采集电路电源
    P3_6 = 1;
//	P4_3 = 1;
//    EX0 = 0;
//	P4 = 0x07;
    P3_5 = 1;
    BSLPFLG = 1;
    
    // close interrupt except ex1
    ET1 = 0;
    P8563_set3s();
    PCON = 0x02;         //单片机进入掉电模式
}

void deep_sleep()
{
    //  关闭无线通信电源
    P3_7 = 1;
    //  关闭采集电路电源
    P3_6 = 1;
//	P4_3 = 1;
//    EX0 = 0;
//	P4 = 0x07;
    P3_5 = 1;
    BSLPFLG = 1;
    
    // close interrupt except ex1
    ET1 = 0;
    P8563_setAlarm();
    PCON = 0x02;         //单片机进入掉电模式
}

/******************************************
设置深度休眠的唤醒时间
输入:g_dslpTime[7]
输出:通过I2C总线将数据传到外部定时器
*****************************************/
void set_wake_time()
{
    uchar i;
    for(i=0;i<7;i++)
    {
        writeData(i+2,g_dslpTime[i]);
    }
}
/******************************************
wait for wake
设置浅睡眠的Timeout时间
从串口读取唤醒标记
如果Timeout时间到,则转入休眠
读到唤醒标记后,设置工作标志进入工作状态。
输出:修改statusFlag,进入工作状态
*****************************************/
void wait_wake()
{
    uchar c, times=3;
    while (0 != times)
    {
        c = getchar();
        if (ISTIMEOUT())
            return;
		
        //  在哪里?重置timeout时间
        update_timeout();
		
        if (WAKEMSG == c)
            times--;
        else
            times = 3;
    }
	
    BSLPFLG = 0;
    // todo: 重新设置工作状态的timeout时间
    
    // 读取所有唤醒信号
    while(c != WAKEMSGEND)
    {
        if (c != WAKEMSG)
            break;
            
        c = getchar();
        if (ISTIMEOUT())
            return;
    }
	
}

/******************************************
接收到命令的起始位后返回

*****************************************/
void get_start_cmd()
{
    uchar c = getchar();
    while (STARTFLAG != c)
        c = getchar();
}

/******************************************
接收命令(0xAA 0x01 0x13 0x01 0x00 B9),保存命令字、地址、CRC	AA02130100BA YB	  AA03130100BB  READ
输出:填充g_cmdData。
*****************************************/
void receive_cmd()
{
    // TODO: add the timeout function
    uchar c=0x00, crc = STARTFLAG;
    uchar i;
    for (i=0; i<20; i++)
        g_cmdData[i] = 0x00;
	
    get_start_cmd();
    if (ISTIMEOUT())
        return;
    // get the cmd
    g_cmdData[CMD] = getchar();
    if (ISTIMEOUT())
        return;
    crc ^= g_cmdData[CMD];

    g_cmdData[CMDTID] = getchar();
    if (ISTIMEOUT())
        return;
    crc ^= g_cmdData[CMDTID];

    g_cmdData[CMDMID] = getchar();
    if (ISTIMEOUT())
        return;
    crc ^= g_cmdData[CMDMID];

    g_cmdData[CMDDLEN] = getchar();
    if (ISTIMEOUT())
        return;
    crc ^= g_cmdData[CMDDLEN];
	
    // get data
    for (i=0; i<g_cmdData[CMDDLEN]; i++)
    {
        g_cmdData[CMDDLEN+i+1] = getchar();
        if (ISTIMEOUT())
            return;
        crc ^= g_cmdData[CMDDLEN+i+1];
    }
	
    g_cmdData[CMDCRC] = crc ^ getchar();
	
}

void Collect()
{
    uchar i;
    uchar f = 1;
    // todo 开采集电路电源
    P3_6 = 0;
    // 是串口发
    for (i=0; i<STNORNUM; i++, f <<= 1)
    {
        if ((g_strainflag & f) == 0)
        {
            continue;
        }
        
        //  选择相应的通道
        P4 = i;
        P1_5 = 0;      //new change
		BSWOVER = 0;
		delay10ms();
        //  开始发方波.
        Init_Timer0INT();
        while (!BSWOVER);
        
        // 设置timeout时间
        set_timeout(40);
		BSDGOT = 0;
        // 等待timeout,或者外部中断。
        while (!BSDGOT)
        {
            if (BTIMEOUT)
                break;
        }
        if(!BSDGOT)
        {
            // timeout时,用0改写数据。
            g_strainData[i][0] = 0;
            g_strainData[i][1] = 0;
            g_strainData[i][2] = 0;
            g_strainData[i][3] = 0;
            g_strainData[i][4] = 0;
        }
        else
        {
            g_strainData[i][0] = g_sdata[0];
            g_strainData[i][1] = g_sdata[1];
            g_strainData[i][2] = g_sdata[2];
            g_strainData[i][3] = g_sdata[3];
            g_strainData[i][4] = g_sdata[4];
        }
            count++;
            ET0 = 1;
        // 找到下一个有效的应变计,设置选通,再开始发方波
    }
    // todo: 关采集电路电源
    P3_6 = 1;
}
/******************************************
执行一条命令
1. 接收一条命令
2. 如果不是发送给自己的,返回。
3. 处理命令
example: 
rec: (0xAA 0x01 0x13 0x01 0x00 crc)
send: (0xAA 0x14 0x13 0x01 0x00 crc)
*****************************************/
void do_cmd()
{
    uchar n;
    receive_cmd();
	
    if (ISTIMEOUT())
        return;
    if (TID != g_cmdData[CMDTID] || MID != g_cmdData[CMDMID])
        return;
	
    if (g_cmdData[CMDCRC] != 0)
    {   // data invalid
        g_cmdData[CMD] = CMD_CRCERR;
        g_cmdData[CMDDLEN] = 0;
        send_cmd();
        return;
    }
	
    switch (g_cmdData[CMD])
    {
    case 0x00:
        break;
    case CMD_ADDRCONFIRM:
        //  地址确认
        g_cmdData[CMD] = 0x14;
        g_cmdData[CMDDLEN] = 0;
        send_cmd();
        break;
    case CMD_COLLECT:
        //  采样命令
        g_cmdData[CMD] = 0x14;
        g_cmdData[CMDDLEN] = 0;
        send_cmd();
		
        //  进行采样
		Collect();
        break;
		
    case CMD_READDATA:
        // 读取数据
        send_data();
        break;
		
    case CMD_RETRY:
        // todo: 重发命令(暂缓)
        break;
		
    case CMD_UPSLPTM:
        //  更新唤醒时间
        n=7;
        CLEAR(g_dslpTime, n)
			switch(g_cmdData[CMDDLEN])
        {
			
	case 0x02:
		g_dslpTime[MIN] = g_cmdData[CMDDATA1];
	case 0x01:
	default:
		g_dslpTime[HOUR] = g_cmdData[CMDDATA0];
		break;
        }
        break;
		
    case CMD_DSLEEP:
        // todo: 将定时器改为每小时报警功能,进入深度休眠
        //set_wake_time();
        deep_sleep();
        break;
    default:
        // send error cmd message
        break;
    }
}

///////////////////////////////////////////////////////////////////////////////
// 外部定时器函数
/********************************************
内部函数,延时1
********************************************/
void Delay()
{
    _nop_();
	_nop_();
	_nop_();
   _nop_(); /*根据晶振频率制定延时时间*/
}

/********************************************
内部函数,I2C开始
********************************************/
void Start()
{  EA=0;
   SDA=1;
   SCL=1;
   Delay();
   SDA=0;
   Delay();
   SCL=0;
}
/********************************************
内部函数,I2C结束
********************************************/
void Stop()
{
   SDA=0;
   SCL=0;
   Delay();
   SCL=1;
   Delay();
   SDA=1;
   Delay();
   EA=1;
}
/********************************************
内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读书据,ack=1;
********************************************/
void WriteACK(uchar ack)
{
   SDA=ack;
   Delay();
   SCL=1;
   Delay();
   SCL=0;
}
/********************************************
内部函数,等待ACK
********************************************/
void WaitACK()
{  uchar errtime=20;
   SDA=1;
   Delay(); /*读ACK*/
   SCL=1;
   Delay();
   while(SDA)
   {  errtime--;
      if(!errtime) Stop();
   }
   SCL=0;
   Delay();
}
/********************************************
内部函数.输出数据字节
入口:B=数据
********************************************/
void writebyte(uchar wdata)
{
   uchar i;
   for(i=0;i<8;i++)
   {
       if(wdata&0x80) SDA=1;
       else SDA=0;
       wdata<<=1;
       SCL=1;
       Delay();
       SCL=0;
   }
   WaitACK();     //I2C器件或通讯出错,将会退出I2C通讯
}
/********************************************
内部函数.输入数据
出口:B
********************************************/
uchar Readbyte()
{
   uchar i,bytedata;
   SDA=1;
   for(i=0;i<8;i++)
   {
      SCL=1; 
      bytedata<<=1;
      bytedata|=SDA;
      SCL=0;
      Delay();
   }
   return(bytedata);
}
/********************************************
输出数据->pcf8563
********************************************/
void writeData(uchar address,uchar mdata)
{
   Start();
   writebyte(0xa2); /*写命令*/
   writebyte(address); /*写地址*/
   writebyte(mdata); /*写数据*/
   Stop();
}
/********************************************
输入数据<-pcf8563
********************************************/
uchar ReadData(uchar address) /*单字节*/
{  uchar rdata;
   Start();
   writebyte(0xa2); /*写命令*/
   writebyte(address); /*写地址*/
   Start();
   writebyte(0xa3); /*读命令*/
   rdata=Readbyte();
   WriteACK(1);
   Stop();
   return(rdata);
}

void ReadBuff(uchar address,uchar count,uchar * buff) /*多字节*/
{  uchar i;
   Start();
   writebyte(0xa2); /*写命令*/
   writebyte(address); /*写地址*/
   Start();
   writebyte(0xa3); /*读命令*/
   for(i=0;i<count;i++)
   {
        buff[i]=Readbyte();
        if(i<count-1) WriteACK(0);
   }
  WriteACK(1);
   Stop();
}

void P8563_set3s()
{
    writeData(0x01,0x11);   // 定时有效
    writeData(0x0E,0x81);   // 64Hz
    writeData(0x0F,0xC0);   // 0xc0/64 = 3s
}

void P8563_setAlarm()
{
    writeData(0x1,0x12); /*报警有效*/
    writeData(0x9,0x55); /*每个小时的59'报警*/ 
    writeData(0x00,0x00);   
}

void P8563_init()
{
    set_wake_time();
	writeData(0x1,0x12); /*报警有效*/
    writeData(0x9,0x55); /*每个小时的59'报警*/ 
	writeData(0x00,0x00);   
}	  

void main()
{
	uchar i,j;
    Init_Interrupt();
    // Init Chip
    Init_Chip();

//	P8563_init();
    
	for (i=0; i<8; i++)
	for (j=0; j<5;j++)
		gx_straindata[i][j] = (i<<4)|(i+j);

	change();
	// 确定应变计个数
//	Init_Strainor();
	g_strainflag = 0xFF;
	gprs_start();

	gprs_Init();
	
    while(1)
	{
            // 工作状态
		gprs_CMGF();
		gprs_delay();
		gprs_CNMI();
		gprs_delay();
		if (gprs_CMGR())
		{
			Collect();
			change();
			gprs_CMGS();
		}
		for(i=0;i<250;i++)
			delay500ms();

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -