LGT端口输入寄存器PINA/B/C/D 正确使用方法 【重要,与AVR不同】
在另一个帖子讨论到,重新开个帖子方便需要的人---------------------------------------------------------------------------------------
手册资料:
考虑到软件能够及时获得端口信号的变化, PINA/B/C/D输入为异步设计,直接反应端口的状态。但这样的做法也同时带来了一些信号同步的问题。建议用户在直接使用端口状态进行程序流程控制时,采用必要的软件滤波算法。 同时也避免直接使用PINA/B/C/D寄存器的值进行程序流程控制,而是首先使用IN指令将其读到内部寄存器,然后使用寄存器的值作后续处理。下面将给出建议的使用端口作为程序流程控制的代码
汇编代码实例
Label:
in r16, PINA
; Skip if PINA is clear, avoid to use sbic directly
sbrc r16, 1
; Skip if PINA is set, avoid to use sbis directly
sbrs r16,1
…..
C语言代码实例
volatile unsigned char pv; /*volatile is necessary to disable optimize on ‘pv’ */
/* wait until PINA is set */
do {
pv = PINA;
} while ((pv&0x2) != 0x02); /* avoid to use while(PINA&0x2) */
手册中提到的这个问题其实很严重,如果没有按照手册中代码写,你的程序很可能运行着就自动复位或者跑飞了。 详细原因手册没有提及。简单原因就是LGT sbic 和 sbis指令针对PINA/B/C/D这几个寄存器操作有局限性。 只有当PIN脚的电平确定,不会变化时才可以用。其它内部IO,由于电平在一个指令周期内确定,因此不受影响。
因此我们在AVR中常用的,比如说检测一个按键 if(!(PINA & 1<<PA0)){xxx} 这样的代码在LGT中就不可以使用了。需要这样:volatile unsigned char tempPina;
tempPina = PINA;
if(!(PINA & 1<<PA0)){xxx}那个变量必须加volatile限定,不然编译器会自动忽略这个变量,直接使用sbic指令了。
但是这样写法大大降低了效率,查看反汇编会发现,多了两条指令。总共需要4条指令。 4个时钟周期,如果是AVR的话,一条sbic需要2个时钟周期,这样LGT的速度就没AVR快了。 {
volatile unsigned char tempPina;
tempPina = PINA;
9e: 80 b1 in r24, 0x00 ; 0
a0: 89 83 std Y+1, r24 ; 0x01
if(!(tempPina & 1<<PA0))
a2: 89 81 ldd r24, Y+1 ; 0x01
a4: 80 fd sbrc r24, 0
a6: fb cf rjmp .-10 ; 0x9e <main+0xa>那如何改进呢。 这里提供一个方法,把PINA重新定义一下。其它端口同理。inline unsigned char LGT_PINA()
{
register unsigned char temp;
temp=PINA;
asm volatile ("" : "+r"(temp));
return temp;
}
#undef PINA
#define PINA LGT_PINA()这样代码可以写的和以前AVR一样:
if(!(PINA & 1<<PA0)){xxx}
看一下反汇编效果:inline unsigned char LGT_PINA()
{
register unsigned char temp;
temp=PINA;
94: 80 b1 in r24, 0x00 ; 0
int main(void)
{
while(1)
{
if(!(PINA & 1<<PA0))
96: 80 fd sbrc r24, 0
98: fd cf rjmp .-6 ; 0x94 <main>
{
asm("nop");
9a: 00 00 nop
9c: fb cf rjmp .-10 ; 0x94 <main>这样就是两条指令了。 一个 in,一个sbrc 达到跟直接写汇编一样的效果。
标记一下,很重要 楼主好细心,学习了! 多谢波仔。这个绝对要MARK。 谢谢波仔的老爸。 这个用法太绝了!嵌入汇编......速度优化了。 谢谢的分享,还有之前内存指针的帖子 建议版主置顶 要标记{:loveliness:} 必须顶。今早试过了,对比效果非常明显。
如果直接判定IO,当IO口加1MHZ的方波信号,会频繁复位
用了lz程序,测试到6MHZ都没问题。而且编译效率很好 楼主够细心的。
折腾LGT的人越多,资料也越完善 怪不得前两天调试的时候,将优化等级调为s后,一运行到按键扫描处就死机,后面只有加了volatile后解决,原来是这个原因。 重要内容。 logicgreen 发表于 2012-6-7 11:10 static/image/common/back.gif
谢谢波仔的老爸。
为何谢他老爸?{:titter:} 这个要标记一下 本帖最后由 logicgreen 于 2012-6-7 15:20 编辑
plc_avr 发表于 2012-6-7 14:01 static/image/common/back.gif
为何谢他老爸?
我错了,谢谢波仔。 哈哈,简单的逻辑推理 logicgreen 发表于 2012-6-7 14:57 static/image/common/back.gif
波仔应该照片的那个小孩,LZ主应该就是波仔老爸,不对么?
你不知道乱说要打PP的!{:lol:} logicgreen 发表于 2012-6-7 14:57 static/image/common/back.gif
波仔应该照片的那个小孩,LZ主应该就是波仔老爸,不对么?
1.楼主叫波仔
2.照片是个美女 logicgreen 发表于 2012-6-7 14:57 static/image/common/back.gif
我错了,谢谢波仔。
哈哈,照片是我女儿。去年刚生的。 学习学习了,多谢 曾经受此困扰,一直查不到原因,谢谢您提供的资料 关注一下 高手如云呀
又学了壹招~~~谢谢分享~~~ 重要标记,现在关注下后续Ic的adc输入阻抗 这个重要 ADC输入应该内置一个采样保持,以降低输入阻抗。 zhiwei 发表于 2012-6-8 09:25 static/image/common/back.gif
ADC输入应该内置一个采样保持,以降低输入阻抗。
不是吧,我还想要输入阻抗∞呢,你还要降低? 学习学习 呵呵。说错了,增大IC输入阻抗,减小对为外部阻抗要求。 zhiwei 发表于 2012-6-8 09:25 static/image/common/back.gif
ADC输入应该内置一个采样保持,以降低输入阻抗。
一般来说SAR ADC必须有采样保持的,而且现在猜测LGT就是为了提高转换速度,把采样保持电容加大了才导致输入阻抗下降。
比较理想的做法是采样保持前面加个buffer,这又牵涉精度和成本问题了…… 支持波仔,难怪之前按键检测不对,都扔一边了! 学习学习 波仔在小波没出生时就是这个名字了~~
波仔这篇写得非常不错,有很高的指导意义! logicgreen 发表于 2012-6-7 11:10 static/image/common/back.gif
谢谢波仔的老爸。
请问一下这个现象以后的版本中会不会得到改进么? zhuisuoji 发表于 2012-6-14 01:37 static/image/common/back.gif
请问一下这个现象以后的版本中会不会得到改进么?
以后的会改进。 mark ... 我用IAR编译出现下面的错误,请问如何解决呢? 标记一下 初学,看看{:lol:} oste_ 发表于 2012-6-14 15:52 static/image/common/back.gif
我用IAR编译出现下面的错误,请问如何解决呢?
这个我没用过IAR,不清楚IAR的内嵌汇编如何写 这个问题值得注意,谨慎使用SBIC,SBIS检测IO状态。 编译过度优化或强行优化是很讨厌的问题,可能给编程带来极大的困扰和麻烦,甚至隐患。 mark!!!!!!!!!!!!!!!!!!!!!!!!!!!! 强顶楼主 顶楼主{:victory:} 等待问题的解决 楼主能否说下PIN的输出用法,我用简单的一个“PORTC^=(1<<x)”命令对C端口操作,发现PC0能正常反转,C端口的其他端口都不能反转,郁闷了几天,现在还不知道怎么回事?注x=0,1,2,3
求答,谢谢! inline unsigned char LGT_PINA()
{
register unsigned char temp;
temp=PINA;
asm volatile ("" : "+r"(temp));
return temp;
}
#undef PINA
#define PINA LGT_PINA() 这种方法,有时候能识别,有时候不能识别啊。 分析的很有条理,学习了。谢谢 不错,学习了 准备使用LGT,顶。 谢谢,学习!!!{:smile:} 一个函数的跳转不会增加指令执行的时间吗? zhonggp 发表于 2012-12-11 19:49 static/image/common/back.gif
一个函数的跳转不会增加指令执行的时间吗?
使用的是内联函数...
页:
[1]