?? comm.c
字號:
#include <common.h>
#include <head.h>
BYTE ToHexchar( BYTE a )
{
a &= 0x0f;
if ( a < 10 )
return a + '0';
return a - 10 + 'A';
}
BYTE HexCharToInt( BYTE c )
{
if ( ((c) >= '0') && ((c) <= '9') )
return (c) - '0';
if ( ((c) >= 'A') && ((c) <= 'F') )
return (c) - 'A' + 10;
if ( ((c) >= 'a') && ((c) <= 'f') )
return (c) - 'a' + 10;
return 0;
}
BYTE TwoHexCharToInt( BYTE c1, BYTE c2 )
{
return (HexCharToInt( c1 ) << 4) | HexCharToInt( c2 );
}
BYTE CalCheckCode( u_char idata *buf, BYTE len )
{
BYTE i, ret;
ret = 0;
for( i = 0; i < len; i++ )
ret += buf[i];
return ret;
}
void EnableSerialComm( void )
{
u_char tmp;
// 串行通訊初始化
SCON = 0x40; // 模式1, 允許接收
T2CON = 0x30; // RXD TXD 使用T2
TR2 = 0;
// 波特率公式:
// baud = f/2/16/(65536-(RCAP2H,RCAP2L))
// f = 40M
// 1200: 0xfbee
// 2400: 0xfdf7
// 4800: 0xfefb
// 9600: 0xff7d
#if (SCH_PCB_VERSION == 1)
tmp = ((BYTE)BAUD_RATE_H*2) + (BYTE)BAUD_RATE_L;
#endif
#if (SCH_PCB_VERSION == 2)
tmp = CommBaudRateConst[P1>>6];
#endif
RCAP2H = CommBaudRateConst[tmp] >> 8;
RCAP2L = CommBaudRateConst[tmp];
TH2 = RCAP2H;
TL2 = RCAP2L;
TR2 = 1;
RE = RECV;
REN = 1; // 啟動接收
ES = 1; // 允許中斷
EA = 1;
}
void FillHalfByteToCommBuf( BYTE cc )
{
CommBuf.MsgData[CommBuf.MsgCnt++] = ToHexchar( cc );
}
void FillByteToCommBuf( BYTE cc )
{
CommBuf.MsgData[CommBuf.MsgCnt++] = ToHexchar( cc >> 4 );
CommBuf.MsgData[CommBuf.MsgCnt++] = ToHexchar( cc );
}
void CommandProcessExtra( void )
{
FillByteToCommBuf( CalCheckCode( CommBuf.MsgData, CommBuf.MsgCnt ) );
CommBuf.MsgData[CommBuf.MsgCnt++] = END_CHAR;
RE = SEND;
BufUseFlag = 1;
CommBuf.SendIdx = 0;
TxdStartFlag = 1;
RecvOkFlag = 0;
TI = 1;
}
void ReadCommand( void )
{
BYTE idx, tmp;
BYTE idata *ptr;
DWORD dtmp;
CommBuf.MsgData[0] = NO_ACK_CHAR;
CommBuf.MsgCnt = CMD_HEAD_LEN;
idx = CommBuf.MsgData[2] - '1';
switch ( CommBuf.MsgData[4] )
{
case READ_MOTOR_STATUS: // 讀電機狀態
if ( idx >= MAX_MOTOR_NUM )
break;
// 正確回答
CommBuf.MsgData[0] = ACK_CHAR;
// 填充電機方向
FillHalfByteToCommBuf( MotorStatus[idx].Dir & DIR_FLAG_MASK );
// 填充電機狀態
tmp = MotorStatus[idx].Status & ZERO_RECORD_MASK ? 2 : 0;
tmp |= MotorStatus[idx].TotalPluseCnt ? 0 : 1;
FillHalfByteToCommBuf( tmp );
// 填充電機脈沖計數
dtmp = MotorStatus[idx].TotalPluseCnt >> 1;
ptr = (BYTE idata*)&dtmp + MSB;
if ( *ptr & 0x40 )
*ptr |= 0x80;
FillByteToCommBuf( *ptr );
ptr++;
FillByteToCommBuf( *ptr );
ptr++;
FillByteToCommBuf( *ptr );
ptr++;
FillByteToCommBuf( *ptr );
break;
case READ_VERSION: // 讀軟件版本號
CommBuf.MsgData[0] = ACK_CHAR;
FillByteToCommBuf( Version );
break;
}
CommandProcessExtra( );
}
void WriteCommand( void )
{
BYTE idx;
BYTE idata *ptr;
WORD tmp;
CommBuf.MsgData[0] = NO_ACK_CHAR;
CommBuf.MsgCnt = CMD_HEAD_LEN;
idx = CommBuf.MsgData[2] - '1';
switch ( CommBuf.MsgData[4] )
{
case WRITE_MOTOR_DATA: // 寫電機數據
if ( idx >= MAX_MOTOR_NUM )
break;
// 已運行
if ( MotorStatus[idx].Status & MOTOR_RUN_MASK )
break;
// 保留零點記錄標志,其余清除
MotorStatus[idx].Status &= ZERO_RECORD_MASK;
// 方向
MotorStatus[idx].Dir = HexCharToInt( CommBuf.MsgData[5] ) & DIR_FLAG_MASK;
// 零位檢測
if ( (HexCharToInt( CommBuf.MsgData[6] ) & 0x03) == 0x03 )
break;
MotorStatus[idx].Status |= HexCharToInt( CommBuf.MsgData[6] ) & 0x01 ? ZERO_CHECK_MASK : 0;
MotorStatus[idx].Status |= HexCharToInt( CommBuf.MsgData[6] ) & 0x02 ? WORK_ZERO_CHECK_MASK : 0;
// 升降頻, 轉換時將頻率計數值放低4位,頻率增量放高4位
MotorStatus[idx].UpDwon = TwoHexCharToInt( CommBuf.MsgData[8], CommBuf.MsgData[7] );
if ( !(MotorStatus[idx].UpDwon & 0xf0) || !(MotorStatus[idx].UpDwon & 0x0f) )
MotorStatus[idx].UpDwon = 0;
// 頻率
MotorStatus[idx].SetFreq = (TwoHexCharToInt( CommBuf.MsgData[9], CommBuf.MsgData[10] )<<8)
| TwoHexCharToInt( CommBuf.MsgData[11], CommBuf.MsgData[12] );
if ( MotorStatus[idx].SetFreq > MAX_FREQ_VAL )
MotorStatus[idx].SetFreq = MAX_FREQ_VAL;
if ( MotorStatus[idx].SetFreq < START_FREQ )
MotorStatus[idx].SetFreq = START_FREQ;
// 脈沖數量
ptr = (BYTE idata*)&MotorStatus[idx].CmdPluseNum + MSB;
*ptr = TwoHexCharToInt( CommBuf.MsgData[13], CommBuf.MsgData[14] );
ptr++;
*ptr = TwoHexCharToInt( CommBuf.MsgData[15], CommBuf.MsgData[16] );
ptr++;
*ptr = TwoHexCharToInt( CommBuf.MsgData[17], CommBuf.MsgData[18] );
ptr++;
*ptr = TwoHexCharToInt( CommBuf.MsgData[19], CommBuf.MsgData[20] );
// 回零命令
if ( MotorStatus[idx].Status & ZERO_CHECK_MASK )
{
// 已在零點
if ( (MotorStatus[idx].TotalPluseCnt == 0) && (MotorStatus[idx].Status & ZERO_RECORD_MASK) )
{
// 保留零點記錄
MotorStatus[idx].Status &= ZERO_RECORD_MASK;
MotorStatus[idx].Dir = 0;
}
}
CommBuf.MsgData[0] = ACK_CHAR;
break;
case WRITE_MOTOR_FREQ: // 改變電機頻率
if ( idx >= MAX_MOTOR_NUM )
break;
// 已啟動
if ( MotorStatus[idx].Status & MOTOR_RUN_MASK )
{
// 不是升降速都可以改變頻率
if ( !MotorStatus[idx].UpDwon )
{
tmp = (TwoHexCharToInt( CommBuf.MsgData[5], CommBuf.MsgData[6] ) << 8)
| TwoHexCharToInt( CommBuf.MsgData[7], CommBuf.MsgData[8] );
if ( tmp > MAX_FREQ_VAL )
tmp = MAX_FREQ_VAL;
if ( tmp < START_FREQ )
tmp = START_FREQ;
MotorStatus[idx].SetFreq = tmp;
CommBuf.MsgData[0] = ACK_CHAR;
}
}
break;
case WRITE_MOTOR_STOP_CMD: // 電機停止
// 停止所有電機
if ( idx == 0xff )
{
if ( Timer[0].MotorIdx )
MotorStatus[Timer[0].MotorIdx-1].Status |= MOTOR_STOP_CMD_MASK;
if ( Timer[1].MotorIdx )
MotorStatus[Timer[1].MotorIdx-1].Status |= MOTOR_STOP_CMD_MASK;
CommBuf.MsgData[0] = ACK_CHAR;
}
else if ( idx < MAX_MOTOR_NUM )
{
MotorStatus[idx].Status |= MOTOR_STOP_CMD_MASK;
CommBuf.MsgData[0] = ACK_CHAR;
}
break;
case WRITE_CLR_PLUSE_CNT:
// 清除所有電機頻率
if ( idx == 0xff )
{
for( idx = 0; idx < MAX_MOTOR_NUM; idx++ )
{
MotorStatus[idx].TotalPluseCnt = 0;
}
CommBuf.MsgData[0] = ACK_CHAR;
}
else if ( idx < MAX_MOTOR_NUM )
{
MotorStatus[idx].TotalPluseCnt = 0;
CommBuf.MsgData[0] = ACK_CHAR;
}
break;
}
CommandProcessExtra( );
}
void RecvMsgProce( void )
{
u_char tmp;
if ( !RecvOkFlag )
return;
// 模塊地址
tmp = HexCharToInt(CommBuf.MsgData[1]);
if ( tmp && (tmp != (P1 & 0x0f) ) )
return;
// 檢查校驗碼
if ( TwoHexCharToInt( CommBuf.MsgData[CommBuf.MsgCnt-3], CommBuf.MsgData[CommBuf.MsgCnt-2] )
!= CalCheckCode( CommBuf.MsgData, CommBuf.MsgCnt-3 ) )
{
CommBuf.MsgData[0] = NO_ACK_CHAR;
CommBuf.MsgCnt = CMD_HEAD_LEN;
CommandProcessExtra( );
return;
}
switch( CommBuf.MsgData[3] )
{
case 'R':
ReadCommand( );
return;
case 'W':
WriteCommand( );
return;
default:
CommBuf.MsgData[0] = NO_ACK_CHAR;
CommBuf.MsgCnt = CMD_HEAD_LEN;
CommandProcessExtra( );
break;
}
}
// 注意:中斷程序中不能調用帶參數子程序
void SerialComm( void ) interrupt 4 using 1
{
if ( RI )
{
RI = 0;
CommChar = SBUF;
if ( (CommChar >= 'a') && (CommChar <= 'z') )
CommChar = CommChar - 'a' + 'A';
if ( !RecvOkFlag && !TxdStartFlag )
{
switch( CommBuf.MsgCnt )
{
case 0:
if ( CommChar == START_CHAR )
{
CommBuf.MsgData[0] = CommChar;
CommBuf.MsgCnt = 1;
}
break;
default:
if ( CommChar == START_CHAR )
{
CommBuf.MsgData[0] = CommChar;
CommBuf.MsgCnt = 1;
break;
}
CommBuf.MsgData[CommBuf.MsgCnt] = CommChar;
CommBuf.MsgCnt++;
if ( CommBuf.MsgCnt == MAX_COMM_BUF_SIZE )
CommBuf.MsgCnt = 0;
if ( CommChar == END_CHAR )
RecvOkFlag = 1;
break;
}
}
}
if ( TI )
{
TI = 0;
if ( (CommBuf.SendIdx < CommBuf.MsgCnt) && TxdStartFlag )
{
SBUF = CommBuf.MsgData[CommBuf.SendIdx];
CommBuf.SendIdx++;
}
else
{
RE = RECV;
CommBuf.MsgCnt = 0;
CommBuf.SendIdx = 0;
TxdStartFlag = 0;
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -