74
嵌入式技术与应用 教案 庞家成 利尔达科技有限公司 编著 (内部资料 版权所有 违者必究)

嵌入式技术与应用 教案 - timuwork.comµŒ入式技术应用教案.pdf · 3. 打开Keil4软件,在Project菜单下选择New uVision Project ... 目名称如My Program,保存到刚才的Project文件夹下面。

Embed Size (px)

Citation preview

嵌入式技术与应用

教案

庞家成

利尔达科技有限公司

编著

(内部资料 版权所有 违者必究)

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 Cortex-M3 内核体系结构

教学目的

和要求

通过此项目的学习使学生了解嵌入式系统的概念、定义、发展、和研究热点。

通过对 CM3 内核体系结构的了解,存储器结构的了解,进一步为后续的 STM32

平台应用提供基础。

嵌入式系统定义、发展、方向

嵌入式微处理器

嵌入式实时操作系统

CM3 内核结构、存储器组织等

教学重点 嵌入式系统组成及常用软硬件平台,CM3 内核结构、存储器组织等

教学难点 CM3 内核结构、存储器组织

教学组织

形式 多媒体面授+动画+技术文档阅读

教学辅助

手段 多媒体展示

课外作业 阅读技术文档《Cortex-M3 权威指南》

课后小结

由于学生开始掌握 51 单片机,对存储器结构相对比较简单的能够理解,而对

于 CM3 内核架构这样比较复杂的系统来说,理解有一定的困难,对 32 位寄存器的

理解有待于加强。

授课主要内容

一、嵌入式系统定义 1、IEEE 定义

嵌入式系统是“用于控制、监视或者辅助操作的机器、设备或装置”(原文为 devices used to

control, monitor, or assist the operation of equipment, machinery or plants)。

通常执行特定功能

嵌入式系统的核心----嵌入式微处理器

严格的时序和稳定性要求

全自动操作循环

1、 微机学会定义

嵌入式系统是以嵌入式应用为目的的计算机系统。可分为系统级、板级、片级

系统级:各种类型的工控机、PC104 模块

板级:各种类型的带 CPU 的主板及 OEM 产品

片级:各种以单片机、DSP、微处理器为核心的产品

2、 定义总结

广义上讲,凡是带有微处理器的专用软硬件系统都可称为嵌入式系统。如各类单片机和 DSP

系统。这些系统在完成较为单一的专业功能时具有简洁高效的特点。但由于他们没有操作系统,

管理系统硬件核软件的能力有限,在实现复杂多任务功能时,往往困难重重,甚至无法实现。

从狭义上讲,我们更加强调那些使用嵌入式微处理器构成独立系统,具有自己操作系统,具

有特定功能,用于特定场合的嵌入式系统。本课程中的嵌入式系统是指狭义上的嵌入式系统。

二、嵌入式系统组成

嵌入式系统由嵌入式硬件与嵌入式软件组成。

嵌入式硬件以芯片、模板、组件、控制器形式埋藏于设备内部。

嵌入式软件是实时多任务操作系统和各种专用软件,一般固化在 ROM 或闪存中。

嵌入式系统软硬兼施,融为一体,成为产品,但在开发过程中需要一些开发工具进

行辅助开发。

驱动器 1 传感器 1

驱动器 2 传感器 2

…… ……

驱动器 N

被控对象

传感器 N

功能层 应用程序

文件系统 图形用户接口 任务管理 软件层

实时操作系统(RTO S)

中间层 BSP/HAL 硬件抽象层 /板级支持包

D/A 通用接口

A/D RO M

I/O

嵌入式

处理器 SDRAM

硬件层

人机交互接口

嵌入式系统

三、嵌入式微处理器 嵌入式处理器可以分为四类:

嵌入式微处理器 EMPU(Embedded Microprocessor Unit)

嵌入式微控制器 EMCU(Embedded Microcontroller Unit)

嵌入式数字信号处理器 EDSP(Embedded Digital Signal Processor)

嵌入式片上系统 ESoC (Embedded System on Chip)

四、嵌入式软件

嵌入式系统软件核心包括:

系统软件:嵌入式操作系统

支撑软件:嵌入式软件开发平台及工具

应用软件:嵌入式应用软件

通用计算机具有完善的操作系统,应用程序的开发以及完成后的软件都在OS平台上面运行,

但一般不是实时的。

嵌入式系统则不同,应用程序用汇编语言和 C 语言来开发,可以没有操作系统直接在芯片

上运行;但是为了合理地调度多任务、利用系统资源,用户必须自行选配 RTOS 开发平台,这样

才能保证程序执行的实时性、可靠性,并减少开发时间,保障软件质量。

国外 RTOS:

VX Works (风河系统)

Windows CE (微软)

pSOSystem (风河系统)

VRTX (明导资讯)

Palm

PowerTV

AMX (KADAK)

C Executive

PSX (JMI)

VelOSity (Green Hills)

OS-9 (Microware Systems)

OSE (Enea OSE Systems)

QNX (QNX Software Sys)

RTXC (Lineo/Embedded Power Corp)

SuperTask! (US Software)

ThreadX (Express Logic)

TNT/RTX (VenturCom)

Windows NT Embedded/XP (微软)

国内 RTOS:

女娲 Hopen

桑夏 2000

Delta OS

中软 Linux2.0

Linux HardHat

Linux (Monta Vista)

Red Flag Linux(红旗 Linux)

HBOS(“天堂之鸟”)

Suse

Red Hat

Embedix

LynxOS (LynuxWorks)

五、嵌入式开发工具 编译器:GNU 编译器

调试工具:GNU 调试工具

集成开发环境(IDE)

绘图入门工具

算法开发工具:UML/SDL 工具库

网络/通信协议

配置管理工具

需求管理工具

DSP 开发工具

器件驱动器开发工具

软硬件协同验证工具

Java 工具

存储器分析工具

软件仿真/建模工具

Win CE 工具

测试软件事件跟踪工具

内电路仿真器(ICE)

ROM 仿真器

JTAG 仿真器

逻辑分析器

示波器

五、Cortex-M3 内核结构

详见《Cortex-M3 权威指南》

六、Cortex-M3 存储器组织

详见《Cortex-M3 权威指南》

七、Cortex-M3 NVIC 与中断

详见《Cortex-M3 权威指南》

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 Keil MDK 工程模板建立

教学目的

和要求

通过此项目的学习使学生了解 Keil MDK 工程的建立流程,怎样运用集成开发

环境进行仿真、下载、调试。通过对 STM 固件库 V3.5 版本的利用,建立合理的工

程模板,为今后的外设资源学习奠定基础。

Keil MDK 工程建立流程

STM 固件库 V3.5 的认识

Keil MDK 中添加固件库 V3.5

Keil MDK 的仿真、下载、调试方法

教学重点 Keil MDK 中添加固件库 V3.5

教学难点 Keil MDK 中添加固件库 V3.5

教学组织

形式 多媒体面授+同步动手+技术文档阅读

教学辅助

手段 多媒体展示

课外作业 阅读技术文档《Cortex-M3 权威指南》、STM 固件库 V3.5

课后小结

由于 STM32 系列微处理器的强大功能,故 STM 公司发布其固件库 V3.5 便于

开发人员使用,缩短开发周期。但如何利用好固件库添加到集成开发环境中是个问

题,学生第一次使用固件库,对其理解还有待加深。

授课主要内容

一、准备工作 1. 下载 STM32F10x_StdPeriph_Lib_V3.5.0 固件库。

2. 下载并安装好 Keil uVision V4.10(MDK4)

二、开始操作

1. 首先解压 STM32F10x_StdPeriph_Lib_V3.5.0 固件库。PS:保留一个备份,你懂的。

解压得到如图 1 所示的几个文件夹。

其中_htmresc 文件夹:里面是 ST 的 Logo 图片,没有多大用,可以删除。

Libraries 文件夹:是比较重要的文件 包含 STM32 的系统文件和大量头文件,即库文件。

Project 文件夹:里面为 STM32F10x 的例程和工程模板。Keil 对应的就是 MDK-ARM 文件下

的工程模板。也可以利用这个工程模板为原型建立自己的工程模板本文不用此法。

Utilities 文件夹:里面有一些实用程序,也没多大用,可删除。

Release_Notes.html:版本注视,可删除。

stm32f10x_stdperiph_lib_um.chm:帮助文件,你懂的。

2. 为了项目程序中的各部分条理清晰,我们建议工程文件夹时对其子目录子下归类建立子文件

夹,例建立一个工程文件夹 My Project,在其下在创建五个子文件夹如图 2 所示:

其中:

CMSIS 文件夹:此文件夹从 STM32F10x_StdPeriph_Lib_V3.5.0 固件库中的 CMSIS 文件夹直接

复制过来。

Libraries 文件夹:此文件夹从 STM32F10x_StdPeriph_Lib_V3.5.0固件库中的 Libraries

文件夹复制过来。只保留当中的 inc 和 src 文件夹。即只包含头文件。

Startup 文件夹:此文件夹从 CMSIS\CM3\DeviceSupport\ST\STM32F10x\Startup 目录下直接

将 Startup 文件剪切出来。其中放置的是启动代码,具体的代码根据所用芯片的容量选择,我们

用的 STM32F103C8 为中等容量芯片,故选择其中的 startup_stm32f10x_md.s 启动代码,其他不

用的可以删除

User 文件夹:User文件夹为用户的应用程序,其中包括 main.c ,stm32f10x_conf.h,

stm32f10x_it.c,stm32f10x_it.h 四个文件,这四个文件可从 V3.5.0 固件库

Project\STM32F10x_StdPeriph_Template 目录下复制过来,当然 main.c 文件中的内容可删除。

Project 文件夹 :此文件夹用来存放项目文件。比如你等下要建立的工程名字 My

Program.uvproj,就放在这里。 在该文件下存放一些项目的输出信息,OUTPUT,和 LISTING 信息,

可以建立这两个文件夹,之后就可以在 OPTIONS FOR TARGET 'PROJECT' 里面进行路径设置。

3. 打开 Keil4 软件,在 Project 菜单下选择 New uVision Project 新建新的项目,键入新的项

目名称如 My Program,保存到刚才的 Project 文件夹下面。

4. 选择芯片类型,根据实际情况选择芯片类型,我们在这里选择 STM32F103c8,确定后弹出一

个窗口询问是否复制启动代码,选择“否”,如图所示。

这时新的项目工程就建立了。

5. 这时点击如图所示的图标。

弹出如下窗口:

可根据实际需要添加相应的文件,如图所示:

添加完后 Project 区域的树形结构如图所示:

6. 接下来要设置设置目标选项,点 图标进入 Target Option 界面如图所示,

在上面设置晶振的实际时钟频率,我们所用的时钟为 8.00MHz。

选择 Output 项进行如图所示设置。

