我觉得位操作十分简单,然而就是这个简单的操作,害了我一整天。我不得不宣布,对外设的位操作失败。
我看了下例程提供的位操作是对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开始。
而地址映射确实在0x4800 0000(否则库函数根本不好用),那么我要问啦,位映射地址:0x4200 0000怎么没有画出来:
不知大家的位操作好用不啦?
本帖最后由 ddllxxrr 于 2021-4-11 16:38 编辑引用: Jacktang 发表于 2021-4-11 18:23 雅特力的F421 的地址是按着STM32F030排的 因此和STM32F030一样,gpio 不支持bit-band
我晕
引用: Jacktang 发表于 2021-4-11 18:31 STM32F030的GPIO是属于AHB2,地址不在位置操作区域,地址映射后对应不是GPIO的寄存器,不能对位操作,F421 ...
谢谢回答
居然还有这个操作。。。想不到!