STM8GPIO入门文件认识Word格式文档下载.docx
《STM8GPIO入门文件认识Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《STM8GPIO入门文件认识Word格式文档下载.docx(16页珍藏版)》请在冰豆网上搜索。
![STM8GPIO入门文件认识Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2022-11/28/67e611c0-b5a2-4bf9-b764-8710e6289e55/67e611c0-b5a2-4bf9-b764-8710e6289e551.gif)
counterGPIOsetininputinteruptactivemode*/
GPIO_Init(WAKEUP_GPIO_PORT,ICC_WAKEUP_GPIO_PIN,GPIO_Mode_In_FL_IT);
注释已经写得很明白了。
玩过430或者stm32的童鞋应该多少都知道,这些比较新款的单片机,跟以前的51不太一样,那就是外部中断源贼多,而且是跟着gpio走的。
坦白说,现在回想起来,其实51的外部中断也是跟着io口走的,想起来了吗?
INT0和INT1就是P3.0和P3.1,只不过它少一点而已。
但鉴于我们现在是要入门,所以,我们先不管中断——说起来,玩这个还真费了我不少劲,不过说起来已经不错了,哈哈,那时候STM32还不会定时中断呢(当然,现在也没弄定时,但既然外部中断都会了,想来也差不多吧~~~)
所以,我们的目标先设得简单一点:
我们只要实现基本的gpio读写功能,读用来读按键,写用来点亮LED。
右键就可以点开
相关函数的定义位置(这里说一下,所谓定义,对函数来说,就是函数实现,与函数声明区分,在讨论程序时,我提到
实现,大多是指的都是这个意义上的
实现,而不再是一般说的那个实现的意思。
voidGPIO_Init(GPIO_TypeDef*GPIOx,
uint8_tGPIO_Pin,
GPIO_Mode_TypeDefGPIO_Mode)
没事,我们不会去看源码。
我们只要看函数接口。
一个是gpio的port口,一个是gpio的pin数,一个是gpio的配置模式。
对单片机比较熟悉的朋友基本不用多说,这里还是简单说一下,在单片机里,io口都是按组划分。
比如说,最常见的8位机一组8个,然后可能有4到6组。
当然也有16位机的16个一组,让我有点奇怪的是STM32是32位ARM,一组却也只有16个。
更有甚者,比如我玩的一个32位系统,居然只有8个一组,看来这个跟位数没必然关系。
说了这么多,我们来看看我们这个stm8l-discover开发套件上的gpio口情况。
用不着看pdf,从开发板引出的管脚就知道。
它总共有41个io口,
共分6组,五组8个,最后一组1个,它以A~F按顺序命名。
分别是GPIOA~GPIOF.这就是我们的port
然后每组分8位,这就是我们的pin。
好了,现在我们搞清楚数目上的状况了。
我们再看第三个参数,IO口类型。
我们可以通过查看gpio.h这个头文件获取相关的信息。
看的时候不妨多看一些我们曾见到的熟面孔,这样会加快熟悉对与其相关的宏和操作函数的了解程度。
比如说,首先我们看到的就是io口类型
typedefenum
{
GPIO_Mode_In_FL_No_IT=
(uint8_t)0x00,/*!
<
Inputfloating,
noexternalinterrupt*/
GPIO_Mode_In_PU_No_IT=
(uint8_t)0x40,/*!
Inputpull-up,
GPIO_Mode_In_FL_IT=
(uint8_t)0x20,/*!
externalinterrupt*/
GPIO_Mode_In_PU_IT=
(uint8_t)0x60,/*!
GPIO_Mode_Out_OD_Low_Fast=
(uint8_t)0xA0,/*!
Output
open-drain,lowlevel,10MHz*/
GPIO_Mode_Out_PP_Low_Fast=
(uint8_t)0xE0,/*!
push-pull,lowlevel,10MHz*/
GPIO_Mode_Out_OD_Low_Slow=
(uint8_t)0x80,/*!
open-drain,lowlevel,2MHz*/
GPIO_Mode_Out_PP_Low_Slow=
(uint8_t)0xC0,/*!
push-pull,lowlevel,2MHz*/
GPIO_Mode_Out_OD_HiZ_Fast=
(uint8_t)0xB0,/*!
open-drain,high-impedancelevel,10MHz*/
GPIO_Mode_Out_PP_High_Fast=(uint8_t)0xF0,/*!
Outputpush-pull,highlevel,10MHz
*/
GPIO_Mode_Out_OD_HiZ_Slow=
(uint8_t)0x90,/*!
Outputopen-drain,
high-impedancelevel,2MHz*/
GPIO_Mode_Out_PP_High_Slow=(uint8_t)0xD0/*!
Outputpush-pull,highlevel,2MHz
}GPIO_Mode_TypeDef;
这是个结构体,如果你熟悉,光看名字就猜到了,如果你不熟悉,看看英文注释也差不多了,当然,假如你对电路的了解不深,那可能不知其所然。
而对我来说,尽管我了解这些都是什么玩意,但是对于部分模式,我并不了解它的作用和意义。
于是我另外花了一些时间,去找这方面的的信息看,最后找到一份
周立功的文档,感觉相当不错,比起那些坑爹的强太多了——说的都是废话。
基本就是把STC那种乱七八糟的pdf里的内容半通不通地翻译成中文而已。
没有任何解释。
具体的文档可以上XX搜索,我记得我是请朋友帮我在XX文库里下的,刚找了找,没找着,下次看看补上链接什么的。
下面是简单总结:
基本输入电路
基本IO输入电路
施密特触发输入电路
弱上拉输入电路
基本IO输入,三态缓冲器,只在读取时,外部状态会反映到内部总线上,其余时刻不影响内部电路。
读取时,CPU发出一个外部选通信号
施密特输入电路
对外部输入脉冲进行整形,它可以去除某种程度的抖动。
带外部弱上拉的输入电路
弱上拉的好处是对外部干扰信号有较好的抵抗能力,但输入阻抗显著降低。
而悬空态的输入电路,对于干扰信号抵抗能力较差。
至于输出,实际上只有两种:
1开漏输出
2内部上拉输出。
对这两个我简单解释一下,开漏和开集电极
是很接近的。
这里的漏
说的是场效应管的漏极,它在功能上类似于三极管的集电极。
英文称之为opendrain和opencollection,也就是别人总是神侃的OD门和OC门。
它就是少了一个
上拉电阻,我个人认为它的最大意义有两个:
1第一,它不怕外部IO短路,可以起相当的保护作用。
2它适合不同电平之间的匹配,比如常见的5V系统和3.3V系统。
但它的缺陷却是,输出的电平是不定的。
也就是
高不一定能高到电源电压,低不能低到地的零电平。
而外部上拉,它则可以保证输出永远是稳定的高或者低电平,但是,很显然它遇到IO短路,会有烧毁IO口的危险。
关于这一部分,其实我并没说的很明白,这其中的内容,咱们有需要再多找资料看吧,嘿嘿,我懂的也就这么多了。
我们这里普普通通,只用
外部上拉输入和外部上拉输入输出。
接着看一下这个不是很长的头文件。
GPIO_Pin_0=
((uint8_t)0x01),/*!
Pin0selected
GPIO_Pin_1=
((uint8_t)0x02),/*!
Pin1selected
GPIO_Pin_2=
((uint8_t)0x04),/*!
Pin2selected
GPIO_Pin_3=
((uint8_t)0x08),/*!
Pin3selected
GPIO_Pin_4=
((uint8_t)0x10),/*!
Pin4selected
GPIO_Pin_5=
((uint8_t)0x20),/*!
Pin5selected
GPIO_Pin_6=
((uint8_t)0x40),/*!
Pin6selected
GPIO_Pin_7=
((uint8_t)0x80),/*!
Pin7selected
GPIO_Pin_LNib=((uint8_t)0x0F),
/*!
Lownibblepinsselected*/
GPIO_Pin_HNib=((uint8_t)0xF0),
Highnibblepinsselected*/
GPIO_Pin_All=
((uint8_t)0xFF)/*!
Allpins
selected*/
}GPIO_Pin_TypeDef;
首先是这个
结构体,注意观察,从0到7很有规律的是十六进制的01到80,显然这是位操作模式。
进一步可以在下面三个体现到,高四位和低四位,还有全八位操作,这是为了提供方面,高四和低四,有点类似51里的SWAP互换高低四位的指令。
我们可以在那几句初始化io的函数调用里看到这个结构体成员(也就是那些GPIO_Pin_0),由此可见,我们选择相应的IO口时,直接通过它就可以了,无须自己去位移或者计算选中相应的IO口线。
下面还有一个经常看到
模式判断宏,这个我还没想到有啥可玩,先不管他。
接下来就是几个函数声明了。
都是名副其实的东西。
来来去去就是三大类:
1初始化,它是用来设置相应IO口的工作模式的;
2写操作,分port口和pin线
3读操作,同样分port口和pin线。
至此,我们已经基本把这个gpio的固件库大致理了个头绪了。
再回头看主函数,我们见到他使用的操作gpio函数——有一些实际上就是
带参的宏定义。
比如说这句
/*
LEDGreenON*/
GPIO_HIGH(LED_GREEN_PORT,LED_GREEN_PIN);
同样可以右键找到这个宏的定义。
在它的discover_board.h里,显然,这是他自己定义的。
打开一看,如下
#defineGPIO_HIGH(a,b)a->
ODR|=b
#defineGPIO_LOW(a,b)a->
ODR&
=~b
以后等你熟悉了STM的寄存器,你也会知道,这实际上是直接操作它的输出寄存器,IDR就是输入寄存器。
但我们这里,暂时不考虑这么多,我们首先坚持只用固件库的原有函数做开发。
既然我们已经分析了gpio操作函数分三大类,也就是说,我们可以直接调用。
好了,经过以上分析,我们是时候真正展开动手来做一个属于自己的gpio项目文件了。
项目的建立见上一篇。
上一篇我们建立了一个只有空函数的可编译的项目文件,现在我们在它的基础上,增加gpio的固件库。
因为我们只要操作gpio,所以我们只需要添加gpio.c和gpio.h
对于文件夹的布置,我个人很欣赏stm例程的做法,于是,也按照它的做法做。
首先是一个
库,命名为Library
然后是我们自己的项目文件,命名为Project
再有一个文件夹属于开发中的文档——以后你就会知道,一个完整的项目必须有一些必要的简洁但完整的开发文档,否则,该程序的可维护性和可读性将大打折扣。
Library下,仍然学习例程,下分inc存放头文件,src存放源文件。
由于我的项目文件中还有别的内容,所以我添加了其它头文件,实际上,对于我们这个gpio来说,除了gpio.h以外,只再需要一个stm8l115x.h。
千万别忘了,因为在结构上,如第一篇分析,它是所有外设头文件的基础,没有它,无法完成项目文件的编译。
Src中,则只有一个gpio.c
当然了,它们的全名是stm8l115_gpio.c和stm8l115x_gpio.h
现在,来写我们的主函数。
我们在Project下建立一个main.c源文件,内容很简单,如下:
复制内容到剪贴板
1.#include"
stm8l15x.h"
2.
3.#include"
stm8l15x_gpio.h"
4.
5.//#include"
stm8l15x_exti.h"
6.
7.//#include"
stm8l15x_it.h"
8.
9.
10.
11.
12.
13.#defineBUTTON_GPIO_PORTGPIOC
14.
15.#defineUSER_GPIO_PINGPIO_Pin_1
16.
17.
18.
19.#defineLD4_GPIO_PORTGPIOC
20.
21.#defineLD4GPIO_Pin_7
22.
23.
24.
25.intmain(void)
26.
27.{
28.
29.GPIO_Init(BUTTON_GPIO_PORT,USER_GPIO_PIN,GPIO_Mode_In_FL_IT);
30.
31.
32.
33.//EXTI_SetPortSensitivity(EXTI_Port_B,EXTI_Trigger_Falling);
34.
35.
36.
37.//EXTI_SetPinSensitivity(EXTI_Pin_0,EXTI_Trigger_Falling);
38.
39.
40.
41.//enableInterrupts();
42.
43.
44.
45.while
(1)
46.
47.{
48.
49.
50.
51.if(GPIO_ReadInputDataBit(BUTTON_GPIO_PORT,USER_GPIO_PIN))
52.
53.GPIO_Init(LD4_GPIO_PORT,LD4,GPIO_Mode_Out_PP_High_Fast);
54.
55.else
56.
57.GPIO_Init(LD4_GPIO_PORT,LD4,GPIO_Mode_Out_PP_Low_Fast);
58.
59.
60.
61.}
62.
63.
这段代码本来是已经做到用gpio口的外部中断了,所以有一些被我注释掉的内容,你可以直接去掉。
我们这个代码实现的功能就是,按着按键时,灯是灭的,松开手时,灯是亮的。
具体理解,如同我前面介绍一样,一句话,查看我所调用的函数的函数声明。
你只需要理解它的接口和返回值即可。
对了,差点忘了两件很重要的事。
1指定头文件搜索的相对路径---这对我来说,曾经是非常蛋疼的一件事,现在其实说白了很简单的事情,让我一下就捅破它吧。
我们的编译器在包含头文件时,需要给它指定一个路径,才能准确在特定位置找到我们要的头文件。
指定路径有两种方式:
1绝对路径
2相对路径
绝对路径就是死的,它就是我们在文件夹的地址栏里看到的这个东西:
C:
\DocumentsandSettings\Administrator\桌面\STM8资料\stm8l-gpio2\Project
它的缺陷是,假设下次你把这个项目文件移到另一个位置,比如说D:
\下,那它就全傻了,届时你会看到一堆的警告和错误,实在颇为状况和…..让人心惊胆战。
所以,一般推荐相对路径。
相对路径以项目文件中的工作环境文件.eew为起点,依次寻找搜寻对应的文件夹,由此,不管我们把文件夹移到哪去,都可以正确找到我们放在里面的头文件。
无论是相对路径还是绝对路径都在一个地方设置。
右键点击WorkPlace里那个灰蓝色
实体,选择Option。
选择C/C++Compiler下的Preprocessor选项卡
因为
把头文件包含进代码里,这一步正是
预编译阶段,所以要设置的是
预编译器
其中
$PROJ_DIR$\正是我们前面说的.eew项目环境文件。
此处要注意的是
\..\它的意思是指,回到上一级文件夹。
回忆一下我们的文件夹是如何布置的。
.eew是存在Project文件夹下,而头文件是在与Project同级的Library下的inc里。
所以,首先要回到上一级文件夹,再找到Library下的inc。
这个过程的演变是
$PROJ_DIR$\..\回到上一级文件夹
$PROJ_DIR$\..\Library\inc找到该文件夹里Library下的inc
对于其他位置,而是类似的方法,但要注意的是,一个位置的相对地址要单独写一行。
2选择ST-LINK编译器,这个简单很多
差点又忘了,首先首先要选择器件型号。
同样在这个Option下,选择第一个GeneralOption
然后在Device下拉菜单里选择,对于我们的stm8l152c6t6,我们能选到的最接近型号就是
选择其中的STM8L152C6
至于另两个选项是设置
程序存储器和数据存储器的模式,这个暂时不会玩,先按默认的选即可。
3点击Debugger
Driver一项选择ST-LINK
好了,OK了,现在点击OK。
然后开始编译和运行我们的程序吧。
首先编译程序。
方法如前所说,右键RebuildAll
然后插上开发板,直接点那个绿色小三角,将会看到它在链接和下载。
这时自动处于debug模式,你可以点那些蓝色箭头,实现单步,全速等调试功能。
也可以直接关掉,即可让开发板直接跑程序了。