点击 Listing 选项,并配置 Listing 文件的所在路径为 Projet 下的 Listing 文件夹。

接下来配置编译器的路径,设置如图所示:在“ C/C++ ” 选项中我们可以加入预定义的宏, 这里请一定加入

USE_STDPERIPH_DRIVER,STM32F10X_MD 这两个宏。另外,我们在下面的“Include Paths”框中可以填入我们.h

文件所在的目录,如“.\Lib;.\Lib\inc;.\User”,方便编译器搜索头文件定义。

如果现在编译,还是有错误的。可以先编译下,

因为 main.c 中有头文件#include "stm32f10x.h"这句,在这个重要的头文件里,并没有定义好一

些东西,分别在 stm32f10x.h 文件中取消对 #define STM32F10X_MD 和

#define USE_STDPERIPH_DRIVER 的屏蔽,这两个定义好,才能正常工作,第一个是选择存储

容量的型号,每种芯片都不太一样,所以让你选择,第二个是使用标准库文件,因为我们是要

用库的,所以必须选择,默认是不用库的,直接进行寄存器的操作。

也可以直接如下图操作。在 Define 中添加 USE_STDPERIPH_DRIVER,STM32F10X_MD

作用是一样的。

选择好后,直接编译,恭喜你,成功了。

最后要说明的就是:

图 4

这个库文件,是必须选择 misc.c 和 stm32f10x_rcc.c 的。

另外就是你选择用什么功能,就把什么功能的 c 文件加进去,我这里已经加了一个对 IO 口的应

用的一个 c 文件。

5:一些重要文件的说明吧

core_cm3.c/core_cm3.h

该文件是内核访问层的源文件和头文件,查看其中的代码多半是使用汇编语言编写的。

stm32f10x.h

该文件是外设访问层的头文件,该文件是最重要的头文件之一。例如

向量等等。除了这些该头文件还定义了和外设寄存器相关的结构体,如:

typedef struct

{

__IO uint32_t CRL;

__IO uint32_t CRH;

__IO uint32_t IDR;

__IO uint32_t ODR;

__IO uint32_t BSRR;

__IO uint32_t BRR;

__IO uint32_t LCKR;

} GPIO_TypeDef;

包含了那么多寄存器的定义,那么在应用文件中(例如自己编写的 main 源文件)只需要包含

stm32f10x.h 即可。

在 stm32f10x.h 8296 行

#ifdef USE_STDPERIPH_DRIVER

#i nclude "stm32f10x_conf.h"

#endif

这里定义了 #i nclude "stm32f10x_conf.h"

system_stm32f10x.c/h

该头文件也可以称为外设访问层的头文件和源文件。在该文件中可以定义系统的时钟频率,定

义低速时钟总线和高速时钟总线的频率,其中最关键的函数就是 SystemInit()了,这个后面会详

细介绍。总之这两个文件是新固件库 V3.5 的重点,有了它粮也大大简化了使用 stm32 的初始化

工作。

stm32f10x_conf.h

这个文件和 V2 版本的库的内容是一样的,需要使用哪些外设就取消哪些外设的注释。

stm32f10x_it.c/h

这两个文件包含了 stm32 中断函数,在源文件和头文件中并没有把所有的中断入口函数都写出

来,而只写了 ARM 内核的几个异常中断,其他的中断函数需要用户自己编写。stm32f10x_it.c

的最后给了这样一个模板。

/******************************************************************************/

/* STM32F10x Peripherals Interrupt Handlers */

/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */

/* available peripheral interrupt handler's name please refer to the startup */

/* file (startup_stm32f10x_xx.s). */

/**

* @brief This handles PPP interrupt request.

* @param None

* @retval None

*/

/*void PPP_IRQHandler(void)

{

}*/

从注释中的英文提示可以看出,中断向量的名称可以从相应的启动代码中找出,例如可以

startup_stm32f10x_md.s 中找到 USART1 中断函数的名称——USART1_IRQHandler。其他的中

断函

名可以以此类推,一一获得,在这里我就不一一复述了。

Libraries 文件夹

该文件夹有包含两个文件夹,一个是 src 文件夹,另一个是 inc 文件夹,顾名思义,一个里面放

的是元件一个里面放的是头文件。这两个文件夹包含了所有的 STM32 的外设驱动函数,其实

和 V2 版本也没有太大的变化。简单来说,外设的驱动相当于 windows 的驱动函数 API,这些

驱动函数看到函数名基本就可以明白这个函数的作用,例如:GPIO_SetBits 可以置位某个 IO

口,相反 GPIO_ResetBits 则可以复位某个 IO 口。我个人认为熟练使用库可以大大提高编程的

效率,同时规范使用库函数也可以提高程序的可读性,让团队中的其他程序员可以快速的明白

代码的作用。

三、其它集成开发环境

本模板的建立还可以考虑使用 IAR FOR ARM 版本的集成开发环境,有需要的同学可以单独交

流。

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 GPIO 控制 LED 灯闪烁

教学目的

和要求

通过此项目的学习使学生了解 STM32F103X 系列微处理器 GPIO 外设资源的

使用,了解 GPIO 的结构与配置方法,掌握程序的配置方法,能够使用固件库提供

的 GPIO 函数进行程序控制。

STM32F103X 系列微处理器 GPIO 的结构

STM32F103X 系列微处理器 GPIO 的配置、复用及中断

STM32F103X 系列微处理器 GPIO 的寄存器及存储器映像

利用集成开发环境建立 GPIO 控制程序进行仿真、下载、调试

教学重点

STM32F103X 系列微处理器 GPIO 的结构;STM32F103X 系列微处理器 GPIO

的配置、复用及中断;STM32F103X 系列微处理器 GPIO 的寄存器及存储器映像;

利用集成开发环境建立 GPIO 控制程序进行仿真、下载、调试

教学难点

STM32F103X 系列微处理器 GPIO 的配置、复用及中断;STM32F103X 系列微

处理器 GPIO 的寄存器及存储器映像;利用集成开发环境建立 GPIO 控制程序进行

仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 STM32F1 系列 参考手册关于 GPIO 章节阅读;扩展上课案例

课后小结 学生对固件库的使用还不是很熟悉,对参考手册的阅读还不能尽快把握住重

点,对库函数的分析还有待加强。

授课主要内容

一、硬件接口原理讲解 虚拟终端模块上有4个LED灯,主要用来编程调试使用。分别接在GPIOF的7、8、9、10引脚上。

LED硬件接口 如图:

STM32的LED原理图与实物图

从原理图上可以看出,4 个 LED 灯共阳极,当对应引脚为低电平时候,LED 灯点亮。

二、软件设计讲解

我们学习单片机,都是从LED流水灯开始入门的。STM32也不例外,这里我们讲解一个LED闪

烁灯。这也是一个STM32最小架构的程序。软件操作步骤如下:

首先双击 IAR 软件的启动图标 ,进入到 IAR 的主界面,然后在菜单栏上选择

Project->Create New Project,新建一个 ARM 的工程,点击 OK。下一步选择好项目的路径并在

文件名中填入你想填入的项目名。点击保存后,会在 IAR 左侧栏 Workspace 中生成你添加的项目。

在该项目名上点击右键 Options,在 General Options 选项的 target 中选择 ST 公司的

STM32F10xxE,在 C/C++ Compiler 选项的 Preprocessor->Additional include directories:(one

per line)下的编辑框中添加:$PROJ_DIR$\..\User

$PROJ_DIR$\..\library\inc

点击 OK,这样一个以 STM32 为平台的 IAR 开发环境搭建完成,现在可以往开发环境中添加程序了。

在左侧栏创建下图所列的文件夹。点左侧栏的空白处点击右键,选择Add->Add Group,输入

文件名:

项目左侧栏

在EWARM文件夹上点击右键,选择Add->Add Files,添加如下文件:

图2-2-3 EWARM文件夹下的内容

在Lib文件夹上点击右键,选择Add->Add Files,从STM32固件库中添加如下文件到项目中去:

Lib文件夹下的内容

点击工具栏上的 新建文件图标,新建文件名为main.c保存到User目录下,添加

stm32f10x_conf.h 、stm32f10x_it.c 、stm32f10x_it.h到User目录下。

在IAR的User文件夹上点击右键,选择Add->Add Files,添加如下文件:

User文件夹下的内容

User文件夹下是自己需要编写的程序,其他是STM32库或STM32官方提供的文件,通常是不

需要修改的。

下面我们将从main.c下手,来了解整个程序的架构。Main.c文件内容如下:

/****************************************************************************

* 文件名: main.c

* 内容简述: 该例程是展示一盏闪烁灯(PF7,PF8,PF9,PF10)

*****************************************************************************/

#include "stm32f10x_lib.h"

void RCC_Configuration(void);

void GPIO_Configuration(void);

void delay();

/*******************************************************************************

* Function Name : main

* Description : Main program.

* Input : None 调试时所打印系统启动信息,一般可

以不用,如果没有定义#define DEBUG,

是不启用的

* Output : None

*******************************************************************************/

int main(void)

{

#ifdef DEBUG

debug();

#endif

//配置系统时钟

RCC_Configuration();

//配置使用的GPIO口

GPIO_Configuration();

while (1)

{

GPIO_ResetBits(GPIOF, GPIO_Pin_7);

GPIO_ResetBits(GPIOF, GPIO_Pin_8);

GPIO_ResetBits(GPIOF, GPIO_Pin_9);

GPIO_ResetBits(GPIOF, GPIO_Pin_10);

delay();

GPIO_SetBits(GPIOF, GPIO_Pin_7);

GPIO_SetBits(GPIOF, GPIO_Pin_8);

GPIO_SetBits(GPIOF, GPIO_Pin_9);

GPIO_SetBits(GPIOF, GPIO_Pin_10);

delay();

}

}

