OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 9990|回复: 6

位带操作设置感觉没问题,为什么不出结果呢?

[复制链接]

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1851
金钱
1851
注册时间
2012-9-16
在线时间
287 小时
发表于 2013-11-26 21:41:29 | 显示全部楼层 |阅读模式
自己做的板子,板子CPU是STM32F207ZET6,现在刚刚测试,直接用库函数没问题代码如下:
      GPIO_ResetBits(GPIOB, GPIO_Pin_5);
      delay_ms(200);
      GPIO_SetBits(GPIOB, GPIO_Pin_5);
      delay_ms(400);
想用位带操作试试,但是没成功,
设置感觉没问题,为什么不出结果呢?
如果代码这样写:
LED1=0;
LED2=0;
LED3=0;
  GPIO_ResetBits(GPIOB, GPIO_Pin_5);
                      delay_ms(200);
GPIO_SetBits(GPIOB, GPIO_Pin_5);
                      delay_ms(400);
PB5亮,但是其他三个灯不亮,首先确定灯没问题,

实在看不出有什么问题,大家帮忙看看?


#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
/********************IO口地址映射详解********************************/
// /**********************************************************************
// #define FLASH_BASE            ((uint32_t)0x08000000) < FLASH base address in the alias region 
// #define SRAM_BASE             ((uint32_t)0x20000000) < SRAM base address in the alias region
// #define PERIPH_BASE           ((uint32_t)0x40000000) < Peripheral base address in the alias region 

// #define SRAM_BB_BASE          ((uint32_t)0x22000000) < SRAM base address in the bit-band region 
// #define PERIPH_BB_BASE        ((uint32_t)0x42000000) < Peripheral base address in the bit-band region 

// #define FSMC_R_BASE           ((uint32_t)0xA0000000) < FSMC registers base address

// #define APB1PERIPH_BASE       PERIPH_BASE
// #define APB2PERIPH_BASE       (PERIPH_BASE + 0x00010000)
// #define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000)   //0x40020000
// #define AHB2PERIPH_BASE       (PERIPH_BASE + 0x10000000)

// < AHB1 peripherals 
// #define GPIOA_BASE            (AHB1PERIPH_BASE + 0x0000) //0x40020000    
// #define GPIOB_BASE            (AHB1PERIPH_BASE + 0x0400) //0x40020400
// #define GPIOC_BASE            (AHB1PERIPH_BASE + 0x0800) //0x40020800
// #define GPIOD_BASE            (AHB1PERIPH_BASE + 0x0C00) //0x40020C00
// #define GPIOE_BASE            (AHB1PERIPH_BASE + 0x1000) //0x40021000
// #define GPIOF_BASE            (AHB1PERIPH_BASE + 0x1400) //0x40021400
// #define GPIOG_BASE            (AHB1PERIPH_BASE + 0x1800) //0x40021800
// #define GPIOH_BASE            (AHB1PERIPH_BASE + 0x1C00) //0x40021C00
// #define GPIOI_BASE            (AHB1PERIPH_BASE + 0x2000) //0x40022000
// **************************************************************************/


#define GPIOA_ODR_Addr    (GPIOA_BASE+14) //0x4002000E 
#define GPIOB_ODR_Addr    (GPIOB_BASE+14) //0x4002040E
#define GPIOC_ODR_Addr    (GPIOC_BASE+14) //0x4002080E
#define GPIOD_ODR_Addr    (GPIOD_BASE+14) //0x40020C0E
#define GPIOE_ODR_Addr    (GPIOE_BASE+14) //0x4002100E
#define GPIOF_ODR_Addr    (GPIOF_BASE+14) //0x4002140E 
#define GPIOG_ODR_Addr    (GPIOG_BASE+14) //0x4002180E

/**********************************************************
14为GPIOx_ODR的偏移量, 10是GPIOx_IDR的偏移量,本程序是用在STM32F207ZET6上,
STM32F207ZET6有144个管脚,没有H、I管脚,这里配置,是为之后拓展使用
**********************************************************/

// #define GPIOH_ODR_Addr    (GPIOH_BASE+14) //0x40021C0E   
// #define GPIOI_ODR_Addr    (GPIOI_BASE+14) //0x4002200E 

#define GPIOA_IDR_Addr    (GPIOA_BASE+10) //0x4002000A 
#define GPIOB_IDR_Addr    (GPIOB_BASE+10) //0x4002040A 
#define GPIOC_IDR_Addr    (GPIOC_BASE+10) //0x4002080A 
#define GPIOD_IDR_Addr    (GPIOD_BASE+10) //0x40020C0A 
#define GPIOE_IDR_Addr    (GPIOE_BASE+10) //0x4002100A 
#define GPIOF_IDR_Addr    (GPIOF_BASE+10) //0x4002140A 
#define GPIOG_IDR_Addr    (GPIOG_BASE+10) //0x4002180A


