c語言埠掃描
⑴ linux 下C語言的syn掃描代碼
//---------------------------------------------------------------------------
//Filename:ss.c
//Author:yunshu
//Write:2004-04-02
//Thanks Wineggdrop
//Modify:2004-09-08
//---------------------------------------------------------------------------
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mstcpip.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
////////////////////////////////////////////////////////////////
//全局變數
////////////////////////////////////////////////////////////////
#define srcPort 88
char srcIP[20] = ;//定義源地址
char tgtIP[20] = ;//定義目的地址
int portNow;//定義正在掃描的埠
//標准埠列表
int ports[20] = ;
typedef struct ip_hdr
{
unsigned char h_verlen; //4位首部長度,4位IP版本號
unsigned char tos; //8位服務類型TOS
unsigned short total_len; //16位總長度(位元組)
unsigned short ident; //16位標識
unsigned short frag_and_flags; //3位標志位
unsigned char ttl; //8位生存時間 TTL
unsigned char proto; //8位協議 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校驗和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
typedef struct tcp_hdr //定義TCP首部
{
USHORT th_sport; //16位源埠
USHORT th_dport; //16位目的埠
unsigned int th_seq; //32位序列號
unsigned int th_ack; //32位確認號
unsigned char th_lenres; //4位首部長度/6位保留字
unsigned char th_flag; //6位標志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校驗和
USHORT th_urp; //16位緊急數據偏移量
}TCP_HEADER;
typedef struct tsd_hdr //定義TCP偽首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //協議類型
unsigned short tcpl; //TCP長度
}PSD_HEADER;
////////////////////////////////////////////////////////////////
//函數原形
////////////////////////////////////////////////////////////////
int send_packet();//發送數據函數
int recv_packet();//監聽數據函數
USHORT checksum( USHORT *, int );//計算檢驗和函數
void usage( char * );//顯示幫助函數
void check_port( char * );//判斷埠是否開放函數
////////////////////////////////////////////////////////////////
//main函數
////////////////////////////////////////////////////////////////
int main( int argc , char *argv[] )
{
WSADATA WSAData;
DWORD thread_ID = 1;
char FAR hostname[128] = ;
HANDLE ThreadHandle[20];
struct hostent *phe;
if( argc != 2 )//檢查命令行參數是否正確
{
usage( argv[0] );
exit( 0 );
}
if ( WSAStartup(MAKEWORD(2,2) , &WSAData) )
{
printf("WSAStartup Error...\n");
exit(0);
}
strcpy(tgtIP,argv[1]);//得到目標主機的ip地址
gethostname(hostname,128);//獲取本機主機名
phe = gethostbyname(hostname);//獲取本機ip地址結構
if(phe == NULL)
{
printf("Get LocalIP Error...\n");
}
strcpy(srcIP, inet_ntoa(*((struct in_addr *)phe->h_addr_list[0])));//得到本機ip地址
//調試用,注釋掉
//printf("test\t%s\n",tgtIP);
//printf("test\t%s\n",srcIP);
//開啟新線程,接受數據包,分析返回的信息
HANDLE RecvHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)recv_packet,NULL,0,&thread_ID);
Sleep(500);//休息一下再啟動發送數據包函數
for(int tmp = 0; tmp < 20; tmp++)
{
++thread_ID;
//要掃描的埠
portNow = ports[tmp];
//開啟新線程,發送數據包
ThreadHandle[tmp] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)send_packet,NULL,0,&thread_ID);
//防止生成線程過快,休息
Sleep(100);
}
DWORD WaitThread = WaitForMultipleObjects( 20 , ThreadHandle , TRUE , INFINITE );
if( WaitThread != WAIT_FAILED)
{
for( int n = 0 ; n < 20 ; n++ )
{
CloseHandle( ThreadHandle[n] );
}
}
CloseHandle( RecvHandle );
WSACleanup();
return 0;
}
//計算檢驗和函數,完全抄別人的
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if(size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return (USHORT)(~cksum);
}
void usage(char *prog)
{
printf("===========================================\n");
printf("Used To Scan Remote Host's Ports\n");
printf("Usage:%s TargetIP\n",prog);
printf("===========================================\n");
exit(0);
}
//發送數據包的函數
int send_packet()
{
SOCKET sendSocket;
BOOL flag;
int timeout;
SOCKADDR_IN sin;
IP_HEADER ipHeader;
TCP_HEADER tcpHeader;
PSD_HEADER psdHeader;
char szSendBuf[60] = ;
int ret;
unsigned long source_ip;
unsigned long target_ip;
//建立原生數據socket
if((sendSocket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("Socket Setup Error...\n");
return 0;
}
//設置自己填充數據包
if(setsockopt(sendSocket, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag)) == SOCKET_ERROR)
{
printf("Setsockopt IP_HDRINCL Error...\n");
return 0;
}
//設置超時時間
timeout = 1000;
if(setsockopt(sendSocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) == SOCKET_ERROR)
{
printf("Setsockopt SO_SNDTIMEO Error...\n");
return 0;
}
target_ip = inet_addr(tgtIP);
source_ip = inet_addr(srcIP);
sin.sin_family = AF_INET;
sin.sin_port = htons(portNow);
sin.sin_addr.S_un.S_addr = target_ip;
//填充IP首部
ipHeader.h_verlen = (4<<4 | sizeof(ipHeader)/sizeof(unsigned long));
ipHeader.total_len = htons(sizeof(ipHeader)+sizeof(tcpHeader));
ipHeader.ident = 1;
ipHeader.frag_and_flags = 0x40;
ipHeader.ttl = 128;
ipHeader.proto = IPPROTO_TCP;
ipHeader.checksum = 0;
ipHeader.sourceIP = source_ip;//源IP
ipHeader.destIP = target_ip;//目的IP
//填充TCP首部
tcpHeader.th_dport = htons(portNow);//目的埠
tcpHeader.th_sport = htons(srcPort); //源埠
tcpHeader.th_seq = 0x12345678;
tcpHeader.th_ack = 0;
tcpHeader.th_lenres = (sizeof(tcpHeader)/4<<4|0);
tcpHeader.th_flag = 2;//syn標志位。0,2,4,8,16,32->FIN,SYN,RST,PSH,ACK,URG(推測,哈哈)
tcpHeader.th_win = htons(512);
tcpHeader.th_urp = 0;
tcpHeader.th_sum = 0;
//填充tcp偽首部
psdHeader.saddr = ipHeader.sourceIP;
psdHeader.daddr = ipHeader.destIP;
psdHeader.mbz = 0;
psdHeader.ptcl = IPPROTO_TCP;
psdHeader.tcpl = htons(sizeof(tcpHeader));
//計算TCP校驗和
memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));
memcpy(szSendBuf + sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
tcpHeader.th_sum = checksum((USHORT *)szSendBuf, sizeof(psdHeader) + sizeof(tcpHeader));
//計算IP檢驗和
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
memcpy(szSendBuf + sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
memset(szSendBuf + sizeof(ipHeader) + sizeof(tcpHeader), 0, 4);
ipHeader.checksum = checksum((USHORT *)szSendBuf, sizeof(ipHeader) + sizeof(tcpHeader));
memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
memcpy(szSendBuf + sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
//發送數據包
ret = sendto(sendSocket, szSendBuf, sizeof(ipHeader) + sizeof(tcpHeader), 0, (struct sockaddr*)&sin, sizeof(sin));
if(ret == SOCKET_ERROR)
{
printf("Send Packet Error...\n");
return 0;
}
else return 1;
}
int recv_packet()
{
SOCKADDR_IN sniff;
SOCKET sock;
char recvBuffer[65000] = ;//緩沖區存放捕獲的數據
//建立socket監聽數據包
sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
sniff.sin_family = AF_INET;
sniff.sin_port = htons(0);
sniff.sin_addr.s_addr = inet_addr(srcIP);
//綁定到本地隨機埠
bind(sock,(PSOCKADDR)&sniff,sizeof(sniff));
//設置SOCK_RAW為SIO_RCVALL,以便接收所有的IP包
//來的
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
WSAIoctl(sock,SIO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);
while(TRUE)
{
memset(recvBuffer , 0 , sizeof(recvBuffer) );
//開始捕獲數據包
int bytesRecived = recv(sock,recvBuffer,sizeof(recvBuffer),0);
if(bytesRecived <= 0)
{
break;
}
check_port(recvBuffer);
}
return 1;
}
void check_port(char *buffer)
{
IP_HEADER *ipHeader;//IP_HEADER型指針
TCP_HEADER *tcpHeader;//TCP_HEADER型指針
ipHeader = (IP_HEADER *)buffer;
tcpHeader = (TCP_HEADER *) (buffer+sizeof(IP_HEADER));
if(ipHeader->sourceIP != inet_addr(tgtIP))
{
return;
}
for(int tmp=0;tmp<20;tmp++)
{
//SYN+ACK -> 2+16=18(也是推測,哈哈)
if(tcpHeader->th_flag == 18 && tcpHeader->th_sport == htons(ports[tmp]))
{
printf("[Found]\t%s\tport\t%d\tOpen\n",tgtIP,ports[tmp]);
}
}
}
⑵ C語言的技巧
如果你真的想學習編程,就請你認真的閱讀下去。
大家都知道C語言很強大,這個強大一是來自其功能,第一次出名就很牛逼的編出了UNIX系統。然後跟著UNIX這個明星,於是自己的影響一路飆升。二是C語言不但能夠寫UNIX的操作系統,而且編寫LINUX和Windows等操作系統時都離不開他的身影。三是它的實用,如果你是一個理科生,如果你學過單片機,你就知道無C不能。第四、很多就是電腦高手或黑客夢想的驅使,還有一些高手的推薦,於是你便選擇的C語言。
不管你是何種原因驅使,何種目的的驅動?當你選擇這個語言的時候,首先要考慮,你的基礎能行不?和你的目的到底是什麼?如果你是一個電腦菜鳥,或只想了解一下什麼是編程,我是不贊成學習C的,因為C初學時,很傷人鬥志的,也就是說你可能學習了一個月,還只能在黑色的框中徘徊,甚至資質差的只能算1+2+3+4+。。。+1000=?這個,,,會讓你成為編程高手嗎?顯然不能!如果你以後會從事硬體方面的開發,或在軟、硬體之間打交道,或一直從事軟體開發,那麼你一定要學習C,而且是不學不行的,有可能你還要學習匯編,因為有些情況匯編對硬體的操作比C更給力。而且他也是是不學不行的。
對於那些幾乎很少和硬、軟體打交道的童鞋,本人不建議學習C,因為一段時間後你會很快放棄它的,因為你知道1+2+3+。。。+1000=?根本就不能稱為程序,如果你掌握技巧,你算得比計算機還快,這和你的編程高手的理想是根本搭不上邊的。浪費你的時間,同時也在考驗你的心理,同時更會給你迷茫。針對基礎差,以後不想在軟體和硬體間混以及只想學習編個程序然後就出結果的童鞋,不建議學習C,你可以學習易語言,學習VB。原因他們是高級語言,簡單,易學、強大、更容易出成果。
比如VB寫個窗口,構建個菜單,寫個網頁瀏覽器、寫個遠控(比如木馬)等等,一個多月絕對能熟練掌握。我學近兩年C了,都沒法編出網頁瀏覽器,更無法讓一個MM圖片來美化我黑不籠統的窗口,但VB你只需要一分鍾,便可以讓你的窗口充滿色彩繽紛的效果,對於網路的埠掃描器,遠程聊天控制,遠程主機資源瀏覽等,VB都行。而且掌握他後,你變又附加的掌握了VBscript這個腳本語言。對於易語言,推薦不會英語的同學學吧,這個是中國人寫的編程工具,我沒用過,根據我的了解,功能也是很強大,中文的編程語言,會讓你更快的掌握這個語言,編出自己的作品。
上面的一番話,只是告訴你C固然好,但不是針對所有人都好。世界上沒有包治百病的仙丹,也沒有適合所有人的編程語言。
對於學習了C的童鞋,你面臨的是如何去深化,去鞏固C。學習了C語言基礎不是代表你已經會用C了,因為這才代表你剛入門,接下來你要學的是《數據結構》,這個是必修的,沒有他你無法編出嚴謹強大的C程序,開發出自己的系統——如果有意向開發系統的。
然後你要去學習操作系統的API,這個也很重要。如果你掌握了API,那麼你才能真正的可以成為自己學過C,會用C,才能知道原來C也可以無所不能。
這里是一個童鞋(08_小汪)的建議,我感覺很好,摘錄下來「首先C是入門,如果想C很牛的話,就要去研究演算法,C是為了過度到C++,C++會了。就要學windows程序設計,然後就學Visual c++,畢竟C++是計算機的底層。。。還有多動手寫程序,不然學的永遠不是自己的。。。」
然後08_小汪又推薦了四本書:
「推薦4本書《C語言陷阱和指針》,《C語言編程專家》,《thinking C++》,《數據結構-使用C++標准模板庫(STL)》。。。去專門的論壇看可能會專業點,畢竟面向的對象不同。。。」
有興趣深入研究C的童鞋,你需要讀一下。
C快速入門的方法是不斷的鞏固、不斷的編程。實踐是學習和掌握的重要途徑。
無論你學任何一門語言,都要一心不變的堅持下去,不要在學VB時,聽某某高手說C很強大,就放棄了VB,或在學易語言時,聽說易語言有局限而立即轉向別的語言。這樣不會成就你編程高手的夢想,只會讓你習慣半途而廢,然後是任何一個語言都不能學會。記住,只要你選擇了,一定要走下去,最後成功的才可能是你
更多資料【【【【愛我中 華夏聯盟 歡迎你】】】】】】
⑶ 100分求linux下C語言埠掃描代碼
linux tcp udp 埠掃描源程序
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <netinet/ip_icmp.h>
#include <stdlib.h>
#include <signal.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#define TRUE 1
#define FALSE 0
#define UDP "UDP"
#define TCP "TCP"
#define tcp "tcp"
#define udp "udp"
typedef struct _GsSockStru{
int fd;
int len;
struct sockaddr_in addr;
}GsSockStru;
static int tcptest( char ip[32], char port[20]);
static int udptest( char ip[32], char port[20]);
void sig_alrm( int signo );
static GsSockStru test_sock;
int
main( int argc, char** argv)
{
char string[64];
char port[20];
char pro[20];
char ip[32];
int res;
int i = 0;
int k = 0;
if( argc>2 || argc<2 )
{
printf("鍙傛暟涓嶆紜?-1\n");
return ( -1 );
}
strcpy( string, argv[1]);
while( *string )
{
if( string[i] == ':' )
break;
pro[k] = string[i];
k++;
i++;
}
pro[k] = '\0';
i++;
k = 0;
while( *string )
{
if( string[i] == ':')
break;
ip[k] = string[i];
k++;
i++;
}
ip[k] = '\0';
i++;
k=0;
while( *string )
{
if( string[i] == '\0')
break;
port[k] = string[i];
k++;
i++;
}
port[k] = '\0';
i++;
memset( &test_sock, 0, sizeof( test_sock ) );
if ( ( strcmp( TCP, pro) != 0 ) && ( strcmp( UDP, pro) != 0 ) && ( strcmp( tcp, pro) != 0 ) && ( strcmp( udp, pro) != 0 ))
{
printf ( "鍙傛暟涓嶆紜?錛?\n" );
return (-1);
}
if ( strcmp( TCP, pro) == 0 || strcmp( tcp, pro) == 0 )
res = tcptest( ip, port );
if ( strcmp( UDP, pro) == 0 || strcmp( udp, pro) == 0 )
res = udptest( ip, port );printf("%d\n",res);
return ( res );
}
int
tcptest( char ip[32], char port[20])
{
int res;
struct timeval tv;
test_sock.fd = socket( AF_INET, SOCK_STREAM, 0 );
if ( test_sock.fd < 0 )
{
printf( "create socket failed -3 \n" );
return ( -3 );
}
memset( &( test_sock.addr ), 0, sizeof( test_sock.addr ) );
test_sock.addr.sin_family = AF_INET;
test_sock.addr.sin_port = htons( atoi( port ) );
inet_pton( AF_INET, ip, &test_sock.addr.sin_addr );
test_sock.len = sizeof( struct sockaddr );
tv.tv_sec = 10;
tv.tv_usec = 0;
setsockopt( test_sock.fd, SOL_SOCKET, SO_RCVTIMEO,
(const char *)&tv, sizeof( tv ) );
res = connect( test_sock.fd,
( struct sockaddr * )( &( test_sock.addr ) ),
test_sock.len );
if ( res < 0 )
{
fprintf( stderr, "connect failed 0\n" );
close( test_sock.fd );
return FALSE;
}
close( test_sock.fd );
return TRUE;
}
int udptest( char ip[32], char port[20])
{
struct icmphdr *icmp_header;
struct sockaddr_in target_info;
int target_info_len;
fd_set read_fd;
int scan_port;
char recvbuf[5000];
struct sockaddr_in target_addr;
int icmp_socket;
int udp_socket;
struct timeval tv;
icmp_header = (struct icmphdr *)(recvbuf+sizeof(struct iphdr));
scan_port = atoi( port );
target_addr.sin_family = AF_INET;
inet_pton( AF_INET, ip, &target_addr.sin_addr );
target_addr.sin_port = htons(scan_port);
if ((udp_socket=socket(AF_INET,SOCK_DGRAM,0))==-1)
{
printf("create socket failed -3\n");
return -3;
}
if ((icmp_socket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))==-1)
{
printf("Create raw socket failed -3\n");
return -3;
}
sendto(udp_socket,NULL,0,0,(void *)&target_addr,sizeof(target_addr));
FD_ZERO(&read_fd);
FD_SET(icmp_socket,&read_fd);
tv.tv_sec = 1;
tv.tv_usec = 0;
select(FD_SETSIZE,&read_fd,NULL,NULL,&tv);
for (;;){
if (FD_ISSET(icmp_socket,&read_fd))
{
target_info_len = sizeof(target_info);
recvfrom(icmp_socket,recvbuf,5000,0,
(struct sockaddr *)&target_info,&target_info_len);
if (target_info.sin_addr.s_addr == target_addr.sin_addr.s_addr
&& icmp_header->type == 3 && icmp_header->code<=12)
{
printf("Port %d : Close\n",scan_port);
return (0);
}
}
return (1) ;
}
}
⑷ 用單片機C語言控制6位密碼鎖。要求有一個清除鍵和確認鍵,密碼輸錯了會有報警音。請高手幫助了
我找到了一個,來自《51單片機C語言應用技術開發大全》
SCH圖正在繪制中。。。
#include <REGX51.H>//51單片機的頭文件
typedef unsigned char uchar; //類型定義,定義uchar類型
typedef unsigned int uint; //類型定義,定義uint 類型
//鍵盤子程序相關說明。
#define BLANKCHAR 10 //定義空白常量
#define PCHAR 11 //定義字元P常量
#define OPENCHAR 12 //定義開鎖字元常量
#define ALARMCHAR 13 //定義字元A常量
#define LINECHAR 14 //定義字元-常量
#define BACKKEY 0X0D //定義退格鍵常量
#define ENTERKEY 0X0F //定義確認鍵常量
#define LOCKKEY 0X0E //定義閉鎖鍵常量
#define NO_KEY 20 //定義無按鍵返回值
#define KEYPORT P2 //定義鍵盤埠
//Delay1Ms
void Delay1Ms()
{
uint i;
for (i=0;i<1000;i++);
}
//定義按鍵掃描碼表 按鍵掃描時,4位列線和4位行線組成位元組數據表
uchar code KEYCODE[]=
{0XEE,0XED,0XEB,0XE7,
0XDE,0XDD,0XDB,0XD7,
0XBE,0XBD,0XBB,0XB7,
0X7E,0X7D,0X7B,0X77};
uchar KeyPre; //保存上次掃描按鍵的鍵值
uchar KeyUp;
//用於控制按鍵去抖動操作。1:掃描時去抖動 2:等待釋放 3:釋放時去抖動。
#define LEDPORT P0 //定義顯示器段碼輸出埠
#define LEDCON P1 //定義顯示器位控制埠
uchar code SEGCODE[]=
{0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,// 0~9的共陽極代碼
0xff,//不顯示的共陽極段碼
0X8C,//字元P的共陽極段碼
0X8F,//┝的共陽極段碼
0X88,//字元A的共陽極段碼
0XBF,//字元-的共陽極段碼
};
//定義LED位碼控制碼
uchar code BITCODE[]={0Xfe,0Xfd,0Xfb,0Xf7,0Xef,0Xdf,0Xbf,0X7f};
uchar DispBuf[6]; //保存顯示的字元
bit DispNormal; //控制顯示時,是正常顯示還是閃爍顯示。
uchar DispCnt; //控制閃爍顯示時的頻率。
#define SHORT_TIME 10 //蜂鳴器響200ms
#define LONG_TIME 100 //蜂鳴器響2s
#define LONGER_TIME 9000 //蜂鳴器響3 minutes
sbit ALARMCON=P3^4; //定義報警控制引腳
bit AlarmEnable; //是否報警或聲音提示
uint AlarmTime; //控制報警時間長度
sbit LOCKCON=P3^3; //定義電子鎖控制引腳
uchar code PassWord[]={1,2,3,4,5}; //定義初時密碼表
uchar PassInBuf[6]; //保存輸入的密碼字元
uchar PassPosi; //用戶輸入密碼字元存放在PassInBuf[]的位置。
bit TimerBit; //20ms定時時間到
uchar SysMode; //系統所處模式 0:輸入密碼模式 1:報警模式 2:開鎖模式
uchar ErrorCnt; //用戶連續輸入密碼出錯次數。
/*
入口參數:
FillChar:寫入緩沖區的字元
出口參數:無
*/
void Fill_Buf(uchar FillChar)
{
uchar i;
for(i=0;i<6;i++)
{
DispBuf[i]=FillChar;//用字元FillChar填充DispBuf[i]
PassInBuf[i]=FillChar; //用字元FillChar填充PassInBuf [i]
}
}
void Fill_Buf_P()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=PCHAR;// DispBuf[0]='P'
}
void Fill_Buf_O()
{
Fill_Buf(BLANKCHAR); // DispBuf[1..5]= ' '
DispBuf[0]=OPENCHAR; // DispBuf[0]='┝'
}
void Fill_Buf_A()
{
Fill_Buf(LINECHAR); // DispBuf[1..5]= ' -----'
DispBuf[0]=ALARMCHAR; // DispBuf[0]='A'
}
/*
入口參數:
DispPosi:要顯示數據的LED號。
DispChar:要顯示的內容。
出口參數:無
*/
void Disp_Led_Sin(uchar DispChar,uchar DispPosi)
{
LEDPORT=SEGCODE[DispChar];//輸出顯示段碼
LEDCON&=BITCODE[DispPosi];//輸出顯示位碼
Delay1Ms(); //延時1MS
LEDCON|=0X3F;//關閉顯示器
}
/*(2)關閉顯示函數Disp_Led_OFF。
函數Disp_Led_OFF在顯示器上顯示空白字元,主要用在閃爍顯示。函數通過6次調用Disp_Led_Sin實現所需功能。代碼如下:*/
void Disp_Led_OFF()
{
uchar i;
LEDCON|=0X3F;// 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(BLANKCHAR,i);//逐個顯示空白字元
}
}
void Disp_Led_All()
{
uchar i;
LEDCON|=0X3F; // 關閉顯示器
for(i=0;i<6;i++)
{
Disp_Led_Sin(DispBuf[i],i); //顯示DispBuf[]中的數值
}
}
void Disp_LED()
{
DispCnt++;
DispCnt%=10;
if(DispCnt==0)
{
DispNormal=~DispNormal;//200ms將閃爍顯示控制位取反
}
if(SysMode==1)
{//報警模式,閃爍顯示
if(!DispNormal)
{
Disp_Led_OFF();//顯示空白字元
return;
}
}
Disp_Led_All();//顯示DispBuf[]中的數值
}
/*
入口參數:
stime:蜂鳴器鳴叫時間。
出口參數:無
*/
void Sys_Speaker(uint stime)
{
AlarmEnable=1;//允許報警
AlarmTime=stime;//報警時間長短
}
void Sys_Alarm()
{
if(AlarmEnable==1)
{//允許報警
ALARMCON=0;//報警
AlarmTime--;
if(AlarmTime==0)
{//停止報警時間到
AlarmEnable=0;
ALARMCON=1;//禁止報警
if(SysMode==1)
{//報警發生在模式1時,要返回模式0
SysMode=0;
Fill_Buf_P();//顯示P
}
}
}
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Find_Key()
{
uchar KeyTemp,i;
KEYPORT=0xf0;//行線輸出0,列線輸出全1
KeyTemp=KEYPORT;//讀按鍵埠值
if(KeyTemp==0xf0)
return NO_KEY;//無鍵按下,返回
KEYPORT=KeyTemp|0x0f;//列線輸出,行線輸入
KeyTemp=KEYPORT;//讀取按鍵埠值
for(i=0;i<16;i++)
{
if(KeyTemp==KEYCODE[i])//根據按鍵埠掃描值,查找按鍵值
return i;//返回按鍵值
}
return NO_KEY;
}
/*
入口參數:無
出口參數:按鍵值或無按鍵
*/
uchar Scan_Key()
{
uchar KeyTemp;
KeyTemp=Find_Key();//掃描鍵盤,獲得按鍵值
if(KeyTemp==NO_KEY)
{
if(KeyUp<2)
{//無按鍵按下,返回
KeyUp=0;
return NO_KEY;
}
if(KeyUp==2)
{//按鍵要釋放,延時去抖動
KeyUp=3;
return NO_KEY;
}
if(KeyUp==3)
{//按鍵釋放,返回鍵值
KeyUp=0;
return KeyPre;
}
}
else
{
if(KeyUp==0)
{//有鍵按下,保存鍵值
KeyUp=1;
KeyPre=KeyTemp;
}
else if(KeyUp==1)
{//去抖動後,再次測到有按鍵按下
if( KeyPre==KeyTemp)
KeyUp=2;
else
KeyPre=KeyTemp;
} else if(KeyUp==3)
{//等待按鍵釋放
KeyUp=2;
}
}
return NO_KEY;
}
/*
入口參數:
Key:按鍵值
出口參數:無
*/
void Key_Process(uchar Key)
{
uchar i;
if(Key==NO_KEY)
return ;//無按鍵,不處理
switch(SysMode)
{
case 0://輸入密碼
switch(Key)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
DispBuf[PassPosi]=LINECHAR;//顯示'-'
PassInBuf[PassPosi]=Key;//保存用戶輸入的密碼
if(PassPosi<5)
PassPosi++;//調整密碼輸入位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case BACKKEY://退格鍵
DispBuf[PassPosi]=BLANKCHAR;//顯示' '
PassInBuf[PassPosi]=BLANKCHAR;//清除當前位置的密碼
if(PassPosi>1)
PassPosi--;//調整顯示位置
Sys_Speaker(SHORT_TIME);//發按鍵提示音
break;
case ENTERKEY://確定按鍵
for(i=0;i<5;i++)
{//比較用戶輸入密碼與系統預設密碼是否一致
if(PassInBuf[i+1]!=PassWord[i])
break;
}
if(i>=5)
{//輸入密碼正確
Fill_Buf_O();//顯示開鎖狀態
PassPosi=1;
LOCKCON=1;//開鎖
ErrorCnt=0;
Sys_Speaker(LONG_TIME);//發長提示音
SysMode=2;//轉模式2
}
else
{
ErrorCnt++;//出錯次數加一
if(ErrorCnt>2)
{//次數超過3次
ErrorCnt=0;
Fill_Buf_A();//顯示報警狀態
PassPosi=1;
Sys_Speaker(LONGER_TIME);//發報警音
SysMode=1;
}
else
{//出錯次數少於3次,用戶重新輸入
Fill_Buf_P();
PassPosi=1;
Sys_Speaker(LONG_TIME);
}
}
break;
case LOCKKEY://閉鎖鍵
Fill_Buf_P();//顯示P
PassPosi=1;
Sys_Speaker(SHORT_TIME);
break;
}
break;
case 2://開鎖狀態
if(Key==LOCKKEY)
{//用戶按動閉鎖按鍵
Fill_Buf_P();
SysMode=0;
LOCKCON=0;//閉鎖
Sys_Speaker(SHORT_TIME);
}
break;
}
}
void Ini_Timer0()
{
TMOD&=0XF0;
TMOD|=0X01;// 初始化T0,模式1
TR0=0;
TH0=(65536-20000)/256;//T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;//啟動T0
ET0=1;//允許T0中斷
}
void Timer0() interrupt 1
{
TR0=0;
TH0=(65536-20000)/256; //T0 賦計數初值
TL0=(65536-20000)%256;
TR0=1;
TimerBit=1;//定時時間到
}
void Ini_System()
{
PassPosi=1;
LOCKCON=0;//閉鎖
Ini_Timer0();//初始化T0
Fill_Buf_P();
EA=1;//允許系統中斷
}
void main()
{
uchar KeyTemp;
Ini_System();
while(1)
{
if (TimerBit==1)
{//定時時間到
Disp_LED();//刷新顯示器
Sys_Alarm();//報警處理
KeyTemp=Scan_Key();//掃描按鍵
Key_Process(KeyTemp);//按鍵處理
TimerBit=0;
}
}
}