STM32L552开发板——GPIO

这次是针对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 )
#define pbin(n) ( ( gpiob->idr&(1 n )
#define pcin(n) ( ( gpioc->idr&(1 n )
#define pdin(n) ( ( gpiod->idr&(1 n )
#define pein(n) ( ( gpioe->idr&(1 n )
#define pfin(n) ( ( gpiof->idr&(1 n )
#define pgin(n) ( ( gpiog->idr&(1 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口的使用,由于篇幅已经太多了,花了一天时间才写完,等下次有空再介绍其他一些基本的功能。

5G即将到来的前夜,运营商承受的压力还将如何继续呈现?
三极管常见分类简介
人脸识别再次发狠 面部被覆盖的人依旧没问题
漫谈笔记本电脑的音质音效
智能制造领域亮点频现、佳音频传,智慧化技术突飞猛进
STM32L552开发板——GPIO
报名开启 | 共赴一场 Flutter 的春日宴
从0到1 微硕开发出一系列高性能功率系磁材
四大创新基础技术驱动雷达技术的发展
沁恒股份USB转4串口芯片CH9344概述
新能源汽车自动驾驶的六个级别
2016 PXI TAC 关注行业应用,应对更智能的测试需求
Fluence宣布与远景动力签署储能电池采购协议
方管的优势特点是什么,它的用途都有哪些
工业机器人市场年增长25% 核心技术匮乏制约中国厂商
45个Git经典操作场景,助你一臂之力
小米宣布21日发布小米电视4, 小米平板3配置泄露
人脸识别给社会带来的复杂影响,人脸识别应该不被滥用
对低功耗的需求很高
虚拟现实大热融资新品不断 未来几年vr头显销量增长率为50%