⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr微秒级与毫秒级精确延时.txt

📁 AVR128的毫秒和微秒级的精确延时程序。
💻 TXT
字号:
AVR微秒级与毫秒级精确延时

/*******************************************************************

                             微秒级精确延时(ICC)

*******************************************************************/

include <iom8v.h>
/*======================================
 微秒级精确延时函数,晶振8M:           
 Delay = 0.125 *((tt*4-1)+9)微秒
 其中9包括了调用方的 r16 赋值 1t
 rcall 3t    nop 1t   ret 4t
 brne指令在当判断条件不成立时是单周期
 最后一次判断只有1个周期,补一个nop
 简化计算 = 0.5tt + 1 (us)
======================================*/
void shortdelay(unsigned char tt)
{
        asm("_L2: subi R16,1");  
        asm(" nop") 
        asm(" brne _L2");
        asm(" nop");
        asm(" ret");
}

void main()
{
        shortdelay( 18 );
        while(1)        {
                shortdelay( 48 );
        }
}


 

/************************************************************************

                                        毫秒级精确延时(ICC)

*************************************************************************/

#include<iom8v.h>

#define xtal 8 //以MHz为单位,不同的系统时钟要修改。

void delay_1ms(void)
{
uint i;
for(i=0;i<(unsigned int)(xtal*143-2);i++);
}


void delay_ms(uint num)
{
uint i;
for(i=0;i<num;i++) delay_1ms();
}

void main(void)
{
DDRB=0xff;
PORTB=0x00;

while(1)
{
delay_ms(100);
PORTB^=0xff;
}
}

 


系统分类: 单片机   |   用户分类: 侃单片机   |   来源: 原创 



AVR的两种位操作的比较(位域方式和移位宏方式) 

AVR的两种位操作的比较(位域方式和移位宏方式) 

测试环境如下: 
硬件:AT90S2313 
软件:    WiinAVR gcc3.3   -Os级优化(最小size)。 


