找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 23940|回复: 15
打印 上一主题 下一主题
收起左侧

STM8单片机零基础学习开发基础篇教程

  [复制链接]
跳转到指定楼层
楼主
ID:223470 发表于 2018-3-16 13:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本文档是学习板stm8单片机篇零基础学习开发基础篇教程;希望给大家的学习中带来帮助;
stm8单片机篇
1章 预备篇
1.1如何在 win7系统下安装基础型学习板实验平台软件

1、双击鼠标左键打开资料中的“基础型学习板实验平台”,“ 基础型学习板 实验平台”如图 1.1- 1 所示。

图 1.1- 1 微云电子出品文件夹
2、打开“基础型学习板实验平台”后,出现一名为 Volume 的文件夹,界面 如图 1.1- 2 所示。

图 1.1- 2 Volume 文件夹
3、双击鼠标左键打开“Volume 文件夹”,出现安装 setup 所在文件夹,如图
1.1- 3 所示。

图 1.1- 3 setup 所在界面
4、右键单击“setup.exe”,选择以管理员身份运行,如图 1.1- 4 所示。

图 1.1- 4 以管理员身份运行安装图标
5、安装程序初始化界面如图 1.1- 5 所示。

图 1.1- 5 安装程序初始化
6、选择目标目录界面,基础型学习板实验平台目录的默认目录是 C:\Program

Files\基础型学习板实验平台\,如图 1.1- 6 所示。

图 1.1- 6 选择目录界面
7、修改保存路径,单击浏览微云电子出品目录以及 National lnstuments 产品 目录,在这里微云电子出品的目录我选用 D 盘名命为基础型学习板实验平台的 文件夹中,单击下一步,如图 1.1- 7 所示。

图 1.1- 7 修改后的保存路径
注:读者可自行选择目录,也可不修改路径,选择默认路径,直接点击下一 步,National lnstuments 产品目录的选择和下载器的目录选择完全一样,这这里 不再重复介绍。
8、目录选择结束的开始安装界面如图 1.1- 8 所示,单击下一步。

图 1.1- 8 开始安装
9、安装进度如图 1.1- 9 所示。


图 1.1- 9 安装进度
8、单击完成,安装成功,安装成功界面如图 1.1- 10 所示。

图 1.1- 10 安装成功界面

1.2如何使用 Downloader

1、左键单击计算机左下方的“开始菜单”中“所有程序”中的“基础型学 习板实验平台”,如图 1.2- 1 所示。




图 1.2- 1 打开 0724 电子出品
2、单击鼠标右键 Downloader,选择以管理员身份运行,这个是我们向 stm8
单片机里下载程序的软件,Downloader 打开界面如图 1.2- 2 所示。

图 1.2- 2 Downloader 界面
3、应用此软件之前需要软件注册,单击软件注册,如图 1.2- 3 所示。
图 1.2- 3 注册界面
4、单击 Port Name 中的下箭头,选择 COM 口,由前面“如何在 win7 系统




下查看 com 口”可知选择 COM3(读者是 COM 几,就选择 COM 几),如图 1.2- 4
所示。

图 1.2- 4 选择 com 口
5、单击注册窗口右侧的蓝色圆箭头,提示输入软件注册码,如图 1.2- 5 所 示。

图 1.2- 5 软件注册界面
6、注意每个学习板的注册码不同,读者请参看学习板上的标签,上面就是 学习板的注册码。在灰色框内输入注册HVGG_GQGG_JJJI_KNHM_JMJH_JKJG 如图 1.2- 6 所示,注意注册码要求英文半角大写。每四位为一组,读者以学习板 标签为主,若输入的注册码不对会有错误提示窗口。输入结束后单击蓝色箭头, 注册成功,如图 1.2- 7 所示。

图 1.2- 6 输入注册码注册

















图 1.2- 7 注册成功
注册部分介绍结束,下载部分在下面下载程序部分介绍。

1.3IAR forstm8软件的安装


在这里我们以 win7 操作系统下为例介绍软件的安装过程。 打开微云电子资料内容中的\相关软件及工具\IAR FOR STM8 v1.3 文件夹,
可看到如图 1.3- 1 所示:




图 1.3- 1 IAR FOR STM8 v1.3 文件夹内容
其中第一个是安装软件,第二个是注册机。右击安装软件,点击“以管理员 身份运行”,操作界面如图 1.3- 2 所示(对于涉及权限的一律点“是”或者“允 许”,以下不再赘述)。

















图 1.3- 2 安装管理权限
打开安装软件后,界面如图 1.3- 3 所示:


图 1.3- 3 打开安装软件界面
点击“next”按钮,之后,选择同意协议,操作如图 1.3- 4 所示,再点击“next”:




图 1.3- 4 接受协议
然后界面如图 1.3- 5 所示:


图 1.3- 5 输入用户信息
其中 Name 和 Company 可以随便填,接下来就是注册和破解的过程了。在 IAR FOR STM8 v1.3 文件夹下找到注册机 key_iar_stm8,同样以管理员身份运行,注 意,此处一定要以管理员的身份运行,否则获取的 ID 号将不准确,会影响以后 软件的使用。操作如图 1.3- 6所示。






图 1.3- 6 注册管理权限
打开之后界面如图 1.3- 7 所示,在 Product 一栏选择 Embedded Workbench For
STM8 1.30,然后点击“Generate”,因为是随机产生的,可多点几次。


图 1.3- 7 注册机界面
把 License number 选定,复制到之前的 License#的条框里。然后点击“next”, 操纵如图 1.3- 8 所示。





图 1.3- 8 输入 License 信息
然后把注册机的 License Key,复制到下图位置,点击“next”,操作如图 1.3- 9
所示。
















图 1.3- 9 输入用户 License Key 信息
接下来是选择安装路径,因为软件不大,所以最好默认安装到 C 盘,如果一 定要更改安装路径,可点击“Change”,操作如图 1.3-10 所示。





图 1.3- 10 修改安装路径
接下来就是选择安装类型(如图 1.3- 11 所示)和安装 ST-LINK 安装包(如 图 1.3- 12 所示),全部选择默认,一路点击“next”就好。

图 1.3- 11 安装类型

图 1.3- 12 ST-LINK 安装
以下两个可以选项不勾选,点击“finish”,就完成了所有的安装。操作如图
1.3- 13 所示。





图 1.3- 13 安装完成
接下来这一步很重要,就是把微云电子资料内容中>安装软件及工具>IAR FOR  STM8  v1.3  里 的 config  文 件 夹 替 换 掉C:\Program  Files\IAR Systems\Embedded Workbench 6.0 Evaluation\stm8(注:个别将软件安装到别的路 径下,请自行分析替换)路径下的config 文件夹。Config 文件夹如图 1.3- 14 所 示。如果没有这一步的话,会影响以后程序的下载。如果在安装过程中忘了这一 步,之后不用重新安装软件,直接加上这一步即可。


图 1.3- 14 config 文件夹
至此,IAR 软件就全部安装完毕了,你会在开始菜单->所有程序中看到一 个 IAR 的相关文件夹。操作如图 1.3- 15 所示。





图 1.3- 15 开始菜单中的 IAR


1.4如何新建工程


1.4.1建立工程


首 先 , 点 击 开 始 菜 单 , 选 择 所 有 程 序 ->IAR Systems->IAR Embedded
Workbench              for              STMicroelectronics              STM8              1.30              Evaluation->IAR              Embedded
Workbench,启动 IAR。操作如图 1.4- 1 所示。


图 1.4- 1 启动 IAR
启动之后如图 1.4- 2 所示:






图 1.4- 2 IAR 运行界面
选择 File>New>Workspace,新建一个 Workplace,用来放置当前要建立的 工程,操作如图 1.4- 3 所示。


图 1.4- 3 建立 Workplace
再点击 Project>Create New Project,如图 1.4- 4 所示:





图 1.4- 4 建立工程
弹出对话框,如图 1.4- 5 所示:


图 1.4- 5 工程类型
Tool chain 默认是 STM8 Series。 无需再选择。这里的工程可以建成四种, 空工程,汇编 ASM,基于 C++或者是 C 语言的,我们这里选择的是 C 然后点 击 OK,弹出保存工程的对话框,如图 1.4- 6 所示:






图 1.4- 6 保存工程对话框
通常,为了方便区分每个工程和便于日后的管理与调试,往往将每个工程用 单独的文件夹来保存,所以,笔者建议在这个步骤多新建一个文件夹,用来保存 新建的工程,点击新建文件夹,取名为“my_first_project”,操作如图 1.4- 7 所 示。






图 1.4- 7 新建工程文件夹
双击打开此文件夹,然后在文件名一栏写入工程的名字 my_first_program, 然后点击保存,操作如图 1.4- 8 所示。
图 1.4- 8 保存工程




工程建好之后,要保存一下 Workplace,选择 File>Save Workspace。操作如 所图 1.4- 9 所示。


图 1.4- 9 保存 Workplace
指 定 要 保 存 的 路 径 , 并 输 入              workspace 的 名 字 , 我 们 这 里 取 名 为
my_first_workplace。





图 1.4- 10 Workplace 名称
一般情况下,project 和 Workplace 的名字最好保持一致,便于以后的管理, 这里,笔者为了让你更好的区分 project 和 Workplace,所以取了不同的名字。至 此,整个工程基本上就建好了,界面如图 1.4- 10 所示。工程建立完毕后的 IAR 界面如图 1.4- 11 所示。
图 1.4- 11 工程建立完毕后的 IAR 界面




1.4.2工程的选项配置


选 择 Project>Options , 或 者 在 Workspace 窗 口 , 选 中 project 名 字 , 右 击 选 择 选 择 “Options…”。操作如图 1.4-12 所示。







弹出 Options 的对话框:
图 1.4- 12 工程选项配置




1)在 Category 中,选择“General Options”,如图 1.4- 13所示:
在 Target 的 Device 中,选择相应的 MCU 型号 STM8S103K3U。其他选 择默认。




图 1.4- 13 配置中的 General Options
这里要提一下,虽然我们学习板上的单片机型号为 STM8S103K3,但是在这 里我们要选择 STM8S103K3U,这可能就是 IAR 软件与单片机不兼容造成的,不 过别担心,这并不会影响我们对单片机的正常使用的。
2)              在 Category 中,选择 C/C++Compiler,显示 compiler 选项页,操作如图
1.4- 14所示。


图 1.4- 14 配置中的 C/C++Compiler 中的 Language




选择 Output list file, 勾选输出列表文件,操作如图 1.4- 15 所示。


图 1.4- 15 配置中 C/C++Compiler 中的 List
3)              在 Category 中,选择 Assembler,显示 Assembler 选项页,操作如图 1.4- 16
所示。


图 1.4- 16 配置中的 Assembler 中的 Language




4)              在 Category 中,选择 Output Converter,显示 Output Converter 选项页 ,操 作如图 1.4- 17所示。

图 1.4- 17 配置中的 Output Converter
在 Debug\Exe 目录中,产生目标文件。IAR 默认的是.out 文件。而我们的 下载器只识别.hex 文件,此处 Output format 选择 Intelextended,然后勾选 Override default。
5)              在 Category 中,选择 Linker,显示 Linker 选项页,config操作如图 1.4- 18
所示,list操作如图 1.4- 19所示。





图 1.4- 18 配置中的 Linker 中的 config


图 1.4- 19 配置中的 Linker 中的 list
选中 Generate linker map file,生成链接映像文件。
6) 在 Category 中,选择 Debugger,显示 Debugger 选项页,这里主要配置下




载程序的方式,因为我们用的是串口下载程序,所以这一步配置不是很重要,
操作如图 1.4- 20所示。
图 1.4- 20 配置中的 Debugger
最后点击“OK”,就完全配置好了。

1.5如何下载程序


1.5.1文件的编译与连接


在代码编辑区,我们先输入一段写好的点亮 led 灯的程序,(此段代码可以在 基础篇>点亮 led 灯里找到,这里引用只是为了讲解如何下载程序,详细代码分 析请参看第二章),如图 1.5- 1 所示:






图 1.5- 1 在 IAR 中输入程序
然后我们点击“Compiled”,编译一下,操作如图 1.5- 2 所示:


图 1.5- 2 编译程序
可以看到下面“Build”一栏中没有错误,如图 1.5- 3 所示:


图 1.5- 3 Build 错误显示栏
然后我们在点击“Make”图标,如图 1.5- 4 所示:


图 1.5- 4 Make 程序
“Build”一栏中显示如图 1.5- 5 所示:





图 1.5- 5 Make 后的 Build 栏
没 有 错 误 和 警 告 , 这 时 候 , 在 我 们 所 建 的 工 程 目 录 D:\......\ 基 础 篇
\my_first_project\Debug\Exe 下,出现 my_first_program.hex 和 my_first_program.out 两个文件,其中,my_first_program.hex 文件是我们将要下载的文件,如图 1.5- 6 所示。


图 1.5- 6 hex 文件

1.5.2程序的下载


关于 Downloder 软件的安装与注册以及串口驱动的安装,请参考 1.2,这里 不再赘述。将硬件跳帽连接好,USB 线连接上电脑的 U口,操作如图 1.5- 7 所 示:






图 1.5- 7 led 灯的硬件连接实物图
选择“开始”菜单,所有程序——>微云电子出品文件夹——>Downloader,
打开 Downloder,如图 1.5- 8 所示:






图 1.5- 8 下载器运行界面
点击下载器按钮,选择相应的串口(串口号在设备管理器里可以看到),若 没有出来串口可点击一下刷新,如图 1.5- 9 所示。





图 1.5- 9 下载器串口操作
然后点击右下角的下一步,出现界面如图 1.5- 10 所示:


图 1.5- 10 下载 hex 文件界面

点击右侧的按钮,选择上面已经编译好的 hex 文件,文件在工程目录
\my_first_project\Debug\Exe 下,然后点击确定,操作如图 1.5- 11 所示。




图 1.5- 11 下载 hex 文件操作
再次点击下一步按钮,就会弹出一个对话框,提示下载成功,如图 1.5- 12
所示。
图 1.5- 12 下载成功界面




这时候,跳上 J7 的跳线帽就可以看到我们的基础型学习板上中间的小灯点 亮了,如图 1.5- 13 所示。

图 1.5- 13 led 灯照亮实物图

1.6特别注意


由于本款单片机学习板是 STM8 和 51 单片机二合一的板子,很多口都是复 用的,所以在调试 STM8 的时候,确定要将 51 设置成高阻输出状态。也就是说 下载一个配置程序 P3M 到 51 单片机里就行了,该程序在目录 51 程序/内。

2章              基础学习篇


2.1GPIO应用之点亮 LED


2.1.1STM8GPIO口原理简介


GPIO 口即通用输入/输出口用于芯片和外部进行数据传输。一个 IO 端口可 以包括多达 8 个引脚,每个引脚可以被独立编程作为数字输入或者数字输出口。 我们这款单片机在 STM8 家族中算比较简单的,只有 PA,PB,PC,PD ,PE 五个口。每个 IO 口都分配五个寄存器,它们是:一个输出数据寄存器 ODR,一 个输入引脚寄存器 IDR,一个数据方向寄存器 DDR,一个选择寄存器 CR1,和 一个配置寄存器 CR2。一个 I/O 口工作在输入还是输出是取决于该口的数据方向 寄存器的状态。 对于常用的几个寄存器介绍如下:




注意:每一个端口寄存器位驱动相应的端口的引脚 。

图 2.1- 1 DDR 寄存器
Px_DDR 寄存器用来配置 IO 口的输入或输出模式,在这里,我们要点亮 led 灯,所以要把与 led 灯相连的口配置成输出模式。与 led灯相连的是 PD4 口,所 以在写代码的时候要把 PD4 口的 DDR 寄存器置 1,DDR 寄存器如图 2.1- 1 所示。

图 2.1- 2 ODR 寄存器
Px_ODR 寄存器,通常只在 IO 口配置成输出的时候起作用,ODR 寄存器里 的值,表示在输出模式下,IO 口引脚上的值。所以,要想把 IO 口的某一个或多 个引脚置高或置低,只需操作 ODR 即可,ODR 寄存器如图 2.1- 2 所示。




图 2.1- 3 IDR 寄存器
当 IO 口配置为输入时,可从此寄存器读取当前 IO 口的状态值。在这里我们 暂时还用不到这个 IDR 寄存器,IDR 寄存器如图 2.1- 3所示。


