2011年5月29日星期日

  125KHZ阅读器 ATMEGA8程序解读

         用ATMEGA8芯片按参考资料里面的网址做了一个125KHZ低频的阅读器,由于基础不好,花了一天多时间阅读代码,自己也是第一次接触ATMEGA8芯片,寄存器设置和工作方式也不是很熟悉。代码某些地方还不是很明白,大部分都搞懂了,非常感谢原作者!

//包含所需头文件 #include 
 
   #include 
  
    /*------宏定义------*/ #define BIT(x)	(1<<(x)) void put_c(unsigned char dat); void put_s(unsigned char *dat,unsigned char enter); void find_start(void); volatile unsigned char bit_array[256]; volatile unsigned char test_end = 0; //端口初始化 void port_init(void) { 	PORTB = 0x00; 	DDRB  = 0x08;    	PORTC = 0x00; 	DDRC  = 0x00; 	PORTD = 0x03; 	DDRD  = 0x02;   //  PD1->TXD   PD0->RXD} //定时T1初始化 void timer1_init(void) { 	TCCR1B = 0x00;//停止定时器   CS1 2:0=000  no clock source	TIMSK |= 0x20;//中断允许    TICIE(T/C1  input capture interrupt enable)=1	TCNT1H = 0xFF; 	TCNT1L = 0xF8;//初始值 	TCCR1A = 0x00;//COM1A1 1:0=00 normal port operation, OC1A/OC1B disconnected. so is COM1B 1:0   WGM1 1:0=00;	TCCR1B = 0xC5;//启动定时器   ICNC1(input capture noise canceler)=1   ICES(input caputure edge select)=1 (a rising edge will trigger)	              //WGM1 3:2 = 00 (T/C mode of operation is normal)CS1 2:0 = 101   CLKio/1024 for the T/C1} //定时器T1输入捕捉中断服务程序 /* *   ???这段代码比较疑惑,如果捕捉到下降沿,就按11扩展,捕捉到上升沿就按00扩展,晶振是11.0592晶振,TC1的时钟频源是1024分频 *   TCNT1计数一次的时间是92.59us,ICR1选择到4~6之间,时钟选择在555us~370us,空跳的地方是不是就直接跳过了? *    * */ISR(TIMER1_CAPT_vect) { 		static unsigned char tr = 0;      //触发沿标志,tr=1 表示下降沿触发		static unsigned char bit_no = 0;  //卡片信息256位的位数		static unsigned char one_time = 0; //没有用到		TCCR1B = 0; 		TCNT1 = 0; 		if(ICR1 > 6) {      //无效的捕获,重新开始			bit_no = 0; 		} 		if(test_end == 0){     //test_end=1标志256位数据接收完成			if(tr == 1){ 				bit_array[bit_no] = 0; 				bit_no++; 				if(bit_no == 0){ 					test_end = 1; 				} 				if(ICR1L > 4){ 					bit_array[bit_no] = 0; 					bit_no++; 					if(bit_no == 0){ 						test_end = 1; 					} 				} 				TCCR1B = 0xC5;	//上升沿触发  启动定时器				tr = 0; 			} 			else			{ 				bit_array[bit_no] = 1; 				bit_no++; 				if(bit_no == 0){ 					test_end = 1; 				} 				if(ICR1L > 4){ 					bit_array[bit_no] = 1; 					bit_no++; 					if(bit_no == 0){ 						test_end = 1; 					} 				} 				TCCR1B = 0x85;	//下降沿触发  启动定时器				tr = 1; 			} 		} } //定时器T2初始化 void timer2_init(void) { 	TCCR2  = 0x00;//停止定时器      	ASSR   = 0x00;//异步时钟模式 AS2=0  clocked from CLKio	TCNT2  = 0x00;//初始值   	OCR2   = 0x2B;//匹配值 	TIMSK |= 0x00;//中断允许 	TCCR2  = 0x19;//启动定时器  WGM20=0  COM2 1:0=01(toggle OC2 on Compare Match) WGM21=1(CTC) CS2 2:0=001  no prescaling} //串口通信初始化 void usart_init(void) { 	UCSRB = 0x00;//禁止中断 	UCSRA = 0x00; //U2X=0	UCSRC = BIT(URSEL) | 0x06; //默认为异步模式 写UCSRC时,URSEL必须为1  UCSZ1:0=11  (UCSRB->UCSZ2=0) 数据帧数为8位   USBS=0 停止位为0	UBRRL = 0x05; 	UBRRH = 0x00; //波特率为115200	UCSRB = 0x98; //RXCIE(rx complete interrupt enable)=1 RXEN(receiver enable)=1   TXEN=1  USZ2=0} void put_c(unsigned char dat) { 3313311	while(!(UCSRA & (1 << UDRE))); //等待发送缓冲器为空	UDR = dat; } void put_s(unsigned char *dat,unsigned char enter) { 	while(*dat) { 		put_c(*dat); 		dat++; 	} 		if(enter == 1) { 		put_c(0x0d); //换行		put_c(0x0a); //回车	} } void put_long(unsigned long dat) { 	unsigned long temp = 1000000000; 	unsigned char i = 0; 	unsigned char out = 0; 	for(i = 0;i < 10;i++) 	{ 		out = dat / temp; 		dat %= temp; 		temp /= 10; 		put_c(out + 48); 	} //	out = dat % temp; //	put_c(out + 48); } void init_devices(void) { 	cli(); //禁止所有中断 	MCUCR  = 0x00; // SE =0 SM2:0 =000 空闲  ISC(interrupt sense control)	MCUCSR = 0x80;//禁止JTAG 	GICR   = 0x00; 	port_init(); 	timer1_init(); 	timer2_init(); 	usart_init(); 	sei();//开全局中断 } //主函数 int main(void) { 	unsigned char i = 0; 	init_devices(); 	//在这继续添加你的代码 	put_s("RFID Card Reader",1); 	while(1){ 		if(test_end == 1){ 			decode(); 			test_end = 0; 		} 	} 	return 0; } void decode(void) { 	unsigned char i,j,k; 	unsigned char id_code[11] = {0,0,0,0,0,0,0,0,0,0,0}; 	unsigned char col_parity = 0; //列偶校验	unsigned char row_parity = 0; //行偶校验	unsigned char temp = 0; 	unsigned char start_data[20] = {1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1}; //停止位是0,用下降沿表示,开始位是111111111,用上升沿01表示	unsigned long rfid = 0; 	for(i = 0;i < 128;i++) { 		for(j = 0;j < 20;j++){ 			if(bit_array[i+j] != start_data[j]){ 					break; 			}	 		} 		if(j == 20){     //找到匹配的起始数据			put_s("",1); 			put_s("Find RFID Card.",1); 			i += 20;     //跳过起始的20位数据			for(k = 0;k < 11;k++){   //除去开头部分有11行 				row_parity = 0;     				//读出五位数据 				temp = 0; 				for(j = 0;j < 5;j++) { 					temp <<= 1; 					if((bit_array[i] == 0) && (bit_array[i+1] == 1)){ 						temp |= 0x01;   //读取“1”						if(j < 4){      //第5位是行校验位							row_parity += 1; 						} 					} 					else if((bit_array[i] == 1) && (bit_array[i+1] == 0)){ 						temp &= 0xfe;   // 读取“0”					} 					else{ 						return; 					} 					i += 2; 				} 				id_code[k] = (temp >> 1);//偶检验位不是有效数据 				temp &= 0x01;  //此时temp为偶检验位				row_parity %= 2; 				if(k < 10){ 					if(row_parity != temp)  //行偶校验失败						return;    				} 				else{ 					if(temp != 0)   //???为什么做这个判断呢						return; 				} 			} 			if(k == 11) { 				put_s("ID Card :",0); 				for(j = 2;j < 10;j++){     //第2行到第9行为卡号					rfid += (((unsigned long)(id_code[j])) << (4 * (9 - j))); //获得卡号				} 			} 			put_long(rfid); 			return; 		} 	} } 
  
 

参考资料:

1.http://www.ourdev.cn/bbs/bbs_content_all.jsp?bbs_sn=1426252

没有评论:

发表评论