/*******************************************************************************

* Function Name : RCC_Configuration

* Description : Configures the different system clocks.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void RCC_Configuration(void) /////////////////////系统时钟配置

{

ErrorStatus HSEStartUpStatus;

//将外设RCC寄存器重设为缺省值

RCC_DeInit();

//设置外部高速晶振(HSE)

RCC_HSEConfig(RCC_HSE_ON);

//等待HSE 起振

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)

{

//预取指缓存使能

程序、时钟、GPIO 中的时钟部分,

下面会有对这个函数的细讲

程序、时钟、GPIO 中的 GPIO 配

置部分,下面会有对这个函数的细

While 语句从 { 到 } 是死循环

部分,即反复执行,除非被中断

GPIO 的执行部分,点亮 LED

延时部分

GPIO 的执行部分,熄灭 LED 等

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

//设置代码延时值

//FLASH_Latency_2 2 延时周期

FLASH_SetLatency(FLASH_Latency_2);

//设置AHB 时钟(HCLK)

//RCC_SYSCLK_Div1 AHB 时钟= 系统时钟

RCC_HCLKConfig(RCC_SYSCLK_Div1);

//设置高速AHB 时钟(PCLK2)

//RCC_HCLK_Div2 APB1 时钟 = HCLK / 2

RCC_PCLK2Config(RCC_HCLK_Div2);

//设置低速AHB 时钟(PCLK1)

//RCC_HCLK_Div2 APB1 时钟 = HCLK / 2

RCC_PCLK1Config(RCC_HCLK_Div2);

//设置ADC时钟频率

RCC_ADCCLKConfig(RCC_PCLK2_Div2);

// PLLCLK = 8MHz * 9 = 72 MHz

//设置PLL 时钟源及倍频系数

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

//使能或者失能PLL

RCC_PLLCmd(ENABLE);

//等待指定的RCC 标志位设置成功等待PLL初始化成功

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

//设置系统时钟(SYSCLK)设置PLL为系统时钟源

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

//等待PLL成功用作于系统时钟的时钟源

// 0x00:HSI 作为系统时钟

// 0x04:HSE作为系统时钟

// 0x08:PLL作为系统时钟

while(RCC_GetSYSCLKSource() != 0x08)

{

}

}

//使能或者失能APB2 外设时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | \

RCC_APB2Periph_GPIOF | \

RCC_APB2Periph_AFIO,ENABLE); //启动GPIO

}

/*******************************************************************************

* Function Name : GPIO_Configuration

* Description : Configures the different GPIO ports.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void GPIO_Configuration(void) /////////配置LED控制

{

//定义一个GPIO结构体

GPIO_InitTypeDef GPIO_InitStructure;

//LED 端口设置

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOF, &GPIO_InitStructure);

}

/*******************************************************************************

* Function Name : NVIC_Configuration

* Description : Configures NVIC and Vector Table base location.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void NVIC_Configuration(void) ////////中断服务配置

{

#ifdef VECT_TAB_RAM

/* Set the Vector Table base location at 0x20000000 */

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else /* VECT_TAB_FLASH */

/* Set the Vector Table base location at 0x08000000 */

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

}

void delay()

{

int i;

for (i=0; i<0xfffff; i++)

;

}

#ifdef DEBUG

/*******************************************************************************

* Function Name : assert_failed

* Description : Reports the name of the source file and the source line number

* where the assert_param error has occurred.

* Input : - file: pointer to the source file name

* - line: assert_param error line source number

* Output : None

* Return : None

*******************************************************************************/

void assert_failed(u8* file, u32 line)

{

/* User can add his own implementation to report the file name and line number,

ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */

while (1)

{

}

}

#endif

stm32f10x_it.c是STM32官方提供的中断函数模板,在这里添加后不需要添加程序,因为在

这个实验中没有使用中断,后面我们将对中断做单独一个实验进行指导。

注:stm32f10x_it.c及头文件不管中断用不用,都需要添加到项目中去,不然在编译程序的时候,

因为有关中断函数没定义而编译不通过、报错等。

RCC_Configuration(void) 复位和时钟控制配置

这个函数的功能,就是配置STM32的时钟了。因为我们使用了ST公司的固件库,所以这个RCC

函数基本上大同小异,复制一下就可以使用了。

一般,初学者会很奇怪,开发板上只有8MHz的晶振,那么STM32的72MHz的运行频率是如

何得到的?从函数中我们可以看到,我们配置STM32的运行频率为72MHz,这是由外部晶振8MHz

乘以9倍的PLL时钟得到的。

复位和时钟控制配置函数如下:

/*******************************************************************************

* Function Name : RCC_Configuration

* Description : Configures the different system clocks.

*******************************************************************************/

void RCC_Configuration(void) /////////////////////系统时钟配置

{

ErrorStatus HSEStartUpStatus;

//将外设 RCC寄存器重设为缺省值

RCC_DeInit();

//设置外部高速晶振(HSE)

RCC_HSEConfig(RCC_HSE_ON);

//等待 HSE 起振

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)

{

//预取指缓存使能

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

//设置代码延时值

//FLASH_Latency_2 2 延时周期

FLASH_SetLatency(FLASH_Latency_2);

//设置 AHB 时钟(HCLK)

//RCC_SYSCLK_Div1 AHB 时钟 = 系统时钟

RCC_HCLKConfig(RCC_SYSCLK_Div1);

//设置高速 AHB 时钟(PCLK2)

//RCC_HCLK_Div2 APB1 时钟 = HCLK / 2

RCC_PCLK2Config(RCC_HCLK_Div2);

//设置低速 AHB 时钟(PCLK1)

//RCC_HCLK_Div2 APB1 时钟 = HCLK / 2

RCC_PCLK1Config(RCC_HCLK_Div2);

//设置ADC时钟频率

RCC_ADCCLKConfig(RCC_PCLK2_Div2);

// PLLCLK = 8MHz * 9 = 72 MHz

//设置 PLL 时钟源及倍频系数

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

//使能或者失能 PLL

RCC_PLLCmd(ENABLE);

//等待指定的 RCC 标志位设置成功 等待PLL初始化成功

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

//设置系统时钟(SYSCLK) 设置PLL为系统时钟源

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

//等待PLL成功用作于系统时钟的时钟源

// 0x00:HSI 作为系统时钟

// 0x04:HSE作为系统时钟

// 0x08:PLL作为系统时钟

while(RCC_GetSYSCLKSource() != 0x08)

{

}

}

//使能或者失能 APB2 外设时钟和 GPIOF端口时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | \

RCC_APB2Periph_AFIO,ENABLE); //启动GPIO

}

对于RCC的配置,我们又回到图2-2中的STM32时钟框图上了。这个函数就是按照STM32时钟框

图来编写的,我们可以根据注释和时钟框图,就可以明白为什么要这样设置了。在没有对系统时

钟有要求的情况下,一般都是默认72MHz,对于要用的外设时钟可以修改上面:

void RCC_Configuration(void)

函数中画红框的RCC_APB2PeriphClockCmd函数,如要添加串口:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | \ //////添加串口1

RCC_APB2Periph_GPIOF | \

RCC_APB2Periph_AFIO,ENABLE);

RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 |

RCC_APB2Periph_GPIOF |

RCC_APB2Periph_AFIO,ENABLE);

注:这里写两个RCC_APB2PeriphClockCmd有一个不同之处就是‘\’,‘\’代表告诉编译器

这个函数将关联到多行书写,如果没有这个‘\’也是可以的。但如果你不想用这个函数时需要

对它的每一行添加‘//’来注释掉。

而有‘\’的只需在函数开头添加‘//’。

主要还是看个人编程的应用,两种方法有利也有弊,比如:我想要添加

RCC_APB2Periph_GPIOF,我们只要在RCC_APB2Periph_GPIOF的前面添加‘//’,而这点有‘\’

的不行的。

ST提供的函数库在函数和变量命名上有非常良好的规范性和易读性,即便没有注释,我们也

可从函数名和变量名来大致判断该函数或变量所包含的意义。

例如: FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); ” 、

“ FLASH_SetLatency(FLASH_Latency_2);”这两个语句的作用是设置STM32内部FLASH的等待周

期。

这里简单的讲解下为什么要FLASH的等待周期?

因为STM32的内部FLASH用于存储代码指令供CPU存取和执行。STM32的CPU的最大速率为

72MHz,但FLASH无法达到这么高的速度,因此要在CPU存取FLASH的过程中插入“等待周期”。显

然CPU速度越快,所要插入的等待周期个数越多,原则是:

(1)当CPU速率为0 ~ 24MHz时,不需要插入等待周期,即等到周期个数为0;

(2)当CPU速率为24 ~ 48MHz时,插入1个等待周期;

(3)当CPU速率为48MHz ~ 72MHz时,插入2个等待周期;

所以我们的虚拟终端的Flash插入2个等待周期。

GPIO_Configuration(void) GPIO配置

这个函数的功能,就是配置STM32的GPIO功能。STM32的IO口可以由软件配置成8种模式:输

入浮空、输入上拉、输入下拉、模拟输入、开漏输出、推挽输出、推挽复用功能、开漏复用功能。

每个IO口可以自由编程。

LED灯的GPIO函数内容有:

/*******************************************************************************

* Function Name : GPIO_Configuration

*******************************************************************************/

void GPIO_Configuration(void) /////////配置LED控制

{

//定义一个GPIO结构体

GPIO_InitTypeDef GPIO_InitStructure;

定义了一个结构体变量,结构体原型:

typedef struct

{

u16 GPIO_Pin;

GPIOSpeed_TypeDef GPIO_Speed;

GPIOMode_TypeDef GPIO_Mode;

}GPIO_InitTypeDef;

//LED 端口设置

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOF, &GPIO_InitStructure);

}

下面我们根据之前讲的GPIO的推挽输出模式框图在这里进行实践阐述:

GPIO的推挽输出模式框图如下:

STM32的GPIO结构图

从上图可以看出,我们可以单独的位设置或位清除,来控制GPIO的输出电平。即只需要通过

输出数据寄存器进行修改,在程序中对应的函数:

“ GPIO_SetBits(GPIOx, GPIO_Pin_x) ” 就可以实现GPIOx 的pinx 位为高电平

“GPIO_ResetBits(GPIOx, GPIO_Pin_x)” 就可以实现GPIOx的pinx位为位电平。

输出控制电路由GPIO_Configuration(void)中的GPIO_InitStructure.GPIO_Mode配置。

到了这里,LED闪烁灯例程就讲完了。我们也可以看到其它的实验程序中都离不开这三个基本的

函数:

1、RCC_Configuration(void) 复位和时钟控制 配置

2、GPIO_Configuration(void) GPIO配置

3、int main(void) main 主函数

下面我们将对程序进行下载。 三、程序下载及调试

点击工具栏上的链接 图标,编译链接后没有错误的话,我们点击仿真下载 图标,这

最终将 GPIO_InitStructure

中定义的变量关联到底层寄

存器

时会进入调试界面。再点击全速运行 图标,让程序全速运行。

这时我们会看到虚拟终端上的LED灯开始不停的闪烁。说明GPIO配置及操作正确。

备注:

如果有好奇的同学可以到STM32的函数库中查找,如果想问这么多,咋查?

教你两种方法:

1、 通过右键中的go to definition X,就能跳转到知道X的定义位置。

查看变量的方法

2、 通过对变量名在工程项目文件中搜索,快捷键是Ctrl+Shift+F,出现以下窗口:

查看变量的方法

喜欢自己想深入研究的可以试下。

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 中断按键控制 LED 灯闪烁

教学目的

和要求

通过此项目的学习使学生了解 GPIO 的中断系统,了解掌握外部中断的中断结

构和配置方法,了解掌握 NVIC 的管理机制,可以利用库函数进行中断配置及中断