图 2.1- 4 CR1 寄存器
通常,模拟开漏输出需要外接上拉电阻,驱动能力较强,推挽输出不需要外 接电阻,驱动能力较弱,对于 led 的点亮,推挽输出足以,所以我们通常将 IO 口配置为推挽输出。当然,也有配置为开漏输出的时候,在以后会遇到。CR1 寄存器如图 2.1- 4 所示。




图 2.1- 5 CR2 寄存器
CR2 控制寄存器多用来在输入模式下控制外部中断,在输出模式下,作用不 大,此款单片机虽然可以最高外接 25M 晶振,但我们还用不到那么高的速度, 所以,IO 的输出速度也可以不必关心。CR2 寄存器如图 2.1- 5 所示。
至此,我们已经把 GPIO 口的所有寄存器了解完毕了。

2.1.2硬件连接原理


LED 灯部分及单片机的学习板上的原理图如图 2.1- 6 所示:

图 2.1- 6 LED 灯硬件原理图
根据上面两个原理图来看:单片机的第 29 脚,即 PD4 口通过名为 BEEP 的 线连接到 J7 跳帽的 2 引脚,J7 跳帽的 1 脚连接着一个电阻和一个 led 灯串联后 接地,由此我们可以判断,要想让 led 小灯亮,就是让 PD4 口置为高电平即可(若 将 J7 的跳帽接到 2,3 脚,则可以驱动蜂鸣器)。

2.1.3原工程详解


由以上两小节我们可知,点亮 led 灯只需配置 PD4 口就好,且看以下代码:




#include<iostm8s103k3.h>              //将 MCU  型号(stm8s103k3)的头文件加进 来
int main( void )
{
PD_DDR |=0x10;              //将 PD.4 设置成输出模式 PD_CR1 |=0x10;              //将 PD.4 设置成推挽输出方式 PD_CR2 &=~0x10;              //设置 PD.4 输出速率最大为 2MHZ
PD_ODR |=0x10;              //将 ODR 寄存器的第 4 位置 1,即 PD.4=1;
while(1);              //始终循环,程序停在此处
}
这里只有一个主函数,每个寄存器包括八位,分别控制 PD0~PD7 八个引脚, 这里与 led 灯相连的是 PD4,
PD_DDR |=0x10;就是 DDR 与十六进制数 10(即二进制 00010000)相或。 因为任何数与 0 相或都不变,与 1 相或则为 1,所以“或”有置位的效果,从右 边低位 0 位算起,第五个数恰好是 PD4 口,所以此句话相当于 PD4 设置成输出 模式。PD_CR1 |=0x10; PD_ODR |=0x10; 两句是同样的道理。
PD_CR2 &= ~0x10;              ~是指取反符号,~0x10 就是 0xef,此句就是 CR2 与 fe
(即二进制 11101111)相与,因为任何数与 1 相与都不变,与 0 相与则必为 0, 所以“或”有清零的效果,所以此句话相当于把 CR2的第 4 位清零(即最大摆 率设为 2MHZ)。这是操作八位寄存器的常用习惯语句,它的好处就是,可以不 影响其他的引脚而直接操作你想操作的位,以后我们会经常用到。
PD_ODR |=0x10; 此句相当于直接把已设置成输出的 PD4 口直接拉成高电 平。
while(1);是个死循环,让程序停在此处,防止程序跑飞。 至此,我们按照上一章的讲解,新建一个工程,把上面的代码编辑好,编译
一下,下载到板子上,注意跳帽的连接,至少连接四个哦,就可以看到中间的 led
灯亮了。

2.1.4学习拓展:闪烁 led


想让 led 灯闪烁,其实就是让灯亮一会,再灭一会,也就是 ODR 这个寄存器 置高再清零的过程,但是单片机若只操作 ODR 寄存器,人的肉眼是看不到 led 灯变化的,所以中间可加一个延时函数。
#include<iostm8s103k3.h>
#define u8 unsigned char              //为了方便编程,以下的程序中的
#define u16 unsigned int              //unsigned char 都可以用 u8 表示。

#define u32 unsigned long void Clk_Config(void)

{
CLK_CKDIVR= 0x00;              //系统时钟 1 分频
while(!(CLK_ICKR & 0x02));              //等待 HSI 准备好


}
void Io_Config(void)




