gpio(general-purpose input/output)是通用输入输出端口的简称,cks32f4xx系列产品通过gpio引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集的功能。最基本的输出功能是由cks32f4xx系列产品控制引脚输出高、低电平,实现开关控制,如把gpio引脚接入到led灯,那就可以控制led灯的亮灭,引脚接入到继电器或三极管,那就可以通过继电器或三极管控制外部大功率电路的通断。最基本的输入功能是检测外部输入电平,如把 gpio引脚连接到按键,通过电平高低区分按键是否被按下。
gpio硬件结构框图
该图从最右端看起,最右端标注着“i/o”的就是代表cks32f4xx系列产品引出的gpio引脚,其余部件都位于芯片内部。引脚处的两个保护二级管可以防止引脚外部过高或过低的电压输入,当引脚电压高于vdd_ft时,上方的二极管导通,当引脚电压低于vss时,下方的二极管导通,由此可以防止不正常电压引入芯片导致芯片的烧毁。这里要特别注意vdd_ft 代表io口兼容3.3v和5v,如果没有标注“ft”,就代表着不兼容5v。在芯片数据手册的引脚定义中,会看到有“电平i/o”一列,有ft标注的即为支持5v,如下图所示:
标号1处是上拉、下拉电阻,从它的结构我们可以看出,通过上、下拉对应的开关配置,我们可以控制引脚默认状态下的电压,开启上拉的时候引脚电压为高电平,开启下拉的时候引脚电压为低电平。同时也可以设置“既不上拉也不下拉模式”,我们也把这种状态称为浮空模式。
标号2处是一个由p-mos和n-mos管组成的单元电路。这个结构使gpio具有了“推挽输出”和“开漏输出”两种模式。上方的p-mos管高电平导通,低电平关闭,下方的n-mos低电平导通,高电平关闭。
标号3处是输出数据寄存器,它为标号2处的双mos管结构电路提供输入控制信号,因此通过修改输出数据寄存器的值就可以修改gpio引脚的输出电平。而图中“置位/复位寄存器 gpiox_bsrr”可以通过修改输出数据寄存器的值从而影响电路的输出。
标号4处是复用功能输出,“复用”是指cks32f4xx系列产品的其它片上外设可以对gpio引脚进行控制,此时gpio引脚用作该外设功能的一部分,算是第二用途。例如我们使用usart串口通讯时,需要用到某个gpio引脚作为通讯发送引脚,这个时候就可以把该gpio引脚配置成usart串口复用功能,由串口外设控制该引脚,发送数据。
标号5处是输入数据寄存器,它连接到图中的ttl施密特触发器,触发器的基本原理是当输入电压高于正向阈值电压时,输出为高;当输入电压低于负向阈值电压时,输出为低;io口信号经过触发器后,模拟信号转化为0和1的数字信号,也就是高低电平,并且是ttl电平协议, 然后存储在“输入数据寄存器。因此,通过读取该寄存器就可以了解gpio引脚的电平状态。
标号6处是复用功能输入,与“复用功能输出”模式类似,同样,如果我们使用usart串口通讯时,需要用到某个gpio引脚作为通讯接收引脚,这个时候就可以把该gpio引脚配置成usart串口复用功能,使usart可以通过该通讯引脚接收远端数据。
标号7处是模拟输入输出,当 gpio引脚用于adc采集电压的输入通道时,用作“模拟输入”功能,此时信号是不经过施密特触发器的,因为经过施密特触发器后信号只有0、1 两种状态,所以adc外设要采集到原始的模拟信号,信号源输入必须在施密特触发器之前。同样的,当 gpio引脚用于dac作为模拟电压输出通道时,此时作为“模拟输出”功能,dac 的模拟信号输出就不经过双mos管结构了,在gpio结构框图的右下角处,模拟信号直接输出到引脚。
gpio的工作模式
- 4种输入模式 -
1.浮空输入
浮空输入状态下,io的电平状态是不确定的,完全由外部输入决定。如果在该引脚悬空的情况下,读取该端口的电平是不确定的。
2.上拉输入
在该模式下,如果io口外部没有信号输入或者引脚悬空,io口默认为高电平。如果i/o口输入低电平,那么引脚就为低电平,mcu读取到的就是低电平。
3.下拉输入
在该模式下如果io口外部没有信号输入或者引脚悬空,io口默认为低电平,如果i/o口输入高电平,那么引脚就为高电平,mcu读取到的就是高电平。
4.模拟功能
当gpio用于模拟功能时,引脚的上、下拉电阻是不起作用的,这个时候即使配置了上拉或下拉模式,也不会影响到模拟信号的输入输出。除了adc和dac要将io配置为模拟功能模式之外,其他外设功能一律要配置为复用功能模式。
- 4种输出模式 -
1.开漏输出(带上拉或者下拉)
在该模式下,若mcu控制输出为高电平1时,输出指令是不会起到作用的。此时i/o端口的电平就不会由输出的高电平决定,而是由i/o端口外部的上拉或者下拉决定,如果没有上拉或者下拉,io口就处于高阻态。虽然通过软件设置内部上拉,也可以输出高电平,但是cks32f4xx系列产品内部上拉是弱上拉,即通过此上拉输出的电流是很弱的,驱动能力很弱。但是在该模式下,当mcu控制输出为低电平0时,即使没有上拉或者下拉,i/o端口也会输出低电平。另一方面,在开漏模式下,施密特触发器是打开的,即输入可用,可以通过输入数据寄存器gpiox_idr读取i/o的实际状态。开漏输出主要有以下两点作用:
a. i/o端口设置成开漏输出模式时,可以用来连接不同电平的器件,用来匹配电平,因为开漏引脚不连接外部的上拉电阻时,只能输出低电平,如果需要同时具备输出高电平的功能,则需要接上拉电阻。因此我们通过改变上拉电源的电压,便可以改变传输电平。比如通过加上上拉电阻就可以提供ttl电平-cmos电平的输出。
b.当多个设置为开漏输出的引脚连接到一条总线上时。通过外加一个上拉电阻,在不增加任何器件的情况下,这些引脚形成了“与逻辑”关系,即“线与”。如果有一个引脚输出为逻辑0,相当于接地,那么与之并联的回路“相当于被一根导线短路”,所以总线上的逻辑电平便为0。只有都为高电平时,总线上的电平才为1。在iic通信中,引脚通常设置为开漏输出模式。
2.复用开漏输出(带上拉或者下拉)
此时gpio复用为其他外设,输出数据寄存器gpiox_odr无效;即输出的高低电平来源于其它外设,除了输出信号的来源改变之外,其他的与开漏输出功能相同。
3.推挽输出(带上拉或者下拉)
在该模式下,如果我们控制输出为0,低电平,则i/o端口的电平就是低电平。若控制输出为1,高电平,则i/o端口的电平就是高电平。此时,外部上拉和下拉的作用是控制在没有输出io口的默认电平。在该模式下,施密特触发器也是打开的,即输入可用,通过输入数据寄存器gpiox_idr可读取i/o的实际状态。
4.复用推挽输出(带上拉或者下拉)
此时gpio复用为其他外设,输出数据寄存器gpiox_odr无效;即输出的高低电平来源于其它外设,除了输出信号的来源改变之外,其他的与推挽输出功能相同。
- 4种输出速度 -
1. 2mhz(低速)
2. 25mhz(中速)
3. 50mhz(快速)
4. 100mhz(高速)
gpio的引脚速度又称输出驱动电路的响应速度,即一个驱动电路可以不失真地通过信号的最大频率。比如信号频率为10mhz,而我们把gpio速度配置成了2mhz,则10mhz的方波很可能就变成了正弦波,发生了失真。芯片内部在i/o口的输出部分安排了多个响应速度不同的输出驱动电路,我们可以根据自己的需要选择合适的驱动电路,通过选择速度来选择不同的输出驱动模块,达到最佳的噪声控制和降低功耗的目的。因为gpio口的速度配置越高,噪声越大,功耗也越大。比如在usart串口通信中,若最大波特率只需115.2k,那用2m的速度就够了,既省电,噪声也小;而在spi接口中,若使用18m或9m的波特率,则需要选用50m的gpio的引脚速度。
注意:cks32f407用于配置pa13输出速度的gpioa_ospeedr寄存器的端口 13配置位(gpioa_ospeedr_ospeedr13[1:0])初始值为00,即pa13的i/o输出速度默认为低速。因此客户在实际使用cks32f407时,要按照参考手册中的介绍来配置gpioa_ospeed寄存器中 ospeedr13[1:0]位,从而来选择pa13的i/o输出指定的速度。
gpio的配置
接下来我们讲解如何利用cks32f4xx系列固件库对gpio口的工作模式进行配置。首先,固件库中定义了一个如下的结构体:
typedef struct{ uint32_t gpio_pin; gpiomode_typedef gpio_mode; gpiospeed_typedef gpio_speed; gpiootype_typedef gpio_otype; gpiopupd_typedef gpio_pupd; } gpio_inittypedef;
通过对该结构体成员中各个变量的初始化,就可以完成对2.2小节中所讲的gpio口的工作模式配置。结构体中各个成员变量的介绍及初始化时可被赋的值如下:
1)gpio_pin:用来选择要控制的gpio引脚,在标准库函数中可选择的值及其定义如下:
#define gpio_pin_0 ((uint16_t)0x0001) #define gpio_pin_1 ((uint16_t)0x0002) #define gpio_pin_2 ((uint16_t)0x0004) #define gpio_pin_3 ((uint16_t)0x0008) #define gpio_pin_4 ((uint16_t)0x0010) #define gpio_pin_5 ((uint16_t)0x0020) #define gpio_pin_6 ((uint16_t)0x0040) #define gpio_pin_7 ((uint16_t)0x0080) #define gpio_pin_8 ((uint16_t)0x0100) #define gpio_pin_9 ((uint16_t)0x0200) #define gpio_pin_10 ((uint16_t)0x0400) #define gpio_pin_11 ((uint16_t)0x0800) #define gpio_pin_12 ((uint16_t)0x1000) #define gpio_pin_13 ((uint16_t)0x2000) #define gpio_pin_14 ((uint16_t)0x4000) #define gpio_pin_15 ((uint16_t)0x8000) #define gpio_pin_all ((uint16_t)0xffff)
2) gpio_mode:用来设置已经选择的gpio引脚的模式,在标准库函数中可选择的值及其定义如下:
typedef enum{ gpio_mode_in = 0x00, /*!设置为输入模式 */ gpio_mode_out = 0x01, /*!设置为输出模式*/ gpio_mode_af = 0x02, /*!设置为复用模式 */ gpio_mode_an = 0x03 /*!设置为模拟模式*/}gpiomode_typedef;
3) gpio_speed:用来设置已经选择的gpio引脚的速度,在标准库函数中可选择的值及其定义如下:
#define gpio_speed_2mhz gpio_low_speed #define gpio_speed_25mhz gpio_medium_speed #define gpio_speed_50mhz gpio_fast_speed #define gpio_speed_100mhz gpio_high_speed
4) gpio_otype:用来设置已经选择的gpio引脚的输出模式,只有输出模式才需要该配置,输入模式下不需要该配置。在标准库函数中可选择的值及其定义如下:
typedef enum{ gpio_otype_pp = 0x00, /*!设置为推挽输出模式 */ gpio_otype_od = 0x01 /*!设置为开漏输出模式 */}gpiootype_typedef;
5) gpio_pupd:用来设置已经选择的gpio引脚的上下拉,在标准库函数中可选择的值及其定义如下:
typedef enum{ gpio_pupd_nopull = 0x00, /*!设置为既不上拉也不下拉/浮空模式 */ gpio_pupd_up = 0x01, /*!设置为上拉模式*/ gpio_pupd_down = 0x02 /*!设置为下拉模式*/}gpiopupd_typedef;
根据上面所讲解的配置方法,我们讲解标准库下的3个实际配置实例。
1) 作为普通的gpio口输出,控制led灯的亮灭,其gpio口初始化函数如下:
void led_gpio_init(void){ gpio_inittypedef gpio_initstructure; rcc_ahb1periphclockcmd(rcc_ahb1periph_gpiof,enable);//使能gpiof时钟 gpio_initstructure.gpio_pin = gpio_pin_2;//led1对应的io口 gpio_initstructure.gpio_mode = gpio_mode_out;//输出模式 gpio_initstructure.gpio_otype = gpio_otype_pp;//推挽模式 gpio_initstructure.gpio_speed = gpio_speed_100mhz;//速度100mhz gpio_initstructure.gpio_pupd = gpio_pupd_up;//上拉 gpio_init(gpiof, gpio_initstructure);//初始化gpio}
2) 复用为can外设的输出。
void can1_gpio_init(void){ gpio_inittypedef gpio_initstructure; rcc_ahb1periphclockcmd(rcc_ahb1periph_gpioa, enable);//使能porta时钟 gpio_initstructure.gpio_pin = gpio_pin_11| gpio_pin_12; gpio_initstructure.gpio_mode = gpio_mode_af; //复用功能 gpio_initstructure.gpio_otype = gpio_otype_pp;//推挽输出 gpio_initstructure.gpio_speed = gpio_speed_100mhz;//100mhz gpio_initstructure.gpio_pupd = gpio_pupd_up; //上拉 gpio_init(gpioa, gpio_initstructure);//初始化pa11,pa12 gpio_pinafconfig(gpioa,gpio_pinsource11,gpio_af_can1); //gpioa11复用为can1 gpio_pinafconfig(gpioa,gpio_pinsource12,gpio_af_can1); //gpioa12复用为can1
3) 当adc采集的输入通道,作为普通模拟输入。
void adc_init(void){ gpio_inittypedef gpio_initstructure; rcc_ahb1periphclockcmd(rcc_ahb1periph_gpioa, enable);//使能gpioa时钟 gpio_initstructure.gpio_pin = gpio_pin_5;//pa5 通道5 gpio_initstructure.gpio_mode = gpio_mode_an;//模拟输入 gpio_initstructure.gpio_pupd = gpio_pupd_nopull ;//不带上下拉 gpio_init(gpioa, gpio_initstructure);//初始化 }
来源:中科芯mcu
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理
基于TLl6C550C实现数字信号处理器与PC机串行通信的应用设计
时域和频域的关系
No-Code Bluetooth NanoBeacon技术在2023年 RFID JOURNAL LIVE荣获 最佳新产品 奖
五轴数控卷簧机控制系统设计与实现?
中芯国际与RRAM领军企业Crossbar达成战略合作协议
MCU微课堂 | CKS32F4xx系列产品GPIO口配置
机房环境监测方案上线 实现集中监控,统一管理
Pantera Capital获得融资超过7000万美元,是区块链发展史上浓墨重彩的一笔
土肥仪的作用与技术参数
一种闭环输入阻抗控制的PFC控制方法
与MAX3108 UART接口
哈佛商业评论专访美格智能:在“差异化”赛道,锻造出海的核心优势
示波器有什么用 示波器的作用详解
施耐德电气PowerTag终端配电智能化系统特点及应用场景介绍
4525DO-DS3AS015DP差压传感器在管道静压测量的应用
共享单车最新消息:网爆ofo拖欠工资?共享单车坏车率太高
四双向模拟开关CD4066
重磅利好:十大物联网发展计划亮相
中国智能手机市场出货量持续下降 非洲等地区的功能手机出货量最大
开口式电流互感器的作用及优势