优先权配置。

STM32F103X 系列微处理器 GPIO 的中断结构

STM32F103X 系列微处理器 GPIO 的中断配置

STM32F103X 系列微处理器 NVIC 的配置

利用集成开发环境建立 GPIO 外部中断控制程序进行仿真、下载、调试

教学重点

STM32F103X 系列微处理器 GPIO 的中断配置;STM32F103X 系列微处理器

NVIC 的配置;利用集成开发环境建立 GPIO 外部中断控制程序进行仿真、下载、

调试。

教学难点

STM32F103X 系列微处理器 GPIO 的中断配置;STM32F103X 系列微处理器

NVIC 的配置;利用集成开发环境建立 GPIO 外部中断控制程序进行仿真、下载、

调试。

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 STM32F1 系列 参考手册关于 GPIO 章节阅读;扩展上课案例

课后小结 学生对 16 级中断优先级的理解有一定的困难,导致 NVIC 的配置有待理解加

深。

授课主要内容

一、硬件接口讲解 虚拟终端模块上有4个LED灯(详情GPIO的LED闪烁灯),当输入电平使用,可用于调试、方向

按键等,按键硬件接口如下:

STM32的按键原理图与实物图

有四个方向键和一个确认按键,引脚:上=PC5、下=PC3、左=PC1、右=PC4、确认键=PC2。

待机唤醒 WKUP 按键,功能:当 STM32 待机后通过 WKUP 按键唤醒控制。引脚接在 PA0(WKUP

第二功能上)。这里我们只使用四个方向键做按键控制。

二、软件设计讲解 如果你是单片机上的新手,你一定会问什么中断?它有什么用途?

这里我们以生活中的例子介绍下:比如你正在家中看书,突然电话铃响了,你放下书,去接

电话,和来电话的人交谈,通完电话,回来继续看你的书,这就是生活中的“中断”现象—就是

正常的工作过程被外部的事件打断了。这里的主函数 main 程序是“你正在家中看书”,中断程序

就是“和来电话的人交谈”,中断触发源是“电话铃响”,中断初始化配置就是“耳朵”了。程序

也就是按照这个流程编写。软件操作步骤如下:

首先双击 IAR 软件的启动图标 ,进入到 IAR 的主界面,然后在菜单栏上选择

Project->Create New Project,新建一个 ARM 的工程,点击 OK。下一步选择好项目的路径并在

文件名中填入你想填入的项目名。点击保存后,会在 IAR 左侧栏 Workspace 中生成你添加的项目。

在该项目名上点击右键 Options,在 General Options 选项的 target 中选择 ST 公司的

STM32F10xxE,在 C/C++ Compiler 选项的 Preprocessor->Additional include directories:(one

per line)下的编辑框中添加:$PROJ_DIR$\..\User

$PROJ_DIR$\..\library\inc

点击 OK,这样一个以 STM32 为平台的 IAR 开发环境搭建完成,现在可以往开发环境中添加程序了。

在左侧栏创建下图所列的文件夹。点左侧栏的空白处点击右键,选择Add->Add Group,输入

文件名:

图2-4-1 项目左侧栏

在EWARM文件夹上点击右键,选择Add->Add Files,添加如下文件:

图2-4-2 EWARM文件夹下的内容

在Lib文件夹上点击右键,选择Add->Add Files,从STM32固件库中添加如下文件到项目中去:

图2-4-3 Lib文件夹下的内容

点击工具栏上的 新建文件图标,新建文件名为main.c 保存到 User目录下,添加

stm32f10x_conf.h 、stm32f10x_it.c 、stm32f10x_it.h到User目录下。

在IAR的User文件夹上点击右键,选择Add->Add Files,添加如下文件:

User文件夹下的内容

在 main.c 文件中,添加内容如下:

/****************************************************************************

* 文件名: main.c

* 内容简述: 该例程将以按键中断方式点亮四盏LED灯

* K8------>led1

* K7------>led2

* K6------>led3

* K5------>led4

*****************************************************************************/

#include "stm32f10x_lib.h"

void RCC_Configuration(void);

void GPIO_Configuration(void);

void Delay(unsigned long nCount);

void EXTI_Configuration(void);

/*******************************************************************************

函数名:main

功能说明:用户程序入口

*/

int main(void)

{

/*

这个函数是ST库中的函数,函数实体在

Libraries\CMSIS\Core\CM3\system_stm32f10x.c

配置内部Flash接口,初始化PLL,配置系统频率

系统时钟缺省配置为MHz,你如果需要更改,则需要去修改相关的头文件中的宏定义

*/

//配置系统时钟

RCC_Configuration();

//配置使用的GPIO口配置配置

GPIO_Configuration();

/*中断初始化*/

EXTI_Configuration();

/*LED初始化-灭*/

GPIO_SetBits(GPIOF, GPIO_Pin_10);

GPIO_SetBits(GPIOF, GPIO_Pin_7);

GPIO_SetBits(GPIOF, GPIO_Pin_8);

GPIO_SetBits(GPIOF, GPIO_Pin_9);

while (1);

中断初始化

对 LED 初始化,默

认下 LED 熄灭。

}

/*******************************************************************************

* Function Name : RCC_Configuration

* Description : Configures the different system clocks.

*******************************************************************************/

void RCC_Configuration(void) /////////////////////系统时钟配置

{

ErrorStatus HSEStartUpStatus;

//将外设RCC寄存器重设为缺省值

RCC_DeInit();

//设置外部高速晶振(HSE)

RCC_HSEConfig(RCC_HSE_ON);

//等待HSE 起振

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)

{

//预取指缓存使能

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

//设置代码延时值

//FLASH_Latency_2 2 延时周期

FLASH_SetLatency(FLASH_Latency_2);

//设置AHB 时钟(HCLK)

//RCC_SYSCLK_Div1 AHB 时钟= 系统时钟

RCC_HCLKConfig(RCC_SYSCLK_Div1);

//设置高速AHB 时钟(PCLK2)

//RCC_HCLK_Div2 APB1 时钟 = HCLK / 2

RCC_PCLK2Config(RCC_HCLK_Div2);

//设置低速AHB 时钟(PCLK1)

//RCC_HCLK_Div2 APB1 时钟 = HCLK / 2

RCC_PCLK1Config(RCC_HCLK_Div2);

//设置ADC时钟频率

RCC_ADCCLKConfig(RCC_PCLK2_Div2);

// PLLCLK = 8MHz * 9 = 72 MHz

//设置PLL 时钟源及倍频系数

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

//使能或者失能PLL

RCC_PLLCmd(ENABLE);

//等待指定的RCC 标志位设置成功等待PLL初始化成功

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

//设置系统时钟(SYSCLK)设置PLL为系统时钟源

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

//等待PLL成功用作于系统时钟的时钟源

// 0x00:HSI 作为系统时钟

// 0x04:HSE作为系统时钟

// 0x08:PLL作为系统时钟

while(RCC_GetSYSCLKSource() != 0x08)

{

}

}

//使能或者失能APB2 外设时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | \

RCC_APB2Periph_GPIOF | \

RCC_APB2Periph_AFIO,ENABLE); //启动GPIO

/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | \

RCC_APB2Periph_AFIO, ENABLE);

}

void GPIO_Configuration(void) /////////配置

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,

ENABLE);

/* Configure PF.07, PF.08, PF.09 and PF.10 as Output push-pull */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出

GPIO_Init(GPIOF, &GPIO_InitStructure);

/* Configure GPIOC as input floating */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_3 | GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空模式

GPIO_Init(GPIOC, &GPIO_InitStructure);

}

/*******************************************************************************

* Function Name : EXTI_Configuration

* Description : Configures the used EXTI lines.

*******************************************************************************/

void EXTI_Configuration(void)

{

EXTI_InitTypeDef EXTI_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

//选择中断管脚PC.1 PC.3 PC.5,PC.4

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource4);

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

EXTI_InitStructure.EXTI_Line = EXTI_Line1 | EXTI_Line4 | EXTI_Line3 | EXTI_Line5; //选择中断

线路4 3 5

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);

#ifdef VECT_TAB_RAM

/* Set the Vector Table base location at 0x20000000 */

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else /* VECT_TAB_FLASH */

/* Set the Vector Table base location at 0x08000000 */

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组

NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQChannel; //选择中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQChannel; //选择中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; //选择中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel; //选择中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

}

void Delay(unsigned long nCount)

{

for(;nCount != 0;nCount--);

}

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t* file, uint32_t line)

{

/* User can add his own implementation to report the file name and line number,

ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* Infinite loop */

while (1)

{

}

}

#endif

中断处理函数在 stm32f10x_it.c 文件中,所使用的中断函数如下:

………………………………

…………………………………………….

/*******************************************************************************

* Function Name : EXTI1_IRQHandler

* Description : This function handles External interrupt Line 1 request.

*******************************************************************************/

void EXTI1_IRQHandler(void)

{

GPIO_SetBits(GPIOF, GPIO_Pin_10);

GPIO_ResetBits(GPIOF, GPIO_Pin_7);

GPIO_SetBits(GPIOF, GPIO_Pin_8);

GPIO_SetBits(GPIOF, GPIO_Pin_9);

//清空中断标志位,防止持续进入中断

EXTI_ClearITPendingBit(EXTI_Line1);

}

………………………………

