[MCU] 【雅特力开发板 AT32F421 测评】3、对外设位操作的疑问,难道不好用

ddllxxrr   2021-4-11 16:31 楼主

我觉得位操作十分简单,然而就是这个简单的操作,害了我一整天。我不得不宣布,对外设的位操作失败。

 

我看了下例程提供的位操作是对RAM的,我觉得没有什么实用价值,谁会没有事跑到RAM去操作一个BIT。

 

我要有价值的那就是象51单片机那样的位操作。我本来十分有把握的建了H文件内容如下:

 

#ifndef __BITBAND__
#define __BITBAND__

//#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))

//#define GPIOA_ODR_Addr    (GPIOA_BASE+0x14) //0x4001080C
//#define GPIOA_IDR_Addr    (GPIOA_Base+0x10) 

//#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 ODR保存要输出的数据;IDR保存读入的数据
//#define PAin(n)  BIT_ADDR(GPIOA_IDR_Addr,n)  //in

//位带操作,实现51类似的GPIO控制功能
//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 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)  //输入


#endif

然而,这就是开始了,一点也不好用,从上午到下午。程序如下:

int main(void)
{
  AT32_Board_Init();
  GPIO_init();
  for(;;)
  {
    PAout(8) = 1;
		//GPIO_SetBits(GPIOA,GPIO_Pins_8);
		PAout(10) = 1;
		AT32_LEDn_Toggle(LED2);
    Delay_ms(200);
    AT32_LEDn_Toggle(LED3);
    Delay_ms(200);
    AT32_LEDn_Toggle(LED4);
    Delay_ms(200);
		PAout(8) = 0;
		//GPIO_ResetBits(GPIOA,GPIO_Pins_8);
		PAout(10) = 0;
		AT32_LEDn_Toggle(LED2);
    Delay_ms(200);
    AT32_LEDn_Toggle(LED3);
    Delay_ms(200);
    AT32_LEDn_Toggle(LED4);
    Delay_ms(200);
  
  }
}

只要我用位操作就不好用,只要我不用位操作就好用。

管脚初始化完的。我后来找了下资料大致原因如下:

 

找到A的定义:

#elif defined (AT32F421xx)
 #define GPIOA_BASE           (AHB2PERIPH_BASE + 0x0000)
 #define GPIOB_BASE           (AHB2PERIPH_BASE + 0x0400)
 #define GPIOC_BASE           (AHB2PERIPH_BASE + 0x0800)
 #define GPIOF_BASE           (AHB2PERIPH_BASE + 0x1400)
#endif

 

找到AHB2PERIPH_BASE的定义:

/** Peripheral memory map */
#define APB1PERIPH_BASE       (PERIPH_BASE)
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
#define AHB2PERIPH_BASE       (PERIPH_BASE + 0x08000000)

 

管脚正好是 AHB2PERIPH_BASE 但为什后边是0x08000000,而根据M4核定义,

应是0x4200 0000开始,而如果按上边公式,我的范围应在,0x5000 0000开始,所以不好用。。。。。。

我开始不淡定了,我把0x0800 0000 减0x0600 0000想让地址落下0x2200 0000但是不好用。

 

不想了,我就是不明白,好好的外设A地址为什么定义到了0x4800 0000开始,而技术手册,明明写着外设从0x400 0000开始。

 

ATYYYY.jpg

 

而地址映射确实在0x4800 0000(否则库函数根本不好用),那么我要问啦,位映射地址:0x4200 0000怎么没有画出来:

 

ATYYYY2.jpg

 

 

不知大家的位操作好用不啦?

本帖最后由 ddllxxrr 于 2021-4-11 16:38 编辑
http://shop34182318.taobao.com/ https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr

回复评论 (8)

雅特力的F421 的地址是按着STM32F030排的 因此和STM32F030一样,gpio 不支持bit-band

点赞  2021-4-11 18:23

STM32F030的GPIO是属于AHB2,地址不在位置操作区域,地址映射后对应不是GPIO的寄存器,不能对位操作,F421模仿的是F030,,,

点赞  2021-4-11 18:31
引用: Jacktang 发表于 2021-4-11 18:23 雅特力的F421 的地址是按着STM32F030排的 因此和STM32F030一样,gpio 不支持bit-band

我晕

http://shop34182318.taobao.com/ https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
点赞  2021-4-11 20:05
引用: Jacktang 发表于 2021-4-11 18:31 STM32F030的GPIO是属于AHB2,地址不在位置操作区域,地址映射后对应不是GPIO的寄存器,不能对位操作,F421 ...

谢谢回答

 

http://shop34182318.taobao.com/ https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
点赞  2021-4-11 20:05

居然还有这个操作。。。想不到!

点赞  2021-4-12 16:27

有些mcu没配置这个cortex的选项,好像近几年的新片子都没配这个。

默认摸鱼,再摸鱼。2022、9、28
点赞  2021-4-12 22:43

8楼 nmg 

找雅特力官方问了下: GPIO bitband因GPIO外设基地址调整,其映射范围超出位带区而无法使用。

点赞  2021-4-14 19:35

哎,用M4内核做M0的事,我们还是把这款当做F030的高频升级版开发比较核实。

点赞  2021-4-15 14:21
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复