赞
踩
总目录传送门:https://archie.blog.csdn.net/article/details/132434192
给工程起一个通用的名字,文件夹的名称是方便改的,工程名称不太方便改
接下来选择器件型号,使用的是stm32f103c8t6
这里弹出的是新建工程小助手,可以帮助快速新建工程
工程文件是空的,现在这个工程还不能用,需要添加一点工程的必要文件
打开固件库的文件夹
启动文件的文件路径:Libraries-CMSIS-CM3-DeviceSupport-ST-STM32F10x-startup-arm-
如下就是STM32的启动文件,STM32的程序就是从启动文件开始执行的。
将全部启动文件全部复制下来,然后回到工程文件夹里
工程文件夹如下,里面是新建工程自动生成的文件
工程文件夹里,新建文件夹(start)用来存放复制过来的启动文件
接着回到固件库的STM32F10x文件,可以看到stm32f10x.h和两个system开头的文件system_stm32f10x.c和system_stm32f10x.h文件,将这三个文件复制下来,也粘贴到Start文件夹下。
打开工程文件夹,新建一个文件夹(user),main函数就放在这个文件夹里
在keil中,在Target点击右键,点击添加组,命名为User
然后在user右键,点击添加新文件,选择c文件,名字为main。路径需要注意为User文件夹,要不然默认是放在文件夹外面的,这样我们就有了main.c文件了。
在main.c里,右键,插入头文件,选择stm32f10x.h
写一个main函数,点击build按钮,编译并建立工程。目前工程还没有添加stm32的库函数,所以还是基于寄存器开发的工程。
int main (void) //main函数是一个int型返回值,void参数的函数
{
while(1)
{
}
}
接下来,进行配置寄存器来完成点灯操作(了解即可)
需要stm32最小系统板,stlink,四根母对母的杜邦线(母对母的杜邦线是指两端都是母插头的杜邦线。这意味着该电缆可以连接两个具有相同或兼容的插头的设备。例如,它可以用于连接两个电子设备的扩展板或连接两个电路板。)
一个灯常量(电源灯),另一个灯默认是闪烁状态(测试程序)
然后,在keil中配置一下调试器,点击魔术棒,选择debug,调试器默认是ULINK,更换为stlink调试器,然后再点击右边的设置按钮,在flash下载这一项,把reset and run 勾上(勾上后,我们下载程序后会立马复位并执行,否则每次下载后,还需要按一下板子上的复位按键才能执行程序),配置好调试器后,点击确定,ok。
然后重新编译一下,再点击LOAD按钮(程序下载到stm32里),板子上灯不闪(因为程序为空)
接下来,配置寄存器,来点亮灯,我们只需要配置3个寄存器就可以点灯了
1.打开GPIOC的时钟(PC13亮灯)
首先RCC的一个寄存器,来使能GPIOc的时钟,GPIO都是APB2的外设,所以在APB2外设时钟使能寄存器RCC_APB2ENR里面配置,在参考手册中可以看到这里有个位4IOPCEN,这一位就是使能GPIOC的时钟的,这一位写1就是打开GPIOC的时钟,(这一位写1,其它无关项先给0,那整个寄存器的2进制数据换成16进制,就是4个分组,也就是0 0 0 0 0 0 1 0)。然后回到keil,在while死循环之前,写上RCC的APB2ENR寄存器等于0x0000 0010,这样就可以打开GPIOC的时钟了。如下图。
2.配置PC13口的模式
在参考手册中找到端口配置高寄存器GPIOx_CRH(因为灯接在PC13口上的,低寄存器是0-7,高寄存器是8-15,所以配置高寄存器),这个x可以是A到E的任意一个字母,然后右边的CNF13和MODE13就是用来配置13号口的,CNF我们需要配置为通用推挽输出模式,也就是这两位为00,MODE配置为输出模式,最大速度可以给50MHz,也就是这两位为11,最后我们对照上面的寄存器,那四位为0011,其它都给配置为0,这样整个寄存器的值换算成16进制就是0030 0000,然后在keil中写上GPIOC的CRH=0x0030 0000。
以上就实现了寄存器方式点灯,代码如下
#include "stm32f10x.h" // Device header
int main (void) // main函数是一个int型返回值,void参数的函数
{
RCC->APB2ENR = 0x00000010; // 打开GPIOC的时钟
GPIOC->CRH = 0x00300000; // 配置pc13的模式
GPIOC->ODR = 0x00002000; // 配置端口输出数据寄存器,pc13高电平灭灯
while(1)
{
}
}
// 最后一行必须是空行,要不然会报错
库函数其实也是间接配置寄存器,所以和上面寄存器方式操作步骤一样。
1.首先是使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);// 打开GPIOC的时钟
使用如下函数来开启时钟,有两个参数,第一个是选择外设,第二个是选择新的状态
右键,跳转到函数定义,有函数的简介和参数说明,brief是简介,param是参数,一共两个参数。第一个参数可以是arg里的任意一个,第二个参数可以是enable或者disable
这个函数内部其实还是配置RCC-APB2ENR这个寄存器,经过函数的包装,我们不需要去查手册来确定哪一位是干嘛。而且,这里已经帮我们用与或来操作了,所以这个库函数是不会影响到寄存器的其它位的,这就是库函数和寄存器的区别
2.第二步是配置端口模式
有两个参数,第一个是选择哪个GPIO,第二个是参数的结构体,这个比上一个函数要麻烦一些,但也是一个套路,我们根据提示来配置参数即可。这里使用了结构体来配置参数,代码逻辑还是有些复杂的,这个后面还会讲。
首先还是去到这个函数的定义,介绍是说根据GPIO-Init结构体的参数来配置GPIO,第一个参数GPIOx,其中x可以是A到G,来选择你要配置哪个GPIO,第二个参数是一个GPIO-InitTypeDef的结构体
我们需要先定义一个结构体,在上面先把这个结构体的类型写上,然后给结构体起个名字,根据官方的推荐,我们最好起一个这样的名字,叫GPIO-InitStructure,然后把结构体的每个参数填上,复制粘贴结构体的名字,然后用点来引出结构体的参数(三个参数:GPIO模式、GPIO端口、GPIO速度)
最后也是一样,右键转到Mode的定义介绍是说这个参数可以是GPIOMode-TypeDef里的一个值,可以选中GPIOMode-TypeDef这个字符,按一下Ctrl+F,搜索一下这个定义的位置,点击find next,可以看到,这是个枚举类型的结构体,GPIOMode就是这里的其中一个值,然后我们选择Out-PP这一项,是通用推挽输出。
然后我们继续看下一个参数 GPIO_InitStructure.GPIO_Pin,转到它的定义,这里下面出现了一个框,这个是说他的定义有很多个,我们在框中选择member这一项,双击,然后跳转的其实还是刚才那个函数说明位置,这个GPIO_Pin的说明是说这个参数在GPIO_pins_define里面定义了,我们还是一样,选中,Ctrl+F, find next,可以看到这里有个宏定义的列表,我们选择GPIO_PIN_13,复制,然后填到第二个参数位置
结构体第三个参数也是一样,右键,跳到定义,选中,Ctrl+F,Find Next,选中50MHz的速度,复制粘贴
目前,结构体变量就有了,如下代码:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
现在,我们就可以填这个GPIO_Init的第二个参数了,第二个参数的说明是一个指向结构体的指针,所以这里我们需要传递结构体的地址,那我们复制结构体的名字,粘贴到第二个参数位置,然后前面加一个取地址的符号(&),这样,GPIO模式就配置完成了,这个配置的操作方式看上去比较难理解,但是STM32的这种方式都是固定的,大家多打几次就知道咋用了。
GPIO_Init(GPIOC,&GPIO_InitStructure);
3.最后,设置端口的高低电平来进行点灯。
函数GPIO_SetBits,可以把指定端口设置为高电平,大家也可以去看一下参数的说明,第一个是GPIOC,第二个是GPIO_Pin_13,这一句就可以将PC13口置为高电平
GPIO_SetBits(GPIOC,GPIO_Pin_13); // 设置端口的高电平
GPIO_SetBits函数可以置低电平,这一句可以将pc13口置为低电平
GPIO_ResetBits(GPIOC,GPIO_Pin_13);// 设置端口的低电平
好了,至于stm32 GPIO口结构,结构体和库函数的操作这些,将在下节叙述
我们新建工程第一个加的就是启动文件,这个启动文件有很多类型,至于选择哪一个,我们要根据芯片型号来选择。在下面的表中,这是stm32f1系列中的型号分类,其中根据Flash的大小,分为了小容量产品LD,中容量产品MD、大容量产品HD…。stm32f100系列为超值系列,简写为VL,F105和F107为互联型产品CL,这个就没有根据Flash大小来分类.stm32f103c8t6的Flash为64K,所以选择MD的启动文件。
型号分类及缩写如下:
1.工程结构主动执行的部分(工程架构左边两个图)
首先是startup启动文件,这个是程序执行最基本的文件,keil中启动文件是用汇编写的,启动文件内定义了中断向量表,中断服务函数等,这个中断函数中有个复位中断,这就是整个程序的入口,当stm32上电复位或者按下复位开关之后,程序就会进入复位中断函数执行,复位函数中断就主要做了两件事情,第一个是调用SystemInit函数,第二个是调用main函数,然后程序就结束了,当然,实际上单片机的程序永远都不会结束,所以在main函数的最后一定有一个死循环,SystemInit函数就是定义在System_xx开头的.c里的,在keil里也可以看到这个函数的定义(在main函数之前,单片机就已经执行了一堆东西了,帮我们把闪存接口,时钟等一系列杂碎的东西都配置好了)。另外在启动文件还定义了stm32所有的其他中断,这些中断达到触发条件后就会自执行,这个中断函数的定义就是在stm32fx_it里面的,自己的中断有建议位置,如下图有所示,当然我们还是习惯在哪里用中断就在哪里,写在别的地方也是可以的,以上就是中断部分的逻辑,另外你也可以自己定义一些用户文件,来封装一些模块供主程序和中断调用,有利于程序结构的模块化,要不然所有的程序都在主函数里,那主函数就太长了,到此为止,这个工程结构主动执行的部分就介绍完了
2.被动执行部分(工程架构右1图)
被动执行部分,相当于stm32的资源了,我们在主函数或者中断函数里,就可以调用这些资源,右上角这两个stm32f10x.h和core_cm3这些文件就是外设和内核外设的寄存器描述,点开文件可以看到,都是寄存器和寄存器名字,还有地址信息等,如果直接调用这些寄存器来使用stm32,那就是寄存器的开发方式,很麻烦,所以就提供了下面的两个文件,就是库函数文件,在keil中可以看到,这每个外设都提供了一大堆函数,这些函数封装了寄存器的操作,给我们提供更加人性化的函数调用方式,只要学会了操作套路,那配置一个外设就很简单,连手册都不需看。这个conf的文件就是用来配置头文件的包含关系的,在keil中可以看到conf文件include了所有的库函数头文件,同时我们在stm32f10x.h的最后又包含了conf,所以在使用这些库函数时,我们只需要包含stm32f10x.h这一个头文件,就相当于包含了所有的库函数头文件,这样我们就可以任意地调用库函数了,以上就是整个工程的结构和每个文件的使用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。