/*******************************************************************************

* Function Name : EXTI3_IRQHandler

* Description : This function handles External interrupt Line 3 request.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void EXTI3_IRQHandler(void)

点亮 GPIOF.7 上的 LED

灯,熄灭其他 LED 灯

{

GPIO_SetBits(GPIOF, GPIO_Pin_10);

GPIO_SetBits(GPIOF, GPIO_Pin_7);

GPIO_ResetBits(GPIOF, GPIO_Pin_8);

GPIO_SetBits(GPIOF, GPIO_Pin_9);

//清空中断标志位,防止持续进入中断

EXTI_ClearITPendingBit(EXTI_Line3);

}

/*******************************************************************************

* Function Name : EXTI4_IRQHandler

* Description : This function handles External interrupt Line 4 request.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void EXTI4_IRQHandler(void)

{

GPIO_SetBits(GPIOF, GPIO_Pin_10);

GPIO_SetBits(GPIOF, GPIO_Pin_7);

GPIO_SetBits(GPIOF, GPIO_Pin_8);

GPIO_ResetBits(GPIOF, GPIO_Pin_9);

//清空中断标志位,防止持续进入中断

EXTI_ClearITPendingBit(EXTI_Line4);

}

………………………………

………………………………

/*******************************************************************************

* Function Name : EXTI9_5_IRQHandler

* Description : This function handles External lines 9 to 5 interrupt request.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void EXTI9_5_IRQHandler(void)

{

GPIO_ResetBits(GPIOF, GPIO_Pin_10);

GPIO_SetBits(GPIOF, GPIO_Pin_7);

GPIO_SetBits(GPIOF, GPIO_Pin_8);

GPIO_SetBits(GPIOF, GPIO_Pin_9);

EXTI_ClearITPendingBit(EXTI_Line5);

}

点亮 GPIOF.10 上的 LED

灯,熄灭其他 LED 灯

点亮 GPIOF.8 上的 LED

灯,熄灭其他 LED 灯

点亮 GPIOF.9 上的 LED

灯,熄灭其他 LED 灯

………………………………

………………………………

在 stm32f10x_it.c 文件中,这里只列出修改的中断函数,没列出的中断函数不需要修改,保持原

样。

EXTI_Configuration(void) 中断配置

这里与之前两个实验的区别就是多了 EXTI_Configuration 函数,从函数所添加的位置上看

出是为了中断初始化。

那么 STM32 中有几个中断源呢?16 个内核+68 个外部=84 个,总共有 84 个中断,这显然比我

们之前所用过的单片机中断要多的多。到这里,可能会有人要问这么多中断咋控制?有啥区别?

下面我们将对这个问题,介绍下 STM32 中的中断:

对于中断的控制,STM32有一个专用的管理机构:NVIC(嵌套向量中断控制器)。

NVIC管理主要管理中断的使能、挂起、优先级、活动等。

知道NVIC,我们还要知道“stm32f10x_it.c”这个C文件,打开这个文件,我们可以看到

“XXX_IRQHandler”函数等等,从函数的名字上看出是中断函数的实现,不过大部分都是空的,

需要用户填写。如果你用到了哪个中断来做相应的处理,就要填写相应的中断处理函数,需要根

据各外设的实际情况来填写。

1)、STM32 的中断优先级判断

每个单片机中都有中断优先级,STM32 也不例外。

STM32中有两个优先级的概念——抢占式优先级和响应优先级,每个中断源都需要被指定这两种

优先级。在程序中我们也注释了哪个是抢占式优先级,哪个是响应优先级。高抢占式优先级的中

断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的

中断可以嵌套低抢占式优先级的中断。

中断优先级的具体操作:当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,

当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之

后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处

理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决

定先处理哪一个。

2)、STM32 中断优先级分组

既然STM32 的每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中

断的优先级。

STM32 把指定中断优先级的寄存器位减少到4 位(AIRCR 高四位),这4 个寄存器位的分组

方式如下:

中断优先级分配图

第0 组:所有4 位用于指定响应优先级

第1 组:最高1 位用于指定抢占式优先级,最低3 位用于指定响应优先级

第2 组:最高2 位用于指定抢占式优先级,最低2 位用于指定响应优先级

第3 组:最高3 位用于指定抢占式优先级,最低1 位用于指定响应优先级

第4 组:所有4 位用于指定抢占式优先级

我们可以通过调用STM32 的固件库中的函数NVIC_PriorityGroupConfig ()选择使用哪

种优先级分组方式,这个函数的参数有下列5 种:

NVIC_PriorityGroup_0 => 选择第0 组

NVIC_PriorityGroup_1 => 选择第1 组

NVIC_PriorityGroup_2 => 选择第2 组

NVIC_PriorityGroup_3 => 选择第3 组

NVIC_PriorityGroup_4 => 选择第4 组

中断优先级分组是为了给抢占式优先级和响应优先级在中断优先级寄丛器的高四位分配各

个优先级数字所占的位数。在一个程序中只能设定一次。如果按照NVIC_PriorityGroup_4这么

分,就分为了16个阶级(1个阶层就是1个preemption优先级),0个阶层。高阶级的事件,可

以打断低阶级的事件(称为嵌套),最多可以完成1个中断和15级嵌套。

例如:一个人叫“EXTI0_IRQChannel”,你指定他进入“阶级8”,则:

NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;

另外,在同一阶级内部,一个人在做事的时候,另外一个人不能打断他(preemption优先

级别相同的中断源之间没有嵌套关系)。还有,如果他们两个同时想做事,因为没有阶层,那么

就根据Vector table中的物理排序,让排名靠前的人去做。

3)、STM32 中断源优先级

接下来就是指定中断源的优先级,中断源优先级是在中断优先级寄存器中设置的,只能设置

及高四位,必须根据中断优先级分组中设置好的位数来在该寄存器中设置相应的数值。假如你选

择中断优先级分组的第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级,那

么抢占式优先级就有000-111共八种数据选择,也就是有八个中断嵌套,而响应优先级中有0和

1两种,总共有8*2=16种优先级。

在一个程序中可以设定多个(最多16 个)优先级,每个中断源只能设定的一个。例如,在我们

的串口按键中断实验程序中,我们打开了4 个中断:中断1、中断3、中断4和中断9_5。

在“NVIC_Configuration()”函数中进行设置,如下: void EXTI_Configuration(void)

{

EXTI_InitTypeDef EXTI_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

//选择中断管脚 PC.1 PC.3 PC.5,PC.4

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource4);

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//输入线路下降沿为中断请求

EXTI_InitStructure.EXTI_Line = EXTI_Line1 | EXTI_Line4 | EXTI_Line3 | EXTI_Line5; //选择中断

线路 1 4 3 5

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);

#ifdef VECT_TAB_RAM

/* Set the Vector Table base location at 0x20000000 */

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else /* VECT_TAB_FLASH */

/* Set the Vector Table base location at 0x08000000 */

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //选择中断分组 2

NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQChannel; //选择中断通道 1

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占式中断优先级设置为 0

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQChannel; //选择中断通道 3

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占式中断优先级设置为 1

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; //选择中断通道 4

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//抢占式中断优先级设置为 2

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;//选择中断通道 5

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占式中断优先级设置为 3

设置中

断管脚

设置管脚为中断模式,

并使能

中断向量的指向位置

是 RAM 中 还 是

FLASH 中

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为 0

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断

NVIC_Init(&NVIC_InitStructure);

}

从这个函数上看到:要使用中断需要设置中断引脚、中断模式以及中断触发电平,不管是 51

还是 AVR 都有这几步,唯独中断优先级需要设置,因为像 51 单片机的中断优先级基本是默认的

(外部中断 0 > 定时/计数器 0 > 外部中断 1 > 定时/计数器 1 > 串行中断)。这也是我们重点讲

中断优先级的原因。在本例程中,中断优先级只有抢占式中断优先级的区别,也就是说不管响应

优先级在哪个级别都无关了。只有中断优先级在抢占式中断优先级相同级别的情况下,响应优先

级才有级别之分。

RCC_Configuration(void) 添加外设时钟支持

在 void RCC_Configuration(void)函数中添加对外设的时钟支持,如下:

void RCC_Configuration(void) /////////////////////系统时钟配置

{

…………………………

//使能或者失能 APB2 外设时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | \

RCC_APB2Periph_GPIOF | \

RCC_APB2Periph_AFIO,ENABLE); //启动 GPIO

/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | \

RCC_APB2Periph_AFIO, ENABLE);

}

GPIO_Configuration(void)添加对输入的配置

在 void GPIO_Configuration(void)函数中添加对 GPIO 的支持,如下:

void GPIO_Configuration(void) /////////配置

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,

ENABLE);

/* Configure PF.07, PF.08, PF.09 and PF.10 as Output push-pull */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出

GPIO_Init(GPIOF, &GPIO_InitStructure);

/* Configure GPIOC as input floating */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_3 | GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空模式

GPIO_Init(GPIOC, &GPIO_InitStructure);

}

到这里中断的实现基本讲完了,下面我们对例程进行仿真下载。

三、程序下载及调试

点击工具栏上的链接 图标,编译链接后没有错误的话,我们点击仿真下载 图标,这

时会进入调试界面。再点击全速运行 图标,让程序全速运行。

默认状态下LED灯是熄灭的。我们依次按下K8、K6、K4、K7,这时会发现与它对应的LED

灯会亮起。说明按键中断响应了。

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 USART 实现与 PC 进行字符的发送与回显

教学目的

和要求

通过此项目的学习使学生了解 USART1 的结构,掌握串口通信的协议,以及

配置方法,掌握库函数对串口通信协议的配置过程,了解串口通信程序的编写步骤。

STM32F103X 系列微处理器 USART1 结构

STM32F103X 系列微处理器 USART1 中断配置

STM32F103X 系列微处理器 USART1 波特率的配置

利用集成开发环境建立串口中断控制程序进行数据的发送与接收,并进行程序

的仿真、下载、调试

教学重点

STM32F103X 系列微处理器 USART1 中断配置;STM32F103X 系列微处理器

USART1 波特率的配置;利用集成开发环境建立串口中断控制程序进行数据的发送

与接收,并进行程序的仿真、下载、调试

教学难点

STM32F103X 系列微处理器 USART1 中断配置;STM32F103X 系列微处理器

USART1 波特率的配置;利用集成开发环境建立串口中断控制程序进行数据的发送

与接收,并进行程序的仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 STM32F1 系列 参考手册关于 USART1 章节阅读;扩展上课案例

课后小结 串口通信在 51 单片机中就已经接触过,学生对 RS232 协议并不陌生,但是利

用固件库配置串口通信过程有一定的难度,对于波特率的计算是重点。

授课主要内容

一、硬件接口讲解

串口CP2102原理图与实物图

虽然 STM32 带 USB 的功能,也能模拟串口,但为了不增加 CPU 的负担,我们这里就采用了 USB

转串口电路,让 CP2102 芯片与 STM32 通信串口通信,并且可以达到 921600 的波特率,实现串口数据

的高速传输。STM32 使用的串口为 1 号串口。

二、软件设计讲解 串口是单片机最常用的外设之一。就算一颗8脚的51贴片芯片,I2C、SPI等可以没有,但一定会有

串口。在STM32中,串口提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之

间进行全双工数据交换。

STM32串口的主要特性如下:

◆全双工的,异步通信

◆NRZ标准格式

◆分数波特率发生器系统

─ 发送和接收共用的可编程波特率,最高达4.5Mbits/s

◆ 可编程数据字长度(8位或9位)

◆ 可配置的停止位-支持1或2个停止位

◆ LIN主发送同步断开符的能力以及LIN从检测断开符的能力

─ 当USART硬件配置成LIN时,生成13位断开符;检测10/11位断开符

◆ 发送方为同步传输提供时钟

◆ IRDA SIR 编码器解码器

─ 在正常模式下支持3/16位的持续时间

◆ 智能卡模拟功能

─ 智能卡接口支持ISO7816-3标准里定义的异步智能卡协议

─ 智能卡用到的0.5和1.5个停止位

◆ 单线半双工通信

◆ 可配置的使用DMA的多缓冲器通信

─ 在SRAM里利用集中式DMA缓冲接收/发送字节

◆ 单独的发送器和接收器使能位

◆ 检测标志