{
PD_DDR |= 0x10;              //PD4 设置为输出 PD_CR1 |= 0x10;              //推挽输出 PD_CR2 &= ~0x10;                            //输出高电平
}
void delay(u16 n)
{
u16 i,j;
while(n --)
{
for(i = 0;i < 32;i ++)
for(j = 0;j < 10;j ++);
}
}
int main( void )
{

//                            Clk_Config(); Io_Config(); while(1)

{

PD_ODR |=0x10; delay(500); PD_ODR &=~0x10; delay(500);

}
}
这里出现了几个新的函数。
Io_Config();这里把 IO 口的配置写成了一个子函数,这样使整个程序思路更 清晰。
delay();延时函数,在默认时钟为 2MHZ 时大约为 1ms,delay(500)就是 延时 500ms。
Clk_Config();主要是为了配置时钟,单片机默认是 2MHZ 的时钟,只要改 变 CLK_CKDIVR 寄存器的值就可以改变系统的时钟,设成 0x00 则是将系统时 钟提高到 16MHZ,所以如果在主函数里加上这个配置函数的话,程序就会变快。 有兴趣的童鞋可以把这一句加上(去掉主函数里这个子函数前面的//就好啦),看 一下灯闪的是不是快了。

2.2GPIO应用之蜂鸣器


蜂鸣器是现在单片机应用系统中很常见的,常用于实现报警功能。蜂鸣器一 般分为有源和无源两种,有源的蜂鸣器只要给它两端加电,就可以响。而无源蜂 鸣器则需要给加一个有频率的方波,才可以响。为了更好地学习和了解蜂鸣器的 原理,我们这套板子配的是无源的蜂鸣器。




2.2.1STM8的蜂鸣器原理简介


其实,由上一节的介绍可知,驱动蜂鸣器和驱动 led 灯的 IO 口是同一个,即
PD4,所以,我们只要把 J7 的跳帽往左一换,如图 2.2- 1 所示:











图 2.2- 1 蜂鸣器硬件连接实物图
蜂鸣器就会响了。但我们这款单片机 STM8 特别集成了蜂鸣器模块,可直接 产生 1K,2K 或 4KHZ 的方波,应用起来非常方便。所以,我们着重介绍内置蜂 鸣器模块的原理,同时也可以更进一步的了解直接操作寄存器的原理。
STM8 单片机一共有四个不同的时钟源,它们是:
               1-24MHz 高速外部晶体振荡器(HSE)
               最大 24MHz 高速外部时钟信号(HSE user-ext)
               16MHz 高速内部 RC 振荡器(HSI)
               128KHz 低速内部 RC(LSI)
在应用蜂鸣器模块时,首先要使能片内的低速 RC 振荡器(当然也能使用外 部的高速时钟),其频率为 128KH,通过操作CLK_ICKR 的 LSIEN 位来实现。 CLK_ICKR 寄存器如图 2.2- 2 所示。





图 2.2- 2 CLK_ICKR 寄存器
注:对于该寄存器的更详细的讲解请参考STM8S微控制器手册
其次就是要配置 BEEP_CSR 寄存器了。BEEP_CSR 寄存器如图 2.2- 3 所示。






图 2.2- 3 BEEP_CSR 寄存器
设置蜂鸣器控制寄存器 BEEP_CSR 中的 BEEPDIV[4:0]来分频获取 8KHZ 的 时钟,再通过 BEEPSEL 最终产生 1KHZ、2KHZ 或4KHZ 的蜂鸣信号,最后使 能该寄存器中的 BEEPEN 位,产生蜂鸣器的输出。 蜂鸣器控制寄存器的设置:
首先设置蜂鸣器的预分频器:BEEPDIV[4:0] = 0e 时,BEEPDIV=16; 再设置 BEEPSEL[1:0]进行蜂鸣器频率选择:
BEEPSEL[1:0]              蜂鸣器频率
00:              输出 fls/(8*BEEPDIV)kHz (输出 1kHz)
01:              输出 fls/(4*BEEPDIV)kHz (输出 2kHz)
1x:              输出 fls/(2*BEEPDIV)kHz (输出 4kHz)
最后将 BEEPEN 位置 1,使能蜂鸣器功能;

2.2.2硬件连接原理


本节的硬件连接在上一节已经提过,这里不再重复。




2.2.3原工程详解


以下是蜂鸣器产生 1kHz 信号程序:


#include<iostm8s103k3.h>
#define u8 unsigned char
#define u16 unsigned int

#define u32 unsigned long void Clk_Config(void)

{
CLK_ICKR=0x08;                //选择 LSI 低速时钟 128KHz CLK_CKDIVR &= 0xf8;                            //实现系统时钟 1 分频; while(!(CLK_ICKR & 0x10));              //等待 LSI 准备好
}
int main( void )
{
Clk_Config();              //时钟初始化
BEEP_CSR= 0X2e;              //使能蜂鸣器,设置蜂鸣器产生 1KHz




信号;





}

while(1)              //无限循环
{
}




修改蜂鸣器控制寄存器 BEEP_CSR 的值,就可以输出 1、2、4KHz 的蜂鸣信 号。BEEP_CSR=0x2e==>1kHz;BEEP_CSR=0x6e==>2kHz;
BEEP_CSR=0xee 或 0xae==>4kHz;

2.3定时器应用之 8位定时器点亮 LED(带中断)


STM8S 提 供 三 种 类 型 的 TIM 定 时 器 : 高 级 控 制 型 (TIM1) 、 通 用 型 (TIM2/TIM3/TIM5)和基本型定时器(TIM4/TIM6)。它们虽有不同功能但都基于共 同的架构。此共同的架构使得采用各个定时器来设计应用变得非常容易与方便 (相同的寄存器映射,相同的基本功能)。
这里,我们配合 led 灯,以 TIM4 为例,介绍一下基本定时器的用法。

2.3.1STM8的基本定时器原理简介


定时器 TIM4 的功能包括:
8 位向上计数的自动重装载计数器,即计数器从 0 开始计数,计到自动重装 载计数器 ARR 里的值时,再重新重 0 开始计数。
               3 位可编程的预分频器(可在运行中修改),提供 1,2,4,8,16,32,64 和 128 这 8
中分频比例。




               在计数器更新时:即计数器溢出,可产生更新中断。 基本定时器较其他定时器相比相对简单,下面我们介绍一下与我们这节的实
验密切相关的几个通用定时器的寄存器。


图 2.3- 1 TIMx_CRI 寄存器
这个定时器的主要作用是第 0 位 CEN 和第 7 位 APPRE,用来使能计数器和 预装载。TIMx_CRI 寄存器如图 2.3- 1 所示。






图 2.3- 2 TIMx_IER 寄存器
如果需要开启计数器中断的话,就把 TIM4_IER 寄存器的第 0 位 UIE 置 1,
TIM4 只有一个溢出中断,即当计数器计满时所产生的中断。IER 寄存器如所图
2.3- 2 示。





图 2.3- 3 SR 寄存器
状态计数器 TIM4_SR 通常都是由硬件自动置位,STM8 也是通过 UIF 位来 判断是否进入中断的,所以在中断函数里,我们往往要手动的清除 UIF 位,以 免发生重复进入中断的错误。SR 寄存器如图 2.3- 3 所示。
注:由于我们参考的是整个STM8S家族的微控制器手册,对于不同型号的 MCU难免有微小的差别,这里,在程序里TIM4的状态寄存器为TIM4_SR,而并 不是TIM4_SR1,对于这些微小的差别,可查询iostm8s103k3.h的头文件。


图 2.3- 4 CNTR 寄存器
记录计数器的当前值,可不需要配置,在编辑程序的过程中,可通过此计数 器里的值,判断已计了多少时间。CNTR 寄存器如图2.3- 4 所示。


图 2.3- 5 PSCR 寄存器
举个例子,比如单片机的系统时钟为 2MHZ,而 TIM4_PSCR 计数器为 0x02, 那么,定时器 TIM4 的工作频率就是2M/2^2=0.5MHZ,换句话说就是计数器 CNTR 每增加 1,计数器就计 2us。PSCR 寄存器如图 2.3- 5 所示。





图 2.3- 6 ARR 寄存器
当计数器计到该寄存器里的值时,又重新返回 0,重新计数。如果开启中断 的话,将产生更新中断。ARR 寄存器如图 2.3- 6 所示。
只要对以上几个寄存器进行简单的设置,我们就可以使用定时器了,并且可 以产生中断。
这一节,我们将使用定时器产生中断,然后在中断服务函数里面翻转 led 上 的电平,来指示定时器中断的产生。接下来我们来说明要经过哪些步骤,才能达 到这个要求,并产生中断。
1)设置 TIM4_ARR 和 TIM4_PSCR 的值。 通过这两个寄存器,我们来设置自动重装的值,以及分频系数。这两个参数
加上时钟频率就决定了定时器的溢出时间。
2)设置 TIM4_IER 允许更新中断。
因为我们要使用 TIM4 的更新中断,所以设置 IER 的 UIE 位,并使能触发中 断。
3)允许 TIM4 工作。 光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要
开启定时器,通过 TIM4_CR1 的 CEN 位来设置。
6)编写中断服务函数。 在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的
相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么 类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态 寄存器 SR 的最低位。在处理完中断之后应该向 TIM4_SR 的最低位写 0,来清除 该中断标志。
通过以上几个步骤,我们就可以达到我们的目的了,使用基本 8 位定时器的 的更新中断,来控制外部 led 的翻转。

2.3.2硬件连接原理


同样是点亮 led 灯的电路原理。




2.3.3原工程详解


打开基础篇的程序,找到 8 位定时器控制 led 灯的例程,首先还是包括头文 件,几个宏定义以及延时函数:
#include<iostm8s103k3.h>
#include <intrinsics.h>
#define u8 unsigned char
#define u16 unsigned int

#define u32 unsigned long void delay(u16 n)

{
u16 i,j;
while(n --)
{
for(i = 0;i < 32;i ++)
for(j = 0;j < 10;j ++);



}
}
然后是系统的时钟配置和 led 灯所占的 IO 口配置
void Clk_Config(void)
{
CLK_CKDIVR= 0x00;              //系统时钟 1 分频
while(!(CLK_ICKR & 0x02));              //等待 HSI 准备好


}
void Io_Config(void)
{
PD_DDR |= 0x10;              //PD4 设置为输出 PD_CR1 |= 0x10;              //推挽输出 PD_CR2 &= ~0x10;                            //输出高电平
}
然后就是定时器的配置了。
void Tim4_Init(void)
{
TIM4_PSCR = 6;              //64 分频得到 250KHZ 的定时器时钟,
定时器加 1 就是 4us
TIM4_ARR = 0xfa;              //1ms 中断一次 TIM4_IER_UIE = 1;              //更新中断使能 TIM4_CR1_ARPE =1;                            //预装载使能 TIM4_CR1_CEN = 1;                            //启动计数器
}




由上面可以看出,定时器定时一周为 1ms。在这里,我们可以看到第 3,4,5 句和我们之前配置寄存器的方式不太一样,其实 STM8单片机是可以按位寻址 的,这些位的定义在头文件 iostm8s103k.h 可以查看到,如图 2.3- 7 所示:


图 2.3- 7 iostm8s103k 头文件
红框内我们可以看到,我们可以直接对 CR1 寄存器的 CEN 位操作。
int main( void )
{

Clk_Config(); Io_Config(); Tim4_Init();

enable_interrupt();
while(1){}
}
在主函数里除了对系统时钟,IO 口,定时器的配置之外,还要开启全局中断, 单片机有很多中断,每个中断都有自己相应的寄存器来开启中断,但 STM8 和
51 一样,必须开启一个总中断。在 STM8 的参考手册里对开总中断的指令可如 图 2.3- 8 所示:






图 2.3- 8 中断指令
在 IAR 中可以用 asm()函数来调用汇编指令,所以这里可以写 asm(“rim”); 来开启总中断。但还有另外一种方式,就是调用enable_interrupt();此函数包含 在头文件 intrinsics.h 里,具体的内容,可以参考 IAR 的 help 相关文档,这里就 不多介绍了。
最后是中断子函数,也是最重要的地方。
#pragma vector = TIM4_OVR_UIF_vector
interrupt root void TIM4_UIF_HANDLER(void)
{
static u16 i;
i++;
if(i == 1000)
{

i = 0; PD_ODR_ODR4=~PD_ODR_ODR4;

}
TIM4_SR_UIF = 0;
}
#pragma vector 是 IAR 中断向量指令,是固定的,iostm8s103k3.h 文件中如 所图 2.3- 9 所示。


图 2.3- 9 iostm8s103k3 中的中断向量指令




