?? pcm-rtx51.c
字號(hào):
/********************************************/
/** PCM-ZXDU1500 **/
/** 操作系統(tǒng) RTX51-TINY **/
/*******************************************/
#include "rtx51tny.h"
#include "reg52.h"
#include "intrins.h"
#include "absacc.h"
#define uchar unsigned char
#define uint unsigned int
#define MAX_NUM_COM1 100 //定義COM1接收緩沖區(qū)長(zhǎng)度
#define COM1_RXD_En() P1_1 = 0
#define COM1_TXD_En() P1_1 = 1
/********************************************/
/** 任務(wù)編號(hào)聲明 **/
/********************************************/
#define TASK_INIT 0 //初始化任務(wù)
#define TASK_COM1 1 //與上位機(jī)通信任務(wù)
#define TASK_COM2 2 //與設(shè)備通信任務(wù)
#define TASK_DATA 3 //數(shù)據(jù)處理任務(wù)
#define TASK_CMD 4 //命令處理任務(wù)
#define TASK_LEDWDT 5 //狀態(tài)燈及看門狗
/********************************************/
/** GM16C550寄存器聲明 **/
/********************************************/
#define RBR XBYTE[0x8000]
#define THR XBYTE[0x8000]
#define DLL XBYTE[0x8000]
#define DLM XBYTE[0x8001]
#define IER XBYTE[0x8001]
#define FCR XBYTE[0x8002]
#define IIR XBYTE[0x8002]
#define LCR XBYTE[0x8003]
#define MCR XBYTE[0x8004]
#define LSR XBYTE[0x8005]
#define MSR XBYTE[0x8006]
#define SCR XBYTE[0x8007]
/********************************************/
/** 控制引腳說(shuō)明 **/
/********************************************/
//串口1(16C550) RS485方式收發(fā)使能,0為接收,1為發(fā)送
sbit P1_1 = P1^1;
sbit P1_2 = P1^2; //串口1(16C550)復(fù)位信號(hào)輸出
sbit P1_3 = P1^3; //看門狗清零輸出
sbit P3_5 = P3^5; //運(yùn)行狀態(tài)燈輸出
void CPU_Init(void); //系統(tǒng)初始化
void COM1_Init(void);
void COM2_Init(void);
void Get_PcmAddr(void); //讀取PCM地址
void Hex2Ascii(uchar,uchar*);
void Int2Ascii(uint,uchar*);
uchar Ascii2Hex(uchar *);
bit Chk_Sum(uchar*);
uchar code ZXDUCMD[2][25]={
{0x10, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0x97, 0x5D, 0x01, 0x12}, //取實(shí)時(shí)數(shù)據(jù)
{0x10, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x74, 0x00, 0x12}, //取參數(shù)
};
uchar code ZXDUSET[] = {0x10, 0x00, 0x00, 0x00, 0x23, 0x01, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //設(shè)置命令的前面字節(jié)
uchar AlarmParaChar[35]; //ZXDU3000告警參數(shù)段
uchar xdata BuffCOM1[MAX_NUM_COM1]; //COM1接收緩存
uchar xdata BuffCOM2[1024]; //COM2接收緩存
uchar xdata BuffCmdSet[100]; //一條設(shè)置命令
uchar xdata BuffDvcReal[1024]; //設(shè)備實(shí)時(shí)數(shù)據(jù)
uchar xdata BuffDvcPara[1024]; //設(shè)備參數(shù)
uchar PcmAddr[2]; //按ASCII存放PCM地址
uchar RXDTimeOut = 0; //超時(shí)計(jì)時(shí)
uchar TXDTimeOut = 0;
uchar xdata *data PtrCOM1RXD; //串口收發(fā)指針
uchar xdata *data PtrCOM1TXD;
uchar xdata *data PtrCOM2RXD;
uchar *data PtrCOM2TXD;
bit FlagCOM1AllOut = 1; //COM1發(fā)送完成標(biāo)志
bit FlagCOM2AllOut = 1; //COM2發(fā)送完成標(biāo)志
bit FlagCmdStart = 0; //接收命令開始標(biāo)志
bit FlagCmdSet = 0; //收到一條設(shè)置命令
bit FlagDataStored = 1; //數(shù)據(jù)存儲(chǔ)完成標(biāo)志
bit CmdCnt = 0; //讀數(shù)據(jù)或參數(shù)的命令記數(shù),只有兩條,所以用bit
/********************************************/
/** 系統(tǒng)初始化任務(wù) **/
/** 初始化外設(shè)并建立其它任務(wù) **/
/********************************************/
void Task_Init(void) _task_ TASK_INIT
{
COM1_RXD_En(); //首先釋放485線
COM2_Init();
COM1_Init();
CPU_Init();
Get_PcmAddr();
os_create_task(TASK_COM1);
os_create_task(TASK_COM2);
os_create_task(TASK_DATA);
os_create_task(TASK_CMD);
os_create_task(TASK_LEDWDT);
os_delete_task(TASK_INIT);
}
/********************************************/
/** 串口1任務(wù) **/
/** 處理接收到的命令,發(fā)送數(shù)據(jù) **/
/********************************************/
void Task_COM1(void) _task_ TASK_COM1
{
uchar CmdTyp; //命令類型
while(1)
{
os_wait(K_SIG,0,0); //等待接收到命令的信號(hào)
CmdTyp = BuffCOM1[8]; //取命令類型
switch(CmdTyp) //根據(jù)命令類型作相應(yīng)處理
{
case 0x31: //命令類型: 41,取實(shí)時(shí)數(shù)
{
COM1_TXD_En(); //充許發(fā)送
PtrCOM1TXD = BuffDvcReal;
FlagCOM1AllOut = 0;
THR = *PtrCOM1TXD++;
break;
}//41
case 0x36: //命令類型: 46,取參數(shù)
{
COM1_TXD_En(); //充許發(fā)送
PtrCOM1TXD = BuffDvcPara;
FlagCOM1AllOut = 0;
THR = *PtrCOM1TXD++;
break;
}//46
case 0x35: //命令類型: 45,遙調(diào)
{
os_send_signal(TASK_CMD); //通知CMD任務(wù)進(jìn)行命令轉(zhuǎn)換
break;
}//45
}
os_switch_task();
}
}
/********************************************/
/** 串口2任務(wù) **/
/** 定時(shí)發(fā)送命令到設(shè)備 **/
/********************************************/
void Task_COM2(void) _task_ TASK_COM2
{
while(1)
{
os_wait(K_TMO,200,0); //等待時(shí)間標(biāo)志,此段時(shí)間,從設(shè)備接收數(shù)據(jù)并存儲(chǔ)完成
os_wait(K_TMO,200,0);
while(!FlagDataStored); //等待數(shù)據(jù)存儲(chǔ)完成,否則接收過程復(fù)蓋原收到數(shù)據(jù)
if(FlagCmdSet) //收到上位機(jī)下發(fā)設(shè)置命令
{
PtrCOM2TXD = BuffCmdSet; //指向設(shè)置命令
FlagCmdSet = 0;
}
else
{
PtrCOM2TXD = ZXDUCMD[CmdCnt]; //指向讀數(shù)據(jù)或參數(shù)命令
CmdCnt = !CmdCnt;
}
FlagCOM2AllOut = 0; //COM2啟動(dòng)發(fā)送
TI = 1;
os_switch_task();
}
}
/********************************************/
/** 數(shù)據(jù)處理任務(wù) **/
/********************************************/
void Task_Data(void) _task_ TASK_DATA
{
uchar xdata *data PtrS;
uchar xdata *data PtrD;
uchar i;
uchar SMR_NUM; //整流模塊數(shù)目
uint SUM; //校驗(yàn)和
union
{
uint i;
uchar c[2];
}a_int;
union
{
float f;
uchar c[4];
}a_float;
while(1)
{
BuffDvcReal[0] = 0x7E; //存放起始數(shù)據(jù)
BuffDvcPara[0] = 0x7E;
BuffDvcReal[1] = 0x32;
BuffDvcPara[1] = 0x32;
BuffDvcReal[2] = 0x30;
BuffDvcPara[2] = 0x30;
BuffDvcReal[3] = 0x46;
BuffDvcPara[3] = 0x46;
BuffDvcReal[4] = PcmAddr[1];
BuffDvcPara[4] = PcmAddr[1];
BuffDvcReal[5] = 0x44;
BuffDvcPara[5] = 0x44;
BuffDvcReal[6] = 0x30;
BuffDvcPara[6] = 0x30;
BuffDvcReal[7] = 0x30;
BuffDvcPara[7] = 0x30;
BuffDvcReal[8] = 0x30;
BuffDvcPara[8] = 0x30;
BuffDvcReal[9] = 0x44; //實(shí)時(shí)數(shù)據(jù)LENGTH 288(10) 120(16)
BuffDvcReal[10] = 0x31; //D120
BuffDvcReal[11] = 0x32;
BuffDvcReal[12] = 0x30;
BuffDvcReal[13] = 0x34; //CID2
BuffDvcReal[14] = 0x31;
BuffDvcPara[9] = 0x35; //參數(shù)LENGTH 86
BuffDvcPara[10] = 0x30; //5056
BuffDvcPara[11] = 0x35;
BuffDvcPara[12] = 0x36;
BuffDvcPara[13] = 0x34; //CID2
BuffDvcPara[14] = 0x36;
BuffDvcReal[15] = 0x30; //協(xié)議轉(zhuǎn)換器狀態(tài)
BuffDvcReal[16] = 0x30;
BuffDvcPara[15] = 0x30;
BuffDvcPara[16] = 0x30;
BuffDvcReal[17] = 0x30; //設(shè)備信息
BuffDvcReal[18] = 0x30;
BuffDvcReal[19] = 0x30;
BuffDvcReal[20] = 0x30;
BuffDvcPara[17] = 0x30;
BuffDvcPara[18] = 0x30;
BuffDvcPara[19] = 0x30;
BuffDvcPara[20] = 0x30;
os_wait(K_SIG,0,0); //等待收到數(shù)據(jù)信號(hào)
while(!FlagCOM1AllOut); //等待數(shù)據(jù)上傳完成,否則上傳過程中更改數(shù)據(jù)
FlagDataStored = 0;
switch(BuffCOM2[7]) //根據(jù)數(shù)據(jù)類型作相應(yīng)處理
{
case 'R': //實(shí)時(shí)數(shù)據(jù)
{
PtrS = BuffCOM2 + 17; //指向交流A相電壓
PtrD = BuffDvcReal + 95; //指向?qū)崟r(shí)數(shù)據(jù)段
for(i = 0; i < 4; i++) //轉(zhuǎn)換相電壓電流,int型轉(zhuǎn)float型
{
a_int.c[1] = *PtrS++;
a_int.c[0] = *PtrS++;
a_float.f = (float)(a_int.i);
Hex2Ascii(a_float.c[3],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[2],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[1],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[0],PtrD);
PtrD += 2;
}
PtrS += 12; //跳過12個(gè)保留字節(jié)
for(i = 0; i < 5; i++) //0: 市電一,1:市電二 1
{ //直流總輸出電壓 4
Hex2Ascii(*PtrS,PtrD);
PtrS++;
PtrD += 2;
}
a_int.c[1] = *PtrS++; //直流總輸出電流 2
a_int.c[0] = *PtrS++;
a_float.f = (float)(a_int.i);
Hex2Ascii(a_float.c[3],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[2],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[1],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[0],PtrD);
PtrD += 2;
for(i = 0; i < 5; i++) //環(huán)境溫度 1
{ //環(huán)境濕度 4
Hex2Ascii(*PtrS,PtrD);
PtrS++;
PtrD += 2;
}
PtrS += 16; //跳過16個(gè)保留字節(jié)
for(i = 0; i < 2; i++) //第1~15路負(fù)載分路熔斷器狀態(tài)
{
Hex2Ascii(*PtrS,PtrD);
PtrS++;
PtrD += 2;
}
PtrS += 4; //跳過4個(gè)保留字節(jié)
for(i = 0; i < 2; i++) //第1~2路蓄電池組分路充放電流 4
{
a_int.c[1] = *PtrS++;
a_int.c[0] = *PtrS++;
a_float.f = (float)(a_int.i);
Hex2Ascii(a_float.c[3],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[2],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[1],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[0],PtrD);
PtrD += 2;
}
for(i = 0; i < 3; i++)
{ //第1~2路蓄電池組溫度 2
Hex2Ascii(*PtrS,PtrD); //第1~2路蓄電池分路熔斷器狀態(tài) 1
PtrS++;
PtrD += 2;
}
SMR_NUM = *PtrS++; //取模塊個(gè)數(shù)
for(i = 0; i < SMR_NUM; i++) //存單體數(shù)據(jù)
{
Hex2Ascii(*PtrS,PtrD); //SMRn輸出電流
PtrS++;
PtrD += 2;
Hex2Ascii(*PtrS,PtrD); //SMRn主散熱器溫度
PtrS++;
PtrD += 2;
Hex2Ascii((uchar)((*PtrS)&0x01),PtrD); //開/關(guān)機(jī)
PtrD += 2;
Hex2Ascii((uchar)(((*PtrS)>>2)&0x01),PtrD); //限流
PtrD += 2;
PtrS++;
}
for(i = 0; i < ((15-SMR_NUM)*8); i++) //不存在的單體填0
{
*PtrD++ = 0x30;
}
SUM = 0; //計(jì)算CHKSUM
for(PtrD = BuffDvcReal + 1; PtrD < (BuffDvcReal + 301);PtrD++)
{
SUM += *PtrD;
}
SUM = SUM % 0xFFFF; //生成校驗(yàn)碼
SUM = ~SUM + 1;
Int2Ascii((uint)SUM, PtrD);
PtrD += 4;
*PtrD++ = 0x0D; //放結(jié)束符
*PtrD++ = 0x00;
*PtrD++ = 0x00;
break;
}//R
case 'P':
{
PtrS = BuffCOM2 + 75; //指向告警參數(shù)設(shè)置段
PtrD = BuffDvcPara + 21; //指向參數(shù)數(shù)據(jù)段
for(i = 0; i < 2; i++) //轉(zhuǎn)換交流高/低壓告警閾值,int型轉(zhuǎn)float型
{
AlarmParaChar[i*2] = *PtrS; //拷貝告警參數(shù)段
a_int.c[1] = *PtrS++;
AlarmParaChar[i*2+1] = *PtrS; //拷貝告警參數(shù)段
a_int.c[0] = *PtrS++;
a_float.f = (float)(a_int.i);
Hex2Ascii(a_float.c[3],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[2],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[1],PtrD);
PtrD += 2;
Hex2Ascii(a_float.c[0],PtrD);
PtrD += 2;
}
for(i = 0; i < 31; i++) //其余告警參數(shù)設(shè)置段
{
Hex2Ascii(*PtrS,PtrD);
AlarmParaChar[i+4] = *PtrS; //拷貝告警參數(shù)段
PtrS++;
PtrD += 2;
}
SUM = 0; //計(jì)算CHKSUM
for(PtrD = BuffDvcPara + 1; PtrD < (BuffDvcPara + 99);PtrD++)
{
SUM += *PtrD;
}
SUM = SUM % 0xFFFF; //生成校驗(yàn)碼
SUM = ~SUM + 1;
Int2Ascii((uint)SUM, PtrD);
PtrD += 4;
*PtrD++ = 0x0D; //放結(jié)束符
*PtrD++ = 0x00;
*PtrD++ = 0x00;
PtrD = BuffDvcReal + 21; //指向系統(tǒng)控制狀態(tài)
PtrS = BuffCOM2 + 233;
Hex2Ascii((uchar)(((*PtrS)>>2)&0x01),PtrD); //控制方式
PtrD += 2;
Hex2Ascii((uchar)(((*PtrS)>>1)&0x01),PtrD); //充電方式
//此處更改了實(shí)時(shí)數(shù)據(jù),重生成校驗(yàn)
SUM = 0; //計(jì)算CHKSUM
for(PtrD = BuffDvcReal + 1; PtrD < (BuffDvcReal + 301);PtrD++)
{
SUM += *PtrD;
}
SUM = SUM % 0xFFFF; //生成校驗(yàn)碼
SUM = ~SUM + 1;
Int2Ascii((uint)SUM, PtrD);
PtrD += 4;
*PtrD++ = 0x0D; //放結(jié)束符
*PtrD++ = 0x00;
*PtrD++ = 0x00;
break;
}
case 'A': //告警數(shù)據(jù)
{
PtrS = BuffCOM2 + 78; //指向模塊數(shù)
SMR_NUM = *PtrS; //存模塊數(shù)
PtrS = BuffCOM2 + 78 + SMR_NUM*3 + 1; //指向告警段
PtrD = BuffDvcReal + 25; //指向?qū)崟r(shí)數(shù)據(jù)告警段 共70字節(jié)
for(i = 0; i < 2; i++) //轉(zhuǎn)換AC_ALARM
{
Hex2Ascii(*PtrS,PtrD);
PtrS++;
PtrD += 2;
}
for(i = 0; i < SMR_NUM*2+1; i++) //存單體個(gè)數(shù)及單體告警
{
Hex2Ascii(*PtrS,PtrD);
PtrS++;
PtrD += 2;
}
for(i = 0; i < (15 - SMR_NUM); i++) //單體數(shù)不足15,其余保留
{
*PtrD++ = 0x30;
*PtrD++ = 0x30;
*PtrD++ = 0x30;
*PtrD++ = 0x30;
}
for(i = 0; i < 2; i++) //轉(zhuǎn)換DC_ALARM
{
Hex2Ascii(*PtrS,PtrD);
PtrS++;
PtrD += 2;
}
SUM = 0; //計(jì)算CHKSUM
for(PtrD = BuffDvcReal + 1; PtrD < (BuffDvcReal + 301);PtrD++)
{
SUM += *PtrD;
}
SUM = SUM % 0xFFFF; //生成校驗(yàn)碼
SUM = ~SUM + 1;
Int2Ascii((uint)SUM, PtrD);
PtrD += 4;
*PtrD++ = 0x0D; //放結(jié)束符
*PtrD++ = 0x00;
*PtrD++ = 0x00;
break;
}
}
FlagDataStored = 1;
os_switch_task();
}
}
/********************************************/
/** 命令處理任務(wù) **/
/********************************************/
void Task_Cmd(void) _task_ TASK_CMD
{
uchar NODE; //命令中的節(jié)點(diǎn)號(hào)
uchar p;
uint sum;
uchar i;
uchar xdata *data PtrD;
union
{
uint i;
uchar c[2];
}a_int;
union
{
float f;
uchar c[4];
}a_float;
while(1)
{
os_wait(K_SIG,0,0); //等待收到設(shè)置命令的信號(hào)
PtrD = BuffCmdSet; //每一次都拷貝命令字符,以免存于內(nèi)存中字符出錯(cuò)
i = 0;
p = 0;
sum = 0;
while(i<16) //要拷貝的字節(jié)數(shù)
{
*PtrD++ = ZXDUSET[i++];
}
if(Chk_Sum(BuffCOM1)) //對(duì)收到的命令作和校驗(yàn),以免命令有誤,導(dǎo)致錯(cuò)誤設(shè)置
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -