stm32f103 GPIO—— 一灯大师之库函数版

最新更新时间:2022-09-30来源: csdn关键字:stm32f103  GPIO  库函数 手机看文章 扫描二维码
随时随地手机看文章

在使用库函数之前,我们先来看GPIO寄存器的结构体

该结构体中的成员,包含了引脚,输出速度,输出模式。我们可以使用这个结构体来对I/O口进行配置。

GPIO_InitTypeDef GPIO_InitStruct; //定义一个结构体,用来需要配置的寄存器信息


void LED_Config(void)

{    


     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);


    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;                        //配置的引脚为Pin6引脚

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;       //配置输出速度为2Mhz

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;      //配置输出模式为通用推挽输出

    GPIO_Init( GPIOC, &GPIO_InitStruct);                               //配置的I/O口组为GPIOC组                     //只要用到I/O口,就一定会用到GPIO_Init(); 函数


    


     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;           /*配置的引脚为Pin7引脚,由于输出速度与输出模式还在结构体里面。所以这里                                                                                        不用重新在配置一次 输出速度与输出模式 */

    GPIO_Init( GPIOC, &GPIO_InitStruct);                   //配置的I/O口组为GPIOC组


  


    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;            //配置的引脚为Pin8引脚

    GPIO_Init( GPIOC, &GPIO_InitStruct);                  //配置的I/O口组为GPIOC组

    


    LED_Close();//关灯



}


void LED_Open(void)        //开灯

{


    GPIO_WriteBit( GPIOC, GPIO_Pin_6, Bit_RESET);        //设置GPIOC的Pin_6引脚输出低电平

    GPIO_WriteBit( GPIOC, GPIO_Pin_7, Bit_RESET);

    GPIO_WriteBit( GPIOC, GPIO_Pin_8, Bit_RESET);

}


void LED_Close(void)        //关灯

{


    GPIO_WriteBit( GPIOC, GPIO_Pin_6, Bit_SET);        //设置GPIOC的Pin_6引脚输出高电平

    GPIO_WriteBit( GPIOC, GPIO_Pin_7, Bit_SET);

    GPIO_WriteBit( GPIOC, GPIO_Pin_8, Bit_SET);

}


实际上,关于初始化函数,我们还可以写成:

void LED_Config(void)

{    


    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);


    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;    //这里将各个引脚进行 | 操作,就可以一下配置多个引脚

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;    

    GPIO_Init( GPIOC, &GPIO_InitStruct);

        

    GPIO_WriteBit( GPIOC, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 , Bit_SET);     //关灯,这里也可以进行多个一起配置

    

}


为什么多个引脚可以一起配置呢?

我们可以看到16个引脚的宏定义的值是多少,那么这些值是怎么来的呢?

 我们用ODR寄存器来举例。如果只想要GPIO_Pin_1置1,那么ODR寄存器的值就是0000 0000 0001(即:0x0001),只想要GPIO_Pin_2置1,那么ODR寄存器的值就是0000 0000 0010(即:0x0002),只想要GPIO_Pin_3置1,那么ODR寄存器的值就是0000 0000 0100(0x0004),只想要GPIO_Pin_4置1,那么ODR寄存器的值就是0000 0000 1000(0x0008)


        以此类推,GPIO_Pin_5的ODR寄存器值为0000 0001 0000(0x0010)


                          GPIO_Pin_6的ODR寄存器值为0000 0010 0000(0x0020)


                          GPIO_Pin_7的ODR寄存器值为0000 0100 0000(0x0040)


                          GPIO_Pin_8的ODR寄存器值为0000 1000 0000(0x0080)


所以,我们看到,在寄存器中,每个引脚的设置值的位权分别是8、4、2、1(即BCD码)

我们知道:


        8 == 1000


        4 == 0100


        2 == 0010


        1 == 0001


它们相互进行位与操作,并不会影响各自的"1",即:不改变位权。利用这个特性,有如下代码来判断,哪个是哪个引脚:

上图是库函数关于GPIO_CRL寄存器中引脚配置的源码


我们来看Pin6与Pin7引脚,我们都知道Pin6与Pin7的选择都是在GPIO_CRL寄存器中配置

