新闻  |   论坛  |   博客  |   在线研讨会
我的DSP之路-关于变量定义和位操作宏
chen_yuangui | 2009-09-06 12:39:15    阅读:8174   发布文章

1.DSP指令没有位寻址,也没有位设置。要设置寄存器的某一位,可以写如下语句:
位清0:                                        位置1:
        LACC        *                                LACC        *       
        AND        #0FFF7H                        OR                #0008H
        SACL        *                                SACL        *

我们可以这样定义位:
        B0                .set                0001h               
        B1                .set                0002h
        B2                .set                0004h
        …
        B15                .set                8000h
再如下宏定义
BCLR        .macro        DMA, MASK                ;Clear bit Macro        (BCLR是PIC33位清除指令)
                LACC        DMA                               
                AND        #(0FFFFh-MASK)               
                SACL        DMA                               
                .endm

BSET        .macro        DMA, MASK                ;Set bit Macro                (BSET是PIC33位设置指令)
                LACC        DMA
                OR        #(MASK)
                SACL        DMA
                .endm
因为SACL可以直接和间接寻址,所以宏也可以直接和间接寻址,但在间接寻址时禁止改变当前AR和ARP;否则会出错。

对于一些如外设寄存器,如地址为7018H的系统配置寄存器SCSR1,我们可以如下定义:
SCSR1                .set                7018h

CLKSRC                .set                4000h
LPM1                .set                2000h
LPM0                .set                1000h
CLKPS2                .set                0800h
CLKPS1                .set                0400h
CLKPS0                .set                0200h
ADC_CLKEN        .set                0080h
SCI_CLKEN        .set                0040h
SPI_CLKEN        .set                0020h
CAN_CLKEN        .set                0010h
EVB_CLKEN        .set                0008h
EVA_CLKEN        .set                0004h
ILLADR                .set                0001h

调用宏:1.直接寻址                                2.间接寻址
MAR         *, AR0                                LDP                #0E0H                (SCSR1高9位地址)
                LAR         AR0, # SCSR1                BSET        SCSR1,CLKSRC       
                BSET         *, CLKSRC                        BCLR        SCSR1, CLKSRC       
                BCLR         *, CLKSRC
间接寻址看起来更直观,LDP指令没有移位载入功能,所以在写LDP指令时还要计算其高9位地址的值,这有点不方便。
直接寻址如果直接加载地址到当前AR,可以少写MAR *, AR0这条指令,即直观,又方便。
执行完宏后如果有必要,要注意DP和AR的恢复。

下面是关于清看门狗的宏:
KICK_DOG        .macro                                                ;Watchdog reset macro
                LDP                #WDKEY>>7                                ;DP-->7000h-707Fh
                SPLK        #05555h, WDKEY                        ;WDCNTR is enabled to be reset by next AAh
                SPLK        #0AAAAh, WDKEY                ;WDCNTR is reset
                .endm
这里的WDKEY定义的也是16位的地址,用直接寻址,自动舍弃高位。
踢狗宏里面没有恢复DP针指,所以在踢完狗后要注意DP指针的恢复。
2008-3-7
关于页面指针的装载
        .bss                x, 1
        LDP                #x
WDKEY        .set        7025h
        LDP                #WDKEY>>7
.bss                x, 1是定义一个变量x,#x就是一个16位的地址,而LDP                #x指令自动的取其地址的高9位送到DP。相当于C语言中的&x。
WDKEY        .set        7025h是定义一个符号名,用法与变量x不同
LDP                #WDKEY>>7       
如果写成LDP        #x>>7或LDP        #WDKEY都是错误的。
以下是对x,WDKEY赋值的直接、间接寻址方式的正确写法:
直接寻址                                        间接寻址
LDP                #x                                        MAR        *, AR1
SPLK        #3000H, x                        LAR        AR1, #x
SPLK        #3000H, x+1                        SPLK        #3000H, *
;赋值下一个存储单元

LDP                #WDKEY>>7                        MAR        *,AR1
SPLK        #55H, WDKEY                LAR        AR1, #WDKEY
SPLK        #AAH, WDKEY                SPLK        #55H, *
;警告,但自动丢掉高9位

.set定义的符号不占数据存储空间,符号代表的是值本身。而用.bss        .WORD等定义的变量是要占数据空间的,变量或常量名代表的是地址而不是其值。

2008-3-7
如果把位测试一起做成宏的话,在BIT                dma, bit code(测试位号=15-bit code)中定义位的话是如下定义:
B0                .set                15
B1                .set                14
…                                  
B15                .set                0
如果要让位的定义统一的话,即在BSET、BCLR、BTST(位测试)中都可以用的话,要改BSET、BCLR宏。修改如下:
BCLR        .macro        DMA, MASK                ;Clear bit Macro        (BCLR是PIC33位清除指令)
                LACC        DMA                               
                AND        #(0FFFFh-(8000h>>MASK))               
                SACL        DMA                               
                .endm

BSET        .macro        DMA, MASK                ;Set bit Macro                (BSET是PIC33位设置指令)
                LACC        DMA
                OR                #(8000h>>MASK)
                SACL        DMA
                .endm

BTST        .macro        DMA, MASK                ;Text bit Macro        (BTST是PIC33的位测设指令)
                BIT                DMA, MASK
                .endm
可以看出关于位测试完全没有必要做成宏,我们要做的只是把两种位定义做成一样的就好了。
关于BSET、BCLR宏参数DMA,其说明是用直接寻址,但用(也只能用)间接寻址中的*操作符也可以。
2008-3-12
宏定义BCLR、BSET是把要设的位清0置1,没设的位原值写入。这对如中断标志位等写1清零的位操作时会出错。
这些位有的是整个寄存器都是写1清零的标志位,有的寄存器又只有一两位。应该如何写通用的BSET、BCLR宏呢?
写1清零的位有:
SCSR2<5>WD_OVERRIDE
WDCR<7>WDFLAG
XINT1CR<15>FLAG                  XINT2CR<15>FLAG       
以上只有一个位的,对其清0置1还可以用原来的BSET、BCLR宏。但对其同字的其他位操作时要注意不要改变标志位。
EVAIFRA        EVAIFRB        EVAIFRC
EVBIFRA        EVBIFRB        EVBIFRC
IFR
对整个字都是标志位的,我们可以另外定义清标志位宏:
FCLR        .macro        DMA, MASK                ;Clear bit Macro        (FLAG  CLR)
                LACC        #8000h>>MASK                                
                SACL        DMA                               
                .endm
不需要置标志位宏。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
我们赖以生存的空间每时每刻都在变化着,正是它的非线性赋予了我们五彩缤纷的生活!
推荐文章
最近访客