─ 接收缓冲器满

─ 发送缓冲器空

─ 传输结束标志

◆ 校验控制

─ 发送校验位

─ 对接收数据进行校验

◆ 四个错误检测标志

─ 溢出错误

─ 噪音错误

─ 帧错误

─ 校验错误

◆ 10个带标志的中断源

─ CTS改变

─ LIN断开符检测

─ 发送数据寄存器空

─ 发送完成

─ 接收数据寄存器满

─ 检测到总线为空闲

─ 溢出错误

─ 帧错误

─ 噪音错误

─ 校验错误

◆ 多处理器通信 -- 如果地址不匹配,则进入静默模式

◆ 从静默模式中唤醒(通过空闲总线检测或地址标志检测)

◆ 两种唤醒接收器的方式:地址位(MSB,第9位),总线空闲

在这里,我们只要了解STM32串口的主要功能,像51单片机一样,会使用3线制的STM32串口通信

就可以了,实际上大部分功能我们可能一辈子都用不到,所以在这里了解就可以了,没必要去深入研究。

USART通过3个引脚与其他设备连接在一起,任何USART双向通信至少需要2个引脚:接受数据输

入(RX)和发送数据输出(TX):

接受数据输入(RX):接受数据串行输入。通过过采样技术来区别数据和噪音,从而恢复数据。

发送数据输出(TX):发送数据输出。当发送器被禁止时,输出引脚恢复到它的I/O端口配置。当发送器

被激活,并且不发送数据时,TX引脚处处于高电平。在单线和智能卡模式里,此I/O口被同时用于数据

的发送和接收。

我们再看下USART框图加深了解:

AHB系统总线在分配到外设中时,分为APB1和APB2,从下图中我们看出USART1使用的是APB2,所有我们

在外设时钟初始化时使用RCC_APB2PeriphClockCmd函数,而不是RCC_APB1PeriphClockCmd函数。

发送过程

接受过程

中断初始化

AHB系统总线框图

配置好了USART1时钟,我们再来看看波特率是如何配置的。

在前面我们讲到一个分数波特率发生器系统,STM32就是用它来产生标准的波特率。

STM32的串口波特率设置公式如下:

上面公式中时钟 f 为系统时钟,即72MHz,常用的波特率及误差如下图所示:

STM32的波特率设置

根据上表,我们看到波特率最大能支持到4500000,不过普通的串口芯片(SP3232等)最高波特率

限制为115200,我们采用的CP2102波特率最高921600,如下图。所以我们程序中采用波特率为921600,

虽然有较大误差,但不影响数据的正常传输。

CP2102技术资料

注意:

在USART1_Configuration函数的注释中,说明配置步骤:

(1)打开GPIO和USART1的时钟

(2)设置USART1两个管脚GPIO模式

(3)配置USART1数据格式、波特率等参数

(4)使能USART1接收中断功能

(5)最后使能USART1功能

以上串口配置顺序不能随意更改,否则程序运行将会出现问题。

三、程序下载及调试 超级终端的配置

依次点击开始->所有程序->附件->通信->超级终端,再按照下图步骤配置:

终端配置

终端配置

终端配置

终端配置

终端配置

终端配置

终端配置

终端配置

终端配置

终端配置

终端最终界面

点击工具栏上的链接 图标,编译链接后没有错误的话,我们点击仿真下载 图标,这时会进

入调试界面。再点击全速运行 图标,让程序全速运行。效果图如下所示。

程序运行后在终端中显示

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 ADC 采集当前电池的电压并将读取的数据发送到超级终端

教学目的

和要求

通过此项目的学习使学生了解 ADC 的结构,了解模数转换的原理与方法,了

解掌握固件库对 ADC 配置的方法与过程,能够运用程序正确的进行模数转换。

STM32F103X 系列微处理器 ADC 的结构

STM32F103X 系列微处理器 ADC 的中断配置

STM32F103X 系列微处理器 ADC 的配置步骤

利用集成开发环境建立 ADC 中断控制程序进行仿真、下载、调试

教学重点 STM32F103X 系列微处理器 ADC 的结构; STM32F103X 系列微处理器 ADC 的

中断配置; STM32F103X 系列微处理器 ADC 的配置步骤

教学难点 STM32F103X 系列微处理器 ADC 的结构; STM32F103X 系列微处理器 ADC 的

中断配置; STM32F103X 系列微处理器 ADC 的配置步骤

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 STM32F1 系列 参考手册关于 ADC 章节阅读;扩展上课案例

课后小结

ADC 模数转换在 51 单片机中就已经接触过,无论是单片机自带 ADC 还是外

扩 ADC 芯片,ADC 的配置步骤都大同小异,学生的难点在于 ADC 的库函数使用

应提高。

授课主要内容

一、硬件接口讲解

电压检测原理图

二、软件设计讲解

AD数模转换的配置之void ADC_GPIO_Configuration(void)

为了程序的模块化,我们把ADC这一模块单独拿出来配置,这里是配置ADC的GPIO端口,修改

为模拟输入。函数内容如下:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOF|RCC_APB2Periph_A

DC3, ENABLE);

//设置ADC时钟频率

RCC_ADCCLKConfig(RCC_PCLK2_Div8);

//定义一个GPIO结构体

GPIO_InitTypeDef GPIO_InitStructure;

//AD 端口设置

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN ; //模拟输入

GPIO_Init(GPIOF, &GPIO_InitStructure);

这样电池采样的ADC就被设置在了GPIOF的6脚上了。

AD数模转换的配置之void ADC_Configration(void)

ADC的配置包括工作模式、软硬件触发模式、数据对齐、信道号等。

/*******************************************************************************

* Function Name : ADC_Configuration

* Description : Configures the ADC.

* Input : None

* Output : None

* Return : None

*******************************************************************************/

void ADC_Configration(void)

{

ADC_InitTypeDef ADC_InitStructure;

ADC_GPIO_Configuration();

该电池电压检测电路比较简单,当电源选择开

关切换到电池供电后,左图上面的 VIN 直接接

电池正极。通过分压后。给 STM32 自带的 ADC

进行采样。采集端口为 PF6(ad3)。

注意:ADC的输入电压不能超过3.3V,否则会

损坏STM32的ADC电路!

/* Resets ADC3*/

ADC_DeInit(ADC3);

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //工作在独立模式

ADC_InitStructure.ADC_ScanConvMode = DISABLE; //DISABLE:单信道模式,ENABLE:多信道模式

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //DISABLE:单一模式,ENABLE:连续模式

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //由软件控制开始转换,而不是

外部触发器

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC 数据右对齐(一般用右对齐)

ADC_InitStructure.ADC_NbrOfChannel = 4; // ADC 信道号4

ADC_Init(ADC3, &ADC_InitStructure);

/* 开始adc3软件转换*/

//配置channel4ADC 第一个转换信道为和采样周期为239.5个周期采样时间

ADC_RegularChannelConfig(ADC3, ADC_Channel_4,1, ADC_SampleTime_239Cycles5);

ADC_Cmd(ADC3,ENABLE);

/* 使能ADC 3复位校准存器*/

ADC_ResetCalibration(ADC3);

/* 检查ADC 3校准寄存器是否结束*/

while(ADC_GetResetCalibrationStatus(ADC3));

/* 开始对ADC3效准 */

ADC_StartCalibration(ADC3);

/*检查ADC3是否校准结束*/

while(ADC_GetCalibrationStatus(ADC3));

ADC_SoftwareStartConvCmd(ADC3, ENABLE);//使能adc3软件转换,开始转换

}

ADC的配置步骤也是不能乱的,必须按照上面的步骤:

1. 配置ADC模式

2. 设置信道及采样率等

3. 校准配置寄存器数值

4. 使能ADC转换

ADC实现模数的转换ADC_Read(void)

我们开启的ADC,现在就差一步:采集数据。

如何采集转换?这个我们是不需要关心的,因为STM32启动ADC初始化后,我们只要调用ADC

数据读取函数,ADC就会自动完成模数转换等操作。下面我们看下数据读取函数:

u16 ADC_Read(void)

{

u32 value;

u8 i;

value=0;

for(i=0;i<32;i++)/////多次采集电压值

{

for(int j=0;j<0xfff;j++);///延时等待转换完毕

value=value+ADC_GetConversionValue(ADC3);

ADC_SoftwareStartConvCmd(ADC3, ENABLE); //使能adc3软件转换,开始转换

value 变量里保存 ADC 多次采集

的数据,多次采集是为了提高采

集数据的精度,这里采集了32次。

}

value=value>>5;

return value;

}

ADC 模数转换的步骤基本完成,下面我们可以看下程序运行的情况了。

三、程序下载及调试

点击工具栏上的链接 图标,编译链接后没有错误的话,我们点击仿真下载 图标,这

时会进入调试界面。再点击全速运行 图标,让程序全速运行。

打开我们的超级终端,超级终端的建立我们再2.5节中我们已经讲过了,这里不再阐述了。看

到的效果图如下:

AD在终端中的显示

Value 右移了 5 为等于

除以 32

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 定时器 PWM 方式调节 LCD 液晶屏背光

教学目的

和要求

通过此项目的学习使学生了解掌握 STM32 定时器的 PWM 功能,以及 PWM

的原理,PWM 的寄存器配置方法,以及程序控制方法。

STM32F103X 系列微处理器定时器结构

STM32F103X 系列微处理器定时器中断配置

STM32F103X 系列微处理器定时器产生 PWM 控制机理

利用集成开发环境建立 PWM 控制程序进行仿真、下载、调试

教学重点

STM32F103X 系列微处理器定时器结构;STM32F103X 系列微处理器定时器

中断配置;STM32F103X 系列微处理器定时器产生 PWM 控制机理;利用集成开发

环境建立 PWM 控制程序进行仿真、下载、调试

教学难点

STM32F103X 系列微处理器定时器结构;STM32F103X 系列微处理器定时器

中断配置;STM32F103X 系列微处理器定时器产生 PWM 控制机理;利用集成开发

环境建立 PWM 控制程序进行仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 STM32F1 系列 参考手册关于定时器章节阅读;扩展上课案例

课后小结

在前续的单片机课程中,定时器是做为重点之一,本次课程所介绍定时器与

51 单片机有类似之处,学生理解比较顺利,但定时器的多种工作方式以及库函数

的使用任然需要加深理解。

授课主要内容

一、硬件接口讲解

LCD背光原理图

彩色液晶屏的背光和其他单色液晶屏的背光原理是一样的,都是采用点亮一个或多个发光二

极管通过导光板达到全屏背光显示的效果。所以我们只需要控制发光二极管的亮度就可以控制

LCD 背光的亮度。对于单片机控制发光二极管常用的控制方法是采用 PWM 脉冲宽度调制方法。

二、软件设计讲解

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用

