STM32F0 位带操作(附带f0 f1 f4通用引脚初始化方案)

2019-07-21 03:39发布

本帖最后由 nashui_sx 于 2019-7-7 22:26 编辑

STM32F030F4不支持位带操作,最近总是来回切换stm32f1 f0,同样写的库 引脚初始化改来改去挺烦的,就想弄个方案解决,给大家分享下

1.普通大家用的模拟位带操作
[mw_shl_code=applescript,true]typedef struct _16_Bits_Struct
{
     u16 bit0  : 1;
     u16 bit1  : 1;
     u16 bit2  : 1;
     u16 bit3  : 1;
     u16 bit4  : 1;
     u16 bit5  : 1;
     u16 bit6  : 1;
     u16 bit7  : 1;
     u16 bit8  : 1;
     u16 bit9  : 1;
     u16 bit10 : 1;
     u16 bit11 : 1;
     u16 bit12 : 1;
     u16 bit13 : 1;
     u16 bit14 : 1;
     u16 bit15 : 1;
} Bits_16_TypeDef;

//使用
#define LED_PORT              GPIOA
#define LED_PIN        GPIO_Pin_4
#define LED0           (((Bits_16_TypeDef *)(&(LED_PORT->ODR)))->bit4)//输出
#define KEY1           (((Bits_16_TypeDef *)(&(KEY_PORT->IDR)))->bit3)//输入[/mw_shl_code]

这样就是往常常用的模拟位带操作的方法,但是给正点原子的#define PAout(n) 还是有点不一样,头文件宏定义还是要改,就想着能不能改进下,下面两行代码,兼容原子的代码
#define LED0 (((Bits_16_TypeDef *)(&(LED_PORT->ODR)))->bit4)//输出
#define KEY1 (((Bits_16_TypeDef *)(&(KEY_PORT->IDR)))->bit3)//输入

