最近因为需要使用STC 1T单片机进行RFID ISO15693 标签读写
调制发送信号时需要周期为 9.44us 左右的精确的同步信号
STC单片机使用 22.1184M 晶振,单周期指令执行时间约为 0.04521us 所以 9.44us时间段大约可执行 208.8 条单周期指令
所以有以下代码
while(1)
{
TL0=0;
//.. 可伸缩地执行少量其它代码
while(TL0<205);
OUTPIN = ~OUTPIN;
}
但实际用示波器对OUTPIN 上信号波形进行观察,发现存在不稳定的现像, 偏差最大时约 0.28us
对该段代码汇编后的汇编语句进行分析, 发现 while(TL0<205); 居然要4条语句才能实现
0034 ?C0057:
0034 E58A MOV A,TL0
0036 C3 CLR C
0037 947F SUBB A,#07FH
0039 40F9 JC ?C0057
对如上汇编代码,如果 MOV A,TL0 执行时TL0 值恰好为 204
哪么多执行一轮就得多耗掉 6个指令周期 恰好为 0.28us
显然无论怎么实现,要测试TL0中值至少得4个指令周期 误差最大为 T x 2 - 2 = 6 周期 这个避免不了
while(x<y) _nop_(); 这样的代码是也存在同样问题。
使用C语的情况下暂时有且只发现switch可以实现误差补偿
while(1)
{
TL0=0;
//.. 可伸缩地执行少量其它代码
while(TL0<(205-16)); // 这个 16可跟据输出进行微调
uTime -= TL0;
switch(uTime)
{
case 8: _nop_();
case 7: _nop_();
case 6: _nop_();
case 5: _nop_();
case 4: _nop_();
case 3: _nop_();
case 2: _nop_();
case 1: _nop_();
case 0: break;
}
OUTPIN = ~OUTPIN;
}
以上代码对的汇编语句容易看出, 执行 NOP 句代数目在uTime-=TL0(SUBB A,TL0)哪一刻就确定了
003B C3 CLR C
003C E500 R MOV A,uTime
003E 958A SUBB A,TL0
0040 F500 R MOV uTime,A
0042 14 DEC A
0043 B41400 CJNE A,#014H,?C0168
0046 ?C0168:
0046 505E JNC ?C0059
0048 900000 R MOV DPTR,#?C0169
004B 75F003 MOV B,#03H
004E A4 MUL AB
004F C583 XCH A,DPH
0051 25F0 ADD A,B
0053 C583 XCH A,DPH
0055 73 JMP @A+DPTR
0056 ?C0169:
0056 020000 R LJMP ?C0079
0059 020000 R LJMP ?C0078
005C 020000 R LJMP ?C0077
005F 020000 R LJMP ?C0076
0062 020000 R LJMP ?C0075
0065 020000 R LJMP ?C0074
0068 020000 R LJMP ?C0073
006B 020000 R LJMP ?C0072
006E 020000 R LJMP ?C0071
0071 020000 R LJMP ?C0070
0074 020000 R LJMP ?C0069
0077 020000 R LJMP ?C0068
007A 020000 R LJMP ?C0067
007D 020000 R LJMP ?C0066
0080 020000 R LJMP ?C0065
0083 020000 R LJMP ?C0064
0086 020000 R LJMP ?C0063
0089 020000 R LJMP ?C0062
008C 020000 R LJMP ?C0061
008F 020000 R LJMP ?C0060
009D ?C0071:
009D 00 NOP
009E ?C0072:
009E 00 NOP
009F ?C0073:
009F 00 NOP
00A0 ?C0074:
00A0 00 NOP
00A1 ?C0075:
00A1 00 NOP
00A2 ?C0076:
00A2 00 NOP
00A3 ?C0077:
00A3 00 NOP
00A4 ?C0078:
00A4 00 NOP
00A5 ?C0079:
00A5 00 NOP
大家还有没更好办法?欢迎一起来讨论。