id="cproIframe_u1788635_2" width="336" height="280" src="http://pos.baidu.com/acom?adn=3&at=231&aurl=&cad=1&ccd=24&cec=UTF-8&cfv=13&ch=0&col=zh-CN&conBW=0&conOP=1&cpa=1&dai=2&dis=0<r=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DltIXPKMjvyCpYbh5HRH4xjvwOKyUIQtwuPEiMsWMv8JXMxoUUfh4v8tfiEDxqXIQ%26wd%3D%26eqid%3Daa7a7de2000169570000000555a36390<u=http%3A%2F%2Fwww.xuebuyuan.com%2F1491988.html&lu_161=0&lunum=6&n=83099053_cpr&pcs=1360x667&pis=10000x10000&ps=326x906&psr=1360x768&pss=1360x346&qn=bfa1d8d4646b99f1&rad=&rsi0=336&rsi1=280&rsi5=4&rss0=%23FFFFFF&rss1=%23FFFFFF&rss2=%230000ff&rss3=%23444444&rss4=%23008000&rss5=&rss6=%23e10900&rss7=&scale=&skin=tabcloud_skin_3&stid=5&td_id=1788635&titFF=%E5%AE%8B%E4%BD%93&titFS=12&titTA=left&tn=text_default_336_280&tpr=1436771383935&ts=1&version=2.0&xuanting=0&dtm=BAIDU_DUP2_SETJSONADSLOT&dc=2&di=u1788635&ti=wince%E4%B8%8BSE955%E6%BF%80%E5%85%89%E5%A4%B4%2CSE655%E7%BA%A2%E5%85%89%E5%A4%B4%E7%9A%84%E9%85%8D%E7%BD%AE%20%7C%20%E5%AD%A6%E6%AD%A5%E5%9B%AD&tt=1436771383901.211.269.269" align="center,center" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="margin: 0px; padding: 0px; border-width: 0px; background: transparent;">
网上搜索一下,发现关于SE955和SE655扫描头的,除了大量的供应商的广告和一本英文datasheet之外,相关资料少之又少。对于做扫描头的工作的,没有一丝的帮助。没法,这就是国内的现状,很多时候都是信息封闭,不愿共享出来。
通过扫描头的datasheet可以知道,扫描头的参数设置有两种方式,第一种是扫描datasheet给出的设置条码,比如扫描datasheet给出的code-93的enable条码,这样扫描头就可以支持code-93类型的条码了(出厂时默认是不支持的),如果扫一次code-93的disable条码,扫描头就不再支持code-93类型的条码。
第二种方式是通过串口来配置条码。wince下的配置如下:其他平台类似,只要读写相应的串口即可;
首先扫描头要上电,通过上层应用给出的接口,可以设置扫描头上电。上电以后就可以对其进行操作了。出厂默认为:low power模式,所以直接给扫描头发送命令很多是不能执行的,返回的只有一条错误码:0x05 0xD1 0x00 0x00 0x01 0xFF 0x29
//必须使用字符数组,否则不能正确操作
static char custom_default[]={0x05,0x12,0x04,0x00,0x00,0xFF,0xE5};
static char param_default[]={0x04,0xC8,0x04,0x00,0xFF,0x30};//factory default value
static char disable_all_code_type[]={0xC9,0x04,0x08,0x00};
static char sleep_mode[]={0xEB,0x04,0x00};
static char wakeup[]={0x00};
static char cmd_ack[]={0x04,0xD0,0x00,0x00,0xFF,0x2C};
static char cmd_nak[]={0x05,0xD1,0x00,0x00,0x01,0xFF,0x29};
static struct _SCANNER_MANAGER_{
int b_init;
HANDLE h_com;
OVERLAPPED o;
}SCANNER_MANAGER_ITEM;
/*
*2's complement sum of message contents excluding checksum
*param: sum of message content
*/
static int __CheckSum(char data[],int d_size)
{
int count=0;
long sum=0;
if(data == NULL || d_size <= 0)
{
return 0;
}
while(d_size--)
{
sum+=(data[d_size] & 0xFF);
}
return ((~sum)+1);
}
static int ReadDataFromCom(void* data)
{
HANDLE h_com;
DWORD dwError;
COMSTAT stat;
int readed,data_len;
char RBuffer[4096]={0};
if(data == NULL)
{
return -1;
}
h_com=SCANNER_MANAGER_ITEM.h_com;
ClearCommError(h_com,&dwError,&stat);
data_len=(stat.cbInQue<4096)?stat.cbInQue:4096;
readed=0;
if(data_len>0) {
ReadFile(h_com,RBuffer,4096,&readed,NULL);
if(readed) { // success
memcpy(data,RBuffer,readed);
return readed;
}
}
return 0;
}
static int WriteDataToCom(void* data,int w_size)
{
HANDLE h_com;
int status=0;
int written=0;
if(data == NULL || w_size <= 0)
{
return 0;
}
h_com=SCANNER_MANAGER_ITEM.h_com;
PurgeComm(h_com,PURGE_TXCLEAR|PURGE_RXCLEAR|PURGE_RXABORT|PURGE_TXABORT);
status=WriteFile(h_com,data,w_size,&written,NULL);
if(!status)//write failed
{
return 0;
}else
{
return written;
}
}
/*
*Init serail
*Scanner Power On
*/
void Scanner1D_Moto_init()
{
if(!SCANNER_MANAGER_ITEM.b_init) {
Scanner_1D_power_on(); //根据用户自己平台对扫描头进行上电
memset(&SCANNER_MANAGER_ITEM,0,sizeof(SCANNER_MANAGER_ITEM));
{
HKEY h_rcom;
HANDLE h_com;
DWORD dwType;
DWORD dwValue;
DWORD dwsize;
TCHAR buf[20];
LPDCB lpDCB=malloc(sizeof(DCB));
dwsize=4;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Drivers\\BuiltIn\\IrCOMM"), 0, 0, &h_rcom);
RegQueryValueEx(h_rcom, _T("Index"), 0, &dwType, (BYTE*)&dwValue, &dwsize);
wsprintf(buf,L"COM%d:",dwValue);
SCANNER_MANAGER_ITEM.h_com=h_com=CreateFile(buf,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0);
if(h_com==INVALID_HANDLE_VALUE) {
return;
}
lpDCB=malloc(sizeof(DCB));
if(GetCommState(h_com,lpDCB)) {
SetupComm(h_com,1024,1024);
lpDCB->BaudRate=CBR_9600;
lpDCB->Parity=NOPARITY;
lpDCB->StopBits=ONESTOPBIT;
lpDCB->ByteSize=8;
SetCommState(h_com,lpDCB);
SetCommMask(h_com,EV_RXCHAR);
Sleep(500);
PurgeComm(h_com,PURGE_RXCLEAR);
SCANNER_MANAGER_ITEM.b_init=1;
}
free(lpDCB);
SCANNER_MANAGER_ITEM.o.Internal=0;
SCANNER_MANAGER_ITEM.o.Offset=0;
SCANNER_MANAGER_ITEM.o.OffsetHigh=0;
SCANNER_MANAGER_ITEM.o.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
}
Sleep(100);
}
}
/*
*exit
*power off
*/
void scanner1D_Moto_exit()
{
if(SCANNER_MANAGER_ITEM.b_init) {
Scanner_1D_power_off();
CloseHandle(SCANNER_MANAGER_ITEM.h_com);
SCANNER_MANAGER_ITEM.h_com=NULL;
SCANNER_MANAGER_ITEM.b_init=0;
}
}
/*
*set custom default value
*/
int SetCustomDefaults()
{
WriteDataToCom(wakeup,sizeof(wakeup));//need wakeup at least remain on 1 second.
Sleep(10);
return WriteDataToCom(custom_default,sizeof(custom_default));
}
/*
*set factory default value
*/
int SetFactoryDefaults()
{
WriteDataToCom(wakeup,sizeof(wakeup));//need wakeup at least remain on 1 second.
Sleep(10);
return WriteDataToCom(param_default,sizeof(param_default));
}
/*
*get all/some paramter values
*/
static int GetParamValues(void* data,char ctrl[],int ctrl_len)
{
HWND h_com;
char buffer[4096]={0};
int len=1;
DWORD dwEvtMask = 0 ;
h_com=SCANNER_MANAGER_ITEM.h_com;
WriteDataToCom(wakeup,sizeof(wakeup));
Sleep(10);//Once the WAKEUP command is sent, the host must wait at least 10 msec
if(WriteDataToCom(ctrl,ctrl_len) > 0)
{
WaitCommEvent(h_com,&dwEvtMask,&(SCANNER_MANAGER_ITEM.o));
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR) {//A character was received and placed in the input buffer
Sleep(50); //needed
len=ReadDataFromCom(buffer);
}
if(len>0 && memcmp(buffer,cmd_nak,sizeof(cmd_nak)/sizeof(char)) != 0)//success
{
memcpy(data,buffer,len);
dwEvtMask=0;
return len;
}
}
return 0;
}
int ParseParamValues(char param_list[],int count,char *output)
{
char buffer[4096]={0};
char get_param[4096]={0};
char *p=NULL;
int len=0,i=0,values=0;
int check_sum=0;
FILE *fp=NULL;
char temp[]={0xC7,0x04,0x00};
if(param_list == NULL || count <= 0 || output == NULL)
{
return 0;
}
len=sizeof(temp)/sizeof(char);
get_param[0]=((len+count+1)&0xFF);
memcpy(get_param+1,temp,len);
memcpy(get_param+len+1,param_list,count);
check_sum=__CheckSum(get_param,len+count+1);
get_param[len+count+1]=((check_sum>>8) & 0xFF);
get_param[len+count+2]=((check_sum) & 0xFF);
len=GetParamValues(buffer,get_param,len+count+3);
p=buffer+5;//skip (length,opcode,src,status,beep-code)
memcpy(output,p,len-7);
return len-7;
}
/*
return: fail return -1
success return 0
*/
int SetParamValues(char param_list[],int count)
{
int check_sum=0;
char temp[]={0xC6,0x04,0x08,0xFF};
int len=0;
char buffer[4096]={0};
if(param_list == NULL || count <= 0)
{
return -1;
}
len=sizeof(temp)/sizeof(char);
buffer[0]=((count+len+1)&0xFF);//length
memcpy(buffer+1,temp,len);
memcpy(buffer+len+1,param_list,count);
check_sum=__CheckSum(buffer,len+count+1);
buffer[len+count+1]=((check_sum>>8)&0xFF);//height byte
buffer[len+count+2]=(check_sum&0xFF);//low byte
WriteDataToCom(wakeup,sizeof(wakeup));
Sleep(10);
WriteDataToCom(buffer,len+count+3);//Length: 1 byte,CheckSum: 2 byte
return 0;
}
扫描头是可以进行配置的,使其支持与禁用某些条码类型,设置有两种方式,一种是扫一下对应的设置条码,另一种是通过SSI(simple serial interface)来设置,下面就讲一下SSI的设置方式。
扫描头在上电以后,就可以对其发送对应参数设置了,摩托罗拉建议设置临时参数,设置永久生效的参数会损害扫描头内部的flash,flash损坏后扫描头将无法使用,比如出现一个点的激光,正常情况是一条线。flash寿命有限,请慎重。临时设置会在扫描头断电以后丢失,每次上电的时候都要设置一次,所以建议将需要设置的参数写入到注册表中,每次上电以后从注册表读取。
附上设置的基本代码,仔细阅读注释部分(请根据自身平台修改部分实现):
- static CHAR wakeup[] = {0x00};
- //2's complement sum of message contents excluding checksum.
- static size_t __CheckSum(CHAR data[],size_t d_size)
- {
- size_t count=0;
- size_t sum=0;
- if(data == NULL || d_size <= 0)
- {
- return 0;
- }
- while(d_size--)
- {
- sum+=(data[d_size] & 0xFF);
- }
- return ((~sum)+1);
- }
- //store params to register,when power off
- int SetScannerSetValueToLocal(void *data,size_t len)
- {
- #ifdef WINCE
- HKEY hk;
- ULONG dw=REG_BINARY,dwDisp;
- ULONG dwSize=sizeof(dw);
- CHAR param[1024]={0};
- size_t iRetVal=0;
- assert(data!=NULL && len>0);
- if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("HARDWARE\\SCANDev\\SETTING"),0,0,&hk))
- {
- if(RegQueryValueEx(hk,_T("Value"),0,&dw,(LPBYTE)param,&dwSize)==ERROR_SUCCESS)
- {
- RegDeleteValue(hk,_T("Value"));
- RegSetValueEx(hk,_T("Value"),0,dw,(LPBYTE)data,len);
- }else
- {
- iRetVal=-1;
- }
- }else
- {
- if(ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE,_T("HARDWARE\\SCANDev\\SETTING"), 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dwDisp))
- {
- RegSetValueEx(hk,_T("Value"),0,dw,(LPBYTE)data,len);
- }else
- {
- iRetVal=-1;
- }
- }
- RegCloseKey(hk);
- return iRetVal;
- #endif
- }
- static void __GetScannerSetValueFromLocal(void *data,size_t in_len,size_t * out_len)
- {
- #ifdef WINCE
- HKEY hk;
- ULONG dw=REG_BINARY;
- ULONG dwSize=sizeof(dw);
- CHAR param[1024]={0};
- if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("HARDWARE\\SCANDev\\SETTING"),0,0,&hk))
- {
- if(RegQueryValueEx(hk,_T("Value"),0,&dw,(LPBYTE)param,&dwSize)==ERROR_SUCCESS)
- {
- if(dwSize <=0)
- {
- return;
- }else
- {
- memcpy(data,param,dwSize);
- *out_len=dwSize;
- }
- }
- }
- RegCloseKey(hk);
- #endif /*end of macro WINCE*/
- }
- //when scanner engine power on,you can call this function
- static size_t SetParamValues(void)
- {
- #ifdef WINCE
- size_t check_sum=0;
- CHAR param_list[1024]={0};
- size_t count=0;
- size_t len=0,i=0;
- CHAR buffer[4096]={0};
- //Attention!!! Temporary change - lost when power removed
- //Failure to meet these conditions can corrupt the scan engine's memory.
- //must be 0x00,0xFF,not is 0x01,0xFF
- CHAR temp[]={0xC6,0x04,0x00,0xFF};
- __GetScannerSetValueFromLocal(param_list,sizeof(param_list),&count);
- if(param_list == NULL || count <= 0)
- {
- return -1;
- }
- len=sizeof(temp)/sizeof(CHAR);
- buffer[0]=((count+len+1)&0xFF); //length
- memcpy(buffer+1,temp,len);
- memcpy(buffer+len+1,param_list,count);
- check_sum=__CheckSum(buffer,len+count+1);
- buffer[len+count+1]=((check_sum>>8)&0xFF); //height byte
- buffer[len+count+2]=(check_sum&0xFF); //low byte
- write_com_data(wakeup,sizeof(wakeup));
- _Sleep(100); //change from 70 to 100ms waiting for scanner wakeup
- write_com_data(buffer,len+count+3); //Length: 1 byte,CheckSum: 2 byte
- return 0;
- #endif /*end of macro WINCE*/
- }
write_com_data的API是平台相关性的,请根据自身平台不同修改实现。