注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
无奇不有的个人空间 https://home.eeworld.com.cn/space-uid-585991.html [收藏] [复制] [分享] [RSS]
日志

结合st官方库文件开发STM32的详细教程

热度 1已有 8909 次阅读2014-11-17 16:34 | STM32, 库文件, 新手, 点亮led

最近因为老师的要求开始着手stm32f103ze的开发。但是仅仅做过c51和msp430的我对arm还是一知半解的,该如何开始才能呢?而且还是在老师严格的时间要求下。于是我开始了自己的探索,上网搜索一下,别人是如何开发的,发现,大神都推荐我用官网的库文件。这个着实让我很兴奋,原来单片机开发过程中枯燥而且不靠谱的寄存器功能配置已经有人给你做好了。所以,什么都没有像就去官网上注册账号,下载了这个库文件。因为官网上找东西不方便,我在此把我下载的库文件给大家:

下载地址:http://download.csdn.net/detail/chamiyouyan/8164641


因为编写匆忙,有什么不足或者错误的地方,还望大家在评论中指出,在下不胜感激!


相信你已经下载了这个库文件,打开以后就傻了。这么多东西,从哪里入手呢?接下来,我将引领大家进行库文件使用前的配置工作。


1.创建一个工程,并且从下面的文件夹中选择您要选用的ARM启动代码。这个启动代码对于新入门的人来讲,我强烈建议您使用官网的代码,毕竟自己是不可能写的,甚至连看懂都费劲。

启动代码的路径:STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm。

在这里说一下什么是启动代码,arm启动代码是初始化arm的程序,在驱动代码中指定,芯片启动配置结束以后,将芯片的控制权交给main函数,当然这个启动代码还会自动的配置中断向量表。为何强烈建议新手使用官网的启动代码呢?因为很多高手或者熟练使用arm的人可能为了修改中断的向量表和中断函数的名称而自己更改这个启动代码,特别是在arm中写操作系统的时候,这个时候的启动代码配置总是为了服务于别人的项目。如果使用这样的代码,在您开发过程中,将会出现许多意想不到的事情,浪费您的体力和脑力。

启动代码有以下几种:


分别用于您芯片的不同特性。我一般选用的就是hd.s的那个,其他的就是功能有些小限制,或者是时钟频率不高。

您一定要记住您选择的启动代码,这个很重要,因为不同的启动代码对应的库文件操作不一样。

2.库文件和您的应用的唯一接口是这个文件:stm32f10x.h(Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x),您需要在您的工程应用中把这个文件包含进去。

包含进去以后,您需要打开这个文件,进行配置。首先找到图中这个地方:

在这里您看到了许多注释,您要做的就是取消刚才您所选的启动文件对应的那个器件的一行的注释。我一般用的是hd.s的启动文件,所以我这里只需要取消#define STM32F10X_HD 这一行的注释即可。注意后面的加上!以后的内容是不用取消注释的,它本身就是注释。

在这个文件中您还需要配置一个地方就是 USE_PERIPH_LIBRARY 的宏定义。这个宏定义的配置取决于您的应用,如果您不想使用库文件进行操作,那就不用取消这个宏定义的注释了。但是我想,您都选择了库文件,干嘛这么矫情的去不用他呢,那您还不如干干脆直接配置寄存器呢。是吧。。。所以,乖乖的把这个玩意的宏定义注释给取消了吧。

这个文件就配置结束了。就需要改两个地方,一个是图片中所说的地方的宏定义按照您选用的器件启动代码取消对应的注释。第二是取消USE_PERIPH_LIBRARY 的宏定义注释。

3.添加启动代码支持的c文件。这个文件在:  Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x 名字为:system_stm32f10x。这个文件中放置的是启动代码中所提到的函数的原型或者系统时钟配置的相关函数,基本上不用修改,除非你不想使你的芯片工作在72MHZ的频率上,在这个文件中的位置上有一个系统时钟的定义,如下图,默认的是72M的,如果您想修改,则把您想要的频率行取消注释,把其他的注释了就可以了。

4.自己根据需要写一个头文件。当然这么说是有点过分了。您也可以用写好的。但是,这个写好的为了全面性,把所有的外设都包括进去了,所以编译的时候会比较慢。当然您也可以使用的方法是在这个文件上把不需要的外设的头文件注释了。这是个好方法。这个文件的名字为:stm32f10x_conf.h。这个文件的位置在:STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\GPIO\IOToggle。这个地方也需要修改哦。打开这个文件,在包含了一系列的头文件下面有一个名为USE_FULL_ASSERT的宏定义。这个宏是用于开关编译的时候的函数参数匹配检测。建议打开,也就是找到这个宏定义的定义处,把原本的注释行取消了。原句为:/* #define USE_FULL_ASSERT    1 */把注释取消了就行了。这个文件修改完毕。


5.最后一步:在stm32f10x_conf.h文件的末尾有一个函数:void assert_failed(uint8_t* file, uint32_t line)。这个函数为用于您刚刚打开的函数参数错误检查的,如果检查出了错误,就执行这个函数。但是库文件中不知道你要做什么,所以这个函数的函数体需要你自己在应用代码中定义。所以你只需要在你的main函数前面添加一个函数即可;void assert_failed(uint8_t* file, uint32_t line) (while(1);)一般情况下,大家都是让这个函数内容为空。

到这里就完成了库文件的配置。接下来开始点亮led灯吧。

用库函数配置外设的步骤:

1.打开外设的时钟,使用函数:

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_PPPx, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PPPx, ENABLE);

因为你的外设的时钟不同,所以有三个函数,您只需要选择其中的一个就行了,当然是对应的选择,不是随意的。

2.创建一个外设的初始化配置结构体:

GPIO_InitTypeDef GPIO_InitStructure;

对结构体中的内容结合你的需要修改:

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 + GPIO_Pin_7 + GPIO_Pin_8 + GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

最后初始化外设:

GPIO_Init(GPIOF,&GPIO_InitStructure);

到这里配置结束。您可以使用库文件中一大坨函数进行芯片的开发了。

接下来给大家我写的按键选择四个led原函数代码:

#include "stm32f10x.h"
#include "stm32f10x_conf.h"


void assert_failed(uint8_t* file, uint32_t line)
{
while(1);
}





int main()
{
    uint8_t a,b,c,d;
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 + GPIO_Pin_7 + GPIO_Pin_8 + GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_Init(GPIOF,&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_Init(GPIOC,&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_Init(GPIOD,&GPIO_InitStructure);
    while(1)
    {
        a = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
        b = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13);
        c = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8);
        d = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_3);
        if (a == 1)
            GPIO_SetBits(GPIOF,GPIO_Pin_6);
        else
            GPIO_ResetBits(GPIOF,GPIO_Pin_6);
        if (b == 1)
            GPIO_SetBits(GPIOF,GPIO_Pin_7);
        else 
            GPIO_ResetBits(GPIOF,GPIO_Pin_7);
        if (c == 1)
            GPIO_SetBits(GPIOF,GPIO_Pin_8);
        else 
            GPIO_ResetBits(GPIOF,GPIO_Pin_8);
        if (d == 1)
            GPIO_SetBits(GPIOF,GPIO_Pin_9);
        else
            GPIO_ResetBits(GPIOF,GPIO_Pin_9);
    }
}

发表评论 评论 (2 个评论)
回复 piedpiper 2015-1-28 00:01
学得很认真啊
回复 无奇不有 2015-1-29 11:29
piedpiper: 学得很认真啊
哈哈,谢谢夸奖!

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章