说明: 
    由于AVR不支持位操作,所以必须通过软件来实现。下面对我所知道的两种方法进行一个简单的比较。 
    1、位域方式。先定义一个位域, 
            typedef struct _bit_struct 
            { 
                unsigned char bit0 : 1 ; 
                unsigned char bit1 : 1 ; 
                unsigned char bit2 : 1 ; 
                unsigned char bit3 : 1 ; 
                unsigned char bit4 : 1 ; 
                unsigned char bit5 : 1 ; 
                unsigned char bit7 : 1 ; 
                unsigned char bit6 : 1 ; 
            }bit_field; 
        再用一个宏    ,来指向要操作的位。 
             #define LED             GET_BITFIELD(PORTB).bit0 
             #define BUTTON      GET_BITFIELD(PINB).bit7 
        使用时只需要直接赋值即可:如LED =     0 ,LED = 1,  或者直接判断 LED==0    ,    LED ==1. 
        这种方法类似C51中的位操作。直接。 
    2、位移宏方式。主要有三个. 
                #define Set_Bit(val, bitn)    (val |=(1<<(bitn))) 
                #define Clr_Bit(val, bitn)     (val&=~(1<<(bitn))) 
                #define Get_Bit(val, bitn)    (val &(1<<(bitn)) ) 
         三个分别用来设置某一位,清除某一位,取某一位的值. 
           使用方法为.Set_Bit(PORTA,3);   Clr_Bit(PORTB,2);   Get_Bit(val,5); 
    3、测试程序. 
       说明,假设PORTB.7接按纽,PORTB.0 接LED 
       测试程序完成如下操作。
 
       当BUTTON == 0时 ,LED输出1 否则输出0, 
       这样的目的是即测试了输入,又测试了输出1和输出0,相对全面一点。  C代码如下. 

                // testled.c     测试AVR的位操作. 
                // 这是gcc;如是其它编译器,请修改。 
                #include <avr/io.h> 

                // 定义一个寄存器(Register)或端口(Port)的八个位 
                typedef struct _bit_struct 
                { 
                    unsigned char bit0 : 1 ; 
                    unsigned char bit1 : 1 ; 
                    unsigned char bit2 : 1 ; 
                    unsigned char bit3 : 1 ; 
                    unsigned char bit4 : 1 ; 
                    unsigned char bit5 : 1 ; 
                    unsigned char bit7 : 1 ; 
                    unsigned char bit6 : 1 ; 
                }bit_field; 

                  //定义一个宏,用来得到每一位的值 
                #define GET_BITFIELD(addr) (*((volatile  bit_field *) (addr))) 

                //定义每一个位 
                #define LED         GET_BITFIELD(PORTB).bit0 
                #define BUTTON      GET_BITFIELD(PINB).bit7 


                #define Set_Bit(val, bitn)    (val |=(1<<(bitn))) 
                #define Clr_Bit(val, bitn)    (val&=~(1<<(bitn))) 
                #define Get_Bit(val, bitn)    (val &(1<<(bitn)) ) 

                int main( void ) 
                { 
                    DDRB = 0x41;   //配置PB0为输出,PB7为输入 
                    if ( BUTTON==0 )     LED = 1; else LED = 0; 
                    //if(!Get_Bit(PINB,7) )  Set_Bit(PORTB,0);    else Clr_Bit(PORTB,0); 
                    while(1); 
                } 
      //     ----------------------        end         ----------------------------- 
    4、测试过程。 
       a.先使用位域方式。 
       主程序中使用 if ( BUTTON==0 )     LED = 1; else LED = 0; 
       结果如下: 
                     int main( void ) 
                    { 
                      4a:    cf ed           ldi    r28, 0xDF    ; 223 
                      4c:    d0 e0           ldi    r29, 0x00    ; 0 
                      4e:    de bf           out    0x3e, r29    ; 62 
                      50:    cd bf           out    0x3d, r28    ; 61 
                        DDRB = 0x41;      //配置PB0为输出,PB7为输入 
                      52:    81 e4           ldi    r24, 0x41    ; 65 
                      54:    87 bb           out    0x17, r24    ; 23 
                        if ( BUTTON==0 )     LED = 1; else LED = 0; 
                      56:    86 b3           in    r24, 0x16    ; 22 
                      58:    e8 2f           mov    r30, r24 
                      5a:    ff 27           eor    r31, r31 
                      5c:    80 81           ld    r24, Z 
                      5e:    86 fd           sbrc    r24, 6 
                      60:    07 c0           rjmp    .+14         ; 0x70 
                      62:    88 b3           in    r24, 0x18    ; 24 
                      64:    e8 2f           mov    r30, r24 
                      66:    ff 27           eor    r31, r31 
                      68:    80 81           ld    r24, Z 
                      6a:    81 60           ori    r24, 0x01    ; 1 
                      6c:    80 83           st    Z, r24 
                      6e:    06 c0           rjmp    .+12         ; 0x7c 
                      70:    88 b3           in    r24, 0x18    ; 24 
                      72:    e8 2f           mov    r30, r24 
                      74:    ff 27           eor    r31, r31 
                      76:    80 81           ld    r24, Z 
                      78:    8e 7f           andi    r24, 0xFE    ; 254 
                      7a:    80 83           st    Z, r24 
                        while(1); 
                      7c:    ff cf           rjmp    .-2          ; 0x7c 

main函数共52Bytes.其中,从lst文件看得出:main函数的初始化用了4条指令,8Bytes. 最后一句while(1);用了1条指令2Bytes.( for循环和do-while也是) 
         DDRB="0x41用了2条指令4Bytes". 计算一下:52-8-4-2=38Bytes,即if ( BUTTON==0 )     LED = 1; else LED = 0; 这句用了19条指令38Bytes. (居然运用了3个寄存器白r24,r30,r31,和一个Z,代码真是苦涩,,我看不懂,准备以后作代码加密用:).  ) 
       b.使用移位宏方式。 
       将 if ( BUTTON==0 )     LED = 1; else LED = 0;  换为等效的     if(!Get_Bit(PINB,7) )  Set_Bit(PORTB,0);    else Clr_Bit(PORTB,0); 

       结果,main函数仅24Bytes.其它代码一样,略去. 所以,上面这句代码仅用了24-14=10Bytes ,5条指令。生成的代码如下: 
              56:    b7 99           sbic    0x16, 7    ; 22 
              58:    02 c0           rjmp    .+4          ; 0x5e 
              5a:    c0 9a           sbi    0x18, 0    ; 24 
              5c:    01 c0           rjmp    .+2          ; 0x60 
              5e:    c0 98           cbi    0x18, 0    ; 24 
    5. 菜论:鱼和熊掌。 
      由于AVR可以对I/O脚进行sbic,sbi,cbi,这样的位操作,所以使用I/O脚操作时,移位宏可以产生高效的代码。 
      例如,要实现上面的几个简单的指令,为了实现LED=1这样的类似C51的sbit的效果,我必须多付出(38-10=28Bytes)的代价。 

    6...... 
        对于I/O脚,可以产生这样高效的代码,是因为有sbi和cbi这样的指令,那么对于一般的变量,又如何呢?................ 

 

 



点击此处查看原文 >> 

系统分类: 软件开发   |    用户分类:    |    来源: 无分类

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -