STM32F103单片机学习笔记2

这次,我们来看看工程文件的建立。以寄存器为例。【后边还有库函数的函数模型建立,跟这个原理相同,只是要动的文件不太一样】

 

MDK5 的安装,请参考光盘“ 6 ,软件资料 1 ,软件 MDK5 安装过程 .txt ”即可,里面
详细介绍了 MDK5 的安装方法,本节我们将教大家如何新建一个 STM32 MDK5 工程。为了
方便大家参考,我们将本节最终新建好的工程模板存放在光盘:4 、程序源码 \1 ,标准例程 -寄
存器版本\ 实验 0 新建工程实验,如遇新建工程问题,请打开该实验对比。
前边的操作跟51基本一致。我们按照51的方式新建项目。
因为 ALIENTEK MiniSTM32 开发板所使用的 STM32 型号为 STM32F103RCT6 ,所以在这里我
们选择 STMicroelectronics STM32F1 Series STM32F103 STM32F103RCT6 (如果使用的是
其他系列的芯片,选择相应的型号就可以了,特别注意: 一定要安装对应的器件 pack 才会显
示这些内容哦!!,如果没得选择,请关闭 MDK ,然后安装 光盘: 6 ,软件资料 \1 ,软件 \MDK5\
Keil.STM32F1xx_DFP.2.2.0.pack 这个安装包)。
【这是来自手册里的提示。如有需要,请自行去正点原子官方文件中提取文件】

 安装完成之后,我们按照图示要求选择器件。注意MINI板选择RC,战舰版或精英版选择ZE。

下半部分的内容看看就行,咱们直接点x关闭即可。(点ok的话会出现奇怪的内容,所以不建议点ok,叉掉就好)

ST 公司提供了 3 个启动文件给我们,分别用于不同容量的 STM32 芯片,这三个文件是:
startup_stm32f10x_ld.s
startup_stm32f10x_md.s
startup_stm32f10x_hd.s
其中, ld.s 适用于小容量 产品; md.s 适用于中等容量产品; hd 适用于大容量产品;
这里的容量是指 FLASH 的大小 . 判断方法如下:
小容量: FLASH 32K
中容量: 64K FLASH 128K
大容量: 256K FLASH
我们开发板使用的是 STM32F103RCT6 FLASH 容量为 256KB ,属于大容量产品,所以我
们选择 startup_stm32f10x_hd.s 作为我们的启动文件。
这三个启动文件在开发板光盘 4 ,程序源码 STM32 启动文件 文件夹里面(也可以从我
们 的论坛 下载到, 下载地 址: http://www.openedv.com/posts/list/313.htm ), 这里我 们把
startup_stm32f10x_hd.s 拷贝到刚刚新建的 USER 文件夹里面。
这是手册里的内容,注意内存的选择。

建立之后,我们按照这样的要求来插入文件。【库函数这个东西在后期编译的时候非常方便,都是,最大的毛病就是 建立巨麻烦!!强烈建议保存源文件,以后直接复制,不用重新建立,不然太累,创建就弄几十分钟。留着以后直接用即可】 

这个时候还不能直接编译。它会因为一些小小的问题报错,我们需要继续解决报错事项。

打开user文件夹,我们可以看到三个新文件夹:DebugConfigListings Objects

USER 文件夹下, startup_stm32f10x_hd.s (启动文件)和 test.uvprojx MDK5 工程文件)
是我们必须用到的 2 个文件,然后 DebugConfig Listings Objects 文件夹是 MDK5 自动生
成的, DebugConfig 文件夹用于存储一些调试配置文件, Listings Objects 文件夹用来存储 MDK
编译过程的一些中间文件。
MDK5.21A 已经默认将这些文件生成在了 Listings Objects 文件夹里面,但是 MDK5.11A
及之前版本是不会自动生成这两个文件夹的,所有中间文件都是生成在工程同面目录下,也就
USER 文件夹下,这样会显得比较混乱。
这里,我们不用 MDK5 自己生成的 Listings Objects 文件夹来存放中间文件,而是在 TEST
目录下新建一个新的 OBJ 文件夹来存放这些中间文件。这样, USER 文件夹专门用来存放启动
文件( startup_stm32f10x_hd.s )、工程文件( test.uvprojx )等不可缺少的文件,而 OBJ 则用来存
放这些编译过程中产生的中间文件 ( 包括 .hex 文件也将存放在这个文件夹里面 ) 。然后把 Listings
Objects 文件夹里面的东西全部移到 OBJ 文件夹下(当然要先关闭 MDK 软件),并删除这两
个文件夹(DebugConfig 文件夹不用删除)。

 

还是那个问题,别拷贝错!库函数和寄存器不一样!!不一样!拷贝错了整个都不能用!

之后我们像51单片机那样,添加system文件,并在system文件下添加三个重要文件 

 user底下再添加test.c文件

接下来我们进行编译环境设置

 

 还有这一步设置

