首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 系统运维 >

STM32F10x 学习札记 1 (使用STM32F10x StdPeriph Driver)

2012-10-19 
STM32F10x 学习笔记 1 (使用STM32F10x StdPeriph Driver)前段时间将 Cortex-M3 权威指南看完了,现在开始拿

STM32F10x 学习笔记 1 (使用STM32F10x StdPeriph Driver)

前段时间将 Cortex-M3 权威指南看完了,现在开始拿块开发板练手。

STM32F1xx 本身并不难,不过因为第一次用 Keil MDK,还有想在程序中使用最新的stm32f10x_stdperiph_lib V3.5,最后让程序跑通也经历了一番周折。这里简单的记录一下,希望对刚刚开始学STM32的初学者有些帮助。(这篇的内容很初级,高手请绕道)

首先介绍一下我这里的实验环境,开发板是块便宜货“神舟IV号STM32F107VCT开发板”,听这个名字就挺山寨,不过便宜倒是真的。仿真器是国内山寨的J-Link V8,买开发板时送的。J-Link 用的是 V4.12 版的驱动程序,segger 网站上有新版的驱动,不过我试过了,新版的驱动添加了检测J-Link是否是山寨的功能,装上也不能用,在网上也没有找到解决办法,所以还是死心吧,4.12 版的驱动也能支持挺多的ARM 芯片型号了。

IDE环境是Keil uVersion V4.10,工具链的版本为:RealView MDK-ARM 4.12,当然是D版的。

总之,这一套从头到脚都挺山寨。不过我这是非商业用途,仅供个人学习,想来 ARM 和 segger 也不会来难为我。

不说废话了。首先讲一讲如何在程序中使用STM32F10x_StdPeriph_Driver。

 

(1)新建一个文件夹存放项目文件,要注意路径不能有中文,我这里目录名取为stm32-test1。

(2)打开Keil uVersion,新建一个项目“test.uvproj”,CPU 选择STM32F107VC。

STM32F10x 学习札记 1 (使用STM32F10x StdPeriph Driver)

(3)Keil uVersion会提示是否添加启动代码,选择否,因为我们要用STM32F10x_StdPeriph_Driver中提供的启动代码。

STM32F10x 学习札记 1 (使用STM32F10x StdPeriph Driver)

(4)给Project Targets 改名,我改的名为:STM32F107。这一步不是必须的,只是默认的名称“Target 1”太没个性了。

(5)Groups 中我建立了三个组:Source、CMSIS、StdPeriphDriver。Source中存放我写的代码,另外两个顾名思义存放相应的代码。

STM32F10x 学习札记 1 (使用STM32F10x StdPeriph Driver)

(6)stm32-test1 目录中也添加相应的三个文件夹:Source、CMSIS、StdPeriphDriver。这时stm32-test1 目录中应该有这些文件(文件夹):

 CMSIS

 Source

 StdPeriphDriver

 test.plg

 test.uvopt

 test.uvproj

 test_STM32F107.dep

 test_Target 1.dep

(7)网上下载的STM32F10x_StdPeriph_Lib_V3.5.0,解压缩后“STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport”和“STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x”目录中的c文件和h文件都拷贝到 CMSIS 目录中。“STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”目录中 “startup_stm32f10x_cl.s”也拷贝到CMSIS 目录中。这里多说一句,startup_stm32f10x_cl.s 是 STM32F105和STM32F107系列的启动文件,cl指的是Connectivity line。如果用的是其他类型的STM32,需要换用合适的启动文件。

(8)“STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\inc”和“STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver\src”文件中的内容都拷贝到StdPeriphDriver目录中。“STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template\stm32f10x_conf.h”拷贝到StdPeriphDriver目录中。读者可能注意到我将c文件和头文件都混到了一个文件夹中了,之所以这样管理文件,是为了让项目的目录结构看起来尽量的简单。现在,CMSIS下的文件应该有这些:

 core_cm3.c

 core_cm3.h

 startup_stm32f10x_cl.s

 stm32f10x.h

 system_stm32f10x.c

 system_stm32f10x.h

StdPeriphDriver目录中文件应该有这些:

 misc.h

 stm32f10x_adc.c

 stm32f10x_adc.h

 stm32f10x_bkp.c

 stm32f10x_bkp.h

 stm32f10x_can.c

 stm32f10x_can.h

 stm32f10x_cec.c

 stm32f10x_cec.h

 stm32f10x_crc.c

 stm32f10x_crc.h

 stm32f10x_dac.c

 stm32f10x_dac.h

 stm32f10x_dbgmcu.c

 stm32f10x_dbgmcu.h

 stm32f10x_dma.c

 stm32f10x_dma.h

 stm32f10x_exti.c

 stm32f10x_exti.h

 stm32f10x_flash.c

 stm32f10x_flash.h

 stm32f10x_fsmc.c

 stm32f10x_fsmc.h

 stm32f10x_gpio.c

 stm32f10x_gpio.h

 stm32f10x_i2c.c

 stm32f10x_i2c.h

 stm32f10x_iwdg.c

 stm32f10x_iwdg.h

 stm32f10x_pwr.c

 stm32f10x_pwr.h

 stm32f10x_rcc.c

 stm32f10x_rcc.h

 stm32f10x_rtc.c

 stm32f10x_rtc.h

 stm32f10x_sdio.c

 stm32f10x_sdio.h

 stm32f10x_spi.c

 stm32f10x_spi.h

 stm32f10x_tim.c

 stm32f10x_tim.h

 stm32f10x_usart.c

 stm32f10x_usart.h

 stm32f10x_wwdg.c

 stm32f10x_wwdg.h

 stm32f10x_conf.h