TIM4_OVR_UIF_vector 实际上就是 0x19,是中断向量的编号,一旦有中断 产生时,CPU 凭借中断向量编号进入中断子函数。那么中断向量编号是如何确 定的呢?
STM8 的 FLASH 地址是从 0x00800 开始,IAR 的中断编号从 0  开始。中 断向量号依次按照中断地址递增。如: 复位向量是0x008000,中断向量号是
0x00; TRAP 的中断地址是 0x008004,中断向量号是 0x01;SPI 中断向量号 是 0x0C;中断向量如图 2.3- 10 所示。


图 2.3- 10 中断向量
图中,我们可以看出,TIM4 的更新(溢出)中断所对应的中断地址是
0x008068,中断向量号是 0x19;当然,我们也可以不需要这么麻烦的去计算向 量编号,我们可以在建好的工程左边,双击iostm8s103k3.h 头文件,就可以直接 用它的宏定义就可以了,就像上面用到的一样,操作如图 2.3- 11 所示。





图 2.3- 11 工程中的头文件
interrupt   void   interrupt_handler(void):   是 声 明 一 个 中 断 函 数 , 注 意
interrupt 是两个下划线,interrupt_handler 是中断函数名字,可自己定义。
static u16 i;
这是定义了一个静态变量 i,定时器每隔 1ms 中断一次,每中断一次,i 就自 加 一 次 , 当 加 到 1000  时 , 正 好 是 1s , 这 时 , i清 零 , 重 新 计 数 , PD_ODR_ODR4=~PD_ODR_ODR4;表示 led 灯翻转,所以整个程序就实现了定时 器定时 1s 闪烁 led 灯的功能了。

TIM4_SR_UIF = 0; 前面已经提到,此位必须每次清零,否则会导致重复中断。 至此,我们已经把所有的代码都详细讲解过了,按照之前的讲解,编译一下

工程,连接好板子,下载程序之后就可以看到 led 灯按照 1s 的速度闪烁了。

2.3.4学习拓展:16位定时器控制 led


8 位定时器计数最大值也就是 255,所以想定时时间大一点,就不得不用变 量 i 来计数了,若是十六位计数器的话,就不一样了,16位通用计数器最大可以 计数到 65535,所以计数的尺度很大,以定时器 TIM2 为例,我们看一下 16 位定 时器如何控制 led 灯,我们只列出与 TIM4 不一样的地方。
void Tim2_Init(void)
{
TIM2_PSCR = 6;              //64 分频得到 1/32MHZ 的定时器时钟,
//定时器加 1 就是 32us
TIM2_ARRH = 0x7a;              //1s 中断一次
TIM2_ARRL = 0x12;
TIM2_IER_UIE = 1;              //更新中断使能 TIM2_CR1_ARPE = 1;                            //预装载使能TIM2_CR1_CEN = 1;                            //启动计数器
}
#pragma vector = TIM2_OVR_UIF_vector
interrupt root void TIM4_UIF_HANDLER(void)
{




PD_ODR_ODR4=~PD_ODR_ODR4; TIM2_SR1_UIF = 0;

}
计数器加 1 为 32us,ARR 寄存器的值为 0x7a12,即 31250,所以计数一周 正好是 1s,所以在中断函数里我们只要翻转 PD4 口就可以了。

2.4UART通用异步收发器


2.4.1STM8串口简介


作为软件开发重要的调试手段,串口的作用是很大的。在调试的时候可以用 来查看和输入相关的信息。在使用的时候,串口也是一个和外设(比如 GPS,GPRS 模块等)通信的重要渠道。
STM8S 家族共有 UART1,UART2,UART3,三组串口,不同型号的单片机内 置不同的串口,有的 STM8 内置有两个串口,这里我们这款单片机内置的是 UART1。接下来我们将从寄存器层面,告诉您如何设置串口,以达到我们最基 本的通信功能。本实例中,我们将实现利用串口 1 接收从串口发过来的数据,把 发送过来的数据直接送回给电脑。
串口最基本的设置,就是波特率的设置。STM8 的串口使用起来还是蛮简单 的,只要您开启了串口时钟,然后配置一下波特率,数据位长度,奇偶校验位等 信息,就可以使用了。下面,我们就简单介绍下这几个与串口基本配置直接相关 的寄存器。关于串口更详细高级的功能请参考《STM8S 微控制器参考手册》。




图 2.4- 1 UART_SR 寄存器
在这里,我们仅用到了状态寄存器第 7 位,由于单片机是 8 位的单片机,所 以每次发送都是以字节为单位向外发送的,为了保证在下一次发数之前的数据已 经发送完毕,必须保证发送数据寄存器为空,即状态寄存器第 7 位置 1。UART_SR 寄存器如图 2.4- 1 所示。


图 2.4- 2 UART_DR 寄存器
当我们把和串口有关的所有寄存器配置好之后,我们只需要将所要发送的数




据写到此寄存器里,比如发送字符 a,就写 UART1_DR=‘a’;就可以了。同样, 当接收到一个字符时,我们也可以从此寄存器里读出一个字符,把它赋值给其他 变量,如 ch=UART1_DR;如何判断是否接收到字符呢?一个方法是产生接收中 断,另一个是使用查询的方法,不断查询 SR 寄存器的 RXNE 位。由于查询方法 很是消耗 CPU,效率不高,所以我们通常用中断的方法。UART_SR 寄存器如图
2.4- 2 所示。


图 2.4- 3 UART_BRR1 寄存器


图 2.4- 4 UART_BBR2 寄存器
对于串口来说配置波特率可能是最重要的步骤了,STM8 单片机就是通过 BRR1 和 BRR2 这两个寄存器(BRR1 寄存器如图 2.4- 3所示,BBR2 寄存器如 图 2.4- 4 所示)来配置波特率的,对于如何配置这两个寄存器,在参考手册里写 的很好,如图 2.4- 5 所示:






图 2.4- 5 配置波特率的操作
fMASTER 指的是系统时钟,默认为 2M,系统时钟可通过 CLK_CKDIVR 寄 存器控制,前面已经提过。在此处,一定要先写 BRR2寄存器,在写 BRR1 寄存 器。图 2.4- 6 是一些常用的波特率配置:


图 2.4- 6 常用波特率配置






图 2.4- 7 UART_CR1 寄存器
通过位 4:M 来控制字长,当需要奇偶校验位或者是有 9 个数据位时要配置 此位,此实验不需要配置。PS 位:用来配置奇校验或偶校验的。这里同样不需 要配置。UART_CR1 寄存器如图 2.4- 7 所示。






图 2.4- 8 UART_CR2 寄存器
这个是一个比较重要的寄存器,当串口全配置好之后,我们通过此寄存器打 开发送或接收的功能,这里,我们常用的有:RIEN 接收中断使能,TEN 发送使 能,REN 接收使能等几个功能。UART_CR2 寄存器如图 2.4- 8 所示。
当然,关于串口的寄存器还有很多,这里我们就不一一介绍了,对串口的基 本操作,有以上这些寄存器就够了,在看一下配置串口的步骤。






图 2.4- 9 字节发送的配置步骤

























图 2.4- 10 字节接收的配置步骤
上面第一个图是字符发送的配置步骤(如图 2.4- 9 所示),第二个是字符接 收的配置步骤(如图 2.4- 10 所示)。因为我们不需要配置奇偶校验和停止位等信 息(全部默认),所以我们不需要步骤 1,2,由此我们就大大简化了程序的配置, 只需要配置 BRR 和 CR2 两个寄存器就好。

2.4.2硬件连接原理


该实验的硬件配置不同于前几个实验:





图 2.4- 11 串口的电路原理图
原理图如图 2.4- 11 所示,电脑 USB 连接着 CH340 芯片,CH340 芯片的 TXD, RXD 与 STM8S 单片机之间隔着两个跳帽,也就是说串口 1 与 USB 串口默认是 分开的,并没有在 PCB 上连接在一起,需要通过跳线帽来连接一下。如图 2.4- 12 所示:


图 2.4- 12 串口的硬件连接实物图
连接上这里之后,我们在硬件上就设置完成了,可以开始软件设计了。

2.4.3原工程详解


