bozai 发表于 2012-6-7 11:02:15

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 达到跟直接写汇编一样的效果。




Appcat 发表于 2012-6-7 11:05:09

标记一下,很重要

ITOP 发表于 2012-6-7 11:05:12

楼主好细心,学习了!

plc_avr 发表于 2012-6-7 11:07:49

多谢波仔。这个绝对要MARK。

logicgreen 发表于 2012-6-7 11:10:51

谢谢波仔的老爸。

plc_avr 发表于 2012-6-7 11:12:16

这个用法太绝了!嵌入汇编......速度优化了。

goodcode 发表于 2012-6-7 11:21:37

谢谢的分享,还有之前内存指针的帖子 建议版主置顶

donny_y 发表于 2012-6-7 12:07:48

要标记{:loveliness:}

sf49ers 发表于 2012-6-7 12:18:05

必须顶。今早试过了,对比效果非常明显。
如果直接判定IO,当IO口加1MHZ的方波信号,会频繁复位
用了lz程序,测试到6MHZ都没问题。而且编译效率很好

rifjft 发表于 2012-6-7 13:25:38

楼主够细心的。

折腾LGT的人越多,资料也越完善

dreampet 发表于 2012-6-7 13:40:38

怪不得前两天调试的时候,将优化等级调为s后,一运行到按键扫描处就死机,后面只有加了volatile后解决,原来是这个原因。

lxvtag 发表于 2012-6-7 13:46:26

重要内容。

plc_avr 发表于 2012-6-7 14:01:30

logicgreen 发表于 2012-6-7 11:10 static/image/common/back.gif
谢谢波仔的老爸。

为何谢他老爸?{:titter:}

liudingding 发表于 2012-6-7 14:14:07

这个要标记一下

logicgreen 发表于 2012-6-7 14:57:08

本帖最后由 logicgreen 于 2012-6-7 15:20 编辑

plc_avr 发表于 2012-6-7 14:01 static/image/common/back.gif
为何谢他老爸?

我错了,谢谢波仔。

inter_zhou 发表于 2012-6-7 15:05:34

哈哈,简单的逻辑推理

plc_avr 发表于 2012-6-7 15:13:18

logicgreen 发表于 2012-6-7 14:57 static/image/common/back.gif
波仔应该照片的那个小孩,LZ主应该就是波仔老爸,不对么?

你不知道乱说要打PP的!{:lol:}

gzhuli 发表于 2012-6-7 15:16:04

logicgreen 发表于 2012-6-7 14:57 static/image/common/back.gif
波仔应该照片的那个小孩,LZ主应该就是波仔老爸,不对么?

1.楼主叫波仔
2.照片是个美女

bozai 发表于 2012-6-7 15:38:55

logicgreen 发表于 2012-6-7 14:57 static/image/common/back.gif
我错了,谢谢波仔。

哈哈,照片是我女儿。去年刚生的。

hpdell 发表于 2012-6-7 15:48:10

学习学习了,多谢

jianjun42 发表于 2012-6-7 15:54:17

曾经受此困扰,一直查不到原因,谢谢您提供的资料

jinqiankun 发表于 2012-6-7 21:01:22

关注一下

moouse 发表于 2012-6-7 21:54:08

高手如云呀

zhuisuoji 发表于 2012-6-7 22:10:15

又学了壹招~~~谢谢分享~~~

xsh2005105326 发表于 2012-6-7 22:13:58

重要标记,现在关注下后续Ic的adc输入阻抗

ylei12 发表于 2012-6-7 23:16:39

这个重要

zhiwei 发表于 2012-6-8 09:25:47

ADC输入应该内置一个采样保持,以降低输入阻抗。

mowin 发表于 2012-6-8 09:42:52

zhiwei 发表于 2012-6-8 09:25 static/image/common/back.gif
ADC输入应该内置一个采样保持,以降低输入阻抗。

不是吧,我还想要输入阻抗∞呢,你还要降低?

bobo2888 发表于 2012-6-8 09:44:30

学习学习

zhiwei 发表于 2012-6-8 10:59:09

呵呵。说错了,增大IC输入阻抗,减小对为外部阻抗要求。

