破解IC电话卡
IC卡内部基本情况:
计数方法:
在67-103地址单元中分为5个不可重置8单元计数器,芯片初始化时,72-103地址单元所对应
的4个较低的8单元计数器中可以放0到8个“1”而67-71地址单元所对应的第5个计数器可以
放0到5个“1”。所谓计数一次,就是将一个单元从“1”写成“0”。一个计数器中8位全为
“0”后,要计数,需借位操作,即将高位计数器的一位从“1”写成“0”而相应其低位计
数器整个字节从“0”擦除成“1”。可见4个8单元计数器如此逐一递减,其最大计数为8的4
次方=4096。第5个计数器中5个单元因处在最高位只能被写“0”无法擦成“1”。因此只能
计数5次。故芯片总计数为5X4096=20480。当全部计数单元(地址67-103)都被写成“0”
时,卡片就用完了,不过,芯片出厂初始化时,初置的计数值由国家不同和卡片面值不同而
不同,如100元卡初置计数值为1000。
举例: 100元(1000计数单元预置初始值).
——–
Byte9 Byte10 Byte11 Byte12 Byte13
————————————————————–
000000 - 00000001 - 01111111 - 00011111 - 00000000
————————————————————–
(3)octal (6)octal (7)octal (1)octal (2)octal
————————————————————–
Value = 0*8^4 + 1*8^3 + 7*8^2 + 5*8^1 + 0*8^
————————————————————–
总值 = 1000 Units
Ⅰ-5)内存数据:
字节 位 二进制 十六进制
+———–+—–+
1 1 –> 8 | | |
+———–+—–+
2 9 –> 16 | 0010 1111 | F | —> 德国
| 0011 0111 | | —> 西班牙
| 0011 1011 | B | —> 希腊
+———–+—–+
3 17 –> 24 | | |
4 25 –> 32 | | | —> 出厂编号(写保护)
5 33 –> 40 | | |
6 41 –> 48 | | |
7 49 –> 56 | | |
8 57 –> 64 | | |
+———–+—–+
9 65 –> 72 | | | —> c4096 )
10 73 –> 80 | | | —> c512 )
11 81 –> 88 | | | —> c64 ) 5个8进制计数区
12 89 –> 96 | | | —> c8 )
13 97 –> 104 | | | —> c0 )
+———–+—–+
14 105 –> 112 | 1111 1111 | $FF |
15 113 –> 120 | 1111 1111 | $FF | —> 所有位都为”1″
16 120 –> 128 | 1111 1111 | $FF |
+———–+—–+
自从80年代中期出现IC电话卡后,基本已取代了原来流行的电话磁卡,磁卡存在存在严重的
安全问题,已逐步淘汰。
即使IC电话卡,也不能算很安全,卡内所有数据只要有简单的读写装置并按时序操作都能读
取,事实上电话卡和信用卡一样内部没有什么秘密信息,仅仅是带串行输出的128位EPROM而
已(对二类卡是256位PROM),不要以为弄懂了它是怎么工作你就有办法重新对卡内数据重新
填充,其开始的64位是带写保护的,在出厂时其熔丝位已被编程,你已无法对其更改,其后
的40位计数单元受内部逻辑控制在写时只能减少不能增加直至到0为止,因此你想用一般的
IC电话卡打免费电话是不可能的,除非你能用微控制器(单片机)仿真它(如果你能读懂本文
介绍的所有内容)。IC电话卡是一种一次性使用的计数卡,以一次性的计数方式,从写满的
计数器中减“1”,直至存储单元减为空为止。
卡片每次消费计数的“单位价值”根据各种应用系统的实际需要而定。例如:对于中国IC电
话卡,如30元卡对应内部计数值为300,每单位值对应0.1元,IC 卡电话机每分钟产生一次
扣费信号,扣费值由当地IC电话管理系统设定,一般是价值0.5元或1元,卡片被计数5次和
10次。对于其它国家属于第一类IC电话卡而言也是如此,只是内部初始计数值不同,每次扣
除额度不一样罢了。其他对于公用加油卡,IC卡计费加油机每一公升(或一加仑)产生一次
扣费操作,卡片被操作一次扣2.5元等等,均属于等同原理。事实上,这类卡内部为128位
(16字节) NMOS存储器,按如下规律分布:
64 位 EPPOM(8字节) 写保护区(芯片数据代码区、发行数据代码区)
40 位 EEPROM(5字节)
24 位 为全“1”(3字节)
共16字节数据。
Ⅰ-2)引脚:
————-+————-
| 1 | 5 | 引 脚:
| | | ——-
+——-\ | /——-+
| 2 +—-+ + 6 | 1 : Vcc = 5V 5 : Gnd
| | | | 2 : Reset 6 : NC
+——–| |——–+ 3 : Clock 7 : I/O
| 3 | | 7 | 4 : NC 8 : NC
| +—-+—-+ |
+——-/ | \——-+ Vcc:电源 Gnd:地脚 Reset:复位
| 4 | 8 |
| | | Clock:时钟 I/O:数据 NC: 空脚
————-+————-
因有三个脚为空脚,目前一般有采用8脚和6脚封装的,6脚封装的无最下一排两个空脚
Ⅰ-3)主要特性:
-采用单一5V电源供电
-遵循ISO/IEC7816-3同步协议进行双向数据传输
-低功耗
-NMOS技术
-高可靠性,抗静电干扰能力>4KV
Ⅰ-4)时序图
复位:
为使地址计数器复位到0,先让Reset端变高。紧跟着一个Clock脉冲(从低到高再降到0),
Reset重新变低,把Clock脉冲包住。随着Reset端变低,地址0单元的数据从I/O上输出。对
应 Clock端的每个脉冲,其上升沿使地址计数器增加。其下降沿使被选通地址单元的数据从
I/O上输出。地址计数器增加到127后返回到0。
__________________
_____| |_____________________________________________ Reset
: :
: _____ : _____ _____ _____ _____
_____:_______| |____:_| |_____| |_____| |_____| |_ Clk
: : : : : : : : : : :
_____:_______:__________:_:_____:_____:_____:_____:_____:_____:_____:_
_____:___n___|_____0____:_|_____1_____|_____2_____|_____3_____|___4_:_ (Address)
: : : : : :
_____: :_______:___________:___________:___________:_
_____XXXXXXXXXXXXXXXXXXXX_______|___________|___________|___________|_ Data
Bit n Bit 0 Bit 1 Bit2 Bit3
写位:
在Reset和Clk端均为低的情况下,如果某地址单元允许写操作(64-103位,且该位必需为
1),则Reset端上的一个脉冲(即从低到高再回低)将允许芯片进行位写操作。在紧跟着的
时钟脉冲期间执行写操作,调整写操作维持时间至少10ms,在这个CLK脉冲期间,地址计数器
不会增加,在CLK写脉冲下降沿,数据0从I/O端输出。从Reset脉冲的上升沿到CLK写脉冲的
下降沿期间,I/O端的数据是无效的。在下一个才CLK脉冲,且Reset为低时,地址计数器又
增1,并在下降沿时,把选通的地址单元的数据送到I/O端。
_____ _____
_____________| |______________________________| |_______________ Reset
: :
___ : _____ ___ : _____
____| |____:__________| |_________| |_____:__________| |____ Clk
: : : : : : : : :
____:________:__________:_____:_________:___:_____:__________:_____:_____
n | n+1 | n+2 | : n+3 | :
(Address)
—-’——–:———-’—–:———’—:—–:———-’—–:—–
: : : : : : :
_________ _: : : ____________: ___: : :
_________XXX_XXXXXXXXXXXXXXXXXXX____________ XX___XXXXXXXXXXXXXXXXXXXXXXX I/O
n n+1 : : n+1 n+2 : :
: : : :
write write
借位写后的字节擦除:
对位地址72-103的字节单元来说,只要在每个字节的前面一位进行一次正常的写操作,就可
以对此字节后一字节进行字节擦除操作。也就是说,每向高一字节进行借位(即写一位
0),紧接着的擦除时序可以对后一字节按字节擦除(即整个字节写1)。被擦除的字节总是
比借位写的字节低一字节。从以下时序图可以看出,首先,完成一个“位写”操作,在CLK
的写脉冲结束后,在CLK为低电平时,在发一个Reset脉冲即启动字节擦除操作。在第二个
CLK脉冲完成字节擦除,脉冲维持时间整定为擦除周期时间(至少1ms)。芯片逻辑控制电路
验证了借位写确已完成从“1”写“0”后,才擦除其低位字节。从Reset的上升沿到擦除操
作的CLK脉冲的下降沿,I/O脚上的数据无效。地址计数器仍然停留在借位写的地址上。
_____ _____
______| |____________________| |_________________________________ Rst
: :
: _______ : _______ ___
______:___________| |______:_____________| |______| |______ Clk
: : : : : : : :
: : : : : : : :
< ————————- address n ————————>:< — n+1 ——
: : : : : : :
: : : : : : :
______: : :______: : :__________: _____
______XXXXXXXXXXXXXXXXXXXXX______XXXXXXXXXXXXXXXXXXXXXXX__________XX_____ I/O
: : n : : n n+1
: : : :
Write Erase
计数方法:
在67-103地址单元中分为5个不可重置8单元计数器,芯片初始化时,72-103地址单元所对应
的4个较低的8单元计数器中可以放0到8个“1”而67-71地址单元所对应的第5个计数器可以
放0到5个“1”。所谓计数一次,就是将一个单元从“1”写成“0”。一个计数器中8位全为
“0”后,要计数,需借位操作,即将高位计数器的一位从“1”写成“0”而相应其低位计
数器整个字节从“0”擦除成“1”。可见4个8单元计数器如此逐一递减,其最大计数为8的4
次方=4096。第5个计数器中5个单元因处在最高位只能被写“0”无法擦成“1”。因此只能
计数5次。故芯片总计数为5X4096=20480。当全部计数单元(地址67-103)都被写成“0”
时,卡片就用完了,不过,芯片出厂初始化时,初置的计数值由国家不同和卡片面值不同而
不同,如100元卡初置计数值为1000。
举例: 100元(1000计数单元预置初始值).
——–
Byte9 Byte10 Byte11 Byte12 Byte13
————————————————————–
000000 - 00000001 - 01111111 - 00011111 - 00000000
————————————————————–
(3)octal (6)octal (7)octal (1)octal (2)octal
————————————————————–
Value = 0*8^4 + 1*8^3 + 7*8^2 + 5*8^1 + 0*8^
————————————————————–
总值 = 1000 Units
Ⅰ-5)内存数据:
字节 位 二进制 十六进制
+———–+—–+
1 1 –> 8 | | |
+———–+—–+
2 9 –> 16 | 0010 1111 | F | —> 德国
| 0011 0111 | | —> 西班牙
| 0011 1011 | B | —> 希腊
+———–+—–+
3 17 –> 24 | | |
4 25 –> 32 | | | —> 出厂编号(写保护)
5 33 –> 40 | | |
6 41 –> 48 | | |
7 49 –> 56 | | |
8 57 –> 64 | | |
+———–+—–+
9 65 –> 72 | | | —> c4096 )
10 73 –> 80 | | | —> c512 )
11 81 –> 88 | | | —> c64 ) 5个8进制计数区
12 89 –> 96 | | | —> c8 )
13 97 –> 104 | | | —> c0 )
+———–+—–+
14 105 –> 112 | 1111 1111 | $FF |
15 113 –> 120 | 1111 1111 | $FF | —> 所有位都为”1″
16 120 –> 128 | 1111 1111 | $FF |
+———–+—–+
下面是一个高人写的程序,以前贴在c51论坛
;2313编程时要选择FSTRT,快速启动
;**** T E L E C A R D S Y S T E M A T T A C K E R ************************
;*
;* Title : TELECARD SIMULATION ROUTE
;* Version : 2.1 (new mode)
;* Last updated : 99.08.18 /99.10.6
;* Card Type : GPM103(Gemplus).SLE4406(Siemens).PCF7960
(Philips)
;*
;* Target : AT90S2313
;* DESCRIPTION
;* This program shows how to implement an AT90S2313
;* as an IC telephony card.
;*
;* Port Usage : PD2(INT0) —> CLK
;* PD3(INT1) —> RST
;* PD4(T0) —> SD
;* XTAL : 10MHz
;*
;***************************************************************************
;Ver 99.10.6
; 1. RST及CLK检测改为中断输入
; 2. 修改擦除过程中读出校验错误的问题(擦除进程ICDATA应右移一位)
(99.10.7)
; 3. RST上升沿使SD变为常高,直至RST下降沿(复位)或CLK下降沿(写/擦除)
; 4. 修正擦除后未清除ERSRDY标志的问题,避免擦除后输出不正确
;Ver 99.10.13
; 1. 仍未解决计费时出错问题,估计写脉冲后输出不对,有待改进
;Ver 99.10.14
; 1.测试:A)加电后,SD端输出为0直至复位后RST下降沿输出
; B)操作期间,RST正脉冲时SD输出为0,写操作时,RST下降沿输出
; 原位地址数据直至写CLK脉冲下降沿.
; C)位地址超过103时,SD输出为1,直至位地址超过127时才翻转为0,
; 即输出为16字节,后3字节为0xFF
; 2.改正程序以与测试结果相符
; 3.费用数据放入EEPROM
;Ver 99.11.10
; 4.擦除及写入后等待相应时间(4ms),此段时间不响应
;Ver 00.3.12
; 1.仔细分析了IC卡,可能用紫外光照射会擦除掉IC卡中EEPROM段信息,即利用
光
; 除掉浮栅上的负电荷,仍需实验,“路漫漫其修远兮,吾将上下而求索!”
; 2.2000/3/25 实验,结论: 悲哀—-不行 :( 阿门,救救我吧!!!!
;Ver 00.3.28
; 1.将写后延时缩短为2ms,嘻嘻嘻嘻嘻嘻。。哈哈。。。咳咳。。呃。 成
功!!!
;Ver 00.3.31
; 1.实验,可打通,但第二次计费时错误断线(打一分钟),估计计费操作之间
IC卡
; 已断电,造成数据不符,须加电池试之,也不排除写操作问题
;Ver 01.2.12
; 1.据说电话机内有金属探测器,须测试之 …….
;
;**** Includes ****
.include “2313def.inc”
;**** Interface pin define ****
.equ CLK = PD2
.equ RST = PD3
.equ SD = PD4
.equ datbuf = 3 ;data buffer pointe to r3
.equ datlgth = 16 ;data buffer length
;**** Global Register Variables ****
.def temp1 = r20 ; Temporary variable
.def temp2 = r21 ; Extra temporary variable
.def mask = r22 ; IC card flag register
.def badr = r23 ; IC card bit address
.def icdata = r24 ; IC card data register
.def status = r25 ; Status register
;mask register flag bit define:
.equ rstcomp = 0 ;Reset card complete
.equ wrtrdy = 1 ;Write ready
.equ wrtcomp = 2 ;Write complete
.equ ersrdy = 3 ;Erasure ready
.equ sdsave = 4 ;Save sd line state
;*******************************************************************************
*******
;IC卡帐号及金额数据区:
.eseg
.ORG 0x00
dat_tab:
.db
0x98,0x35,0x22,0x99,0x02,0x55,0x61,0xa0,0x00,0x00,0x7f,0x3f,0x0f,0xff
,0xff,0xff
; [ CHD ] [ ID ] [ COUNTER ]
; 7*64+6*8+4=497=
;*******************************************************************************
*******
;**** Interrupt Vectors **** code segment
.cseg
.org 00
rjmp RESET ; Reset handle
rjmp CLK_INT ; INT0 handle
rjmp RST_INT ; INT1 handle
; rjmp ICP_INT ; Input Capture1 Interrupt
; rjmp OC1_INT ; Output Compare1 Interrupt
; rjmp OVF1_INT ; Overflow1 Interrupt
; rjmp OVF0_INT ; Overflow0 Interrupt
; rjmp RX_END ; UART Receive Complete
; rjmp UDR_EMP ; UART Data Register Empty
; rjmp TX_END ; UART Transmit Complete
; rjmp AC_INT ; Analog Comparator
;***************************************************************************
;*
;* FUNCTION
;* CLK_INT
;*
;* DESCRIPTION
;* Detect ICcard reader’s CLK line
;*
;***************************************************************************
CLK_INT:
sbis PIND,CLK
rjmp CLK_fall
CLK_rise: ;CLK rising edge
sbic PIND,RST
rjmp IC_reset
sbrc mask,wrtrdy
rjmp IC_WRT
sbrc mask,ersrdy
rjmp IC_ERS
cbr mask,(1<
inc badr
cpi badr,8
brne CLK_riseret ; bit address =< 7,not
ready new data
clr badr
inc ZL
cpi ZL,datbuf+datlgth
brne rdydata
ldi ZL,datbuf
rdydata:
ld icdata,Z
rjmp CLK_riseret
IC_WRT:
lsr icdata ;right rotate
andi icdata,0b01111111 ;write 0 to current bit address
cbr mask,1<
sbr mask,1<
mov temp1,badr
inc temp1
ser temp2 ;temp2 <– 0xff
clc ;clr C flag
shift:
ror temp2
dec temp1
brne shift
ld temp1,Z
and temp1,temp2
st Z,temp1
rjmp WrtDelay
IC_ERS:
lsr icdata
andi icdata,0b01111111 ;write 0 to current bit address
mov temp1,ZL ;ZL –> temp1
ser temp2 ;temp2 < — 0xff
inc ZL
ers_nxt:
st Z+,temp2 ;(Z) <– 0xff, Z <– Z+1
cpi ZL,datbuf+datlgth
brne ers_nxt
mov ZL,temp1 ;ZL <– temp1
cbr mask,1<
WrtDelay: ;Write 1/0,delay 1ms
ldi temp1,100
WrtDelay1:
ldi temp2,33 ;1
WrtDelay2:
dec temp2 ;1
brne WrtDelay2 ;2 33(1+2)
dec temp1 ;1
brne WrtDelay1 ;2 [33(1+2)+1+2]
*100=10200*100ns=1.02ms
rjmp CLK_riseret
IC_reset: ;reset iccard
clr badr
clr ZH
ldi ZL,datbuf
ld icdata,Z
sbr mask,(1<
cbr mask,(1<<<<
CLK_riseret:
in temp1,MCUCR
cbr temp1,1<
out MCUCR,temp1 ;set INT1 to interrupt on
falling edge
reti
CLK_fall: ;CLK falling edge
sbrc mask,rstcomp
rjmp CLK_fallret
SD_out:
lsl icdata ;output data bit
brcs SD_high
cbi PORTD,SD
rjmp CLK_fallret
SD_high:
sbi PORTD,SD
CLK_fallret:
in temp1,MCUCR
sbr temp1,1<
out MCUCR,temp1 ;set INT1 to interrupt on
rising edge
reti
;***************************************************************************
;*
;* FUNCTION
;* RST_INT
;*
;* DESCRIPTION
;* Detect ICcard reader’s RST line
;*
;***************************************************************************
RST_INT:
sbic PIND,RST
rjmp RST_rise
RST_fall: ;RST falling edge interrupt
sbrs mask,rstcomp
rjmp Cmp_rst
cbr mask,(1<
lsl icdata ;rstcomp=1,output 1st bit
after reset
brcs setSD
cbi PORTD,SD
rjmp RST_fallret
setSD:
sbi PORTD,SD
RST_fallret:
in temp1,MCUCR
sbr temp1,(1<
out MCUCR,temp1
reti
Cmp_rst:
sbrc mask,wrtcomp
rjmp Cmp_rst1
sbr mask,(1<
cbi PORTD,SD ;output old bit
sbrc mask,sdsave
sbi PORTD,SD
rjmp RST_fallret
Cmp_rst1:
sbr mask,(1<
cbr mask,(1<
cbi PORTD,SD ;output old bit
sbrc mask,sdsave
sbi PORTD,SD
rjmp RST_fallret
RST_rise: ;RST rising edge interrupt
cbr mask,1<
sbic PIND,SD
sbr mask,1<
cbi PORTD,SD ;Active SD to low until CLK falling
edge
in temp1,MCUCR
cbr temp1,(1<
out MCUCR,temp1
reti
;***************************************************************************
;*
;* FUNCTION
;* ic_init/rd_tab
;*
;* DESCRIPTION
;* Initialization of port used by the IC interface
;* and get out data stored by EEPROM .
;*
;***************************************************************************
RESET:
ic_init:
cli ;disable all
interrupt
ldi temp1,low(RAMEND) ;initialize stack
out SPL,temp1
ldi temp1,(0<<<
out DDRD,temp1
ldi temp1,(0<<<
out PORTD,temp1
;*** read eeprom data table ***
rd_eeprom:
clr ZH
ldi ZL,datbuf ; Load low part of byte address into
ZL
clr temp1
loadbyte:
out EEAR,temp1
sbi EECR,EERE ;set EEPROM Read strobe
in temp2,EEDR ;get data
st Z+,temp2 ;store to SRAM (Z),Z <– Z+1
inc temp1
cpi ZL,datbuf+datlgth ;reached the end? (16bytes)
brne loadbyte ;if not, loop more
;**** Interrupt Initialization ****
ldi temp1,(1<<<<
INT0/INT1(rising edge)
out MCUCR,temp1
;
ldi temp1,(1<<
out GIFR,temp1
ldi temp1,(1<<
out GIMSK,temp1
;*** flag mask and register initialize ***
clr mask
ldi ZL,datbuf
clr badr
sei ;Enable global interrupt
LOOP: rjmp LOOP
—–此内容被jdog于2005-02-23,22:56:11编辑过
我公布元程序,是去年用CV写的,程序有些记不清了,所以没有注释
程序比较垃圾,有兴趣就看一下吧
用Tiny13,连接如下
,————+————,
| 8 | 4 |
+——\ | /——+
| 7 +—-+—-+ 3 |
+——-| |——-+
| 6 + +—-+ 2 |
+——/ | \——+
| 5 | 1 |
‘————+————’
8-〉Tiny13.8
7-〉Tiny13.7
6-〉Tiny13.6
6-〉NC
4-〉Tiny13.4
3-〉Tiny13.1(Reset,仅在ISP时有用,平时不用)
2-〉Tiny13.5
1-〉NC
#pragma regalloc-
register char index @4;
register char ibit @5;
register char rst @6;
register char temp @7;
register char deced @8;
#pragma regalloc+
//前8字节为地区IC卡数据,接着5字节为计数值,后3字节不用动
//所有字节均要倒序比如01001000B就要写00010010B
eeprom unsigned char card[16]={0x98,0x35,0x22,0x99,0x02,0x55,0x61,0xa0,0x00,0x00,0x7f,0x3f,0x0f,0xff,0xff,0xff};
interrupt [EXT_INT0] void ext_int0_isr(void)
{
#asm
CLI
in r7,0x16
bst r7,2
brtc notrst
clr r4
clr r5
clr r8
rjmp go
notrst:
mov r0,r6
dec r0
brpl decv
clr r8
INC R5
LDI R30,LOW(7)
CP r30,r5
BRSH noinc
CLR R5
INC R4
noinc:
LDI R30,LOW(15)
CP R30,r4
BRSH go
CLR R4
rjmp go
decv:
LDI r30,low(8)
cp r4,r30
brlo go
LDI r30,low(13)
cp r4,r30
brsh go
cp r4,r8
brne write
MOV R30,R4
SUBI R30,-LOW(1)
CLR R31
SUBI R30,LOW(-_card)
SBCI R31,HIGH(-_card)
MOVW R26,R30
ser R30
ST X,R30
mov r31,r4
inc r31
RCALL EEPROMWRB
clr r8
rjmp go
write:
LDI R30,LOW(1)
MOV R0,R5
rrl:
DEC R0
BRMI rok
LSL R30
rjmp rrl
rok:
MOV R7,R30
COM R7
MOV R30,R4
CLR R31
SUBI R30,LOW(-_card)
SBCI R31,HIGH(-_card)
PUSH R31
PUSH R30
LD R30,Z
AND R30,R7
POP R26
POP R27
ST X,R30
mov r8,r4
mov r31,r4
RCALL EEPROMWRB
go:
clr r6
sei
#endasm
}
// Pin change interrupt service routine
interrupt [PCINT0] void pin_change_isr(void)
{
#asm
sbic 0x16,2
inc r6
#endasm
}
// Declare your global variables here
void main(void)
{
OSCCAL=0x7f;
PORTB=0x00;
DDRB=0x1;
GIMSK=0x60;
MCUCR=0x03;
PCMSK=0x04;
GIFR=0x60;
ACSR=0x80;
#asm
LDI R30,LOW(16)
MOV R4,R30
CLR R0
CLR R5
CLR R8
LDI R26,LOW(_card)
ldi r30,low(8)
mov r6,r30
ldi r30,low(12)
mov r7,r30
load:
SBIC EECR,EEWE
RJMP load
OUT EEARL,R0
SBI EECR,EERE
IN R30,EEDR
cp r0,r6
brlo notv
cp r0,r7
brsh notv
or r5,r30
notv:
ST X,R30
INC R26
INC R0
CP R0,R4
BRSH loaded
RJMP load
loaded:
cp r5,r8
BRNE ready
subi r26,6
clr r27
ldi r30,low(254)
st x,r30
;要加钱了
ready:
clr R4
clr r5
clr r6
sei
#endasm
while (1)
{
temp=card[index];
temp>>=ibit;
#asm
bst r7,0
in r7, 0x18
bld r7,0
out 0x18,r7
#endasm
};
//R31:地址,R30:数据
#asm
EEPROMWRB:
SBIC EECR,EEWE
RJMP EEPROMWRB
IN R0,SREG
CLI
OUT EEARL,R31
SBI EECR,EERE
IN R7,EEDR
;CP R30,R7
;BREQ EEPROMWRB0
OUT EEDR,R30
SBI EECR,EEMWE
SBI EECR,EEWE
EEPROMWRB0:
OUT SREG,R0
ret
#endasm
}
On June 3, 2006 7:45 am
你是否已经掌握以上技术?请指教!
Comment by dylsu — June 8, 2007 @ 9:27 pm