STM32单片机与51单片机有很大区别,不仅结构上有很大差异,STM32更复杂一些,在操作上来说,STM32也要复杂很多,51单片机上手写代码,可以很直接操作引脚,但是STM32单片机在操作引脚之前需要作很多初始化工作,比如开启时钟使能,GPIO管脚初始化。
下面就入门STM32单片机开发做一个简单的介绍,本文是仿真,不需要真实的STM32单片机,只需要电脑安装开发相关的软件即可,主要是keil-mdk,proteus。
keil这里安装的是支持STM32单片机的版本,这个需要安装mdk那个版本。这里提供一个支持mdk的keil下载链接,提取码:1234。它的安装和破解和keil-51类似,破解也是使用keygen.exe来生成注册码,安装之后,还需要安装支持STM32单片机的包:Keil.STM32F1xx_DFP.1.0.5.pack,将上面链接下载的包离线安装即可,如下所示:
选择keil工具栏上的Pack Install按钮,在弹出框中选择File->Import,弹出选择文件对话框,选中下载的pack包,即可离线安装。
我们要构造STM32工程,还需要一个标准库,同样的,在刚才的下载链接里面自带了:STM32F10x_StdPeriph_Lib_V3.5.0.rar,解压之后,结构如下所示:
我们这里使用标准库来构建STM32工程,这里面有我们工程需要的头文件和源文件,以及启动文件。我们新建STM工程之前,先准备一个这样的工程文件结构:
这里Core,也可以起名CMSIS,根据个人习惯,字面意思就是核心文件,这里我们要将标准库中core_cm3.h , core_cm3.c文件拷贝进来。路径是STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport
Fwlib是固件库firmware library的意思,这里我们把标准库中STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src的inc和src文件夹都拷贝过来。
Project 是用来存放keil工程的,后面在keil中新建工程,我们把保存位置指定到这里。
User,这里是用户文件,拷贝STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x下的stm32f10x.h,system_stm32f10x.c,system_stm32f10x.h文件 和
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template 下的stm32f10x_conf.h,stm32f10x_it.c,stm32f10x_it.h,system_stm32f10x.h(重复)。
Startup启动文件存放的文件夹,这里我们把STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm下的s结尾的文件都拷贝过来(实际只用到一个)。
这样,我们除了Project文件夹中没有文件之外,其他四个目录都有了文件。
keil新建工程
打开keil-mdk,新建工程,位置选择刚才准备的Project文件夹。
在接下来的向导,为构建目标选择设备,我们选择STM32F103C8,其他也可以,根据仿真需要选择。
这个新工程是没有任何内容的,我们要重新设置。点击工具栏的"管理工程项目"按钮(三色块):
Project Targets 修改为工程名称,
Groups这里添加四个Group,分别是Core,Fwlib,Startup,User,他们里面的文件,我们通过选择之前放到文件夹Core,Fwlib,Startup,User里面的文件,结构如下所示:
我们还需要手动在User目录中添加main.c文件,然后通过在User这个Group上右键选择:添加已有文件到组中。
最终的工程文件结构:
我们可以在main.c中增加部分代码,让他可以作为一个空工程编译。
#include "stm32f10x.h"
int main()
{
}
这个时候直接编译项目会报错,我们需要作设置,设置头文件查找范围,具体操作是点击工具栏魔法棒(Options for Targets),弹出框中选择c/c++,Define处输入USE_STDPERIPH_DRIVER,下方的Include Paths选择我们的文件夹Core,Fwlib/inc,User三个目录,手动选择:
最后可以编译成功:
因为仿真最后需要的是hex文件,所以还需要一个设置,点击Options for Targets,切换到output,然后勾选Create HEX File:
STM32单片机点灯的代码有一些复杂,主要需要开启时钟,并设置管脚电平。
#include "stm32f10x.h"
void Delay()
{
unsigned int i, j;
for(i = 0; i < 2000; i++)
for(j = 0; j < 110; j++);
}
void LED_Config()
{
GPIO_InitTypeDef GPIO_InitStructure; // GPIO初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //APB2时钟使能,这里单片机开启的是B口,所以对应RCC_APB2Periph_GPIOB,如果开启A口,这里对应RCC_APB2Periph_GPIOA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; // 管脚B5作为输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //时钟频率
GPIO_Init(GPIOB, &GPIO_InitStructure); // GPIO初始化,开启GPIOB,如果要开启A或者C,改变这里的GPIOA或者GPIOC
}
int main()
{
LED_Config();
while(1)
{
GPIO_SetBits(GPIOB, GPIO_Pin_5);
Delay();
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
Delay();
}
}
编译不报错,就可以开始进行仿真了,在proteus中,我们搭建如下所示的led设计图:
选择芯片STM32F103C8,然后找到发光二极管LED-GREEN,再加上电阻,接地。简单的连线,STM32单片机好像和51单片机有些不一样,这里还需要对连线作处理,在菜单栏Design选择Power Rail Configuration,把GND和VCC/VDD左侧列出的部分都通过中间的Add(右移)箭头添加到右边:
还有一个地方很重要,需要设置,就是单片机的晶振频率,如果不设置,将会报错:
Access to register of unclocked peripheral at 0x40010C00 cause BUS_FAULT [U1_CM3CORE]
这个问题只有在仿真的时候可能会报错,有的地方说需要在代码里面设置开启时钟使能,但是我们的代码里面明显设置了,就是 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 这句代码。这个问题很折腾人,我开始以为是代码没有执行到main.c文件中的内容,其实不是的,而是晶振频率问题,但是同样不设置频率,我使用STM32CubeMX生成的代码执行就没有问题,这也很奇怪。
这里的50MHz就是代码中设置的时钟频率GPIO_Speed_50MHz。
最后仿真不报错的情况:
这里是使用标准库建立STM32工程,所以加入了一些标准库的头文件和源文件,这里根据项目特点新建了Core,Fwlib,Project,Startup,User文件夹,并加入了相关文件,最后在keil工程的目标中建立的组Core,Fwlib,Startup,User并不是一个意思,只是名字相同而已,最后还需要手动添加文件到这些组中。