2.改进位带操作
分析 #define LED0 PAout(4) 和#define LED0 (((Bits_16_TypeDef *)(&(GPIOA->ODR)))->bit4)的差异
也就是4和->bit4的差异,这俩看着有规律可是怎么都替换不了
后来想起来二进制转10进制的方法  //用n替换"0x##n##L"中的"n"的方法,就尝试了下,确实可以
以#define PAout(n)   (((Bits_16_TypeDef *)(&(GPIOA->ODR)))->bit##n##)  为例
PAout(n)中的n 在  (((Bits_16_TypeDef *)(&(GPIOA->ODR)))->bit##n##)中 会替换##n##
这样PAout(1)就等价于执行(((Bits_16_TypeDef *)(&(GPIOA->ODR)))->bit1),就兼容原子的代码了


下面代码放到f0的sys.h  就能和f1 f4的外带操作一样了
[mw_shl_code=applescript,true]//方案2
//会有叉叉提醒
//关掉这个功能:Dynamic Syntax Checking。
//具体做法是 Edit - Configurations - Text Completion - Dynamic Syntax Checking,把enable去掉就可以了。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct _16_Bits_Struct
{
     u16 bit0  : 1;
     u16 bit1  : 1;
     u16 bit2  : 1;
     u16 bit3  : 1;
     u16 bit4  : 1;
     u16 bit5  : 1;
     u16 bit6  : 1;
     u16 bit7  : 1;
     u16 bit8  : 1;
     u16 bit9  : 1;
     u16 bit10 : 1;
     u16 bit11 : 1;
     u16 bit12 : 1;
     u16 bit13 : 1;
     u16 bit14 : 1;
     u16 bit15 : 1;
} Bits_16_TypeDef;
//用n替换"0x##n##L"中的"n"
#define PAout(n)   (((Bits_16_TypeDef *)(&(GPIOA->ODR)))->bit##n##)  //输出
#define PAin(n)    (((Bits_16_TypeDef *)(&(GPIOA->IDR)))->bit##n##)  //输入
#define PBout(n)   (((Bits_16_TypeDef *)(&(GPIOB->ODR)))->bit##n##)  //输出
#define PBin(n)    (((Bits_16_TypeDef *)(&(GPIOB->IDR)))->bit##n##)  //输入
#define PCout(n)   (((Bits_16_TypeDef *)(&(GPIOC->ODR)))->bit##n##)  //输出
#define PCin(n)    (((Bits_16_TypeDef *)(&(GPIOC->IDR)))->bit##n##)  //输入
#define PDout(n)   (((Bits_16_TypeDef *)(&(GPIOD->ODR)))->bit##n##)  //输出
#define PDin(n)    (((Bits_16_TypeDef *)(&(GPIOD->IDR)))->bit##n##)  //输入
#define PEout(n)   (((Bits_16_TypeDef *)(&(GPIOE->ODR)))->bit##n##)  //输出
#define PEin(n)    (((Bits_16_TypeDef *)(&(GPIOE->IDR)))->bit##n##)  //输入
#define PFout(n)   (((Bits_16_TypeDef *)(&(GPIOF->ODR)))->bit##n##)  //输出
#define PFin(n)    (((Bits_16_TypeDef *)(&(GPIOF->IDR)))->bit##n##)  //输入
#define PGout(n)   (((Bits_16_TypeDef *)(&(GPIOG->ODR)))->bit##n##)  //输出
#define PGin(n)    (((Bits_16_TypeDef *)(&(GPIOG->IDR)))->bit##n##)  //输入[/mw_shl_code]

使用的时候代码会有个叉叉,但是功能不影响,强迫症的我,百度了下解决方案
//关掉 Dynamic Syntax Checking这个功能
//具体做法是 Edit - Configurations - Text Completion - Dynamic Syntax Checking,把enable去掉就可以了。
完美解决


至此,以后f1 f0的代码就能直接通用了



以下是附带的,引脚初始化通用代码,与位带操作相结合完美解决f0 f1 f4外设代码移植的通用性
具体是在f0 f1 f4 sys.h sys.c 分别添加一下代码(附带优点,自动识别要初始化的时钟总线)

里面用到的一个函数power  指数次方,用于计算时钟总线
[mw_shl_code=applescript,true]u32 power(u32 x,u32 y)
{
                u32 mul = 1;

                u32 i;
                for( i = 0;i<y;i++)
                {
                                mul = mul * x;
                }
                return mul;
}[/mw_shl_code]
f0的  [mw_shl_code=applescript,true]
//sys.h
typedef enum
{
                GPIO_FK_IN=0,
                GPIO_AD_IN=1,

                GPIO_KL_OUT=2,
                GPIO_KL_AF_OUT=3,
                GPIO_TW_OUT=4,
                GPIO_TW_AF_OUT=5,

          GPIO_P_NO=6,
                GPIO_P_UP=7,
                GPIO_P_DOWN=8,

                GPIO_2MHz=9,
                GPIO_10MHz=10,
                GPIO_50MHz=12,
                GPIO_100MHz=13
}GPIO_My_TypeDef;
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_My_TypeDef mode,GPIO_My_TypeDef up_down,GPIO_My_TypeDef speed);