打开基础篇程序,串口发数的程序,让我们一起分析一下代码: 当然开始还是固定的头文件,宏定义,延时函数和系统时钟配置:
#include <iostm8s103k3.h>
#include<string.h>
#include <intrinsics.h>
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
const char table[]={"Wish you study SCM happy!\n"};
void delay(u16 n)
{
u16 i,j;
while(n --)




{
for(i = 0;i < 32;i ++)
for(j = 0;j < 10;j ++);



}
}
void Clk_Config(void)
{
CLK_CKDIVR= 0x00;              //系统时钟 1 分频
while(!(CLK_ICKR & 0x02));              //等待 HSI 准备好


}
这里新定义了一个数组 table,我们的目的就是用串口把这个数组里的信息发 到上位机上去。然后是串口的初始化配置:
void Uart_Init(void)
{
UART1_BRR2 = 0x00;
UART1_BRR1 = 0x0d;              //2MHZ 时波特率 9600 对应数 值
UART1_CR2 = 0x08;              //开启发送
}
这里只配置了波特率和开启发送功能,其他寄存器全部选择默认。一般情况 下,都是一个停止位,没有校验,8 个数据位,这些在很多的上位机软件里也是 默认的,所以这里都没有改动。
为了调用方便,我们把发送字节写成了一个简单的子函数,如下:
void UART1_Sendint(unsigned int ch)
{
while((USART1_SR & 0x80) == 0x00);              // 等待数据的传送
UART1_DR = ch;
}
然后是主函数了:
int main( void )
{
u8 i;

//Clk_Config(); Uart_Init();



while(1)
{
for(i=0;i<=strlen(table);i++)
{
UART1_Sendint(table[ i]);

[ i]


}
delay(500);
}
}
主函数里配置完串口后,在 while(1)的循环里,设了一个 for 循环,把数 组 table 里的每个元素按顺序发送出去,为了区别每次之间的发送,特设了 500ms 的延时。strlen()函数是获取字符串数组的长度,在 C 语言里经常用到,包含在头 文件 string.h 里。
接下来我们就用串口调试助手来看一看程序的效果吧。 先按照之前的方法将程序下载到板子上,然后别的可以不用动,在电脑上直
接 打 开 微 云 电 子 资 料 内 容 里 的 “ 相 关 安 装 软 件 及 工 具 ” 文 件 夹 里 的

串口调试助手,注意这时为了避免电脑串口的重复 占用,一定要把下载器完全关掉,必要的时候可重新拔插一下 USB 数据线。打 开的串口调试助手如图 2.4- 13 所示:



图 2.4- 13 串口调试助手
选择好 COM 口和波特率,并打开串口,因为我们发送的是字符,所以不要 十六进制显示,把 Receive As HEX 之前的勾取消,这时,我们就看到接收区出 现我们想看到的字符了,显示界面如图 2.4- 14 所示。





图 2.4- 14 接收串口显示

2.4.4学习拓展:UART之串口收发数


上面的软件设计仅仅介绍了串口的发数功能,在这一小节,我们详细的介绍 一下如何利用接收中断,来接收字符,并把它发送出去。首先还是头文件,宏定 义和系统配置:
#include <iostm8s103k3.h>
#include <intrinsics.h>
#define u8 unsigned char
#define u16 unsigned int

#define u32 unsigned long void delay(u16 n)

{
u16 i,j;
while(n --)
{
for(i = 0;i < 32;i ++)
for(j = 0;j < 10;j ++);
}
}
void Clk_Config(void)
{
CLK_CKDIVR= 0x00;              //系统时钟 1 分频
while(!(CLK_ICKR & 0x02));              //等待 HSI 准备好





}
然后是串口的初始化:
void Uart_Init(void)
{
UART1_BRR2 = 0x00;
UART1_BRR1 = 0x0d;              //2MHZ 时波特率 9600 对应数值
UART1_CR2 = 0x2c;              //开启发送 接收及接收中断
}
这里 CR2 寄存器里我们使能了发送,接收和接收中断功能。详情见图。 然后是发送函数,和主函数,注意主函数容易忘记开总中断。
void UART1_Sendint(unsigned int ch)
{
while((USART1_SR & 0x80) == 0x00);              // 等待数据的传送
UART1_DR = ch;
}
int main( void )
{

//Clk_Config(); Uart_Init();

enable_interrupt();
while(1)
{
}
}
#pragma vector=UART1_R_RXNE_vector
interrupt root void UART1_Recv_IRQHandler (void)
{
unsigned int              ch;


ch = UART1_DR; UART1_Sendint(ch);



}
这个是接收中断函数,其中中断向量编号 UART1_R_RXNE_vector 是查看头 文件 iostm8s103k3.h 看到了,之前也有提到。每当上位机发送一个字符时就会引 起中断,在接收中断里我们把接收到的字符,即 DR 寄存器里的数读出来,赋给 ch 变量,然后再用UART1_Sendint();函数原封不动的发送出去,这样我们再上位 机上就可以看到你发送什么,接收区就显示什么了。串口显示如图 2.4- 15所示。





图 2.4- 15 发送接收串口显示
当然,感兴趣的童鞋也可以变个花样,比如发送“1”,返回“2”,发送“a”, 返回“b”什么的。本串口软件还支持发送汉字,感兴趣的童鞋可以自己上网查 一查如何编辑汉字,这里我们就不再介绍了。

2.5ADC模拟/数字转换


这一节我们将向大家介绍 STM8 的 ADC。本节将利用 STM8 的 ADC 通道 3
来采样外部温度或光强值。

2.5.1STM8ADC简介


在许多的单片机应用系统中,都需要 A/D 转换器,将模拟量转换成数字量。 在 STM8 单片机中,提供的是 10 位的 A/D,通道数随芯片不同而不同,少的有
4 个通道,多的则有 16 个通道(实际准确的通道数量由数据手册的引脚描述说 明)。下面的实验程序首先利用定时器定时对 A/D 输入进行采样,然后分别将采 样结果的高 8 位和低 8 位依次用串口发送出去。这样可以控制采样的时间,以免 单片机采样过快,产生溢出错误。
同样,我们结合着寄存器,了解一下 ADC 的功能。






图 2.5- 1 ADC_CR1 寄存器
ADC 支持 5 种转换模式:单次模式、连续模式、带缓存的连续模式、单次 扫描模式、连续扫描模式。
              单次模式:ADC 仅在唯一的通道(由 ADC_CSR 寄存器的 CH[3:0]选定) 上完成一次转换,一旦转换完成,转换后的数据存储在 ADC_DR 寄存器中,EOC
(转换结束)标志被置位。
  连续和带缓存的连续模式:在连续转换模式中,ADC 在唯一选定的通道 上完成一次转换后立即开始下一次在同样通道上的转换。通过将 CONT 位置位 将 ADC 设为连续模式。不带缓冲功能的连续模式中,转换结果数据保存在 ADC_DR 寄存器中,同时EOC 标志置位。若缓存功能被使能,那么将转换结果 会填满数据缓存,此时,EOC 置位。
              单次扫描模式:与非扫描模式相比,此模式是用来转换从 AIN0 到 AINn
(n 为通道编号)之间的一连串模拟通道,也是只完成一次转换。此模式中,转 换从 AIN0 通道开始,数据结果被保存在数据缓冲寄存器 ADC_DBxR 中,当最 后一个通道(通道 n)被转换完后,EOC 被置位。
 连续扫描模式:该模式和单次扫描模式相近,知识每一次在最后通道转 换完成时,一次新的从通道 0 到通道 n 扫描转换会自动开始。
在本实验中我们只用到了最简单的单次模式,由定时器控制每次转换的开 启,注意 ADON 位的两次开启,第一次只是把 ADC 从低功耗模式唤醒,之后每 次要开启转换时都要将 ADON 位置位才可以。ADC_CR1 寄存器如图 2.5- 1 所示。






图 2.5- 2 ADC_CR2 寄存器
此寄存器我们主要了解它的第 1 位和第 3 位,上面已经介绍过是什么是扫描 模式和单通道模式了,即扫描模式是开启很多个通道,这里,我们只开了一个通 道,所以在配置此寄存器时位 1 要保持为 0。ADC_CR2 寄存器如图 2.5- 2 所示。
由于单片机为 8 位单片机,而 ADC 采样为 10 位,所以涉及一个在数据如何 存储的问题。数据左对齐和右对齐的区别如图 2.5- 3所示:






图 2.5- 3 数据左对齐右对齐区别
然后是状态寄存器,重点是位 7,位 5 和位[3:0],ADC_CSR 寄存器如图 2.5- 4
所示:






