stm32的官方库非常方便,但是里面的使用手册是英文的,而且也没有很详细的使用说明,对新手来说入门比较困难,而且网上现存的教程要么是针对v2.x的库的,要么是针对keil 4.x的,这两个东西更新后差别都蛮大。有新的可用为何不用最新的呢?
一: 用keil 5构建模板工程。在keil顶部选Project->New uVision Project, 输入工程名称,进入device选择界面。注意,因为keil 5变成了在线安装Package的模式(即刚安装好软件并不附带各种芯片的包,用哪个下哪个),如果你已经安装了ST的Package,不要用那个Package!!Keil 5暂时不兼容官方库,如果用了的话编译会报错。解决方案:1.使用附带的ARM - ARM Cortex M3 2.如果还不行就下载我这个吧,下载好之后模板就全部构建完成了。
在你想要创建工程的文件夹下创建三个文件夹:Library、Project和Output,把刚才创建的工程所有文件剪切进Project文件夹。好了之后,我们需要添加库函数文件。解压库函数包,把解压目录下Library文件夹中的CM3文件夹和STM32F10x_StdPeriph_Driver文件夹复制到工程目录下Library文件夹下,把标准库目录下的:STM32F10x_StdPeriph_Lib_V3.5.0ProjectSTM32F10x_Std Periph_Template文件夹下的main.c、stm32f10x_conf.h、stm32f10x_it.h、 stm32f10x_it.c 拷贝到你的工程Project目录下。
用keil打开你刚才创建的工程,右键点击Source Group->Manage Project Item
把Groups改成下图这样:
然后选择STARTUP,点击右下方的Add Files,添加startup_stm32f10x_md.s ( . LibrariesCMSISCM3DeviceSupportSTSTM32F10xstartuparm
),注意后缀,.s为汇编文件。(具体添加哪一个需要根据你的板载芯片来定,我的芯片Flash是128k的,属于MD,因此添加startup_stm32f10x_md.s,若为256k,则应添加startup_stm32f10x_hd.s,其他请参见官方文件进行选择)然后选择Library,在library组里面添加 “LibrariesSTM32F10x_StdPeriph_Driversrc”里面的全部文件 。
再选择CMSIS,添加Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x”路径下的 system_stm32f10x.c文件,以及LibrariesCMSISCM3CoreSupport下的core_cm3.c 文件。注意,除了了一个.s文件外,只添加.c即可,不需要添加.h。
添加完之后是这个样子(刚添加完没每个文件前有那个加号,编译一次之后就有了):
添加完之后还不能编译,因为此时Keil还是从默认的路径去寻找要包括的头文件,肯定是找不到的,因此我们要更改一下路径设置,点击魔棒按钮:
点上面C/C++那一栏,点开之后下面有一个Include Paths,点开,修改成下图这样
就是从库函数存放的位置寻找头文件。根据库函数的声明,我们需要根据自己不同的芯片uncomment掉相应的注释。库函数stm32f10x.h原话如下:
但大家可以试一下,修改这个文件是修改不了的,因为它是只读的。一种做法是找到这个文件之后右键勾掉只读选项再修改,但这种做法太麻烦。Keil提供了一个宏定义的功能,我们只需要在刚才C/C++选项框那里Define栏写上相应代号就行了,相同的还有USE_STDPERIPH_DRIVER, 定义这个才能使用外设库。在Define栏输入USE_STDPERIPH_DRIVER,STM32F10X_MD。
这就相当于在程序中写:#define USE_STDPERIPH_DRIVER
#define STM32F10X_MD
省事很多。
还有在Output选项卡中勾选Create HEX File, 点Select Folder for Objects,选择你建立的Output文件夹(这样所有的生成文件都在Output下,方便管理)。至此,构建就完成了。
大家写程序只需要在main.c中写就行,那么如何引用库函数呢?只需要在main开头写一句include “stm32f10x.h”就可以了,这样就已经包含进了所需的所有库函数。
现在可以编译一下试一下。如果失败,那么可能有两种原因,一是你操作的过 程失误,重新来一下;二是keil5提供的devices还是不兼容,刚才建立工程的时候大家选择的是ARM - ARM Cortex M3 ,其实应该什么都不选的,但什么都不选工程无法建立,那大家可以通过直接下载我的这个工程来规避这个问题。
下面解释一下在Project文件夹下刚才复制进的几个文件:
1.stm32f10x_conf.h文件:该文件不需要手动添加进工程,会自动添加。打开之后会发现,该文件就是include了各种外设的头文件。我们需要用那个,就保留哪个include即可,其他可以删掉或注释掉。默认是全部包含,当然我们不去改动也完全可以。
2.stm32f10x_it.c文件:这个文件包含了所要使用的中断,如果有的话加入即可。
大家可以注意到解压开库函数zip之后有一个chm文件,那个就是官方固件库文档,使用很方便,用哪个查哪个即可,不过当然是全英文。
这里举几个例子说明如何使用这个文档吧,以按键控制LED为例。
首先一定要仔细读这个文档首页的几个链接的内容。看完之后,我们首先明白使用GPIO,就要先用PPP_InitTypeDef函数定义相应结构体,
GPIO_InitTypeDef GPIO_InitStruct;
然后使能对应的时钟,即RCC。用哪个函数呢?打开文档,选择Modules-STM32F10x_Periph_Driver-RCC-RCC_Exported_Functions,这个就是RCC相关的函数了,通过硬件原理图我们可以发现GPIO使用的是APB2时钟,因此就是这个函数了:
该函数参数:
因此我们写成:
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE ) ;
就是这样,其他的函数使用方法和这个大同小异。
同时,大家也要下载官方硬件的Reference Manual,代号RM0008,可以到我个人网页中下载。推荐仔细阅读前几个章节,后面的需要用那个读哪个。
案例程序main.c:
/*************************************************************
* 作者:Alan Zhao *
* 博客:alanzjl.sinaapp.com *
* CSDN博客:http://blog.csdn.net/alanzjl *
*************************************************************
* 针脚说明:Key1-PA0,Key2-PA1,LED1-PA2,LED2-PB2,LED3-PA3 *
*************************************************************
*/
#include "stm32f10x.h"
enum{LED1,LED2,LED3}LED;
enum{Key1,Key2}Key;
void delay(int nms){ //延时
for(;nms>=0;nms--){
int n;
for(n=1200;n>=0;n--);
}
}
void LED_Init(GPIO_TypeDef* Pin_Mode, uint16_t pin){ //LED初始化
GPIO_InitTypeDef GPIOInitStructure;
if(Pin_Mode == GPIOA) //由于LED1和LED3为PA,LED2为PB,因此此处需判断
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
else if(Pin_Mode == GPIOB)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIOInitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIOInitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIOInitStructure.GPIO_Pin = pin;
GPIO_Init(Pin_Mode,&GPIOInitStructure);
}
void Key_Init(uint16_t pin){ //按键初始化
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = pin;
//GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init (GPIOA,&GPIO_InitStruct);
}
int Keyscan(uint16_t pin){ //键盘扫描 pin为按键管脚
uint8_t status;
status=GPIO_ReadInputDataBit(GPIOA,pin); //读取按键状态,0为按下
if(status==0){
return 1;
}
else
return 0;
}
void LED_ON(LED){ //开灯函数
if(LED==LED1){
GPIOA->BRR=GPIO_Pin_2;
}
else if(LED==LED2){
GPIOB->BRR=GPIO_Pin_2;
}
else if(LED==LED3){
GPIOA->BRR=GPIO_Pin_3;
}
return;
}
void LED_OFF(LED){ //关灯函数
if(LED==LED1){
GPIOA->BSRR=GPIO_Pin_2;
}
else if(LED==LED2){
GPIOB->BSRR=GPIO_Pin_2;
}
else if(LED==LED3){
GPIOA->BSRR=GPIO_Pin_3;
}
return;
}
/****************************************************************/
int main(void){
LED_Init(GPIOA,GPIO_Pin_3);
LED_Init(GPIOA,GPIO_Pin_2);
LED_Init(GPIOB,GPIO_Pin_2);
Key_Init(GPIO_Pin_0);
Key_Init(GPIO_Pin_1);
LED_OFF(LED1); //初始化时全部关灯
LED_OFF(LED2);
LED_OFF(LED3);
while(1){
LED_ON(LED2);
delay(1000);
LED_OFF(LED2);
delay(1000); //LED2不停闪烁
if(Keyscan(GPIO_Pin_0)){
delay(200); //去抖动
if(Keyscan(GPIO_Pin_0)){
while(Keyscan(GPIO_Pin_0));
GPIOA->ODR ^= GPIO_Pin_2; //灯状态取反
}
}
if(Keyscan(GPIO_Pin_1)){
delay(200); //去抖动
if(Keyscan(GPIO_Pin_1)){
while(Keyscan(GPIO_Pin_1));
GPIOA->ODR ^= GPIO_Pin_3; //灯状态取反
相关文件下载:STM32官方固件库v3.5 http://download.csdn.net/detail/alanzjl/8638291
STM32官方固件库v3.5模板工程 http://download.csdn.net/detail/alanzjl/8638303
上一篇:STM32基于库函数工程模板
下一篇:STM32学习笔记——独立看门狗IWDG介绍及配置
推荐阅读最新更新时间:2024-11-02 10:49
- 热门资源推荐
- 热门放大器推荐
设计资源 培训 开发板 精华推荐
- 2S锂电池充电+均衡板 TP5100+ETA3000方案
- 采用 LTC1929-PG 2V/20A CPU 电源并具有有源电压定位的典型应用电路
- LT1021CCN8-5 用于处理更高负载电流的电压基准的典型应用
- KIT34675EPEVBE: Evaluation Kit - 34675, Single-cell Li-Ion Battery Charger
- CAV4201 350mA 高效降压 LED 驱动器的典型应用,适用于 6-LED 的 36V 应用
- ESP32-SOLO
- LTC1473L,用于 3.3V 应用的自动电源路径切换
- 具有峰值电流软启动、小尺寸的 LTC3632EDD、3.3V、20mA 稳压器的典型应用电路
- LT8641EUDC 2MHz、5V、3.5A 降压转换器的典型应用电路
- 串口转USB HID类键盘CH9328_JX