//sys.c
//stm32 通用外设初始化方案,方便不同芯片移植
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_My_TypeDef mode,GPIO_My_TypeDef up_down,GPIO_My_TypeDef speed)
{
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_AHBPeriphClockCmd(power(2,((uint32_t)GPIOx-(uint32_t)GPIOA)/0x0400)*(uint32_t)RCC_AHBPeriph_GPIOA, ENABLE);
        
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin;        

        if(mode==GPIO_FK_IN)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
        if(mode==GPIO_KL_OUT||mode==GPIO_TW_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                 
        if(mode==GPIO_KL_AF_OUT||mode==GPIO_TW_AF_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                 
        if(mode==GPIO_AD_IN)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

        if(mode==GPIO_TW_OUT||mode==GPIO_TW_AF_OUT)
                GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                 
        if(mode==GPIO_KL_OUT||mode==GPIO_KL_AF_OUT)
                GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

        if(up_down==GPIO_P_NO)
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        if(up_down==GPIO_P_UP)
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;               
        if(up_down==GPIO_P_DOWN)
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

         if(speed==GPIO_2MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
         if(speed==GPIO_10MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
        if(speed==GPIO_50MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               
        
  GPIO_Init(GPIOx, &GPIO_InitStructure);
}[/mw_shl_code]
f1
[mw_shl_code=applescript,true]//sys.h
typedef enum
{
                GPIO_FK_IN=0,
                GPIO_AD_IN=1,

                GPIO_KL_OUT=2,
                GPIO_KL_AF_OUT=3,
                GPIO_TW_OUT=4,
                GPIO_TW_AF_OUT=5,

          GPIO_P_NO=6,
                GPIO_P_UP=7,
                GPIO_P_DOWN=8,

                GPIO_2MHz=9,
                GPIO_10MHz=10,
                GPIO_25MHz=11,
                GPIO_50MHz=12,
                GPIO_100MHz=13
}GPIO_My_TypeDef;
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_My_TypeDef mode,GPIO_My_TypeDef up_down,GPIO_My_TypeDef speed);


//sys.c
//stm32 通用外设初始化方案,方便不同芯片移植
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_My_TypeDef mode,GPIO_My_TypeDef up_down,GPIO_My_TypeDef speed)
{
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(power(2,((uint32_t)GPIOx-(uint32_t)GPIOA)/0x0400+2), ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin;        

        if(mode==GPIO_AD_IN)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        if(mode==GPIO_FK_IN && up_down==GPIO_P_NO)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        if(mode==GPIO_FK_IN && up_down==GPIO_P_DOWN)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;  
        if(mode==GPIO_FK_IN && up_down==GPIO_P_UP)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  
        if(mode==GPIO_KL_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
        if(mode==GPIO_TW_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        if(mode==GPIO_KL_AF_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
        if(mode==GPIO_TW_AF_OUT)               
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

         if(speed==GPIO_2MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        if(speed==GPIO_25MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
        if(speed==GPIO_50MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               

  GPIO_Init(GPIOx, &GPIO_InitStructure);                 
}
[/mw_shl_code]




f4的
[mw_shl_code=applescript,true]
//sys.h
typedef enum
{
                GPIO_FK_IN=0,
                GPIO_AD_IN=1,

                GPIO_KL_OUT=2,
                GPIO_KL_AF_OUT=3,
                GPIO_TW_OUT=4,
                GPIO_TW_AF_OUT=5,

          GPIO_P_NO=6,
                GPIO_P_UP=7,
                GPIO_P_DOWN=8,

                GPIO_2MHz=9,
                GPIO_10MHz=10,
                GPIO_25MHz=11,
                GPIO_50MHz=12,
                GPIO_100MHz=13
}GPIO_My_TypeDef;
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_My_TypeDef mode,GPIO_My_TypeDef up_down,GPIO_My_TypeDef speed);


//sys.c
//stm32 通用外设初始化方案,方便不同芯片移植
void My_GPIO_Init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,GPIO_My_TypeDef mode,GPIO_My_TypeDef up_down,GPIO_My_TypeDef speed)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
   
        RCC_AHB1PeriphClockCmd(power(2,((uint32_t)GPIOx-(uint32_t)GPIOA)/0x0400), ENABLE);
        
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin;        

        if(mode==GPIO_FK_IN)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
        if(mode==GPIO_KL_OUT||mode==GPIO_TW_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                 
        if(mode==GPIO_KL_AF_OUT||mode==GPIO_TW_AF_OUT)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                 
        if(mode==GPIO_AD_IN)
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

        if(mode==GPIO_TW_OUT||mode==GPIO_TW_AF_OUT)
                GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                 
        if(mode==GPIO_KL_OUT||mode==GPIO_KL_AF_OUT)
                GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

        if(up_down==GPIO_P_NO)
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        if(up_down==GPIO_P_UP)
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;               
        if(up_down==GPIO_P_DOWN)
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

         if(speed==GPIO_2MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
        if(speed==GPIO_25MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
        if(speed==GPIO_50MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               
        if(speed==GPIO_100MHz)
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;         

  GPIO_Init(GPIOx, &GPIO_InitStructure);         
}
[/mw_shl_code]

使用方法:(自动识别要初始化的时钟总线
#define LED_PORT              GPIOA
#define LED_PIN        GPIO_Pin_4//能或组合引脚
led初始化My_GPIO_Init(LED_PORT,LED_PIN,GPIO_TW_OUT,GPIO_P_DOWN,GPIO_10MHz);//推挽输出 下拉 10m

#define KEY_PORT              GPIOA
#define KEY_PIN        GPIO_Pin_3//能或组合引脚
key初始化My_GPIO_Init(KEY_PORT,KEY_PIN,GPIO_FK_IN,GPIO_P_UP,GPIO_50MHz);//浮空输入 上拉 50m
这样以后外设的代码就能兼容f0 f1 f4了,直接复制过去,完美直接用

欢迎大家提提意见











友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。