历史上的今天
返回首页

历史上的今天

今天是:2025年06月11日(星期三)

正在发生

2020年06月11日 | STM32自学笔记(一)GPIO配置与使用

2020-06-11 来源:eefocus

由于是stm32学习的第一个章节,会啰嗦一些,旨在帮助和我一样刚接触stm32时一头雾水的朋友,更好地理解、学会它。


很多学过51,刚开始学stm32的朋友可能会和我一样十分不适应,在我看来,stm32与51代码最大的区别在于,stm32几乎所有外设都要进行配置过后才能使用,比如说你想操作一个IO口,那么首先要对这个IO口所挂载的时钟进行使能,再对此IO口进行配置、使能。这也是为什么51点亮一个LED只需要一行代码,你找到的stm32的代码却看着都让人头大的原因。



为什么要进行初始化(配置)?就GPIO来说,51的IO口很简单,能且只能实现高低电平的输入输出;而stm32可以在此基础上,指定GPIO输入输出的类型,速率等一系列参数,正因为stm32可以实现更多的功能,因此要进行初始化,指定GPIO的参数。实际上配置完成后,就使用上来说是不会比51复杂到哪去的。因此,先耐着性子学会GPIO的配置吧。


认识GPIO初始化

首先要适应这种stm32的代码风格:对每个模块都写一个xxx_Init()函数进行初始化(配置)。至于这个函数里要写些什么,视这个模块用到哪些功能而定。比如说我想写一个程序控制LED的亮灭,需要用到GPIO,所以要做以下的事情:对GPIO的时钟进行使能、对GPIO进行初始化。把这两个过程写在一个名为LED_Init()的函数中,这样只需要在main()中调用一下LED_Init()就可以实现LED模块的初始化了。



本章仅讲解GPIO的初始化,其他功能怎么初始化在以后的章节中会进行讲解。


首先,我们要认识下面这个结构体:GPIO_InitTypeDef


typedef struct 

{  

    uint16_t GPIO_Pin;     

    GPIOSpeed_TypeDef GPIO_Speed;    

    GPIOMode_TypeDef GPIO_Mode;  

}GPIO_InitTypeDef; 


它具有三个成员变量:GPIO_Pin,  GPIO_Speed,  GPIO_Mode


对于GPIO的配置其实就是指定这三个参数的值。接下来通过一个实例讲解这三个变量的含义。


GPIO_InitTypeDef  GPIO_InitStructure; 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  //LED0-->PB.5 端口配置 

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出 

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度 50MHz 

GPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数配置 GPIO 


这便是GPIO初始化的常用格式(事实上stm32任何外设的初始化都可以参照这种格式)


1.首先,要实例化一个GPIO_InitTypeDef对象,名为GPIO_InitStructure。


2.接下来对它的三个成员变量进行配置。其中GPIO_Pin用来设置是要初始化哪个或者哪些IO口(这里要注意,决定的不是A、B、C...,而是GPIOx后面的数字,也就是16个引脚中的哪一个); GPIO_Mode 是用来设置输出输入模式(GPIO共有8种模式,这里用到的是推挽输出);GPIO_Speed 是IO口速度设置,有2M、10M、50M三个可选值。


3.最后,调用一下GPIO_Init()函数,GPIO的初始化就完成了。GPIO_Init()第一个参数填GPIOx,也就是确定A、B、C...,结合前面设置的GPIO_Pin,就确定了具体是哪一个IO口;第二个参数填 &GPIO_InitStructure,将我们之前设置好的参数通过GPIO_InitStructure这个对象输入进去,实现GPIO的初始化。


完整的GPIO初始化流程

接下来给出一个完整的GPIO初始化实例,用了两个IO口(PB5、PE5)分别控制两个LED。


void LED_Init(void)

{

 GPIO_InitTypeDef  GPIO_InitStructure;

                        //GPIO_InitTypeDef结构体用于配置GPIO,首先实例化一个它的对象

 

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB、PE端口的时钟

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz

 GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定的参数初始化GPIOB.5

 GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高电平

 

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;     //LED1-->PE.5 端口配置

 GPIO_Init(GPIOE, &GPIO_InitStructure);   //推挽输出,IO口速度为50MHz

    //这里虽然配置的是另一个IO口PE.5,但仍旧使用了上面配置PB.5时的对象,是因为两个IO参数一样,若出现参数不一样的情况,要重新实例化一个对象(或者更改之前对象的参数)

 GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高电平

}


认真理解这段代码。其中有两句代码是之前没有提到过的,分别是时钟的使能与GPIO_SetBits() 这个函数。



GPIO 是挂载在 APB2 总线上的外设,在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的,至于其他情况下时钟使能是什么函数,在以后的章节中会提到。



至于GPIO_SetBits() 在下文进行讲解。


IO口操作

GPIO配置完成后,就可以对IO口进行操作了。常用两种方式进行操作,效果是一样的。


寄存器版

在sys.h中有以下定义


#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出

#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

......

//这里由于篇幅关系仅给出GPIOB的定义,其余GPIO端口都有类似定义


这使IO口的操作变得和51一样简单


#define LED PBout(5) //define下提高程序可读性

...

LED = 1; //输出高电平

LED = 0; //输出低电平

LED_in = PBin(5); //读取PB.5电平


可以直接用PBout(5)=1进行GPIOB.5的高电平输出,也可以像51一样先宏定义改个名称,增强可读性。


库函数版

//输出

GPIO_SetBits(GPIOB,GPIO_Pin_8); //PB.8输出高电平

GPIO_ResetBits(GPIOB,GPIO_Pin_8); //PB.8输出低电平

//输入

GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) //读取PE.2电平

Tips:操作IO口前,必须先进行对应的GPIO初始化

推荐阅读

史海拾趣

Hsuan Mao Technology Co公司的发展小趣事

Hong Kong X'Tals Ltd在电子行业的发展故事

故事一:精密时间与频率产品的创新之路

Hong Kong X'Tals Ltd(简称HKC)自1991年成立以来,一直致力于精密时间和频率产品的研发与生产。公司最引人注目的成就是其KSTAR系列全球导航卫星系统(GNSS)驯服振荡器(GNSSDO)的推出。这款新产品不仅接收来自北斗、GPS、GLONASS和GALILEO等多卫星系统的信号,还具备高灵敏度和低噪声的特点,长期频率稳定性优于1E-12。KSTAR系列GNSSDO的推出,标志着HKC在通讯、自动驾驶、能源和金融等领域的时间同步解决方案上达到了国际领先水平。这一创新不仅增强了公司在全球市场的竞争力,也为众多行业客户提供了更加精准和可靠的时间同步服务。

故事二:从石英晶体到国际市场的跨越

HKC的母公司Kolinker Industrial Equipments Ltd拥有超过13年的中国晶体行业经验,并在深圳设立了首家中国本地的晶体工厂,该工厂荣获QS9000和ISO/TS16949认证。这一成就不仅体现了HKC在晶体制造领域的专业实力,也为其产品打入国际市场奠定了坚实的基础。HKC凭借其高质量的石英晶体产品,成功进入东欧、日本、韩国、中国大陆、北美、台湾和西欧等市场,成为国际市场上备受瞩目的晶体产品供应商。

故事三:技术研发与产品多元化的并行发展

HKC深知技术研发对于企业发展的重要性,因此不断加大在研发领域的投入。公司不仅专注于晶体、谐振器和振荡器的研发与生产,还积极拓展产品线,推出了一系列满足不同行业需求的电子产品。例如,在工业自动化领域,HKC设计并制造了多款机电一体化设备,赢得了国内外众多知名家电制造商的青睐。此外,公司还涉足新能源行业,通过投资组建益阳晶鑫新能源科技实业有限公司,致力于多晶硅产业链的建设与发展。

故事四:品质管理与国际认证的双重保障

HKC始终将品质管理视为企业发展的生命线。公司早在2000年和2003年就分别通过了ISO9002 1994及ISO9001 2000质量管理体系认证,成为同行业中最具实力的公司之一。这一系列的国际认证不仅证明了HKC在品质管理方面的卓越表现,也为其赢得了国内外客户的广泛信赖。HKC始终坚持以客户为中心,不断提升产品品质和服务水平,努力成为电子行业的佼佼者。

故事五:全球化战略与本土化运营的有机结合

随着全球市场的不断扩大,HKC积极实施全球化战略,在全球多个地区设立分公司和生产基地。同时,公司也注重本土化运营,根据不同地区的市场特点和客户需求,提供定制化的产品和服务。例如,HKC在中国内地市场就设立了多家子公司和生产基地,通过深入了解本地市场需求和客户需求,不断优化产品结构和服务模式,赢得了中国市场的广泛认可。这种全球化战略与本土化运营的有机结合,为HKC的可持续发展提供了强有力的支撑。

B&K Precision公司的发展小趣事

为了进一步拓展国际市场,B&K Precision在全球范围内设立了多个分公司和办事处。其中,2012年在中国设立的分公司百科中国仪器有限公司是一个重要的战略布局。这一举措不仅加强了公司在亚洲市场的地位,也为各地客户提供了更为迅速和便捷的售后服务保障。同时,通过与国际知名企业的合作与交流,B&K Precision不断吸收先进的技术和管理经验,为公司的持续发展注入了新的动力。

