用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
没有评论:
发表评论