?? mss_spi.c
字號:
///////////////////////////////////////////////////////////////////////////////
//
// Hopinfo Copyright.
//
// www.chinahopeinfo.com.cn
//
// 2005.04.26
//
// 審閱:黃平生
//
// 指紋模塊(MSS)和HOST通信采用SPI通信接口,在該設計中8051作為HOST端,工作模式為
// 主設備,指紋模塊工作模式為負設備,接收/發送的時鐘由8051提供,通信速率由8051處
// 理速度決定,MSS在時鐘的下降沿對齊要發送/接收數據位的中間,MSS在時鐘的下降沿有
// 效。
// 基本通信原理是:當MSS有數據發送時向HOST申請中斷,置MSS_INT為低電平,HOST決定
// 是否接收數據;HOST有數據要發送時,直接向MSS發送,因為HOST為主設備。
//
///////////////////////////////////////////////////////////////////////////////
#include "Global.h"
///////////////////////////////////////////////////////////////////////////////
// 內部存儲區變量 0~256
// 全局變量定義
extern data uchar checksum; // 校驗和
extern data uchar testchecksum; // 接收到的校驗和
extern data uchar key; // 鍵盤值
extern data uchar MSG; // 信息號
extern data uchar CSH; // 校驗和ASC高字節
extern data uchar CSL; // 校驗和ASC低字節
extern data uint SOHptr; // SPI緩沖區頭指針
extern data uint ETXptr; // ETX位置
extern data uint CommandLen; // 命令體長度
extern data uchar pulse; // 蜂鳴次數
extern data uint time_out; // 通用超時定時器
extern data char groupclass; // 用戶分組信息
extern data char User_id[6]; // 用戶編號0~65534
extern data uchar cur_time[15]; // 系統當前時間顯示存儲區 XXXX年XX月XX日XX時XX分XX秒星期X
extern data uint index; // 數據索引
extern data uint trans_ctr; // 發送數據指針
extern data uint trans_size; // 發送數據大小
extern bdata bit reverse; // LCD底色顯示控制
extern bdata bit HandwareErr; // 指紋模塊工作狀態
extern bdata bit managemode; // 管理員比對操作
// 全局臨時變量
extern idata char Start_user_id[6]; // 開始用戶編號
extern idata char End_user_id[6]; // 終止用戶編號
extern idata char Start_time[5]; // 開始時間
extern idata char End_time[5]; // 終止時間
extern idata char Security_level; // 安全等級0~4
extern idata char ManageClass; // 管理分類'M'管理用戶'G'普通用戶
extern idata char AppClass; // 應用分類'F'指紋用戶'P'密碼用戶
extern idata char Password[7]; // 密碼
extern idata char wieformat; // 韋根通信格式
///////////////////////////////////////////////////////////////////////////////
// 內部存儲區變量 256~1280
// 全局變量定義
extern xdata uchar SPIbuf[BUFSIZE]; // SPI和串行通信緩沖區
extern xdata uchar trans_buf[TRANSBUFSIZE];// 發送數據緩沖區
///////////////////////////////////////////////////////////////////////////////
// 程序存儲區變量 0~32K
// SPI通信顯示信息
code char Putf[] =" -按下手指- ";
code char Liftf[] =" -抬起手指- ";
code char success[] =" <<成功>> ";
code char failure[] =" <<失敗>> ";
code char welcome[] ="歡迎";
code char // 指紋模塊返回信息顯示
disp_err[12][12]=
{
" -沒有手指- ",
" -圖像太差- ",
" -手指不同- ",
" -手指太偏- ",
" -不能注冊- ",
" -已 注 冊- ",
" -沒有注冊- ",
" -比對失敗- ",
" -沒有空間- ",
" -不能使用- ",
" -系統復位- ",
" -不能通信- ",
};
///////////////////////////////////////////////////////////////////////////////
// 十毫秒延時函數,累積系統若干條指令
///////////////////////////////////////////////////////////////////////////////
void Wait10ms()
{
idata uint i;
for(i=0;i<3600;i++){}
}
///////////////////////////////////////////////////////////////////////////////
// 一秒鐘延時函數,累積10ms計數
///////////////////////////////////////////////////////////////////////////////
void OneSecond()
{
idata uchar i;
for(i=0;i<100;i++)
{
Wait10ms();
}
}
///////////////////////////////////////////////////////////////////////////////
// MSS和HOST通信包結構采用標準不定長信息包結構
//
// 信息包結構定義如下:
// SOH 地址4字節ASC碼 信息號1字節ASC碼 STX 命令體ASC碼3~ ETX 校驗2字節AC碼 EOT
// 0B 1B 2B 3B 4B 5B 6B NB N+1B N+2B N+3B N+4B
// 01H 30H 31H 30H 32H 30H~39H 02H 03H 04H
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// SPI_Transfer
// 使用SPI 協議同時發送<SPI_byte>
// SCK 空閑為高 在SCK 下降時位鎖存
//
// 此程序的時序如下
//
// 參數 時鐘數
// MOSI 有效到SCK 下降沿 6
// SCK 上升到 MISO 鎖存 2
// SCK 下降到 MOSI 有效 7
// SCK 高時間 13
// SCK 低時間 8
///////////////////////////////////////////////////////////////////////////////
char SPItrans(char SPI_byte)
{
idata uchar i;
MSS=0; // SPI選通
for(i=8;i>0;i--)
{
MOSI=SPI_byte&0x80; // 移下一位到 MSB
SPI_byte=SPI_byte<<1;
SCK=0; // 時鐘下降沿接收
SPI_byte|=MISO;
SCK=1; // 時鐘上升沿發送
}
MSS=1;
key=0;
return(SPI_byte);
}
///////////////////////////////////////////////////////////////////////////////
// 生成信息包的信息號'0~'9'
///////////////////////////////////////////////////////////////////////////////
void NewMsgNum()
{
MSG++;
if(MSG>0x39){MSG=0x30;}
}
///////////////////////////////////////////////////////////////////////////////
// 將16進制數據校驗和轉換為ASC碼校驗和,以便發送
///////////////////////////////////////////////////////////////////////////////
void CS_ASCII()
{
checksum=~checksum+1; // 校驗和求補
CSH=((checksum>>4)&0x0f)+0x30;
if(CSH>0x39)
{CSH+=0x07;}
CSL=(checksum&0x0f)+0x30;
if(CSL>0x39)
{CSL+=0x07;} // 校驗和轉換成兩位ASCII碼 高位CSH 低位 CSL
}
///////////////////////////////////////////////////////////////////////////////
// 將ASC碼校驗和轉換為16進制校驗和,以便比較
///////////////////////////////////////////////////////////////////////////////
void HEX_CS()
{
CSH-=0x30;
if(CSH>9){CSH-=0x07;}
CSL-=0x30;
if(CSL>9){CSL-=0x07;}
checksum=((CSH<<4)&0xf0)+CSL;
}
///////////////////////////////////////////////////////////////////////////////
// 將ASC碼數據轉換為16進制數據
///////////////////////////////////////////////////////////////////////////////
uchar Asc_hex(char alpha)
{
alpha=alpha-0x30;
if(alpha>0x09)alpha=alpha-0x07;
return alpha;
}
///////////////////////////////////////////////////////////////////////////////
// 將16進制數據轉換為ASC碼數據
///////////////////////////////////////////////////////////////////////////////
char Hex_ascii(uchar h)
{
h=h+0x30;
if(h>0x39)
{h+=0x07;}
return h;
}
///////////////////////////////////////////////////////////////////////////////
// 組織發送命令頭
///////////////////////////////////////////////////////////////////////////////
void Preamble()
{
Rstwdt(); // 喂狗
SPItrans(SOH);
SPItrans('0');
SPItrans('1');
SPItrans('0');
SPItrans('2');
SPItrans(MSG);
checksum=MSG;
SPItrans(STX);
checksum+=0xc6; // 校驗和
Rstwdt(); // 喂狗
}
///////////////////////////////////////////////////////////////////////////////
// 組織發送命令體,命令不同,對應的命令體內容和長度也不相同
///////////////////////////////////////////////////////////////////////////////
void Command()
{
idata uchar i;
for(i=0;i<CommandLen;i++)
{
Rstwdt(); // 喂狗
SPItrans(SPIbuf[i]); // 發送命令體
checksum+=SPIbuf[i]; // 校驗和
}
}
///////////////////////////////////////////////////////////////////////////////
// 組織發送命令尾
///////////////////////////////////////////////////////////////////////////////
void Postamble()
{
Rstwdt(); // 喂狗
SPItrans(ETX);
checksum+=ETX; // 校驗和
CS_ASCII();
SPItrans(CSH);
SPItrans(CSL);
SPItrans(EOT);
Rstwdt(); // 喂狗
}
///////////////////////////////////////////////////////////////////////////////
// 組織發送整個命令包
///////////////////////////////////////////////////////////////////////////////
void SendMsg()
{
Preamble(); // SPI前導數據結構
Command(); // 命令體
Postamble(); // SPI校驗和結束符
}
///////////////////////////////////////////////////////////////////////////////
// 向MSS發送"ACK"或"NAK"
///////////////////////////////////////////////////////////////////////////////
void SendNACK(uchar NACK)
{
Rstwdt(); // 喂狗
SPItrans(SOH);
SPItrans('0');
SPItrans('1');
SPItrans('0');
SPItrans('2');
SPItrans(MSG);
SPItrans(NACK);
SPItrans(EOT);
Rstwdt(); // 喂狗
}
///////////////////////////////////////////////////////////////////////////////
// HOST接收MSS數據,按照標準信息包進行檢查
// 如果接收錯誤向MSS發送NAK,如果3次發送錯誤返回失敗
// 如果接收成功向MSS發送ACK
// 如果15秒內不能檢測到MSS的數據發送中斷,那么MSS可能故障
///////////////////////////////////////////////////////////////////////////////
bit SPIReceive()
{
idata uchar temp; // 臨時變量
idata uchar NAKcounter; // NAK計數器
idata uint R_BUF; // 接收緩沖區指針
idata uint i; // 計數器
for(R_BUF=0; R_BUF<BUFSIZE; R_BUF++)
SPIbuf[R_BUF]=0; // 接收緩沖區清零
time_out=1500; // 如果15秒內MSS無數據返回退出錯誤
do
{
Rstwdt(); // 喂狗
if(time_out==0)
{
HandwareErr=ERROR; // MSS可能故障
time_out=0;
return ERROR; // 返回
}
}while(MSS_INT); // 檢測MSS通信中斷
NAKcounter=3; // NAK計數器
do
{
R_BUF=0; // 接收緩沖區計數
SOHptr=0;
ETXptr=0;
MSS=1;
time_out=1200; // 12000msSPI數據傳輸一個包時間
do
{
do
{
Rstwdt(); // 喂狗
if(time_out==0)
{
HandwareErr=ERROR; // MSS可能故障
return ERROR; // 返回
}
temp=SPItrans(0); // 接收數據
}while(temp==0);
SPIbuf[R_BUF++]=temp; // 非零數據存入緩沖區
if(R_BUF>BUFSIZE)break; // 緩沖區滿
if(time_out==0)
{
HandwareErr=ERROR; // MSS可能故障
return ERROR; // 返回
}
}while(temp!=EOT); // 通信結束
i=0;
do
{
if(SPIbuf[i]==SOH) // 定位數據頭
{
SOHptr=i;
break;
}
i++;
Rstwdt(); // 喂狗
}while(i<R_BUF);
if(SOHptr==R_BUF)
{
goto SPIerr; // 緩沖區滿,數據錯誤
}
else if(SPIbuf[SOHptr+6]!=STX)
{
goto SPIerr; // STX錯誤
}
else if(SPIbuf[R_BUF-4]!=ETX)
{
goto SPIerr; // ETX錯誤
}
else
{
MSG=SPIbuf[SOHptr+5]; // 保存信息號
ETXptr=R_BUF-4;
Rstwdt(); // 喂狗
CSH=SPIbuf[ETXptr+1];
CSL=SPIbuf[ETXptr+2];
HEX_CS();
testchecksum=0;
for(i=0;i<ETXptr-SOHptr+1;i++) // 計算校驗和
{
Rstwdt(); // 喂狗
testchecksum+=SPIbuf[SOHptr+i];
}
temp=testchecksum+checksum;
temp=temp&0xff;
if(temp!=0)
goto SPIerr; // 校驗
SendNACK(ACK); // 發送 ACK
return OK;
}
SPIerr:
Rstwdt();
SendNACK(NAK); // 發送 NAK 重新接收DSP數據
NAKcounter--;
}while(NAKcounter>0);
HandwareErr=ERROR; // MSS可能故障
return ERROR;
}
///////////////////////////////////////////////////////////////////////////////
// HOST接收MSS發送的NAK或ACK數據,按照標準信息包進行檢查
// 如果2秒內不能檢測到MSS的數據發送中斷,那么MSS可能故障
///////////////////////////////////////////////////////////////////////////////
uchar ACKReceive()
{
idata uchar temp; // 臨時變量
idata uchar R_BUF; // 接收緩沖區計數
for(R_BUF=0; R_BUF<255; R_BUF++)
SPIbuf[R_BUF]=0; // 接收緩沖區清零
time_out=200; // 如果2秒內MSS無數據返回退出錯誤
do
{
Rstwdt(); // 喂狗
if(time_out==0)
{
HandwareErr=ERROR; // MSS可能故障
time_out=0;
return ERROR; // 返回
}
}while(MSS_INT); // 檢測MSS通信中斷
R_BUF=0;
time_out=50; // 500ms接收SPI數據包
do
{
do
{
temp=SPItrans(0); // 接收SPI字節
if(time_out==0)
{
HandwareErr=ERROR; // MSS可能故障
return ERROR; // 返回
}
}while(temp==0); // 空字符不接收
SPIbuf[R_BUF++]=temp;
if(R_BUF>20)
{
break; // ACK或NAK命令長度不超過20
}
if(time_out==0)
{
HandwareErr=ERROR; // MSS可能故障
return ERROR; // 返回
}
}while(temp!=EOT); // 接收到EOT結束符
if(SPIbuf[R_BUF-2]==ACK)
{
return ACK; // 返回ACK
}
else if(SPIbuf[R_BUF-2]==NAK)
{
return NAK; // 返回NAK
}
HandwareErr=ERROR; // MSS可能故障
return ERROR;
}
///////////////////////////////////////////////////////////////////////////////
// 顯示公共錯誤信息
///////////////////////////////////////////////////////////////////////////////
void disperr(uchar id)
{
Rstwdt(); // 喂狗
GLCD_Locate(16,32);
reverse=1;
dprintf(failure,12); // 失敗
reverse=0;
GLCD_Locate(0,48);
dprintf(" ",15); // 清行
GLCD_Locate(16,48);
if(id<'A')
{
dprintf(disp_err[id-0x30],12); // 顯示正常錯誤信息
}
else
{
if(id<='F')
{
HandwareErr=ERROR; // MSS不能正常工作
dprintf(disp_err[10],12); // 顯示模塊復位
TURN_ON();
}
else
{
dprintf(disp_err[11],12); // 顯示ACK錯誤
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -