《嵌入式系统开发》0806504130
实验指导书
实验一、按键输入及LED实验 2课时 实验二、STM32串口实验 2课时 实验三、定时器中断实验 2课时 实验四 PWM输出实验 2课时 实验五 TFTLCD显示实验 2课时 实验六 AD转换实验 2课时 实验七 UCOSII任务调度实验 4课时
金陵科技学院智控学院 自动化
《嵌入式系统开发》0806504130 实验指导书
实验一 按键输入及LED实验
实验时间:2016-03-29(周二3,4节),实验学时:2,实验地点:C105
一、实验目的与要求:
(1)熟悉MDK的编程环境;
(2)掌握基于固件库MDK5工程模板的方法;
(2)掌握STM32的IO口作为输入、输出使用的方法;
二、实验器材:
计算机,STM32F103RCT6实验平台。
三、实验过程
1.熟悉led和按键硬件电路; 2.建立工程模版;
3.根据实验内容编写主程序及应用程序 4.下载调试及仿真。
3.1实验内容:通过MiniSTM32开发板上载有的3个按钮(KEY0/KEY1/WK_UP),来控制板上的2个LED,其中KEY0控制DS0,按一次亮,再按一次,就灭。KEY1控制DS1,效果同KEY0。WK_UP按键则同时控制DS0和DS1,按一次,他们的状态就翻转一次。 3.2本实验用到的硬件资源有: 1) 指示灯DS0、DS1
2) 3个按键:KEY0、KEY1和KEY_UP。 3.3、硬件设计
(1)输出引脚LED(DS0和DS1)。其电路在ALIENTEK MiniSTM32开发板上默认是已经连接好了的。DS0接PA8,DS1接PD2。所以在硬件上不需要动任何东西。其连接原理如图1.1所示。
图1.1 LED与STM32连接原理图
(2)输入引脚,在MiniSTM32开发板上的按键KEY0连接在PC5上、KEY1连接在PA15上、WK_UP连接在PA0上。如图1.2所示:
图1.2 按键与STM32连接原理图
1
《嵌入式系统开发》0806504130 实验指导书
这里需要注意的是:KEY0和KEY1是低电平有效的,而WK_UP是高电平有效的,除了KEY1有上拉电阻(与JTDI共用),其他两个都没有上下拉电阻,所以,需要在STM32内部设置上下拉。
3.4、软件设计
首先建立工程目录,如下图1.3所示。
① 组USER下面存放的主要是用户代码。system_stm32f10x.c里面主要是系统时钟初始化函数SystemInit相关的定义,一般情况下文件用户不需要修改。stm32f10x_it.c里面存放的是部分中断服务函数。main.c函数主要存放的是主函数。
② 组HARDWARE下面存放的是每个实验的外设驱动代码,他的实现是通过调用FWLib下面的固件库文件实现的,比如led.c 里面调用stm32f10x_gpio.c里面的函数对led 进行初始化,这里面的函数是讲解的重点。后面的实验中可以看到会引入多个源文件。
③ 组SYSTEM是ALIENTEK提供的共用代码,包含Systick延时函数,IO口位带操作以及串口相关函数。
④ 组CORE下面存放的是固件库必须的核心文件和启动文件。这里面的文件用户不需要修改。
⑤ 组FWLib下面存放的是ST官方提供的外设驱动固件库文件,这些文件大家可以根据工程需要来添加和删除。每个stm32f10x_ppp.c源文件对应一个stm32f10x_ppp.h头文件。 ⑥ HARDWARE主要添加本项目中用到的.c文件。
图1.3 工程目录
在HARDWARE文件夹目录下,建立key文件夹,放key.c、key.h文件,建立led文件夹,放led.c、led.h文件。
在Manage Project Items管理里面新建一个HARDWARE的组,并把led.c、key.c加入到这个组里面;点击魔术棒,添加led.h和key.h所在的目录,然后就可以在HARDWARE下完成key.c、key.h、led.c、led.h文件的编写。 3.4.1输出引脚配置
STM32的IO口相比51而言要复杂得多,所以使用起来也困难很多。首先STM32的IO口可以由软件配置成如下8种模式:
1、输入浮空 2、输入上拉 3、输入下拉 4、模拟输入 5、开漏输出
2
《嵌入式系统开发》0806504130 实验指导书
6、推挽输出
7、推挽式复用功能 8、开漏复用功能
在HARDWARE->LED文件夹下面,保存为led.c,内容为: #include \void LED_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
RCC_APB2Periph_GPIOD, ENABLE); //使能PA,PD端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //LED0-->PA.8 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.8 GPIO_SetBits(GPIOA,GPIO_Pin_8); //PA.8 输出高 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//LED1-->PD.2 端口配置,推挽输出 GPIO_Init(GPIOD, &GPIO_InitStructure);//推挽输出,IO口速度为50MHz GPIO_SetBits(GPIOD,GPIO_Pin_2); //PD.2输出高 }
头文件led.h如下: #ifndef __LED_H #define __LED_H #include \//LED端口定义
#define LED0 PAout(8) // PA8 #define LED1 PDout(2) // PD2
void LED_Init(void);//初始化 #endif
这里使用的是位带操作来实现操作某个IO口的1个位的,通过位带操作PA8输出高低电平从而控制LED0的方法如下:
LED0=1; //通过位带操作控制LED0的引脚PA8输出高电平 LED0=0; //通过位带操作控制LED0的引脚PA8输出低电平 同样我们也可以使用固件库操作和寄存器操作 来实现IO口操作。库函数操作方法如下:
GPIO_SetBits(GPIOA, GPIO_Pin_8); //设置GPIOA8输出1,等同LED0=1; GPIO_ResetBits (GPIOA, GPIO_Pin_8); //设置GPIOA8输出0,等同LED0=0;
库函数操作就直接调用两个函数即可控制IO 输出高低电平。我们也通过直接操作寄存器
BRR和BSRR的方式来操作IO口输出高低电平,方法如下: GPIOA->BRR=GPIO_Pin_8; //设置GPIOA.8输出1,等同LED0=1; GPIOA->BSRR=GPIO_Pin_8; //设置GPIOA.8输出0,等同LED0=0;
对于上面三种方法,大家根据自己喜好来选择一种即可。在IO 口速度没有太大要求的情况下效果都是一样的。 3.4.2输入引脚配置
3
《嵌入式系统开发》0806504130 实验指导书
在HARDWARE文件夹下建立key.c文件以及头文件key.h。下面我们首先打开key.c文件,key.c代码如下:
#include \#include \//按键初始化函数
//PA15 和PC5 设置成输入 void KEY_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);//使能PORTA,PORTC时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //关闭jtag,使能SWD,可以用SWD模式调试
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA15
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PC5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//PA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0 }
//按键处理函数 //返回按键值
//mode:0,不支持连续按;1,支持连续按; //返回值:
//0,没有任何按键按下 //KEY0_PRES,KEY0按下 //KEY1_PRES,KEY1按下 //WKUP_PRES,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;
4