图 2.5- 4 ADC_CSR 寄存器
把位 5 置 1 后,每次转换结束后都会产生转换结束中断,在中断里要清除 EOC 标志,位[3:0]是选择要转换的通道 AINx,如果是单次模式,则转换的就是 AINx 通道,如果是扫描模式,则转换的是从 AIN0 到 AINx 通道。


图 2.5- 5 ADC 数据高位寄存器


图 2.5- 6  ADC 数据低位寄存器
当转换结束后,采样结果从这两个寄存器里读出,如果是多通道扫描模式, 数据则储存在 ADC_DBxRH 和 ADC_DBxRL 寄存器里。ADC 数据高位寄存器如 图 2.5- 5 所示,ADC 数据低位寄存器如图 2.5- 6 所示。
关于更多的 ADC 的详细功能,请参考 STM8S 微控制器参考手册。




2.5.2硬件连接原理


原理图如图 2.5- 7 所示:


图 2.5- 7 ADC 电路原理图
如上图中红框的两个跳帽,将 J2  和 J3 的 2,3 脚连接起来,可采集光强数据, 切换 J2 为 1,2 脚,可采集温度数据。硬件连接如图2.5- 8 所示:
图 2.5- 8 ADC 硬件连接实物图

2.5.3软件设计


打开基础篇的最后一个程序,同样开始是头文件,宏定义,延时函数和系统 时钟配置:
#include <iostm8s103k3.h>
#include <intrinsics.h>
#define u8 unsigned char
#define u16 unsigned int

#define u32 unsigned long u16 Adc_Data;





void delay(u16 n)
{
u16 i,j;
while(n --)
{
for(i = 0;i < 32;i ++)
for(j = 0;j < 10;j ++);
}
}
void Clk_Config(void)
{
CLK_CKDIVR= 0x00;              //系统时钟 1 分频
while(!(CLK_ICKR & 0x02));              //等待 HSI 准备好
}
然后是 ADC 配置:
void Adc_Config(void)
{
ADC_CR2 = 0x00;              //              禁止扫描,数据左对齐
ADC_CSR = 0x23;              // 选择转换通道为模拟通道 3 开启中断
ADC_CR1 |= 0x01;              // 从低耗唤醒转换
delay(1);              // 等待 ADC 模块的上电完成
}
这里我们用的是单次转换模式,开启的是模拟通道 3,在原理图上连线写的
,只是一个名称,不要和通道 3 混淆。


void Tim4_Config(void)
{
TIM4_PSCR = 2;              //4 分频得到 250KHZ 的定时器时钟,定 时器加 1 就是 4us
TIM4_ARR = 0xfa;              //1ms 中断一次 TIM4_IER_UIE = 1;              //更新中断使能 TIM4_CR1_ARPE= 1;                            //预装载使能 TIM4_CR1_CEN = 1;                            //启动计数器
}
用定时器比较容易控制 ADC 的转换频率,这里 TIM4 定时器 1ms 中断一次, 因此在定时器中断函数里:
#pragma vector = TIM4_OVR_UIF_vector
interrupt root void TIM4_UIF_HANDLER(void)
{
static u16 i;
i++;
if(i == 10)
{




i = 0;
ADC_CR1 |= 0x01;
}
TIM4_SR_UIF = 0;
}
同样设置了一个计数变量 i,每次 i 计 10 时(即每隔 10ms),开启一次转换, 当转换完毕时,ADON 位自动清零。
以下是串口的初始化和发送函数,不再详述。
void Uart_Init(void)
{
UART1_BRR2 = 0x00;
UART1_BRR1 = 0x0d;              //2MHZ 时波特率 9600 对应数 值
UART1_CR2 = 0x08;              //开启发送
}
void UART1_Sendint(unsigned int ch)
{
while((UART1_SR & 0x80) == 0x00);              // 等待数据的传送
UART1_DR = ch;
}
主函数,注意要使能全局中断。
int main( void )
{

// Clk_Config(); Tim4_Config(); Adc_Config(); Uart_Init();

enable_interrupt();
while(1)
{


}
}
最后是 ADC 转换结束中断,在每隔 10ms 开启一次中断后,ADC 开始转换, 转换结束后产生如下中断:
#pragma vector = ADC1_EOC_vector
interrupt root void ADC1_EOF_HANDLER(void)
{
u8 temp;
if(ADC_CSR_EOC != 0)
{

ADC_CSR_EOC = 0; temp = ADC_DRH; UART1_Sendint(temp);





temp= ADC_DRL; UART1_Sendint(temp);

}
}
此时状态寄存器的 EOC 位一定会被硬件置 1,所以要清零,然后将 ADC_DRH
和 ADC_DRL 里的数读出来,由串口发送到上位机显示。 最后,编译一下程序,下载到板子上,打开串口调试助手,可看到串口发送
的数据,如图 2.5- 9 所示:

图 2.5- 9 串口发送数据
用手遮挡住光敏电阻,或者是捂住热敏电阻,应该可以看到串口调试助手中 数值的变化。
在本章,我们主要是为了讲解单片机的 ADC 采样功能才使用了热敏电阻和 光敏电阻的的模拟电路,对于热敏电阻与光敏电阻当然有更多的功能啦,下一章 我们将会配合着数码管介绍热敏电阻。

2.5.4学习拓展:趣味心电监测仪


了解了 ADC 的工作原理后,我们依据此原理在上位机上制作了一个有趣的 心电监测仪。心脏检测仪工作的硬件原理图如图 2.5- 10所示:






图 2.5- 10 心脏检测仪原理图
其硬件跳帽如图 2.5- 11 所示,黄色框内即为红外对管:


图 2.5- 11 趣味心脏检测仪的硬件连接
要想要红外对管正常工作,必须使图中红框内的 DRIVER 拉低,DRIVER 信 号是由 IrAD-driver 经过一个反相器得到的,因此只需将IrAD-driver 拉高即可。 从原理图中可以看到,IrAD-driver 由单片机的 PA1 产生,因此在写程序的时候 要将 PA1 口初始化为输出,且给其高电平。此外,还需要把上面 ADC 采集程序 中的转换通道改成模拟通道 2.此时单片机采集到的才是 ADIN_2,即红外对管电 路产生的输出电压。注意:要把 J4 跳线帽的 1、2 脚相连。当心脏跳动时,产生 的电压会发生变化,我们将变化的电压值采集进来进行处理,利用串口发送到上 位机,就可以在上位机显示心跳波形啦!由于程序与 ADC 采集的基本相同,这 里只列出与之不同的地方!
下面一段程序是初始化 PA1 为输出,且给其高电平,从而使红外对管工作。
void GPIO_Config(void)
{




PA_DDR|=0x02; PA_CR1|=0x02; PA_CR2&=~0x02; PA_ODR|=0x02;

}


下面一段程序与前面基本相同,只是将 ADC 转换通道由模拟通道 3(ADIN_1)
改成了模拟通道 2(ADIN_2). void Adc_Config(void)
{
ADC_CR2 = 0x00;              // 禁止扫描,数据左对齐
ADC_CSR = 0x22;              // 选择转换通道为模拟通道 2,开启中断
ADC_CR1 |= 0x01;              // 从低耗唤醒转换
delay(1);              // 等待 ADC 模块的上电完成
}
在这里我们只将采集到电压的高八位发送至串口,用高八位值的变化来反映 采集心脏电压的变化趋势!因此,下面的一小段中断程序中只有发送高八位的语 句!
#pragma vector = ADC1_EOC_vector
interrupt root void ADC1_EOF_HANDLER(void)
{
u8 temp;
if(ADC_CSR_EOC != 0)
{

ADC_CSR_EOC = 0; temp = ADC_DRH; UART1_Sendint(temp);

}
}
将程序下载到学习班中,结合心电监测仪观察现象。 心电监测仪的使用方法如下:打开心脏检测仪软件,打开方法为单击电脑左
下角的开始菜单中的所有程序中的基础型学习板实验平台,如图 2.5- 12 所示。





图 2.5- 12 心电监测仪打开方法
打开软件后,先单击左侧的方框选择 COM 口,然后单击右上角的心形按钮, 如图 2.5- 13 所示红框内。

图 2.5- 13 操作心脏检测仪




读者坐姿端正心情放松,用食指指肚儿轻轻放在红外对管上,在软件中就可 以看到 AD 采集到的心脏电压波形。通过此软件就可以观测到自己的心跳波形变 化情况啦!是不是很有趣呢!如图 2.5- 14 所示:
图 2.5- 14 上位机软件界面