以上五个故事,展现了B&K Precision公司从车库起步到成为全球电子测量领域领导者的发展历程。通过不断创新和拓展业务,公司成功应对了市场变化和挑战,成为了电子行业中的佼佼者。

DOMINANT公司的发展小趣事

随着公司业务的不断发展,统明亮开始积极拓展全球市场。它通过与国内外知名企业的合作,不断提升自身的品牌影响力和市场竞争力。同时,统明亮还积极参加各类国际展会和交流活动,与全球各地的客户建立了紧密的合作关系。这些努力使得统明亮在全球LED市场中的份额不断扩大,其品牌影响力也得到了进一步提升。

请注意,由于篇幅限制,以上仅为三个简要故事。如果需要更多关于DOMINANT公司的发展故事,建议查阅相关报道和资料。

Force Technologies Ltd公司的发展小趣事

背景:在电子行业竞争日益激烈的背景下,Force Technologies Ltd意识到通过并购整合可以迅速扩大规模、提升竞争力。

发展:公司精心挑选了几家在特定领域具有优势的企业作为并购目标,并成功完成了多起并购案。这些并购不仅为公司带来了先进的技术和人才资源,还极大地丰富了产品线和市场布局。通过并购整合,Force Technologies Ltd在多个细分领域均占据了领先地位。

Everspin Technologies公司的发展小趣事

Everspin一直致力于MRAM技术的创新和发展。其中,自旋转移力矩MRAM(STT-MRAM)是该公司的重要技术之一。Everspin在平面内和垂直磁隧道结(MTJ)STT-MRAM位单元的开发方面取得了显著成果,并积累了超过600项有效专利和应用的知识产权组合。这些技术的创新和专利的积累,使得Everspin在MRAM市场中保持了领先地位。

Dytran Instruments Inc公司的发展小趣事

1980年,Dytran由传感器行业的资深人士尼古拉斯·D.改变(Nicholas D. Change)创立。在此之前,尼古拉斯在纽约地区的一家开创性传感器制造商担任产品线经理,积累了丰富的行业经验。他看到了传感器市场的巨大潜力,于是决定成立自己的公司,将自己的设计和创新带入这个不断增长的领域。Dytran的名字来源于“动态”和“换能器”的结合,寓意着公司专注于动态测量和转换技术的研发。

在创业初期,Dytran就展现出了其技术实力。公司专注于压电加速度计的研发和生产,凭借其卓越的性能和稳定性,迅速在市场上崭露头角。此后,Dytran不断推出新的传感器产品,如称重传感器、压力传感器和脉冲锤等,逐渐在电子行业树立了其技术领先的形象。

问答坊 | AI 解惑

降低噪声与干扰

降低噪声与干扰 1)  能用低速芯片就不用高速的,高速芯片用在关键地方。 (2)  可用串一个电阻的办法,降低控制电路上下沿跳变速率。 (3)  尽量为继电器等提供某种形式的阻尼。 (4)  使用满足系统要求的 ...…

查看全部问答>

使用AVR实现的频谱分析仪--DIY类型

老外做的一个频谱分析仪分享下:http://elm-chan.org/works/rsm/report_e.html…

查看全部问答>

如何自动隐藏任务栏与开始菜单?

WINCE启动后,要求自动隐藏任务栏与开始菜单。请问通过设置哪里来实现?…

查看全部问答>

如何实现485通信

pc机经232-〉485转换器,后和多台485设备双向通信,我写过232的,对于485不清楚。 请问: (1)这个应该是全双工方式还是半双工方式? (2)如果是半双工如何知道现在有没有485设备占用通信线路? (3)如果发送不成功怎么知道?怎么办?再 ...…

查看全部问答>

isd4002

本帖最后由 paulhyde 于 2014-9-15 08:56 编辑 请问怎样将录音放到指定的地址?  …

查看全部问答>

我的EK-LM3S811-ND Rev2 无法download 和debug

按照LM3S811 TI Evaluation kit光盘资料中的LM3S811EVALUATION KIT README FIRST安装驱动,安装后和资料里显示是驱动名称不一样. 资料讲的是LM3S811 Virtual COM Port(com6).”而我安装后显示\"stellaris ICDI Debug port(COM15)\",\"\"stellaris IC ...…

查看全部问答>

在EPWM中断的设置中为什么要对FLAGH寄存器进行操作啊

求助!!!在下面的程序中,在对EPWM中断的设置中,为什么还要对flash进行操作呢? interrupt void epwm1_timer_isr(void) {    // Put the Flash to sleep    FlashRegs.FPWR.bit.PWR = FLASH_SLEEP;    EPwm1 ...…

查看全部问答>