于测量、通信、功率控制与变换的许多领域中。通过调节 PWM 产生的脉冲占空比,

来控制 LCD 背光的直流分量,达到调光亮度的目的。

利用 LCD 图片显示,对它加入 LCD 背光调节控制。在 LCD 实验的基础上添加

一个 LCD 背光模块程序 BackLight.c。软件操作步骤如下: 新建一个新的文件夹,比如命名为【LCD背光PWM调节】。拷贝【FSMC_LCD图片及

文字显示】下的 文件夹到 【 LCD背光 PWM 调节】下, 删除 \Obj文件 夹下除

stm32f10x_vector.c和cortexm3_macro.s之外的所有内容。

双击 IAR 软件的启动图标 ,进入到 IAR 的主界面,然后在菜单栏上选择

Project->Create New Project,新建一个 ARM 的工程,点击 OK。下一步选择好项目

的路径,路径为 LCD 背光 PWM 调节\Obj。在文件名中填入你想填入的项目名。点击保

存后,会在 IAR 左侧栏 Workspace 中生成你添加的项目。在该项目名上点击右键

Options,在 General Options 选项的 target 中选择 ST公司的 STM32F10xxE,在 C/C++

Compiler 选项的 Preprocessor->Additional include directories:(one per line)

下的编辑框中添加:

$PROJ_DIR$\..\User

$PROJ_DIR$\..\library\inc

$PROJ_DIR$\..\User\TFT_LCD

点击 OK,这样一个以 STM32 为平台的 IAR 开发环境搭建完成,现在可以往开发环境

中添加程序了。

在左侧栏创建下图所列的文件夹。点左侧栏的空白处点击右键,选择Add->Add

Group,输入文件名:

项目左侧栏

在EWARM文件夹上点击右键,选择Add->Add Files,添加如下文件:

EWARM文件夹下的内容

在Lib文件夹上点击右键,选择Add->Add Files,从STM32固件库中添加如下文件到项目中去:

Lib文件夹下的内容

点击工具栏上的 新建文件图标,分别新建文件名为BackLight.c、main.c和

BackLight.h保存到LCD背光PWM调节\User\TFT_LCD下。

在IAR的User文件夹上点击右键,选择Add->Add Files,添加如下文件:

User文件夹下的内容

三、程序下载及调试

点击工具栏上的链接 图标,编译链接后没有错误的话,我们点击仿真下载

图标,这时会进入调试界面。再点击全速运行 图标,让程序全速运行。一直按

着 K8 按键,LCD 背光慢慢变亮。一直按着 K6 按键 LCD 背光慢慢变暗。

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 3 课型 面授+操作

教学内容 FSMC 访问 LCD 液晶屏并实现图形的高速读写

教学目的

和要求

通过此项目的学习使学生了解掌握 FSMC 的机制,了解 FSMC 做为 LCD 驱动

器的配置方法,能够利用集成开发环境进行 LCD 的控制显示。

STM32F103X 系列微处理器 FSMC 结构

STM32F103X 系列微处理器 FSMC 配置

STM32F103X 系列微处理器 FSMC 做为 LCD 控制器的配置

利用集成开发环境建立 LCD 控制程序进行仿真、下载、调试

教学重点

STM32F103X 系列微处理器 FSMC 结构;STM32F103X 系列微处理器 FSMC

配置;STM32F103X 系列微处理器 FSMC 做为 LCD 控制器的配置;利用集成开发

环境建立 LCD 控制程序进行仿真、下载、调试

教学难点

STM32F103X 系列微处理器 FSMC 结构;STM32F103X 系列微处理器 FSMC

配置;STM32F103X 系列微处理器 FSMC 做为 LCD 控制器的配置;利用集成开发

环境建立 LCD 控制程序进行仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 STM32F1 系列 参考手册关于 FSMC 章节阅读;扩展上课案例

课后小结

可变静态存储器控制器做为 STM32 微处理器一个功能强大的外设,其配置灵

活,能够运用在多种控制场合,做为 LCD 驱动器使用更是常见应用之一,但在 51

单片机中并没有此硬件,因此学生学习起来比较吃力,但利用 51 单片机所学的

12864 液晶控制原理,可以有效的辅助 FSMC 的学习,软件配置依然是重点。

授课主要内容

一、硬件接口讲解

LCD液晶屏接口原理图及实物图

液晶屏采用FSMC静态存储器控制器控制LCD液晶屏,,地址映射在BANK1 NOR/PSRAM4(NE4)。

FSMC 总线地址线和数据线可以与其他设备共用,比如我们后面会讲 NORflash 的读写。只需要

通过地址映射来区别每一个设备。

调节液晶背光的方式使用 PWM 控制,PWM 的调光前面的实验中已运用过。

二、软件设计讲解

LCD 液晶屏在生活中很常见,学过 51 的人都应该用过 128X64、1602 等液晶屏,

也知道这些液晶屏是用 IO 口模拟 LCD 读写时序。彩屏也一样,也可以用 IO 口模拟

时序。当你用 IO 模拟操作彩屏的时候,你会发现彩屏有很明显的刷屏现象,最主要

一个原因就是 CPU 的总线主频和 IO 口的响应速度。即变是用 STM32 这种总线主频

为 72MHz 的单片机用普通 IO 口模拟也会有刷屏现象。虽然不是很严重,但也影响

效果。这里我们引入一个 STM32 集成的“LCD 控制器”,相当于 PC 机上的集成显卡,

带动彩屏基本看不出有刷屏现象,它就是 FSMC 静态存储器控制器。说它是“LCD

控制器”有点浪费,它还可以同时访问 SRAM 和 NORFLASH 或者 NANDFLASH 等,

变成“内存读写控制器”和“FLASH 读写控制器”,就看你怎么分配地址和片选了。

这里我们介绍它的“LCD 控制器”功能。软件操作步骤如下:

首先双击 IAR 软件的启动图标 ,进入到 IAR 的主界面,然后在菜单栏上选择

Project->Create New Project,新建一个 ARM 的工程,点击 OK。下一步选择好项目

的路径并在文件名中填入你想填入的项目名。点击保存后,会在 IAR左侧栏 Workspace

中生成你添加的项目。在该项目名上点击右键 Options,在 General Options 选项的

target 中 选 择 ST 公 司 的 STM32F10xxE , 在 C/C++ Compiler 选 项 的

Preprocessor->Additional include directories:(one per line)下的编辑框中添

加:$PROJ_DIR$\..\User

$PROJ_DIR$\..\library\inc

$PROJ_DIR$\..\User\TFT_LCD 点击 OK,这样一个以 STM32 为平台的 IAR 开发环境搭建完成,现在可以往开发环境

中添加程序了。

在左侧栏创建下图所列的文件夹。点左侧栏的空白处点击右键,选择Add->Add

Group,输入文件名:

项目左侧栏

在EWARM文件夹上点击右键,选择Add->Add Files,添加如下文件:

EWARM文件夹下的内容

在Lib文件夹上点击右键,选择Add->Add Files,从STM32固件库中添加如下文件

到项目中去:

Lib文件夹下的内容

在User文件夹下需要在添加一个文件夹TFT_LCD,点击工具栏上的 新建文件

图 标 ,分 别新 建文 件名 为 LCD_Driver.c 、 LCD_Driver.h 、 LCD_Driver_api.c 、

LCD_Driver_api.h 、 LCD_Driver_font.h 和 LCDConf.h 保 存 到 LCD 背 光 PWM 调 节

\User\TFT_LCD下,再新建文件名为main.c的主程序文件添加到User目录下。添加

stm32f10x_conf.h 、stm32f10x_it.c 、stm32f10x_it.h到User目录下。

在IAR的User文件夹点击右键,选择Add->Add Group,输入文件名。再点击右键添

加其他文件,选择Add->Add Files,User和TFT_LCD文件夹下的文件如下:

User文件夹下的内容

我们先看下FSMC地址框图:

FSMC地址框图

从上图上看到FSMC BANK是从0x6000 0000到0x9FFF FFFF地址段,NAND地址段我们的

虚拟终端上没有NANDFLASH,只有NORFLASH,所以是不使用的。虚拟终端用FSMC访问

LCD彩屏使用FSMC_Bank1_NOR/SRAM4段,地址映射在BANK1 NOR/PSRAM4(NE4)。

FSMC提供了所有的LCD控制器的信号:

1. FSMC_D[16:0] � 16bit的数据总线

2. FSMC NEx:分配给NOR的256M,再分为4个区,每个区用来分配一个外设,

这四个外设的片选分为是NE1-NE4,对应的引脚为:PD7—NE1,PG9—NE2,PG10-NE3,PG12—NE4

3. FSMC NOE:输出使能,连接LCD的RD脚。

4. FSMC NWE:写使能,连接LCD的RW脚。

5. FSMC Ax:用在LCD显示RAM和寄存器之间进行选择的地址线,即该线用于

选择LCD的RS脚,该线可用地址线的任意一根线,范围:FSMC_A[25:0]。 注:RS = 0时,表示读写寄存器;RS = 1表示读写数据RAM。

我们的虚拟终端选择NOR的第四个存储区来给LCD彩屏使用,地址映射在BANK1

NOR/PSRAM4(NE4) 并且使用FSMC_A0控制LCD的RS脚,则访问LCD显示RAM的基址为

0x6c00 0002,访问LCD寄存器的地址为:0x6c00 0000。

初始化了液晶屏,下一步就是要使用它了,比如最起码的图片和汉字。

图片显示需要通过图片取模软件Image2Lcd对图片取模,提取十六进制数组,软

件路径:当前例程下\工具\Image2Lcd\Image2Lcd\Img2Lcd.exe,界面如下:

取模软件Image2Lcd使用步骤

打开需要转换的图片,选择所需要转换类型、模式等,最后点击保存,生成一个

C文件,里面就是我们需要调用的数组了,我们使用的该数组的文件名为bmp2.h。 汉字显示也是采用取模软件获取汉字数组,软件路径:\FSMC_LCD图片及文字显

示\工具\字模软件\zimo221.exe,界面及操作步骤如下:

汉字取模软件使用步骤

汉字取模软件使用步骤

输入完汉字后按Ctrl+Enter,在点阵区显示输入的汉字:

汉字取模软件使用步骤

下一步:

汉字取模软件使用步骤

将软件在点阵生成区生成的数组拷贝到项目中去,我们拷贝的文件名为 bmp.h 中。

三、程序下载及调试

点击工具栏上的链接 图标,编译链接后没有错误的话,我们点击仿真下载

图标,这时会进入调试界面。再点击全速运行 图标,让程序全速运行。液晶屏

上会显示如下界面:

程序运行后LCD上的显示

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 4 课型 面授+操作

教学内容 µC/OS-II 操作系统内核机制

教学目的

和要求

通过此情境的学习使学生了解 µC/OS-II 操作系统结构、各个重要功能部分的