这里特别提醒大家: 图中 1 处,我们必须根据所用 STM32F1 型号的容量,来输入相关宏
定义,对于 STM32F103 系列芯片,设置原则如下:
16KB FLASH 32KB 选择: STM32F10X_LD
64KB FLASH 128KB 选择: STM32F10X_MD
256KB FLASH 512KB 选择: STM32F10X_HD
因为 MniSTM32 使用的是 STM32F103RCT6 FLASH 容量为 256KB ,所以,这个位置我们 设置为: STM32F10X_HD

后边我们像51单片机那样,构建hex文件,然后随便导入一个工程文件样板进行编译 。这个时候,我们才算是正式完成基础框架的构建。

接下来,咱们顺势看看走马灯设计。

 这个是引脚结构。

我们打开样本文件,建立一个叫hardware的文件夹,里面再建立一个叫key的文件夹。之后以同样的方式,在key中建立一个key.c的文件。

#include "key.h"
#include "delay.h"
//按键初始化函数
//PA0.15 和 PC5 设置成输入
void KEY_Init(void)
{
RCC->APB2ENR|=1<<2; //使能 PORTA 时钟
RCC->APB2ENR|=1<<4; //使能 PORTC 时钟
JTAG_Set(SWD_ENABLE); //关闭 JTAG,开启 SWD
GPIOA->CRL&=0XFFFFFFF0; //PA0 设置成输入 
GPIOA->CRL|=0X00000008; 
GPIOA->CRH&=0X0FFFFFFF; //PA15 设置成输入 
GPIOA->CRH|=0X80000000; 
GPIOA->ODR|=1<<15; //PA15 上拉,PA0 默认下拉
GPIOC->CRL&=0XFF0FFFFF; //PC5 设置成输入 
GPIOC->CRL|=0X00800000; 
GPIOC->ODR|=1<<5; //PC5 上拉
} 
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//返回值:
//0,没有任何按键按下
//KEY0_PRES(1),KEY0 按下
//KEY1_PRES(2),KEY1 按下
//WKUP_PRES(3),WK_UP 按下
//注意此函数有响应优先级,KEY0>KEY1>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按 
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{
delay_ms(10);//去抖动
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(WK_UP==1)return WKUP_PRES; 
}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; 
return 0;// 无按键按下
}

先看看程序设计,我们大概浏览一下。 

以下内容比较专业,于是我直接从手册当中引用了

这段代码包含 2 个函数, void KEY_Init(void) u8 KEY_Scan(u8 mode) KEY_Init 是用来
初始化按键输入的 IO 口的。实现 PA0 PA15 PC5 的输入设置,注意这调用了: JTAG_Set
这个函数,用于禁止 JTAG ,开启 SWD ,因为 PA15 占用了 JTAG 的一个 IO ,所以要禁止 JTAG
从而让 PA15 用作普通 IO 输入。
KEY_Scan 函数,则是用来扫描这 3 IO 口是否有按键按下。 KEY_Scan 函数,支持两种
扫描方式,通过 mode 参数来设置。
mode 0 的时候, KEY_Scan 函数将不支持连续按,扫描某个按键,该按键按下之后必
须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次
触发,而坏处就是在需要长按的时候就不合适了。
mode 1 的时候, KEY_Scan 函数将支持连续按,如果某个按键一直按下,则会一直返
回这个按键的键值,这样可以方便的实现长按检测。
有了 mode 这个参数,大家就可以根据自己的需要,选择不同的方式。这里要提醒大家,
因为该函数里面有 static 变量,所以该函数不是一个可重入函数,在有 OS 的情况下,这个大家
要留意下。同时还有一点要注意的就是,该函数的按键扫描是有优先级的,最优先的是 KEY0
第二优先的是 KEY1 ,最后是 WK_UP 按键。该函数有返回值,如果有按键按下,则返回非 0
值,如果没有或者按键不正确,则返回 0
保存 key.c 代码,然后我们按同样的方法,新建一个 key.h 文件,也保存在 KEY 文件夹下
面。在 key.h 中输入如下代码:

 

#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#define KEY0_PRES 1 //KEY0 按下
#define KEY1_PRES 2 //KEY1 按下
#define WKUP_PRES 3 //WK_UP 按下
#define KEY0 PCin(5) //PC5
#define KEY1 PAin(15) //PA15 
#define WK_UP PAin(0) //PA0 WK_UP 
void KEY_Init(void); //IO 初始化
u8 KEY_Scan(u8 mode); //按键扫描函数 
#endif

这是头文件代码的输入。【记得把key.h也加到hardware里面】

回到主界面,在test.c当中再写一段代码:

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h" 
#include "key.h" 
int main(void)
{
u8 t; 
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
LED_Init(); //初始化与 LED 连接的硬件接口
KEY_Init(); //初始化与按键连接的硬件接口
LED0=0; //点亮 LED0
while(1)
{
t=KEY_Scan(0); //得到键值
switch(t)
{
case KEY0_PRES:
LED0=!LED0;
break;
case KEY1_PRES:
LED1=!LED1;
break;
case WKUP_PRES:
LED0=!LED0;
LED1=!LED1;
break;
default:
delay_ms(10);
}
}
}

编译之后发现没有报错,也没有警告。我们按照上次笔记所写,通过 daplink下载器把程序内容运行一下。结果确实亮了(忘了录视频了,我截一段别人的视频也不太合适x)

本次的学习内容就到这里

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值