STM32初学笔记(三)单个GPIO引脚操作
搭建完成项目框架后,来实现一个基本的GPIO操作,使引脚输出高低电平。除了本篇文章提到的3种方法以外,STM32还可以使用一种叫做位绑定的方法,这里暂时不用。 嵌入式程序开发主要分为两大类:(1)直接操作寄存器;(2)调用库函数。直接操作寄存器,开发难度大、速度慢、程序不便于阅读和移植等,51单片机就是使用这种开发方式,本篇文章的前两个引脚操作方法也是这种方式;库函数开发方式是开发者调用封装好的库函数接口,不直接操作寄存器,上一篇中创建的工程项目就是基于标准库的。 本篇文章主要内容: 1、直接操作端口寄存器 2、通过位操作寄存器 3、通过库函数操作 1、直接操作端口寄存器 操作寄存器必须对STM32各个寄存器功能,需要仔细学习芯片的参考手册相关内容。 以STM32F103为例,它有5个GPIO端口为A、B、C、D、E,每个端口有2个控制寄存器端口配置低寄存器(GPIOx_CRL)和端口配置高寄存器(GPIOx_CRH),1个端口输入数据寄存器(GPIOx_IDR),1个端口输出数据寄存器(GPIOx_ODR),以及一些其他的寄存器。 操作GPIOA端口,共有16个引脚,每个引脚需要控制寄存器中的4位来控制工作模式,所以需要两个32位的控制寄存器。 - //1、设置GPIOA.0的工作模式,推挽输出最大50MHz
- //2、设置引脚输出一个高电平
- GPIOA->CRL = 0X03;
- GPIOA->ODR = 0X01;
-
- //1、设置GPIOA.8的工作模式,推挽输出最大50MHz
- //2、设置引脚输出一个高电平
- GPIOA->CRH = 0X03;
- GPIOA->ODR = 0X10;
复制代码
2、通过位操作寄存器 第1部分的操作,看似只对一位进行了设置,但是事实上对整个寄存器进行了操作,GPIOA端口的其他引脚的输出也会被改变。若要不改变其他的引脚输出,需要对寄存器当前值进行逻辑运算后再写入寄存器。 STM32的GPIO端口还提供了专门的位操作寄存器,端口位设置/复位寄存器(GPIOx_BSRR)和端口位复位寄存器(GPIOx_BRR),每一位对应一个引脚,1表示对该位进行操作,0表示不造作,不改变对应位的当前值。 - //1、设置GPIOA.0的工作模式,推挽输出最大50MHz
- //2、设置引脚输出一个高电平
- GPIOA->CRL = 0X03;
- GPIOA->BSRR = 0X01;
复制代码
3、通过库函数操作 调用库函数需要根据库函数手册了解函数的功能和参数,可以通过网络搜索下载固件库手册。 用到引脚的初始化函数,参数为引脚名称(如GPIOA)和初始化结构体;用到读输入数据函数、置位函数和复位函数。熟悉C语言的话,程序理解起来会很容易,未涉及任何计算。即使不了解硬件,从函数名和赋值的参数也能够大概理解每一句的含义,如果对硬件有基本的了解,那么理解的会更好。 相比于前两种方法来说,调用库函数省却了很多基础的运算,编写的代码经过长时间以后仍然能够很快看懂,其他人编写的代码也很容易读懂,便于借鉴交流。初学者会觉得函数太多,在了解硬件的知识以外,还得了解很多函数,很繁琐,很混乱;但学习库函数是一个磨刀不误砍柴工的事情,对于项目开发和维护非常方便。 - int main(void)
- {
- //初始化端口,参数是一个结构体数据
- //GPIOA的低8位设置为推挽输出,高8位设置为浮空输入
- //设置多个引脚时,使用或运算对各个引脚同时初始化
- GPIO_InitTypeDef GPIOAstruct1;
- GPIO_InitTypeDef GPIOAstruct2;
-
- GPIOAstruct1.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIOAstruct1.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
- GPIOAstruct1.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIOAstruct1);
-
- GPIOAstruct2.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIOAstruct2.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
- GPIOAstruct2.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIOAstruct2);
- /*
- 实现一个简单的功能,读取高8位引脚的值,对相应的低8位(0-8,1-9,...)进行置位1和复位0操作
- 使对应引脚电平相同
- */
- while (1)
- {
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_0);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_0);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_1);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_1);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_2);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_2);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_3);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_3);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_12) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_4);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_4);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_5);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_5);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_6);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_6);
-
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == 1) GPIO_SetBits(GPIOA, GPIO_Pin_7);
- else GPIO_ResetBits(GPIOA,GPIO_Pin_7);
-
- }
-
- return 0;
- }<span style="background-color: rgb(255, 255, 255);"> </span>
复制代码
文章出处:樊学谦 机械智者
|