2.6SPI串行外设接口


2.6.1SPI总线协议简介


SPI 是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接 口。是 Motorola 首先在其 MC68HCXX 系列处理器上定义的。SPI 接口主要应用 在 EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信 号解码器之间。SPI,是一种高速的,全双工,同步的通信总线。
SPI 接口一般使用 4 条线:
MISO 主设备数据输入,从设备数据输出。 MOSI 主设备数据输出,从设备数据输入。 SCLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。只有在片选选通时,才可以对从机进 行读或写操作,一般情况下低电平有效。
一般情况下,SPI 也可以仅有 3 条线组成,即 SCK 时钟线,SDA 数据线和
CS 片选,SDA 可配置为双向数据传输。SPI 时序如图 2.6- 1 所示:





图 2.6- 1 SPI 时序
从机在时钟线的上升沿或者下降沿锁存数据。
SPI 主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作; 提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。出于 这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM8 也有 SPI 接口。这里我们只对STM8S 的 SPI 接口做一个简单的介绍,通过寄存器对 SPI 接口进行详细了解一下。
关于 SPI 的配置很简单,只需要配置 CR1 和 CR2 两个寄存器就好。SPI_CR1
寄存器如图 2.6- 2 所示,SPI_CR2 寄存器如图 2.6- 4 所示。





图 2.6- 2 SPI_CR1 寄存器
位 7 是用来配置 SPI 在传输数据时是高字节在前还是低字节在前。比如
DS1302 芯片就是低字节在前,而 TM1628 则是低字节在前。
位 6 是开启 SPI,位 5:3 控制 SPI 的波特率,最高可达到 8M。
位 2 是将单片机配置为主设备还是从设备,一般情况下,我们都用单片机做 主设备来驱动其他设备。
位 1 和位 0 的功能如图 2.6- 3 所示:

图 2.6- 3 SPI_CRI 位 1 位 0 功能





图 2.6- 4 SPI_CR2 寄存器
对于单工通信,SPI 可以配置为两种方式:
               1 条时钟线和 1 条双向数据线
               1 条时钟线和 1 条数据线(双工或接收方式) 这两种方式由 BDM 和 BODE 控制,
              1 条时钟线和 1 条双向数据线
置 SPI_CR2 寄存器中的 BDM 位启用此模式。在这个模式中,SCK 用作时钟, 主模式中的 MOSI 或从模式中的 MISO 用作数据通信。传输的方向(输入或输出) 由 SPI_CR2 寄存器里的 BODE 位控制,当这个位是 1 的时候,数据线是输出, 否则是输入。
              1 条时钟和 1 条数据线(双工或只接收方式)
为了释放一根 I/O 脚作为它用,可以通过设置 SPI_CR2 寄存器中的 RXONLY
位来禁止 SPI 输出使能 。这样的话,SPI 将运行于只接收模式。当 RXONLY 位




置 0 时,SPI 又会恢复到全双工模式。
位 1 使能从模式软件管理,位 0 选择主模式,这两位在配置过程中都要置 1, 详细介绍请参考手册。
还有,在 SPI 通信过程中,PE5 引脚,也就是 NSS 引脚,一般就配置为普通 的 IO 口即可,手动的拉低或拉高来控制从机的片选。

图 2.6- 5 SPI_SR 寄存器
这个寄存器,我们通常只是判断位 7,即 SPI 是否空闲。SPI_SR 寄存器如图
2.6- 5 所示。





图 2.6- 6 SPI_DR 寄存器
当把 SPI 配置好之后,只需要向这个寄存器里写数或者读数。SPI_DR 寄存 器如图 2.6- 6 所示。

2.6.2硬件连接原理


由于本节只对 SPI 进行原理性介绍,具体应用请参考下一章内容。

2.6.3原工程详解


打开基础篇程序,找到 SPI 的工程,我们这里只分析一下 SPI 的配置。
void SPI_Init(void)
{
PB_DDR|=0x70;              //PE5 输出,其余保持原功能
PB_CR1|=0x70;              //对应位设置为推挽输出              /*mosi 引脚必须设置为推挽 输出,否则输出为锯齿波*/
PB_CR2&=~0x70;              //输出最大频率为 2Mhz
SPI_CR2 = 0X03;              //软件管理使能开,主模式
SPI_CR1 = 0X04;              //MSB 在前;使能开;1MHZ              (HSE = 8MHZ);主模




式;


SPI_CR1_BR =0; SPI_CR1_SPE =1;

}

// 空闲状态时 scl=0;采用从第一个时钟边沿开始




在配置 SPI 之前,要配置一下 SPI 相应的 IO 口,PE5 和 MOSI 引脚都要配 置为输出模式。SPI 配置步骤如图 2.6- 7 所示。




图 2.6- 7 SPI 配置步骤
然后我们再看一下怎么进行 SPI 通信。
main()
{

Clk_Config(); SPI_Init();



while(1)
{
PB_ODR_ODR4=0;
while(!SPI_SR_TXE);
//              delay(1);
SPI_DR = 0x0A;
while(!SPI_SR_TXE);

// delay(1); PB_ODR_ODR4=1; delay(100);

}
}
看到主函数我们知道,等待 SPI 的 BUSY 位不忙得时候,往 SPI_DR 寄存器 里写数即可。
至此,SPI 的内容我们就介绍完了,具体应用请看下一章读写 SD 卡。

2.7本章小结


至此,关于 STM8 的最基础的知识我们已经完全介绍完了,GPIO,通用定 时器,串口,ADC 和 SPI。是不是掌握了呢,接下来,我们将进入稍稍难一点的 中级篇,程序难度高一些,但也更加有趣,让我们继续加油吧!


高级应用篇,不知道大家是否需要,等待下载量情况,后续推出。


完整的pdf格式文档51黑下载地址:
学习板stm8单片机篇零基础学习开发基础篇教程.pdf (6.81 MB, 下载次数: 195)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏9 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:126534 发表于 2019-1-26 14:06 | 只看该作者
正是需要的,楼主威武。请问楼主中、高级篇什么时候上传。
回复

使用道具 举报

板凳
ID:544220 发表于 2019-5-21 21:41 | 只看该作者
语句有些解释得很到位,希望有更多的解释出来,谢谢,
回复

使用道具 举报

地板
ID:33899 发表于 2019-7-24 11:08 | 只看该作者
很好的教程,感谢楼主
回复

使用道具 举报

5#
ID:509605 发表于 2019-11-12 13:54 | 只看该作者
很适合初学者的教程
回复

使用道具 举报

6#
ID:663680 发表于 2019-12-18 17:44 | 只看该作者
写的很好,看了前面几章感觉解释的很清楚
回复

使用道具 举报

7#
ID:640709 发表于 2020-2-1 12:25 | 只看该作者
不错不错,好资料,收下了!
回复

使用道具 举报

8#
ID:388929 发表于 2020-2-12 10:18 | 只看该作者
很适合
回复

使用道具 举报

9#
ID:388929 发表于 2020-2-13 14:13 | 只看该作者
请教一下,我看到中断那一部分,interrupt root void TIM4_UIF_HANDLER(void),这句是不是少了点什么,我一直都编译不成功
回复

使用道具 举报

10#
ID:669166 发表于 2020-3-22 13:36 | 只看该作者
不错,下载学习了
回复

使用道具 举报

11#
ID:576801 发表于 2020-8-5 17:01 | 只看该作者
问题是实验平台哪里下载啊?
回复

使用道具 举报

12#
ID:688700 发表于 2020-8-13 11:55 | 只看该作者
有pwm输出和pid的教程吗
回复

使用道具 举报

13#
ID:850855 发表于 2020-11-28 21:27 来自手机 | 只看该作者
请问第一步的基础型学习板实验平台软件在哪下载
回复

使用道具 举报

14#
ID:850855 发表于 2020-11-28 21:45 来自手机 | 只看该作者
zm9989 发表于 2020-8-13 11:55
有pwm输出和pid的教程吗

请问一下那个实验平台软件在哪里下载呢?
回复

使用道具 举报

15#
ID:81138 发表于 2021-1-27 09:25 | 只看该作者
那个实验平台软件在哪里下载呢?
回复

使用道具 举报

16#
ID:62246 发表于 2021-10-3 17:07 | 只看该作者
非常感谢!现在正用到。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表