概念及实现原理,在此基础上掌握 µC/OS-II 系统移植的条件和方法。

操作系统及 µC/OS-II 概述

任务、进程概念

µC/OS-II 内核结构

µC/OS-II 任务管理

µC/OS-II 时间管理

任务之间通信与同步

教学重点 µC/OS-II 内核结构;µC/OS-II 任务管理;µC/OS-II 时间管理;任务之间通信

与同步

教学难点 µC/OS-II 任务管理;µC/OS-II 时间管理;任务之间通信与同步

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示

课外作业 《嵌入式实时操作系统 μC/OS-II》第二版 邵贝贝相关阅读

课后小结

由于学生没有系统学习过操作系统,所以对于嵌入式实时操作系统 µC/OS-II

的理解有一定的难度,本节内容重点掌握概念,以及任务管理机制,学生课后需要

好好学习邵贝贝的相关书籍。

授课主要内容

一、 嵌入式实时操作系统 实时系统的特点是,如果逻辑和时序出现偏差将会引起严重后果的系统。有两种类型的实时

系统:软实时系统和硬实时系统。在软实时系统中系统的宗旨是使各个任务运行得越快越好,并

不要求限定某一任务必须在多长时间内完成。

在硬实时系统中,各任务不仅要执行无误而且要做到准时。大多数实时系统是二者的结合。

实时系统的应用涵盖广泛的领域,而多数实时系统又是嵌入式的。这意味着计算机建在系统内部,

用户看不到有个计算机在系统里面。以下是一些嵌入式系统的例子:

实时应用软件的设计一般比非实时应用软件设计难一些。本章讲述实时系统概念。 二、µC/OS-II 内核结构

μC/OS-Ⅱ是怎样处理临界段代码的;

什么是任务,怎样把用户的任务交给μC/OS-Ⅱ;

任务是怎样调度的;

应用程序 CPU 的利用率是多少,μC/OS-Ⅱ是怎样知道的;

怎样写中断服务子程序;

什么是时钟节拍,μC/OS-Ⅱ是怎样处理时钟节拍的;

μC/OS-Ⅱ是怎样初始化的,以及

怎样启动多任务;

三、µC/OS-II 任务管理

如何在用户的应用程序中建立任务、删除任务、改变任务的优先级、挂起和恢复任务,以及

获得有关任务的信息。

µC/OS-Ⅱ可以管理多达 64 个任务,并从中保留了四个最高优先级和四个最低优先级的任务

供自己使用,所以用户可以使用的只有 56 个任务。任务的优先级越高,反映优先级的值则越低。

在最新的 µC/OS-Ⅱ版本中,任务的优先级数也可作为任务的标识符使用。

过程控制

食品加工

化工厂

汽车业

发动机控制

防抱死系统(ABS)

办公自动化

传真机

复印机

计算机外设

打印机

计算机终端

扫描仪

调制解调器

通讯类

Switch Hurb

路由器

机器人

航空航天

飞机管理系统

武器系统

喷气发动机控制

民用消费品

微波炉

洗碗机

洗依机

稳温调节器

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 5 课型 面授+操作

教学内容 µC/OS-II 操作系统应用程序开发

教学目的

和要求

通过此情境的学习使学生了解 µC/OS-II 操作系统结构、各个重要功能部分的

概念及实现原理,在此基础上掌握 µC/OS-II 系统移植的条件和方法。

µC/OS-II 变量类型及应用程序基本结构

µC/OS-II API 介绍

µC/OS-II 多任务实现机制

µC/OS-II 移植条件

µC/OS-II 移植步骤

利用集成开发环境建立应用控制程序进行仿真、下载、调试

教学重点 µC/OS-II 多任务实现机制;µC/OS-II 移植条件;µC/OS-II 移植步骤;利用集

成开发环境建立应用控制程序进行仿真、下载、调试

教学难点 µC/OS-II 多任务实现机制;µC/OS-II 移植条件;µC/OS-II 移植步骤;利用集

成开发环境建立应用控制程序进行仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 《嵌入式实时操作系统 μC/OS-II》第二版 邵贝贝相关阅读

课后小结

由于学生没有系统学习过操作系统,所以对于嵌入式实时操作系统 µC/OS-II

的理解有一定的难度,本节内容重点掌握多任务管理机制,学生课后需要好好学习

邵贝贝的相关书籍。

授课主要内容

一、µC/OS-II 的 API 介绍 任何一个操作系统都会提供大量的 API 供开发者使用,µC/OS-II 也是如此,几个比较重要的

API 函数参考相关文档。

二、µC/OS-II 的多任务实现机制

例如,两个任务:任务 A 和任务 B,它们需要通过访问同一个数据缓冲区合作完成一项工作,

任务 A 负责向缓冲区写入数据,任务 B 负责从缓冲区读取该数据。显然,当任务 A 还未向缓冲区

写入数据时(缓冲区为空时),任务 B 因不能从缓冲区得到有效数据而应该处于等待状态,只有

等任务 A 向缓冲区写入了数据之后,才应该通知任务 B 去取数据。

例如,任务 A 和任务 B 共享一台打印机,如果系统已经把打印机分配给了任务 A,则任务 B

因不能获得打印机的使用权而应该处于等待状态,只有当任务 A 把打印机释放后,系统才能唤醒

任务 B 使其获得打印机的使用权。如果这两个任务不这样做,那么也会造成极大的混乱 。

系统中的多个任务在运行时,经常需要互相无冲突地访问同一个共享资源,或者需要互相支

持和依赖,甚至有时还要互相加以必要的限制和制约,才保证任务的顺利运行。因此,操作系统

必须具有对任务的运行进行协调的能力,从而使任务之间可以无冲突、流畅地同步运行,而不致

导致灾难性的后果。

与人们依靠通信来互相沟通,从而使人际关系和谐、工作顺利的做法一样,计算机系统是依靠任

务之间的良好通信来保证任务与任务的同步的。

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 5 课型 面授+操作

教学内容 µC/OS-II 在 STM32 开发板上的移植 API 移植

教学目的

和要求

通过此情境的学习使学生了解 µC/OS-II 操作系统结构、各个重要功能部分的

概念及实现原理,在此基础上掌握 µC/OS-II 系统移植的条件和方法。

µC/OS-II 变量类型及应用程序基本结构

µC/OS-II API 介绍

µC/OS-II 多任务实现机制

µC/OS-II 移植条件

µC/OS-II 移植步骤

利用集成开发环境建立开发板移植控制程序进行仿真、下载、调试

教学重点 µC/OS-II 多任务实现机制;µC/OS-II 移植条件;µC/OS-II 移植步骤;利用集

成开发环境建立开发板移植控制程序进行仿真、下载、调试

教学难点 µC/OS-II 多任务实现机制;µC/OS-II 移植条件;µC/OS-II 移植步骤;利用集

成开发环境建立开发板移植控制程序进行仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 《嵌入式实时操作系统 μC/OS-II》第二版 邵贝贝相关阅读

课后小结

由于学生没有系统学习过操作系统,所以对于嵌入式实时操作系统 µC/OS-II

的理解有一定的难度,本节内容重点掌握多任务管理机制,学生课后需要好好学习

邵贝贝的相关书籍。

授课主要内容

一、移植条件 移植 µC/OS-II 到处理器上必须满足以下条件

(1)处理器的 C 编译器能产生可重入代码

µC/OS 是多任务内核,函数可能会被多个任务调用,代码的重入性是保证完成多任务

的基础。可重入代码指的是可被多个体任务同时调用,而不会破坏数据的一段代码,或者说代码

具有在执行过程中打断后再次被调用的能力。

(2)用 C 语言可打开和关闭中断

ARM 处理器核包含一个 CPSR 寄存器,该寄存器包括一个全局的中断禁止位,控制

它便可打开和关闭中断。

(3)处理器支持中断并且能产生定时中断

µC/OS-II 通过处理器产生的定时器中断来实现多任务之间的调度。ARM Cortex-M3 的处理器

都支持中断并能产生定时器中断,专门有一个 SysTick 定时器来实现。

(4)处理器支持能够容纳一定量数据的硬件堆栈(通常需要几十 KByte 字节)

比如 AT98C51 处理器,内部只有 128 字节的 RAM,要运行,需外扩 RAM。CM3 的芯片,

内部可多达 128KByte 的容量,因此可直接使用。

(5)处理器有将堆栈指针和其他 CPU 寄存器读出和存储到堆栈(或内存)的指令

µC/OS-II 进行任务调度时,会把当前任务的 CPU 寄存器存到此任务的堆栈中,然后,

再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以,寄存器的入栈和

出栈是 µC/OS-II 多任务调度的基础。

二、移植步骤

所谓移植,就是使一个实时操作系统能够在某个微处理器平台上或微控制器平台上运行。由

µC/OS-II 的文件系统可知,在移植过程中,用户需要关注的就是与处理器相关的代码。这部分包

括一个头文件 OS_CPU.H、一个汇编文件 OS_CPU_A.ASM 和一个 C 代码文件 OS_CPU_C.C。

OS_CPU.H

OS_CPU_C.C

OS_CPU_A.ASM

#define 设置一个常量的值

声明 10 个数据类型

用#define 声明三个宏

用 C 语言编写六个简单的函数

编写四个汇编语言函数

移植

杭州科技职业技术学院

教 案

教师姓名 庞家成 课程名称 嵌入式技术应用 授课对象 应用电子技术

授课日期 课时 8 课型 面授+操作

教学内容 基于 µC/OS-II 程序设计实例

教学目的

和要求

通过此情境的学习使学生了解基于 µC/OS-II 程序设计结构、任务划分与优先

级分配,各个子任务实现等,掌握基于 µC/OS-II 程序设计的方法步骤。

实例介绍

实例分析、任务划分及优先权分配

任务实现详解

利用集成开发环境建立实例控制程序进行仿真、下载、调试

教学重点 实例分析。任务划分及优先权分配;利用集成开发环境建立实例控制程序进行

仿真、下载、调试

教学难点 实例分析。任务划分及优先权分配;利用集成开发环境建立实例控制程序进行

仿真、下载、调试

教学组织

形式 多媒体面授+操作演示+技术文档阅读

教学辅助

手段 多媒体展示,实验实训平台控制效果展示

课外作业 《嵌入式实时操作系统 μC/OS-II》第二版 邵贝贝相关阅读

课后小结

由于学生没有系统学习过操作系统,所以对于嵌入式实时操作系统 µC/OS-II

的理解有一定的难度,本节内容重点掌握 µC/OS-II 程序设计的方法步骤,学生课

后需要好好学习邵贝贝的相关书籍。

授课主要内容

一、实例分析 详见参考资料

二、任务划分及优先权分配 详见参考资料

三、任务实例详解 详见参考资料