对于某个具体的项目,这些文件不一定都会用到,不过放在这里也没什么坏处。

(9)将.\CMSIS;.\StdPeriphDriver 这两个目录加入到头文件的搜索目录中。

STM32F10x 学习札记 1 (使用STM32F10x StdPeriph Driver)

(10)将 startup_stm32f10x_cl.s 添加到组 CMSIS 中,新建个main.c 文件,加入到组 Source 中。

(11)修改“stm32f10x.h”文件。在文件中找到这一段:

#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)   /* #define STM32F10X_LD */          /*!< STM32F10X_LD: STM32 Low density devices */  /* #define STM32F10X_LD_VL */    /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */    /* #define STM32F10X_MD */         /*!< STM32F10X_MD: STM32 Medium density devices */  /* #define STM32F10X_MD_VL */   /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */    /* #define STM32F10X_HD_VL */          /*!< STM32F10X_HD: STM32 High density Value line devices */  /* #define STM32F10X_HD */          /*!< STM32F10X_HD: STM32 High density devices */  /* #define STM32F10X_XL  */               /*!< STM32F10X_CL: STM32 XL-density devices */  /* #define STM32F10X_CL */           /*!< STM32F10X_CL: STM32 Connectivity line devices */#endif


将对 “#define STM32F10X_CL”的注释去掉。

找到“#define USE_PERIPH_LIBRARY ”将注释去掉。

(12)将“system_stm32f10x.c”加入到组“CMSIS”中,找到如下代码:

 

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE    HSE_Value */ #define SYSCLK_FREQ_24MHz  24000000#else/* #define SYSCLK_FREQ_HSE    HSE_Value *//* #define SYSCLK_FREQ_24MHz  24000000 */ /* #define SYSCLK_FREQ_36MHz  36000000 *//* #define SYSCLK_FREQ_48MHz  48000000 *//* #define SYSCLK_FREQ_56MHz  56000000 */#define SYSCLK_FREQ_72MHz  72000000#endif

根据板子上的使用的时钟系统来确定SYSCLK的频率。

至此,该设置的都设置的差不多了,可以开始写应用代码了。我这里以闪灯程序为例吧。我的开发板上有四个LED,分别对应的GPIO端口D 的 PD2、PD3、PD4和PD7。

下面先给一个不利用STM32F10x_StdPeriph_Driver 中库函数,只利用STM32F10x_StdPeriph_Driver中给出的外设寄存器的定义。下面是main.c 的代码。

 

#include "stm32f10x.h"void delay(void){uint32_t i;for(i = 0; i < 3000000L; i++){}}int main(void){RCC->APB2ENR  |=  0x00000020;GPIOD->CRL = 0x24422244; //PD2 PD3 PD4 PD7 Set to Output mode  for(;;){GPIOD->ODR = 0x00000000;delay();GPIOD->ODR = 0x0000009C;delay();}}


 

下面再给个利用TM32F10x_StdPeriph_Driver 中库函数的代码。

#include "stm32f10x.h"#define RCC_GPIO_LED                                 RCC_APB2Periph_GPIOD#define GPIO_LED_PORT                                GPIOD    #define GPIO_LED1                                    GPIO_Pin_2    #define GPIO_LED2                                    GPIO_Pin_3    #define GPIO_LED3                                    GPIO_Pin_4    #define GPIO_LED4                                    GPIO_Pin_7#define GPIO_LED_ALL                        GPIO_LED1 |GPIO_LED2 |GPIO_LED3 |GPIO_LED4 void delay(void){uint32_t i;for(i = 0; i < 3000000L; i++){}}int main(void){GPIO_InitTypeDef GPIO_InitStructure;SystemInit();/* Enable GPIOB, GPIOC and AFIO clock */RCC_APB2PeriphClockCmd(RCC_GPIO_LED | RCC_APB2Periph_AFIO , ENABLE);  /* LEDs pins configuration */GPIO_InitStructure.GPIO_Pin = GPIO_LED_ALL;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIO_LED_PORT, &GPIO_InitStructure);for(;;){GPIO_SetBits(GPIO_LED_PORT, GPIO_LED_ALL);delay();GPIO_ResetBits(GPIO_LED_PORT, GPIO_LED_ALL);        delay();}}

编译程序,在链接阶段报错了,错误信息如下:

Build target 'STM32F107'linking...test.axf: Error: L6218E: Undefined symbol GPIO_Init (referred from main.o).test.axf: Error: L6218E: Undefined symbol GPIO_ResetBits (referred from main.o).test.axf: Error: L6218E: Undefined symbol GPIO_SetBits (referred from main.o).test.axf: Error: L6218E: Undefined symbol RCC_APB2PeriphClockCmd (referred from main.o).test.axf: Not enough information to list image symbols.test.axf: Finished: 1 information, 0 warning and 4 error messages.Target not created


 

说的很明白,GPIO_Init、GPIO_ResetBits、GPIO_SetBits、RCC_APB2PeriphClockCmd 这几个函数的实现没有找到。解决的办法显而易见,将“stm32f10x_gpio.c”和 “stm32f10x_rcc.c”两个文件加入到组“StdPeriphDriver”中,再编译就通过了。将程序下载到板子上,一切正常。

上面只说了个大概的流程,还有些如何设置J-Link 一类的都略去了,因为介绍这些的文章实在是太多了。


 

热点排行