📄 straincollector.c
字号:
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 + -