鸽了这么久终于又想起了CSDN的密码
今天大家一起来学习stm32,对于32如何建工程,网络上已经有很多例子,包括文件也有很多,如果需要的话可以在文末找到群号,我会在群文件里面分享,这里就不再浪费口舌。
32对于51单片机来说,无论是I/O口还是寄存器都有特别大的变化,举个很简单的例子:51单片机的I/O一般是不需要配置的,而32的I/O口需要使能,需要选择模式。(模拟输入、浮空输入、上、下拉输入、开漏输出、推挽输出、复用开漏/推挽输出共计八个模式),所以,想要学好32就必须了解32的库函数定义。
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
这就是一段GPIO初始化的结构体,结构体里面仍然是结构体,比如mode这个
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
真正初始化的函数是
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
相信大家看到这里已经懵逼了,这到底该**怎么才能初始化啊,一个I/O口怎么这么麻烦!
不要炸鸡,听我给大家讲解
首先看到前两个函数框,大家估计已经明白了,32的库函数几乎有一半都是结构体,所以大家C语言功底一定要扎实,咱们写单片机的不像搞程序的那个复杂深入,但是基本功一定不要落下。
大家看到入口参数其实就俩GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct
我们先看看GPIO_TypeDef* GPIOx
,从名字上就能看出这是找I/O口的,就和51单片机是一样的,比如51叫P1那么32就叫GPIOA,第二个是初始化I/O口的,我们右键进入定义看看
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
这里也就是刚刚那一段,我们可以看到这个结构体里面有三个东西
uint16_t GPIO_Pin; GPIOSpeed_TypeDef GPIO_Speed; GPIOMode_TypeDef GPIO_Mode;
看后面的注释可以知道uint16_t GPIO_Pin;
是定义引脚的,也就是51中的P1^1一样
GPIOSpeed_TypeDef GPIO_Speed;
这是定义I/O口频率的,我们右键进去看看
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
这里我们有三个选择10 2 50,根据需要自行决定
我们看下一个
GPIOMode_TypeDef GPIO_Mode;
这是对IO口模式的选择,继续右键
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
可以看到这里也就是我最开始说的八种模式
好了了解这些之后我们就开始第一步,初始化一个I/O口吧,那么因为我的LED在B5和E5,那我就以这两个I/O口为例子。
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5 端口配置, 推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure); //推挽输出 ,IO口速度为50MHz
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
}
我知道大家又懵了,我来依次为大家解答
Q:第一行干什么的?
A:第一行相当于是定义一个GPIO_InitStructure结构体来初始化I/O口
Q:RCC_APB2PeriphClockCmd是什么东西?
A:这是使能B E这两个I/O口的函数。因为GPIOB和BPIOE在APB2总线上(可以在中文参考手册查到其他GPIO的总线,群里有),所以我们需要用这个函数,大家记住即可。
接下来的三行就是一个规范的结构体使用方法,根据定义中的数据,依次录入。那么因为我们是要点灯,所以我们用推挽输出。接着GPIO_Init来根据参数初始化GPIOB。
GPIO_SetBits是输出高电平的函数,使用方法看我例程也就明白了
这里补充一下:低电平是GPIO_ResetBits
Q:为什么GPIOE你只设置了Pin脚的参数,其他参数都不设置呢?
A:因为其他的和GPIOB一样,都是推挽输出和50MHz所以不需要另外设置。
LED_Init写完了之后我们就可以写主函数了
int main(void)
{
delay_init();
LED_Init();
while(1)
{
LED0 = 0;
LED1 = 1;
delay_ms(300);
LED0 = 1;
LED1 = 0;
delay_ms(300);
}
}
学过51的同学应该都能看懂吧?
不过还是得说明一下
delay_init();
这个函数在delay.h
里面已经定义过了,不需要自己写。(群里有工程文件)
LED0 和LED1需要我们自己在led.h头文件中宏定义
#define LED0 PBout(5)
#define LED1 PEout(5)
赶快将代码编译到stm32开发板上试试吧!
下一篇我将会更新STC51的PWM,然后更新STC12的PWM,为更新STM32的PWM做好准备
交流群号:1033131250