搜索
bottom↓
回复: 5

winavr位操作的探讨

[复制链接]

出0入0汤圆

发表于 2014-5-3 08:57:27 | 显示全部楼层 |阅读模式
本帖最后由 neo 于 2014-5-3 09:07 编辑

CVAVR下的程序
  1. #include <mega16.h>
  2. #define LED PORTA.4

  3. void main( void )
  4. {
  5. DDRA=0x10;
  6. LED=0;
  7. }
复制代码

对应的反汇编

  1. --- 无源文件 -----------------------------------------------------------------------

  2. --- C:\Users\AX\Desktop\avr_test2\main.c ---------------------------------------
  3. DDRA=0x10;
  4. 00000048  LDI R30,0x10                Load immediate
  5. 00000049  OUT 0x1A,R30                Out to I/O location
  6. LED=0;
  7. 0000004A  CBI 0x1B,4                Clear bit in I/O register
  8. --- 无源文件 -----------------------------------------------------------------------
  9. 0000004B  RJMP PC-0x0000                Relative jump
  10. 0000004C  NOP                 Undefined
  11. 0000004D  NOP                 Undefined
复制代码
在winAVR里没有和CVAVR里同样的位操作指令,在网上看到一篇帖子WINAVR中avr单片机的位操作 其中提到了位域的方法,从C编写的角度看该方法和CVAVR里的比较类似,对应的C代码如下:
  1. #include<avr/io.h>


  2. // 定义一个寄存器(Register)或端口(Port)的八个位
  3. typedef struct _bit_struct  
  4. {
  5.     unsigned char bit0:1 ;
  6.     unsigned char bit1:1 ;
  7.     unsigned char bit2:1 ;
  8.     unsigned char bit3:1 ;
  9.     unsigned char bit4: 1 ;
  10.     unsigned char bit5: 1 ;
  11.     unsigned char bit6: 1 ;
  12.     unsigned char bit7: 1 ;
  13. }bit_field;

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

  16. //定义每一个位
  17. #define LED GET_BITFIELD(PORTA).bit4


  18. int main( void )
  19. {
  20. DDRA=0x10;
  21. LED=0;
  22. return 0;
  23. }
复制代码
其反汇编如下:

  1. --- C:\Users\AX\Desktop\avr_test/main.c ----------------------------------------
  2. {
  3. DDRA=0x10;
  4. 00000036  LDI R24,0x10                Load immediate
  5. 00000037  OUT 0x1A,R24                Out to I/O location
  6. LED=0;
  7. 00000038  IN R30,0x1B                In from I/O location
  8. 00000039  LDI R31,0x00                Load immediate
  9. 0000003A  LDD R24,Z+0                Load indirect with displacement
  10. 0000003B  ANDI R24,0xEF                Logical AND with immediate
  11. 0000003C  STD Z+0,R24                Store indirect with displacement
  12. }
  13. 0000003D  LDI R24,0x00                Load immediate
  14. 0000003E  LDI R25,0x00                Load immediate
  15. 0000003F  RET                 Subroutine return
  16. --- 无源文件 -----------------------------------------------------------------------
  17. 00000040  CLI                 Global Interrupt Disable
  18. 00000041  RJMP PC-0x0000                Relative jump
复制代码


从中可见CVAVR使用的是CBI指令对PORTA.4进行操作。WINAVR位域的方法是使用掩码的间接实现方法对PORTA.4进行操作,共使用了5条指令,代码效率不高。
CVAVR这种PORTA.x这种赋值方法有一大好处就是可以实现如下的定义
当LED点灯电路使用的是OC接法时
  1. #define OFF 1
  2. #define ON 0
  3. #define LED PORTA.4
复制代码

如果LED电路是直接高电平驱动则定义
  1. #define OFF 0
  2. #define ON 1
  3. #define LED PORTA.4
复制代码


对应的点亮部分只需执行LED=ON就可以了,不必要关心硬件电路究竟如何,这样就非常方便硬件的调试。不知WinAVR里有没有类似的方法。
1、C接口友好。
2、直接使用SBI CBI对端口位操作。

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出10入10汤圆

发表于 2014-5-3 09:30:30 | 显示全部楼层
#define LED_FLASH                 PORTB ^= (1 << PB1)
#define LED_ON                 PORTB |= (1 << PB1)
#define LED_OFF                 PORTB &= ~(1 << PB1)

出0入0汤圆

 楼主| 发表于 2014-5-3 09:32:04 | 显示全部楼层
  1. PORTA&=~(1<<PA5);
  2. 0000003D  CBI 0x1B,5                Clear bit in I/O register
复制代码


PORTA&=~(1<<PA5);会直接被编译为CBI,如果能实现PORTA(addr,value)封装就方便了。

出0入0汤圆

 楼主| 发表于 2014-5-3 09:42:17 | 显示全部楼层
szxszx 发表于 2014-5-3 09:30
#define LED_FLASH                 PORTB ^= (1

如果定义了N多个端口 当外部硬件发生了变化就要一个个修改定义 这样不是很方便

出0入0汤圆

发表于 2014-5-3 15:32:03 | 显示全部楼层
#define DEF_2( a, b )        a ## b

#define PORT( a )            DEF_2( PORT, a )
#define SBI(a, b )            a != (1<<b )

#define SBI_P( a, b )        SBI( PORT(a), b )

SBI_P( A, 2 );    //PORTA |= (1<<2 );

出0入0汤圆

发表于 2014-5-3 15:32:34 | 显示全部楼层
这样移植比较方便
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 15:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表