// #define GPIOH_IDR_Addr    (GPIOH_BASE+10) //0x40021C0A 
// #define GPIOI_IDR_Addr    (GPIOI_BASE+10) //0x4002200A  
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

// #define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
// #define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

// #define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
// #define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入






纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-11-26 23:25:36 | 显示全部楼层
F2没用过,不过据说和F4差不多吧.
F4的如下:
 
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define Aout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define Ain(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define Bout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define Bin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define Cout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define Cin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define Dout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define Din(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define Eout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define Ein(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1851
金钱
1851
注册时间
2012-9-16
在线时间
287 小时
 楼主| 发表于 2013-11-27 08:28:25 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子哥,代码确实和STM32F4的有点类似,我看了也没什么问题,但是就是不出结果,从网上查到了这样一段,

#define BITBAND(addr,bitnum)   ((addr&0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
把该地址转换成一个指针
#define  MEM_ADDR(addr)   *((volatile unsigned long  *)(addr))
#define  BIT_ADDR(addr, bitnum)    MEM_ADDR(BITBAND(addr, bitnum))
可进行位操作
BIT_ADDR(PORTA, 2) = 0;   // GPIOA.2 = 0;
BIT_ADDR(PORTB, 3) = 1;   // GPIOB.3 = 1;

最后一个并不能在keil中正常使用,因为PORTA和PORTB是一个结构体指针指向的是PORTA和PORTB外设的基址,要想操作任意的寄存器必须传入PORTA->ODR的地址,才可能操作这个寄存器,所以应该写为:
第一种方法:
#define BITBAND(addr,bitnum)   ((addr&0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define  MEM_ADDR(addr)   *((volatile unsigned long  *)(addr))
#define  BIT_ADDR(addr, bitnum)    MEM_ADDR(BITBAND(addr, bitnum))


BIT_ADDR((unsigned long)&(PORTA->ODR), 2) = 0;   // GPIOA.2 = 0;
BIT_ADDR((unsigned long)&(PORTB->ODR), 3) = 1;   // GPIOB.3 = 1;

或者将上面的两个宏定义改写:
第二种方法:
#define BITBAND(addr,bitnum)   ((addr&0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define  MEM_ADDR(addr)   *((volatile unsigned long  *)(addr))
#define  BIT_ADDR(addr, bitnum)    MEM_ADDR(BITBAND((unsigned long)&addr, bitnum))


BIT_ADDR(PORTA->ODR, 2) = 0;   // GPIOA.2 = 0;
BIT_ADDR(PORTB->ODR, 3) = 1;   // GPIOB.3 = 1;

但是,我试了也没成功,出现错误
main.c(21): error:  #158: expression must be an lvalue or a function designator

关键提到的这句话有点不大理解,
最后一个并不能在keil中正常使用,因为PORTA和PORTB是一个结构体指针指向的是PORTA和PORTB外设的基址,要想操作任意的寄存器必须传入PORTA->ODR的地址,才可能操作这个寄存器,
纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
回复 支持 反对

使用道具 举报

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1851
金钱
1851
注册时间
2012-9-16
在线时间
287 小时
 楼主| 发表于 2013-11-27 12:55:30 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子哥,问题已解决,将
#define GPIOA_ODR_Addr    (GPIOA_BASE+14) //0x4002000E 
#define GPIOB_ODR_Addr    (GPIOB_BASE+14) //0x4002040E
#define GPIOC_ODR_Addr    (GPIOC_BASE+14) //0x4002080E
#define GPIOD_ODR_Addr    (GPIOD_BASE+14) //0x40020C0E
#define GPIOE_ODR_Addr    (GPIOE_BASE+14) //0x4002100E
#define GPIOF_ODR_Addr    (GPIOF_BASE+14) //0x4002140E 
#define GPIOG_ODR_Addr    (GPIOG_BASE+14) //0x4002180E

改为:
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014 
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414  
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814  
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14  
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014  
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414     
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814    
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14     
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014  

可是数据手册的偏移地址就是14和10,难道数据手册有问题?
纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
回复 支持 反对

使用道具 举报

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1851
金钱
1851
注册时间
2012-9-16
在线时间
287 小时
 楼主| 发表于 2013-11-27 12:58:05 | 显示全部楼层



纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
回复 支持 反对

使用道具 举报

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1851
金钱
1851
注册时间
2012-9-16
在线时间
287 小时
 楼主| 发表于 2013-11-27 13:06:04 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子哥,不好意思,突然明白了,偏移地址是0X14,那么十进制是20,#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014  
哎,自己太粗心了!
纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-11-27 23:44:13 | 显示全部楼层
回复【6楼】象牙塔:
---------------------------------
恭喜
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-8 12:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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