其中这一段代码,一开始pinpos为0,所以0x01<<0,即还是0x01,所以pos == 0x01,然后用前面的


(GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8)  &  0x01,如果与下来的结果为1,这样就可以判断是不是GPIO_Pin_1被选择了。


然后,下一次循环,pinpos + 1,则0x01<<1,则变成0x02,(GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8)  &  0x02,如果与下来的结果为1,这样就可以判断是不是GPIO_Pin_2被选择了。然后,如此循环,直到0x01<<8。这里只移动8位是因为该寄存器是低位寄存器,只配置Pin0~Pin7引脚。


所以:

我们只要在源码中看到某成员的宏定义数值为8、4、2、1这样的结构,我们就可以写成GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8这样进行赋值。所以,关灯也可以写成:GPIO_WriteBit( GPIOC, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 , Bit_SET);  


BCD码(Binary-Coded Decimal),用4位 二进制数 来表示1位 十进制数 中的0~9这10个数码,是一种二进制的数字编码形式,用 二进制编码的十进制 代码。. BCD码这种编码形式利用了四个位元来储存一个十进制的数码,使 二进制 和 十进制 之间的转换得以快捷的进行。. 这种编码技巧最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。. 相对于一般的 浮点 式 记数法 ,采用BCD码,既可保存数值的精确度,又可免去使计算机作浮点运算时所耗费的时间。. 此外,对于其他需要高精确度的计算,BCD编码亦很常用。


8421 BCD码是最基本和最常用的BCD码,它和四位自然二进制码相似,各位的权值为8、4、2、1,故称为有权BCD码。和四位自然二进制码不同的是,它只选用了四位二进制码中前10组代码,即用0000~1001分别代表它所对应的十进制数,余下的六组代码不用。


三色灯

如果有三色灯,我们还可将灯的颜色和点灯、关灯封装在一个函数内:(这样的话,想要打开某种颜色的灯时,就只调用这个函数就行了)


typedef enum LED_RGB{     //这里使用枚举来代替宏定义,当我们需要多次宏替换时候,就不要使用宏定义了,最好使用枚举

    LEDR=0x01,

    LEDG,

    LEDB


}LED_RGB_T;


typedef enum LED_STATUS{

    LED_OPEN=0x01,

    LED_CLOSE    


}LED_STATUS_T;


void LED_Config(void)

{

     GPIO_InitTypeDef  GPIO_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);



    GPIO_InitStruct.GPIO_Pin     =GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;

    GPIO_InitStruct.GPIO_Mode    =GPIO_Mode_Out_PP;

    GPIO_InitStruct.GPIO_Speed   =GPIO_Speed_2MHz;

    GPIO_Init(GPIOC,&GPIO_InitStruct);


    GPIO_SetBits(GPIOC,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8);


}


void LED_CTRL(LED_RGB_T LED,LED_STATUS_T LED_status )

{

    switch(LED){

        case LEDR:       

                if(LED_status==LED_OPEN){       

                    GPIO_ResetBits(GPIOC,GPIO_Pin_8);         //打开红灯

                }else{

                    GPIO_SetBits(GPIOC,GPIO_Pin_8);        //关闭红灯

                }

            break;

        case LEDG:       

                if(LED_status==LED_OPEN){         

                    GPIO_ResetBits(GPIOC,GPIO_Pin_7);        //打开绿灯

                }else{

                    GPIO_SetBits(GPIOC,GPIO_Pin_7);        //关闭绿灯

                }

            break;

        case LEDB:        

                if(LED_status==LED_OPEN){        

                    GPIO_ResetBits(GPIOC,GPIO_Pin_6);        //打开蓝灯

                }else{

                    GPIO_SetBits(GPIOC,GPIO_Pin_6);        //关闭蓝灯

                }

            break;

        default:

            break;

    }

}


int main(void)

{

    LED_Config();

    while(1){

        LED_CTRL(LEDR,LED_OPEN);         //打开红灯


        LED_CTRL(LEDR,LED_CLOSE);       //关闭红灯

    }

}

