STM32L552开发板——GPIO

发表于 2020-05-30 09:53:49 收藏 已收藏
赞(0) •  评论(0
400万+工程师在用
400万+工程师在用

STM32L552开发板——GPIO

发表于 2020-05-30 09:53:49
+关注

这次是针对NUCLEO_L552ZE_Q开发板的第三次评测贴,上次的帖子介绍了如何在Windows平台上搭建开发环境,既然环境已经准备好了,接下来我们就要开始动手写程序测试了(写程序是不会写的,这辈子都不会写程序的,因为有STM32CubeMX),是的,STM32CubeMX把基本的程序框架都写好了,对于基本的测试,只需敲几行字母就行了,真是懒人的必备,哈哈哈。

废话不多说,相信许多玩过单片机的朋友都知道,拿到一款单片机,写程序的第一步无非就是GPIO口的输出输入功能,输出功能就是点亮一盏LED,输入功能就是按键扫描,那接下来我们就遵守这一不成文的规定,先从GPIO口的输出输入功能入手。

评测内容        

1、新建MDK-ARM工程,使用STM32CubeMX新建一个工程;

2、GPIO口电平输出功能,控制NUCLEO_L552ZE_Q开发板上的红色LED灯闪烁;

3、GPIO口电平输入功能,使用NUCLEO_L552ZE_Q开发板上的USER BUTTON按键控制红色LED灯闪烁的频率大小。

新建MDK-ARM工程        

在开始之前,我们还需要了解一些如何使用STM32CubeMX新建一个工程的知识。

01 新建目录  

在电脑的磁盘上新建一个文件夹,这个文件夹并不是工程目录,至于工程目录是哪个,稍后会说。注意,文件件的名称,上级名称,上上级名称等,就是整个路径,一定不能含有中文!半个中文都不能有!不信你可以试试。为了演示,我就随便建个名为“Demo”的文件夹,如下图。

02 新建STM32CubeMX工程  

1、打开STM32CubeMX,鼠标左键单击“New Project”中的“ACCESS TO MCU SELECTOR”,

2、在弹出的“New Project from a MCU/MPU”窗口中的左侧的搜索框中输入你需要的单片机型号,我这里输入“STM32L552ZE”,

3、然后在左下角的“MCUs/MPUs List”中选择所需要的单片机型号,我这里选择STM32L552ZET6Q,双击单片机型号,

4、弹出窗口问你是否使用TrustZone,我选择No,然后就创建了一个STM32CubeMX工程。

03 配置STM32CubeMX工程  

1、设置工程属性,点击STM32CubeMX工程窗口上方的“Project Manager”选项,在最左边选项切换到“Project”,

2、在“Project Location”中选择在第一步的时候创建的文件夹,

3、在“Project Name”中填入工程名(不能是中文),填入的工程名就是这个工程的根目录,路径如蓝色框所示,

4、在“Toolchain / IDE”中选择“MDK-ARM”,其他保持默认即可,具体如下图所示,

5、最左边选项切换到“Code Generator”,在右边的“STM32Cube MCU packages an embedded software packs”中有三个选项,意思分别为拷贝全部的库文件到工程目录中、仅拷贝需要的库文件到工程目录中、仅在工程文件中引用需要的库文件(库文件放在STM32CubeMX的安装目录中),我选择第二项,

6、设置时钟属性,点击STM32CubeMX工程窗口上方的“Project Manager”选项,在“HCLK(MHz)”中输入需要的时钟频率,按回车键,在弹出的提示中选择Ok便可,我输入STM32L552ZET6Q的最大时钟频率:110MHz,其他的保持默认:内部高速时钟16MHz和内部低速时钟32KHz,

7、配置点亮LED灯的GPIO,NUCLEO_L552ZE_Q开发板上共有三盏LED灯,分别为红绿蓝三色,根据原理图提供的信息,红绿蓝三盏等分别接在了单片机的PA9、PC7和PB7引脚,我选择了最经典的红色LED,在“Pinout & Configuration”中使用鼠标左键点击单片机模型上的PA9引脚(右侧从上往下数第8个引脚),在小窗口中选择“GPIO_Output”,至此,STM32CubeMX工程就配置好了。

04 保存STM32CubeMX工程  

点击上方菜单中的“File”,选择“Save Project”即可。

05 生成MDK-ARM工程  

鼠标左键单击右上方的“GENERATE CODE”,软件便可根据之前的配置自动生成一个代码工程,如果在第一步中创建的目录中有中文,在这一部生成代码工程的时候就会出现错误提示,导致工程创建失败,因此需要特别注意。

GPIO口电平输出功能:点亮一盏LED灯         01 了解一下工程的目录结构  

irvers:存放STM32的固件库以及ARM公司提供的CMSIS库,通常情况下不需要修改里面的文件内容;

inc:存放用户编写的.h文件,文件内容可修改;

MDK-ARM:存放MDK的工程文件,以及STM32的启动文件,文件内容通常情况下不需要修改;

src:存放用户编写的.c文件,文件内容可修改。

02    

D在MDK-ARM文件夹内,双击打开.uvprojx后缀的工程文件,不需要改动,直接链接一遍,看是否有问题,结果0错误、0警告。

03    

打开main.c文件,找到主函数main(),在主函数的while循环内添加如下代码,意思为每隔500ms对PA9引脚进行电平取反操作,让红色LED灯闪烁。

04 配置目标属性  

1、电机窗口上方的魔术棒,弹出配置窗口;

2、切换到“Debug”选项;

3、选择调试器,我使用ST-Link Debugger;

4、电机左侧的“Settings”

5、在弹出的窗口中切换到“Flash Download”选项,勾选“Reset and Run”,使得将程序烧录到单片机后就会自动复位并运行程序。

6、点击“确定”、“OK”确认修改后,再次编译链接工程,0错误0警告。

05 烧录程序  

1、使用一根Micro USB数据线链接电脑与开发板上的ST-Link USB-A口,如果还没安装驱动,可查看我上一期的帖子,末尾有附件,如果开发板上的LD4亮红色,LD6亮绿色,说明连接正常。

2、电机MDK软件左上角的下载按钮,开始将程序下载到单片机上运行。

3、观察运行情况,红色LED灯开始闪烁,说明GPIO口能够正常输出高低电平。

GPIO口电平输入功能:按键扫描         01 重新生成MDK-ARM工程  

将MDK-ARM工程关闭,根据原理图知道开发板上的USER按键连接在单片机的PC13引脚,回到STM32CubeMX工程,在“Pinout & Configuration”中使用鼠标左键点击单片机模型上的PC13引脚(芯片模型的左侧从上往下数第7个引脚),在小窗口中选择“GPIO_Input”,保存STM32CubeMX工程并且点击“GENERATE CODE”重新生成代码。

02 实现按键扫描代码  

1、打开MDK-ARM工程,在main.c源文件的主函数实现代码的开头添加如下代码,声明两个局部变量。

2、在主函数的while循环内添加如下代码,实现按键扫描和LED闪烁功能。

3、修改完之后,编译链接一遍代码,将代码烧录到开发板上,用手按开发板左下方的USER按键,观察红色LED的闪烁频率变化情况,实际情况如下:

仿位带操作:实现与51单片机一样的IO口操作方法

使用过正点原子Cortex_M3或者Cortex_M4系列单片机开发板的朋友都应该接触过位带操作功能,在Cortex_M3权威指南(中文)中的第5.5节有如下介绍

在CM3中,有两个区中实现了位带。其中一个是SRAM区的最低1MB范围,第二个则是片内外设区的最低1MB范围。这两个位带中的地址除了可以像普通的RAM一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。

文中所述的位带区与位带别名区有如下对应关系

STM32单片机的GPIO口地址就在片内外设区的最低1MB范围内,意思就是能够通过位带别名区中的每一个地址,操作到对应的片内外设区的外设寄存器中的一个bit,往位带别名区中的地址写1,则对应的片内外设区的外设寄存器中的相应位就会置1,读取位带别名区中的地址的值,就会返回对应的片内外设区的外设寄存器中的相应位的值,GPIO口的每一个Pin的电平就是由ODR寄存器中的每一个位来控制,以及通过IDR寄存器中的一个位来获取一个Pin的电平。但是,我查找过Cortex_M33的手册,并没有发现这个位带别名区,也就是Cortex_M33没有位带操作功能,但我可以通过自定义一个位域结构体来实现类似的操作,实现代码如下:

typedef struct

{

uint16_t OD0 : 1;

uint16_t OD1 : 1;

uint16_t OD2 : 1;

uint16_t OD3 : 1;

uint16_t OD4 : 1;

uint16_t OD5 : 1;

uint16_t OD6 : 1;

uint16_t OD7 : 1;

uint16_t OD8 : 1;

uint16_t OD9 : 1;

uint16_t OD10 : 1;

uint16_t OD11 : 1;

uint16_t OD12 : 1;

uint16_t OD13 : 1;

uint16_t OD14 : 1;

uint16_t OD15 : 1;

} ODR_TypeDef;

#define PAin(n) ( ( GPIOA->IDR&(1 << (n)) )>>n )

#define PBin(n) ( ( GPIOB->IDR&(1 << (n)) )>>n )

#define PCin(n) ( ( GPIOC->IDR&(1 << (n)) )>>n )

#define PDin(n) ( ( GPIOD->IDR&(1 << (n)) )>>n )

#define PEin(n) ( ( GPIOE->IDR&(1 << (n)) )>>n )

#define PFin(n) ( ( GPIOF->IDR&(1 << (n)) )>>n )

#define PGin(n) ( ( GPIOG->IDR&(1 << (n)) )>>n )

#define PAout(n)  ( ((ODR_TypeDef *)(&(GPIOA->ODR)))->OD##n )

#define PBout(n)  ( ((ODR_TypeDef *)(&(GPIOB->ODR)))->OD##n )

#define PCout(n)  ( ((ODR_TypeDef *)(&(GPIOC->ODR)))->OD##n )

#define PDout(n)  ( ((ODR_TypeDef *)(&(GPIOD->ODR)))->OD##n )

#define PEout(n)  ( ((ODR_TypeDef *)(&(GPIOE->ODR)))->OD##n )

#define PFout(n)  ( ((ODR_TypeDef *)(&(GPIOF->ODR)))->OD##n )

#define PGout(n)  ( ((ODR_TypeDef *)(&(GPIOG->ODR)))->OD##n )

可将此代码封装到一个头文件内供调用,使用方法同正点原子的源码一样。

总结        

可见,在STM32CubeMX的帮助下,实现一些基础的功能代码还是比较方便的,加之有HAL固件库的支持,无论单片机的底层寄存器如何变化,HAL固件库都已经统一封装成一致的函数名,使用起来也非常方便。本次测试的GPIO口操作,主要使用到了两个函数:HAL_GPIO_TogglePin和HAL_GPIO_ReadPin,两个函数的实现也比较简单,都是直接操作寄存器:

本次我们介绍了GPIO口的使用,由于篇幅已经太多了,花了一天时间才写完,等下次有空再介绍其他一些基本的功能。

打开APP阅读更多精彩内容

收藏

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉

相关话题

评论(0)

加载更多评论

分享到

QQ空间 QQ好友 微博
取消