viperchaos

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

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

//包含所需头文件 
#include <avr/io.h> 
#include <avr/interrupt.h> 

/*------宏定义------*/ 
#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) 
{ 
	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

posted on 2011-05-29 19:11  viperchaos  阅读(1134)  评论(0)    收藏  举报