目录
面包板的使用方法
第一个演示代码:LED闪烁
最后一次快速新建工程演示
点击新建工程
选择芯片
在工程文件夹中创建Start、Library、User
Start文件夹的必备文件复制操作
Library文件夹的必备文件复制操作
User文件夹的必备文件复制操作
在keil中创建Start、Library、User分组并添加文件
添加Start、Library、User文件夹路径
设置Debug并选择调试器
主函数编辑和测试
keilkill批处理文件工具介绍
正式演示LED闪烁代码
RCC的库函数
GPIO的库函数
开启时钟和初始化GPIO
四个GPIO的输出函数
GPIO_ResetBits点亮LED
GPIO_Setbits熄灭LED
GPIO_WriteBit点亮和熄灭LED
GPIO_Write
实现LED闪烁
推挽输出和开漏输出模式下的特点检验
第二个演示代码:Led流水灯
第三个演示代码:蜂鸣器
使用库函数的方法
第一种就是像这样先打开.h文件的,拉到最后看一下都有哪些函数
第二种就是打开提供资料文件夹里的这个库函数用户手册
最后一种方式就是百度搜索,参考一下别人的代码
声明:本专栏是本人跟着B站江科大的视频的学习过程中记录下来的笔记,我之所以记录下来是为了方便自己日后复习。如果你也是跟着江科大的视频学习的,可以配套本专栏食用,如有问题可以QQ交流群:963138186
上一篇详细介绍了GPIO输出的理论部分知识
接下来本篇将演示三个程序:LED闪烁/流水灯/蜂鸣器
我们先来看一下面包板的使用方法
面包板的使用方法
下图就是面包板的正面了,
下面这个是把它背面的双面胶撕掉的样子,
这里一条一条的就是面包板内部的金属爪,
这个图就是这个金属爪的示意图:
当我们把元件的引脚插到面包板的孔里以后,它内部的金属爪就会夹住引脚。
再看一下背面的图,我们可以发现金属爪的排列规律是:中间的金属爪是竖着放的,上下4排是连在一起的4个整体的金属爪,
这就意味着竖着的5个孔,内部都是连接在一起的
这样,我们元件插在一纵排的不同孔位时,内部的金属爪就实现了线路的连接。
而上下四排孔整体是连在一起的,这4排是用于供电的。
这里也标了第一排是正极,第二排是负极,第三排也是正极,第4排也是负极。
如果我们需要供电,就从上下的孔位中用跳线引出来即可
另外再说明一下,这个供电的引脚,有的面包板并不是一整排都是连接的,有些面包板这中间这4个地方都是断开的。
如果是断开的,就需要像这样,在中间用跳线把两边连在一起
如果是连在一起的面包板内部是这样的
然后我们举个例子来演示一下面包板的使用
如果我们要用这个面包板实现电源直接点亮一个led灯的电路就可以这样连接:
首先把上面两排的供电引脚接上电源的正负极
然后用跳线将正极引下来到这个孔里
然后再纵向下面的孔横着插一个限流电阻到右边的这个孔:
接着再在右边纵向上面的孔横着插一个led到右边的这个孔
然后再用跳线把右边引到负极
这样整个电路的电流就是从电源正极出来,通过金属爪,再通过跳线,再通过金属爪下来,然后通过电阻,再通过金属爪上去,然后通过led,最后通过金属爪到跳线,最后接回负极。
这样就用面包板实现了电源直接点亮一个led灯的电路,也是最基础的面包板的基本使用方法。
第一个演示代码:LED闪烁
首先按照接线图把面包板的电路搭建好
注意正负极,不懂如何接的,可以后台私信我或者评论区留言,或者直接看B站江科大的视频演示:[3-2] LED闪烁&LED流水灯&蜂鸣器_哔哩哔哩_bilibili
电路接好后,打开Keil软件新建一个工程。
注:这里再复习一下新建工程的步骤,创建工程有点麻烦,我最后写一遍了,以后就直接复制现有的工程再做修改就行了,就不用从头开始新建工程了。
最后一次快速新建工程演示
点击新建工程
选择存放工程的文件夹,
这里我们接着新建一个文件夹命名为3-1LED闪烁,再点进去,起个工程名,叫Project,保存
选择芯片
选择STM32F103C8,点击OK
直接将这个窗口关闭
然后打开我们刚刚创建的工程文件夹“3-1 LED闪烁”
在工程文件夹中创建Start、Library、User
进去后在里面再新建3个文件夹,分别叫Start、Library、User
Start文件夹的必备文件复制操作
然后打开我们的固件库文件(不知道固件库在哪里的可以去看我之前的博客)
这里最后再放一次固件库的链接,自取!
链接:https://pan.baidu.com/s/1PWtIvq4vzX5K1lQgCW0eKw
提取码:t7i0
找到启动文件
全选复制
把全部复制的这些文件放到我们刚刚创建好的Start文件夹下
同样在固件库里面再找到stm32f10x和system的两个文件
将这三个文件复制
也粘贴到我们刚创建的Start文件夹下
同样的找到core_cm3的两个文件,
找到后复制这两个文件
也粘贴到我们的Start文件夹下
这样Start文件夹的文件就复制完成了
Library文件夹的必备文件复制操作
然后找到标准外设驱动的文件夹(和前面一样的路径)
Src下的全部文件都全选复制
粘贴到我们刚刚创建好的Library文件夹下
然后再打开inc
也是全选复制
粘贴到Library文件夹下
这样Library文件夹的文件就也复制完成了
User文件夹的必备文件复制操作
最后打开Project文件夹
复制这四个文件
粘贴到我们创建的User文件夹下
到此为止,我们的工程文件就复制完成了
在keil中创建Start、Library、User分组并添加文件
然后回到Keil,点击这里,把默认的组关闭
在这里新建3个组,
命名为Start、Library、User
然后选中Start,右边点击Add,打开我们创建的Start文件夹,文件类型选择所有文件
首先添加后缀为md.s的启动文件,然后按住Ctrl,把其他的.c和.h文件都选中,Add
这样Start组里面的文件就添加好了
然后选中Library,点添加文件
这样Library组里的文件就添加好了
然后选中User,添加文件
添加好后点击OK
这样我们的工程里的组和文件就都添加好了
添加Start、Library、User文件夹路径
接着点击这里
把我们自己建的文件夹(Start、Library、User)的路径都添加进来
在这里写上”USE_STDPERIPH_DRIVER”这个字符串
设置Debug并选择调试器
最后是Debug,调试器选择STLINK或者如果你使用的是DAP或者其他的调试器请根据实际选择
比如我使用的是DAP,那么选择这个
然后Setting,Flash下载,勾上复位并执行这个勾
最后确定
这样工程选项就配置好了
主函数编辑和测试
接着我们打开main.c
把main.c原来的代码全部删除掉
然后再空白处右键添加头文件
写上主函数
注意!!!框架后面这一行必须要空一行,否则编译会警告!!!
这样整个工程就建好了。
编译测试一下没有问题
然后下载测试也是没有问题的
keilkill批处理文件工具介绍
这个分享一个小工具:
工具领取链接:https://pan.baidu.com/s/1qGZWu6SkLfReXCLLPk7LdA
提取码:lu9r
这个东西是一个批处理文件,它可以把工程编译产生的中间文件都删掉,我们可以把它复制到我们的创建的工程文件夹“3-1 LED闪烁”里
因为这个工程编译产生的文件比较大,主要占空间是Listings和Objects,里面都是一些中间文件。如果想要把工程分享给别人的话,可以先双击一下这个批处理文件,这时它就会把这些中间文件都删除掉,这样整个工程文件的大小就不会那么大了,也就可以把这整个工程文件夹压缩打包分享给别人了。
正式演示LED闪烁代码
现在我们开始学习如何点亮一个LED
之前也介绍过,操作STM32的GPIO总共需要三个步骤:
第一步,使用RCC开启GPIO的时钟;
第二步,使用GPIO_Init函数初始化GPIO;
第三步,使用输出或者输入的函数控制GPIO口。
在这里总共涉及了RCC和GPIO两个外设,我们先来看一下这两个外设都有哪些库函数:
先看RCC的库函数
RCC的库函数
我们可以在library中找到RCC.h,
点这个文件双击打开,然后拖到最下面
在.h文件的最下面一般都是库函数所有函数的声明,在这里我们可以看到RCC有很多的库函数,但实际上这里的大部分函数我们都不会用到,我们最常用的只有这三个函数:RCC AHB外设时钟控制,RCC APB2外设时钟控制,RCC APB1外设时钟控制
AHB外设时钟控制的函数就是使能或者失能AHB外设时钟的,
它的第一个参数就是选择哪个外设,STM32互联型的设备可以在这个列表选择:
其他设备在下面这个列表选择,
接着第二个参数就是enable或者disable
然后下面的APB2外设时钟控制和ABP1外设时钟控制函数都是一样的操作方法,
都是第一个参数选择外设,第二个参数使能或失能,
如果你不清楚哪个外设是连接在哪个总线上的,还可以在列表找一下,列表中出现的就肯定是这个总线的外设
那RCC的库函数就介绍完了,接着我们再看一下GPIO的库函数,
GPIO的库函数
我们打开GPIO.h去的文件,然后拖到最后,
这些就是GPIO的全部库函数
我们目前需要了解的就是前面的这些函数,
第一个就是GPIO_DeInit, 参数可以写GPIOA、GPIOB等等,调用这个函数之后,所指定的GPIO外设就会被复位,这就是这个函数的用途。
第二个AFIODeInit也是一样可以复位AFIO外设,这个AFIO我们后面再讲。 第三个GPIO_Init是非常重要的函数,这个函数的作用是用结构体的参数来初始化GPIO口。我们需要先定义一个结构体变量,然后再给结构体赋值,最后调用这个函数,这个函数内部就会自动读取结构体的值,然后自动把外设的各个参数配置好。这种Init函数在STM32中基本所有的外设都有,一般我们初始化外设都是使用这个Init函数来完成的。 第4个是GPIO_StructInit,这个函数可以把结构体变量赋一个默认值。
接下来这4个就是GPIO的读取函数:
然后下面跟着的4个就是GPIO的写入函数:
这些函数就可以实现读写GPIO口的功能:
剩下的这些函数我们暂时不会用到,
所以这里面重要的函数就是GPIO_Init和这8个读写函数:
我们就来试试用这些函数来操作GPIO:
开启时钟和初始化GPIO
我们回到main.c文件
首先调用的是RCC里面的APB2外设时钟控制函数
我们复制粘贴到这里:
然后选中它,右键跳转的定义,
我们需要点亮PA0口的led,根本上一篇我们学习的GPIO基本结构图,PA0接的是APB2
所以选择RCC APB2外设GPIOA这一项
复制粘贴到第一个参数的位置:
第二个参数选择ENABLE放到第二个参数,这样时钟就开启了。
接着调用GPIO_Init函数
复制粘贴到这里
第一个参数选择GPIOA,
第二个参数是一个结构体,我们先把结构体类型复制下来,
在上面粘贴,
起个名字叫GPIO_InitStructure
注意:这里这个结构体实际上也是一种局部变量,在有些老的编译器,它要求所有的局部变量定义必须放到函数的最前面,如果你的编译器是这样的话,就需要把这一行提到最前面去,
我这个编译器是支持在函数中间定义变量的,所以就放在这个位置。
接着我们复制结构体名字,用一个点把结构体的成员都引出来
然后依次选中结构体成员,右键跳转看一下说明,复制粘贴一下参数(这里再之前有详细讲过了,看不太清楚的可以去翻前面的博客看一下)
这样就找到了这个结构体的成员(即GPIO的8种工作模式)
AIN是模拟输入,In_floating是浮空输入,Ipd是下拉输入,IPU是上拉输入,Out_ OD是开漏输出,Out_ PP是推挽输出,AF_OD是复用开漏,AF_PP是复用推挽,那我们点灯用的是推挽输出,所以复制Out_ PP是推挽输出,
粘贴到GPIO_MODE这里来:
接下来GPIO_PIN选择引脚,我们继续右键跳转,这里GPIO_PIN有多个定义,我们选择member这一项。
然后选中这个CTRL+F
这里因为我们用的是GPIOA外设的0号引脚,所以选择GPIO_Pin_0
放到这里
接着第三个Speed还是一样的步骤
输出速度选择50MHz就行了
最后把GPIO初始化结构体的地址放到GPIO_Init的第二个参数,
这样初始化就完成了。
当这个GPIO_Init函数执行完,这个GPIOA外设的0号引脚就自动被配置为推挽输出、50MHz的速度。
它内部的主要执行逻辑就是读取结构体的参数,执行一堆判断和运算,最后写入到GPIO配置寄存器,至于操作的细节,我们就不用再关心了。
到现在GPIO初始化就已经完成了。
我们接下来就可以使用GPIO的这些输入输出函数了。
四个GPIO的输出函数
本小节先介绍这四个GPIO的输出函数,
第一个GPIO_SetBits函数,第一个参数是GPIOx,第二个参数是GPIO_Pin, 这个函数可以把指定的端口设置为高电平;
第二个GPIO_ResetBits,参数和上面的一样,这个可以把指定的端口设置为低电平;
第三个GPIO_WriteBit, 这个函数有三个参数,前两个也是指定端口的,第三个是BitVal, 这个是根据第三个参数的值来设置指定的端口; 第四个是GPIO_Write, 第一个参数是GPIOx,选择外设,第二个参数是PortVal, 这个参数可以同时对16个端口进行写入操作。
那我们分别来用一下试试:
GPIO_ResetBits点亮LED
首先试一下GPIO_ResetBits。 可以看一下函数说明。 第一个参数是GPIOX,可以是A到G,
第二个是要写入的GPIO_Pin_x,x可以是0~15
那我们就写入GPIOA,GPIO_Pin_0
这样就行了,编译一下。
没有错误,下载看一下。
可以看到这个led就已经点亮了
这说明我们端口配置的没问题,而且PA0已经输出了低电平。
GPIO_Setbits熄灭LED
那我们再换GPIO_Setbits函数试试
这个参数是一样的,不用更改
编译下载,可以看到led就已经熄灭了
GPIO_WriteBit点亮和熄灭LED
然后我们再试一下第三个函数GPIO_WriteBit
这里前两个参数也是一样的,第3个参数我们转到定义看一下第三个参数的介绍是指定写入的数据值,这个参数可以是BitAction这个枚举中的一个值
Bit_RESET是清除端口值,也就是置低电平,Bit_SET是设置端口值,也就是置高电平。
我们先复制一下Bit_RESET,放到这里
编译下载,可以看到led又亮起来了
再把这个改成Bit_SET
编译下载,可以看到led又熄灭了
这就是这三个函数的用法。
GPIO_Write
这第4个函数我们等下再介绍。
实现LED闪烁
接下来我们先来完成led闪烁的任务,为了实现led闪烁,我们就需要在主循环里写上点亮led延时一段时间,熄灭led延时一段时间这样的逻辑。
点亮Led我们可以用刚才那句,改成bit_reset, 这样就是点亮led的;然后复制一下改成bit_set, 这就是熄灭led,
那中间需要加两个延时函数来进行一段延时,这里给大家提供了一个现成的延时函数代码
领取链接:https://pan.baidu.com/s/1qQP_eN_Gdsnr_RmvhKsfIQ
提取码:5oqu
我们先把它们添加到工程里面来:
先复制打开led闪烁的工程,这里再新建一个文件夹,名称可以叫system,存放系统的资源。 然后把那两个Delay文件粘贴到这里
回到Keil软件,点击三个箱子的按钮,添加组,也叫system。把它往上挪个位置,然后右边添加文件,打开system,把Delay的两个文件添加进来,然后OK,
这样Delay文件就添加完成了,
最后别忘了点击魔术棒按钮,添加这个新文件夹的头文件路径
这样就完成了。
我们可以打开delay.h看一下,这里就是3个延时函数,分别是微秒延时、毫秒延时、毫秒延时。
打开.c文件,可以看到这些函数的定义。
这里是用SysTick定时器来实现的延时,具体怎么实现的大家不用管的,这个延时函数一般都是直接拿来用就行了,不需要修改什么。
那我们回到main.c,使用这个延时函数模块,需要先在上面写上头文件
然后复制毫秒延时函数,放在这里,参数给500,这样就可以延时500ms。
编译,没有错误下载
这时led就开始闪烁了
STM32-LED闪烁
如果我们把这个延时改短点儿,比如100ms,这样led就闪得更快了。
这就是第一个led闪烁的代码了。
这里除了WriteBit函数外,还可以用SetBits和ResetBits来实现,那我把它们都写上,给大家参考一下:
这样也可以实现led闪烁。
最后大家可能觉得调用这些函数只能填他给的指定参数,如果我们非要给一个数,1是高电平,0是低电平,这样该怎么办呢?
我们复制一下这个GPIO_WriteBit函数,然后把Bit_RESET改成0 ,Bit_SET改成1,
但如果直接这样编译的话会有两个警告,
说的是枚举类型中混入了其他类型的变量,所以如果想直接写1和0的话,需要在这里加上强制类型转换,把1和0类型转换为BitAction的枚举类型。
这样再编译就没有问题了。
推挽输出和开漏输出模式下的特点检验
最后,我们再研究一下推挽输出和开漏输出的驱动问题。
我们把这个LED拔掉,然后把长角插到PA0口,短脚插到负极,这样led就是高电平点亮的方式,可以看到led也是正常闪烁,说明在推挽模式下,高低电平都是有驱动能力的。
那我们把这个端口的模式GPIO_Mode换成auto OD开输出模式,编译下载。
编译下载可以看到led就不亮了,
现在led还是高电平点亮的方式,Led不亮说明开漏输出的模式,高电平是没有驱动能力的。 我们把LED再改回低电平驱动的方式,可以看到LED又亮起来了,这说明开漏模式的低电平是有驱动能力的。
这就印证了我们上一小节讲的推挽输出和开漏输出的特性:推挽输出高低电平均有驱动能力,开漏输出高电平相当于高阻态没有驱动能力,低电平有驱动能力。
一般输出用推挽模式就行了,特殊的地方才会用到开漏模式。
这就是led闪烁代码的全部内容了。
第二个演示代码:Led流水灯
接下来看看第二个代码演示:Led流水灯
先来看一下接线图
这里需要拿出8个LD,正极都插到正极的供电口,负极依次插到PA0到PA7的端口。
插完电路后,我们复制一下led闪烁的工程。改个名字叫3-2 LED流水灯
这样直接复制现有工程,就不用再费时间新建工程了。
打开工程了,然后我们来修改一下这个代码,实现led流水灯的程序。
第一句打开GPIOA的时钟,因为我们连接的都是GPIOA的端口,所以第一句不用变的。
接着初始化端口的这一部分,这里只初始化的GPIOA的0号端口,我们流水灯用的是GPIOA的0~7号端口,所以这里要加一些端口,那怎么加呢?
在这里我们可以直接在GPIO_Pin_0后面加上或GPIOPIN1再加上或GPIOPA,这样就可以一次性把三个端口都初始化了。
为什么可以这样来使用呢?我们转到定义看一下
这里可以看到PIN0对应的数据是0X0001,然后PIN1、PIN2 、pin3依次为0X0002、 0X0004、 0X0008,如果把这个16进制换成二进制的话,就是0000000000000001,然后是0010,0100,1000。在这里每个端口对应一个位,如果把它们进行按位或的操作,比如Pin0,Pin1和Pin2按位或,那结果就是0111。
这样就相当于同时选中了三个端口,这就是安位货的操作逻辑。
最后我们还可以看到这里有个GPIO_Pin_All,它对应的数据就是0xFFFF。
也就是所有位都为1,这样就相当于选中了所有的引脚。
在这里除了这个GPIO_Pin可以用按位或的操作方式外,这个时钟控制的这一项也是可以用按位或的操作方式来选择多个外设的。
你看它这里的定义也是一样的,数据的规律是每一位对应一个外设。
还有这个GPIO_SetBits, 这里也可以用按位或选择多个引脚
这样就能同时设置多个引脚了,所以这个函数名字也多了个S,
GPIO_ResetBits也是一样,在这个函数介绍里也写了这个参数可以是GPIO_Pin_x的任意组合,说的就是这个方式。
因此,我们就可以在这里使用按位或把这8个引脚都选上,当然,这里也可以直接写GPIO_Pin_All,这样就把16个端口全部配置了
改成推挽输出模式
然后是主循环里面,我们先把这些删掉,
现在为了同时控制16个端口,我们就可以使用GPIO_Write这个函数了
我们复制过来,第一个参数是GPIOx, 我们直接写GPIOA,
第二个参数PortVal我们转到定义看一下,这里写的是指定写到输出数据寄存器的值,
下面我们可以看到这第二个参数就是直接写到GPIO的ODR寄存器里的,所以我们可以写0x0001对应二进制就是00000000000000001。
因为C语言不支持直接写二进制,所以这里只能转化为16进制来写,这16个二进制分别对应PA0到PA15,总共16个端口,最低位对应PA0,最高位是PA15。
因为是低电平点亮,所以前面再加一个按位取反的符号
这样就是第一个led点亮,其他都熄灭了
Delay 500ms
复制,然后这里依次改为
这样就行了,高八位我们暂时不用
编译没有错误,下载,可以看到led依次点亮
STM32-流水灯
如果想快一点的话,可以改成100ms。 那我们第2个程序led流水灯到这里就完成了。
第三个演示代码:蜂鸣器
接下来是第3个程序蜂鸣器
我们先看一下接线图
蜂鸣器的VCC正极接到正极供电孔,GND负极接到负极供电孔。然后I/O控制级就随便选择一个IO口接上就行了。图中选择的是PB12号口。注意,A15、B3、B4这三个口大家先别选。
我们从引脚定义图可以看到,这三个口默认是JTAG的调试端口,如果要用作普通端口的话,还需要再进行一些配置。
我们给PB12输出低电平,蜂鸣器就会响,输出高电平蜂鸣器就不响。
那我们复制一下led闪烁的程序,改个名字叫3-3 蜂鸣器。
打开工程,首先是时钟,因为我们用的是PB口,所以这里改为GPIOB,
然后是端口PB12号,所以这里是PIN12
端口模式仍然是推挽输出,速度50M初始化这里也应该是对GPIOB的初始化
到这里,我们的PB12号口就已经初始化好了。
然后是输出,我们把这些先删掉
这两个地方都改为B、12
这就完成了,编译,下载可以听到蜂鸣器已经在响了
STM32-蜂鸣器
我们让它换个响的模式,这里改成这样,
响100ms,停100ms,再响100ms,再停700ms,编译下载
使用库函数的方法
最后再给大家介绍几种使用库函数的方法。
第一种就是像这样先打开.h文件的,拉到最后看一下都有哪些函数
要用哪个函数就选中然后在右键转到定义,查看一下函数和参数的用法
第二种就是打开提供资料文件夹里的这个库函数用户手册
领取链接:https://pan.baidu.com/s/1nE5woVsjRPuUdBVZoLMo6A
提取码:de24 这里面有所有函数的介绍和使用方法
这个文档是中文的,看起来比较好理解,而且这个函数下面都还给了例子,要用的话直接复制过来就行了。
不过这个用户手册的版本并不对应我们现在用的这个库函数的版本。 我们使用的库函数是V3.5.0版本的,
这个用户手册是老版本库函数的,所以有部分用法会有一些出入,但是整体上的差异都不大,参考这个用户手册也是没有问题的。
V3.5.0的库函数目前好像还是没有这种用户手册。ST公司并没有发布V3.5.0版本的库函数用户手册,而是在这个固件库压缩包中给了这样的一个帮助文档,
我们可以打开看一下,比如可以找到GPIO这一节
最后一种方式就是百度搜索,参考一下别人的代码
比如我们可以打开百度搜索STM32 GPIO,这种方式是最常见的方式,就不用赘述了。
本节的任务到这里就全部完成了,我们下一小节再来继续学习GPIO的输入部分。
QQ交流群:963138186
本篇就到这里,下篇继续!欢迎点击下方订阅本专栏↓↓↓