#region 字段
DispatcherTimer timer;
DispatcherTimer fontTimer;
public int Port = 0;
TestItemsModel ConfigModel = new TestItemsModel();
bool isFirstLoad = true;
string IP = string.Empty;
SocketServer server = null;
// 每次发送的数据长度
const int SEND_DATA_LEN_ONE_TIME = 256;
//字库在SPI Flash中的起始地址
const int FONT_BASE_ADDR_IN_SPI_FLASH = 0X00;
//IC卡数据长度
const int IC_CARD_DATA_LEN = 128;
const int IC_CARD_DRIVER_NAME_LEN = 12;
const int IC_CARD_GENDER_LEN = 2;
const int IC_CARD_IDENTIYT_NUMBER_LEN = 18;
const int IC_CARD_DRIVER_LICENSE_LEN = 18;
const int IC_CARD_DRIVER_LICENSE_LMT_LEN = 3;
const int IC_CARD_DRIVER_LEGAL_CODE_LEN = 18;
const int IC_CARD_RESERVED_STD_EXTEND_LEN = 56;
const int IC_CARD_CHECKSUM_LEN = 4;
const int ACK_TIME_OUT = 10;
const int ERASE_FLASH_ACK_TIME_OUT = 60;
private void OnReceiveMsg(string msg)
{
}
private void OnOpen(bool result)
{
if (result)
{
IndicatorLightColor = Brushes.Green;
BtnDes = "关闭";
}
else
{
IndicatorLightColor = Brushes.Red;
BtnDes = "打开";
}
bIsComPortOpen = result;
}
private bool CheckPortOpen()
{
if (!bIsComPortOpen)
{
ShowTip("端口未打开");
}
return bIsComPortOpen;
}
private void FontTimer_Tick(object sender, EventArgs e)
{
}
private bool CheckUpdate()
{
if (!bIsComPortOpen)
{
ShowTip("端口未打开");
return false;
}
if (bIsFlashErase)
{
ShowTip("还在擦除Flash...");
return false;
}
if (bIsFontLibInSending)
{
ShowTip("已经在字库升级中...");
return false;
}
if (string.IsNullOrEmpty(FilePath) || !File.Exists(FilePath))
{
ShowTip("字库文件路径无效!");
return false;
}
return true;
}
private void UpgradeFont(object o)
{
if (CheckUpdate())
{
dt = DateTime.Now;
fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
long m_FontLibFileLen = fs.Length;
if (m_FontLibFileLen == 0)
{
ShowTip("字库文件大小为:0");
return;
}
byte[] byteArray = new byte[m_FontLibFileLen];
fs.Read(byteArray, 0, (int)m_FontLibFileLen);
int m_CurSndPos = 0;
int m_CurSPI_Flash_Addr = 0;
int m_LastSndLen = 0;
if (m_FontLibFileLen < SEND_DATA_LEN_ONE_TIME)
{
m_CurSndPos = 0; // 发送的位置在m_pBuffer中的偏移
m_LastSndLen = (int)m_FontLibFileLen;
SendFontDataToCom((uint)m_CurSPI_Flash_Addr, byteArray, (uint)m_LastSndLen);
bIsFontLibInSending = true;
}
else
{
m_CurSndPos = 0;
m_LastSndLen = SEND_DATA_LEN_ONE_TIME;
SendFontDataToCom((uint)m_CurSPI_Flash_Addr, byteArray, (uint)m_LastSndLen);
bIsFontLibInSending = true;
}
int Range = (int)m_FontLibFileLen / (SEND_DATA_LEN_ONE_TIME); /* 文件长度 */
if (Range == 0) // 说明只需一步即可达到100%
{
Range = 1;
}
else if (Range > 0 && (m_FontLibFileLen % (SEND_DATA_LEN_ONE_TIME)) != 0)
{
Range += 1;
}
LinkMsg = "0%";
startTime = DateTime.Now;
endTime = DateTime.Now;
int AckCmdLen = 1;
byte[] AckCmdBuf = new byte[256];// [256] = { 0 };
/* 一直接收不到单片机回复,超时10秒退出 */
while (bIsFontLibInSending) /* 字库升级中 */
{
AckCmdLen = GetAckCmdBuf(AckCmdBuf, 256);
if (AckCmdLen != 0)
{
ParaseFontUpdateAck(AckCmdBuf, AckCmdLen);
startTime = DateTime.Now;
}
else
{
endTime = DateTime.Now;
TimeSpan timeSpan = endTime - startTime; // 两个CTime相减得到CTimeSpan
double nTSeconds = timeSpan.TotalSeconds; // 得到总的秒数
if (nTSeconds > ACK_TIME_OUT)
{
fontTimer.Stop();
bIsFontLibInSending = false;
m_CurSndPos = 0;
m_LastSndLen = 0;
m_CurSPI_Flash_Addr = 0;
TxtMsg = "字库升级超时失败!";
//SetStauesText("字库升级超时失败!");
}
}
}
}
}
private void ParaseFontUpdateAck(byte[] PAckCmdBuf, int Len)
{
byte[] TmpStatues = new byte[128];
string str = GetStrByArray(PAckCmdBuf);
if (str.Contains(CMD_WRITE_SPI_FLASH))
{
uint AckComWriteSPI_Flash_Addr = 0;
uint AckComWriteSPI_Flash_Len = 0;
/* 写入SPI Flash的地址 */
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[3] << 24);
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[4] << 16);
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[5] << 8);
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[6] << 0);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[7] << 24);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[8] << 16);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[9] << 8);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[10] << 0);
if ((AckComWriteSPI_Flash_Len == m_LastSndLen)
&& (AckComWriteSPI_Flash_Addr == m_CurSPI_Flash_Addr))
{
m_CurSndPos += m_LastSndLen; /* 已经发送的长度累增 */
m_CurSPI_Flash_Addr += m_LastSndLen; /* 当前写文件地址累增 */
if (m_CurSndPos < m_FontLibFileLen)
{
/* 发送剩余的 */
if (m_FontLibFileLen - m_CurSndPos <= SEND_DATA_LEN_ONE_TIME)
{
m_LastSndLen = m_FontLibFileLen - m_CurSndPos;
SendFontDataToCom(m_CurSPI_Flash_Addr, PAckCmdBuf, m_LastSndLen);
bIsFontLibInSending = true;
}
else
{
m_LastSndLen = SEND_DATA_LEN_ONE_TIME;
SendFontDataToCom(m_CurSPI_Flash_Addr, m_pBuffer, m_LastSndLen);
else if (m_CurSndPos == m_FontLibFileLen) /* 写完成 */
{
ProVal = (int)m_CurSndPos;
ProVisual = Visibility.Collapsed;
fontTimer.Stop();
bIsFontLibInSending = false;
m_CurSndPos = 0;
m_LastSndLen = 0;
m_CurSPI_Flash_Addr = 0;
endTime = System.DateTime.Now;
TimeSpan timeSpan = endTime - startTime; // 两个CTime相减得到CTimeSpan
double nTSeconds = timeSpan.TotalSeconds; // 得到总的秒数
TxtMsg = $"字库升级成功,共耗时:{nTSeconds}秒";
if (m_pBuffer != null)
{
m_pBuffer = null;
}
}
//CProgressCtrl *pProgressCtrl = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS_UPDA
}
else /* 写Flash 出错 !*/
{
//sprintf(TmpStatues, "MCU写地址出错:AckAddr:%x, AckLen:%d, Addr:%x, Len:%d Pos:%d",\
// AckComWriteSPI_Flash_Addr, AckComWriteSPI_Flash_Len, \
// m_CurSPI_Flash_Addr, m_LastSndLen, m_CurSndPos);
//SetStauesText(TmpStatues);
//SendFontDataToCom(m_CurSPI_Flash_Addr, m_pBuffer + m_CurSndPos, m_LastSndLen);
//bIsFontLibInSending = true;
}
}
}
private void CleaningMemory(object o)
{
if (CheckPortOpen())
{
if (true == bIsFlashErase)
{
ShowTip("正在清除");
return;
}
SendEraseFlashToCom(FONT_BASE_ADDR_IN_SPI_FLASH, 0);
}
}
void SendFontDataToCom(uint WriteAddr, byte[] pSndBuf, uint SndBufLen)
{
/* 发送:#WW + 地址(4字节) + 长度(4字节) ... 数据(长度不超过256) ... 校验和(#W,参与校验,共1字节) + OO# */
byte[] pTmpBuf = null;
uint CalcBufLen = 0;
byte[] pCalcAddr = new byte[512];// [512] = { 0 };
pTmpBuf = pCalcAddr; /* 计算校验和的起始地址 */
/* 命令头 */
pTmpBuf[CalcBufLen++] = (byte)'#';
pTmpBuf[CalcBufLen++] = (byte)'W';
pTmpBuf[CalcBufLen++] = (byte)'W';
/* 写入SPI Flash的地址 */
pTmpBuf[CalcBufLen++] =(byte) ((WriteAddr >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 24) & 0xff);
/* 写入数据的长度 */
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 24) & 0xff);
//真正发送的数据
Array.Copy(pSndBuf, 0, pTmpBuf, CalcBufLen, SndBufLen);
CalcBufLen += SndBufLen;
byte XorSum = XorCheckSum(pCalcAddr, CalcBufLen);
pTmpBuf[CalcBufLen++] = XorSum;
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'#';
try
{
SerialHelper.serialP.Write(pTmpBuf, 0, (int)CalcBufLen);
}
catch (Exception ex)
{
LogService.Instance.Debug("SendFontDataToCom:" + ex.Message);
TxtMsg = "写字库数据失败!";
}
}
void FontPath(object o)
{
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
ofd.DefaultExt = ".*";
ofd.Filter = "字库文件|*.DZK";
if (ofd.ShowDialog() == true)
{
FilePath = ofd.FileName;
}
}
//清除
void SendEraseFlashToCom(UInt32 ClearAddr, UInt32 ClearLen)
{
string msg = "正在擦除Flash...";
if (bIsFlashErase)
{
ShowTip(msg);
return;
}
TxtMsg = msg;
bIsFlashErase = true;
/* 发送:#WW + 地址(4字节) + 长度(4字节) ... 数据(长度不超过256) ... 校验和(#W,参与校验,共1字节) + OO# */
byte[] pTmpBuf = null;
byte[] pCalcAddr = null;
uint CalcBufLen = 0;
pTmpBuf = new byte[512];
pCalcAddr = pTmpBuf; /* 计算校验和的起始地址 */
/* 命令头 */
pTmpBuf[CalcBufLen++] = (byte)'#';
pTmpBuf[CalcBufLen++] = (byte)'C';
pTmpBuf[CalcBufLen++] = (byte)'L';
pTmpBuf[CalcBufLen++] = (byte)'R';
/* 写入SPI Flash的地址 */
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 24) & 0xff);
/* 写入数据的长度 */
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 24) & 0xff);
byte XorSum = XorCheckSum(pCalcAddr, CalcBufLen);
pTmpBuf[CalcBufLen++] = XorSum;
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'#';
SerialHelper.serialP.Write(pTmpBuf, 0, (int)CalcBufLen);
}
byte Hex2BCD(byte Val)
{
byte t_h = 0, t_l = 0;
byte temp = 0;
t_h = (byte)(Val / 10);
t_l = (byte)(Val % 10);
temp = (byte)((t_h << 4) + t_l);
return temp;
}
byte BCD2Hex(byte Val)
{
return (byte)(((Val >> 4) & 0xf) * 10 + (Val & 0xf));
}
byte XorCheckSum(byte[] pBuff, uint Len)
{
byte CheckSum = 0;
if (null == pBuff)
{
return CheckSum;
}
for (uint i = 0; i < Len; i++)
{
CheckSum ^= pBuff[i]; //*(pBuff + i);
}
return CheckSum;
}
byte AndCheckSum(byte[] pBuff, uint Len)
{
byte CheckSum = 0;
if (null == pBuff)
{
return CheckSum;
}
for (uint i = 0; i < Len; i++)
{
CheckSum += pBuff[i]; //*(pBuff + i);
}
return CheckSum;
}
#region 清理存储器
int GetAckCmdBuf(byte[] PAckCmdBuf, int Len)
{
int len, Idx;
int AckCmdLen = 0; // 单片机返回的应答个数
byte[] RxDataBuf = new byte[COM_READ_BUF_LEN];// [COM_READ_BUF_LEN] = { 0 }; // 串口读取的缓存
int TotalRcvLen = 0; // 保存当前缓存的个数
/* 以下你可以根据自己的通信协议加入处理代码 */
len = SerialHelper.serialP.Read(PAckCmdBuf, 0, COM_READ_BUF_LEN - TotalRcvLen); //pCtrlComm->Read(RxDataBuf + TotalRcvLen, COM_READ_BUF_LEN - TotalRcvLen);
if (len > 0)
{
TotalRcvLen += len; // 长度累加
}
for (Idx = 0; Idx < TotalRcvLen; Idx++)
{
if (('O' == RxDataBuf[Idx])
&& ('O' == RxDataBuf[Idx + 1])
&& ('#' == RxDataBuf[Idx + 2]))
{
AckCmdLen = (int)Idx + 3;
TotalRcvLen -= (int)AckCmdLen; /* 数据向前移动 */
byte[] pTmpBuf = new byte[RxDataBuf.Length + AckCmdLen];
if (Len >= AckCmdLen)
{
Array.Copy(RxDataBuf, 0, pTmpBuf, 0, RxDataBuf.Length + AckCmdLen);
}
else
{
LinkMsg = "超出缓存限制!";
AckCmdLen = 0;
}
for (int TmpIdx = 0; TmpIdx < TotalRcvLen; TmpIdx++)
{
RxDataBuf[TmpIdx] = pTmpBuf[TmpIdx];
}
break;
}
}
return AckCmdLen;
}
//打开串口
private void OpenPort(object model)
{
SerialHelper.OpenSerialPort(SelectSerialPort.Name, Convert.ToInt32(SelectBaudRate.Name), Convert.ToInt32(SelectDataBits.Name),
Convert.ToInt32(SelectStopBit.Name), Convert.ToInt32(SelectCheckBit.Value));
}
private void HandleTest(object model)
{
TestItemDataModel mod = (TestItemDataModel)model;
SendType(Convert.ToInt32(mod.TestItemDes));
mod.SendStatus = "已手动发送";
}