本帖最后由 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了,直接复制过去,完美直接用
欢迎大家提提意见
一周热门 更多>