gzhuli 发表于 2012-6-8 11:21:30

zhiwei 发表于 2012-6-8 09:25 static/image/common/back.gif
ADC输入应该内置一个采样保持,以降低输入阻抗。

一般来说SAR ADC必须有采样保持的,而且现在猜测LGT就是为了提高转换速度,把采样保持电容加大了才导致输入阻抗下降。
比较理想的做法是采样保持前面加个buffer,这又牵涉精度和成本问题了……

jlhgold 发表于 2012-6-8 11:37:10

支持波仔,难怪之前按键检测不对,都扔一边了!

bobo2888 发表于 2012-6-8 15:21:02

学习学习

fsclub 发表于 2012-6-8 16:26:18

波仔在小波没出生时就是这个名字了~~

波仔这篇写得非常不错,有很高的指导意义!

zhuisuoji 发表于 2012-6-14 01:37:44

logicgreen 发表于 2012-6-7 11:10 static/image/common/back.gif
谢谢波仔的老爸。

请问一下这个现象以后的版本中会不会得到改进么?

logicgreen 发表于 2012-6-14 11:17:10

zhuisuoji 发表于 2012-6-14 01:37 static/image/common/back.gif
请问一下这个现象以后的版本中会不会得到改进么?

以后的会改进。

ahfong2006 发表于 2012-6-14 14:14:28

mark ...   

oste_ 发表于 2012-6-14 15:52:20

我用IAR编译出现下面的错误,请问如何解决呢?

10646686 发表于 2012-6-14 16:40:01

标记一下

苦行僧 发表于 2012-6-29 08:11:58

初学,看看{:lol:}

bozai 发表于 2012-6-29 12:47:51

oste_ 发表于 2012-6-14 15:52 static/image/common/back.gif
我用IAR编译出现下面的错误,请问如何解决呢?

这个我没用过IAR,不清楚IAR的内嵌汇编如何写

logicgreen 发表于 2012-6-29 17:11:02

这个问题值得注意,谨慎使用SBIC,SBIS检测IO状态。

su_mj000 发表于 2012-7-2 13:03:40

编译过度优化或强行优化是很讨厌的问题,可能给编程带来极大的困扰和麻烦,甚至隐患。

Tliang 发表于 2012-9-9 14:31:05

mark!!!!!!!!!!!!!!!!!!!!!!!!!!!!

ybx520 发表于 2012-9-13 12:08:00

强顶楼主

ybx520 发表于 2012-9-15 21:12:30

顶楼主{:victory:}

ybx520 发表于 2012-9-17 21:06:10

等待问题的解决

AAaa00002012 发表于 2012-10-9 09:16:33

楼主能否说下PIN的输出用法,我用简单的一个“PORTC^=(1<<x)”命令对C端口操作,发现PC0能正常反转,C端口的其他端口都不能反转,郁闷了几天,现在还不知道怎么回事?注x=0,1,2,3
求答,谢谢!

cheky77 发表于 2012-11-4 13:20:40

inline unsigned char LGT_PINA()
{
      register unsigned char temp;
      temp=PINA;
      asm volatile ("" : "+r"(temp));
      return temp;      
}
#undef PINA
#define PINA LGT_PINA()   这种方法,有时候能识别,有时候不能识别啊。

cumt_123456 发表于 2012-11-8 23:39:19

分析的很有条理,学习了。谢谢

michael1517 发表于 2012-11-11 20:00:15

不错,学习了

ziho2005 发表于 2012-12-8 17:45:54

准备使用LGT,顶。

dory_m 发表于 2012-12-10 15:47:00

谢谢,学习!!!{:smile:}

zhonggp 发表于 2012-12-11 19:49:47

一个函数的跳转不会增加指令执行的时间吗?

foxpro2005 发表于 2013-5-11 12:58:53

zhonggp 发表于 2012-12-11 19:49 static/image/common/back.gif
一个函数的跳转不会增加指令执行的时间吗?

使用的是内联函数...
页: [1]
查看完整版本: LGT端口输入寄存器PINA/B/C/D 正确使用方法 【重要,与AVR不同】