关键字:stm32f103  GPIO  库函数 编辑:什么鱼 引用地址:stm32f103 GPIO—— 一灯大师之库函数版

上一篇:stm32——端口重映射
下一篇:GPIO寄存器的地址怎么寻找

推荐阅读

STM32F103配置串口(USART)流程
1:设置中断分组 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);2:使能用作串口(RX/TX)的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE); //串口时钟和GPIO时钟都需要设置3:GPIO模式设置 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; //TX GPIO_InitStruct.GPIO_Mode = GPIO_Mode_A
发表于 2022-10-26
STM32学习之路-用STM32库函数配置RCCc
利用STM32提供的RCC函数配置RCC定义错误状态变量ErrorStatus HSEStartUp;初始化RCC状态寄存器RCC_DeInit();使能高速外部晶振HSERCC_HSEConfig(RCC_HSE_ON);参数有3个:RCC_HSE_OFF: HSE oscillator OFFRCC_HSE_ON: HSE oscillator ONRCC_HSE_Bypass: HSE oscillator bypassed with external clock等待高速外部晶振工作HSEStartUp = RCC_WaitForHSEStartUp();if (HSEStartUp == SUCCESS){FLASH_Pre
发表于 2022-10-20
51单片机基础之GPIO输出
代码:#include <reg52.h> //引用51单片机的头文件,包含寄存器等操作sbit LED=P2^0; //定义P2^0引脚,这属于位操作,等下用于输出高低电平,以便于点亮LED灯void delay(unsigned int u16)//unsigned是无符号类型,也就是非负数,这个函数可以实现0.6秒内的延时,本质上就是让CPU等待{ while(u16--);}void main(void) //主函数,程序都是从主函数开始执行的。{ while(1) //循环操作,一直执行程序 { LED=0;
发表于 2022-10-17
51单片机基础之<font color='red'>GPIO</font>输出
51单片机基础之GPIO输入
代码:#include <reg52.h> //引入头文件sbit KEY=P3^1; //定义一个按键sbit LED=P2^0; //定义一个LED灯void delay(unsigned int u16) //延时函数,0.6秒以内的延时{ while(u16--);}void main(void) //主函数,程序从这里执行{ while(1) //代码循环执行 { if(KEY==0) //检车按键是否按下,之所以检测是否等于低电平,是因为按键另一边连着地
发表于 2022-10-17
51单片机基础之<font color='red'>GPIO</font>输入
兆讯216兆M3内核MCU,MH2103ACCT6完美替代STM32F103C8T6/CBT6
兆讯恒达软硬件完美替代F103/105系列,F103系列等 MH2103CCCT6/MH2103ACCT6 MH2103ARPT6 MH2103AVET6 MH2103AVGT6 MH2103AZET6 主频216兆 内置的存储器包括:最大1024K Flash,96K S 该系列内置了多达2个高级、10个通用定时器、2个基本定时器、3个12位的、2个12位的, 还包含标准和先进的通信接口包括:3个S接口、2个I2S接口、2个接口、5个U(S)ART接口、1个2.0 全速串行通信接口、1个总线控制器、1个O接口 MH2103A(C)xxxx系列工作于-40℃至+85℃的温度范围,供电电
发表于 2022-10-17
STM32F103ZE+SHT30检测环境温度与湿度(IIC模拟时序)
一、环境介绍工程编译软件: keil5温湿度传感器: SHT30MCU : STM32F103ZET6程序采用模块化编程,iic时序为一个模块(iic.c 和 iic.h),SHT30为一个模块(sht30.c 和 sht30.h);IIC时序采用模拟时序方式实现,IO口都采用宏定义方式,方便快速移植到其他平台使用。工程源码完整下载地址: https://download.csdn.net/download/xiaolong1126626497/18973724二、SHT30介绍特点:1. 湿度和温度传感器2. 完全校准、线性化和温度3. 补偿数字输出,宽电源电压范围,从2.4 V到5.5 V4. I2C接口,通信速度高达1MHz和
发表于 2022-10-13
<font color='red'>STM32F103</font>ZE+SHT30检测环境温度与湿度(IIC模拟时序)
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved