I/O口

单片机应用系统中,常有用单片机的I/O口来实现自关机(彻底关机)的功能。一般用单片机的一个I/O口控制一个电子开关来实现,因单片机关电后,失去电源,所以在关机时,实现关机的IO口的电平必须用低电平。

但在这里有一个矛盾,就是在电子开关关闭电源时,因有电源滤波电容的存在,单片机系统的电压不是立即变为0,而是慢慢变低,当电压低到一定电压时,单片机 将进入复位状态、或程序跑飞状态、或不确定状态,此时单片机控制关电的I/O口也可能变回高电平,将使电子开关重新开通。

解决方法:

一般单片机最低工作电压要比正常工作的电压低一些,我们就用这个差别来设计关机电路,就是让电子开关的开通电压必须大于单片机的最低工作压,这样在单片机正常工作时,此控制电压较高,能维持电子开关的正常导通,而当单片机在关电过程中因低压而产生的I/O口的高电平,因电压较低,不足以维持电子开关的导通, 从而实现彻底的关电。


在关机状态时:

S1按下,Q2导通,单片机工作后,POWER输出高电平,Q1导通,维持Q2的导通实现开机。

在开机状态时:

1、软件关机:MCU的POWER引脚输出低电平,Q1截止,Q2关断,关机。(一般用于延时关机,象数字万用表即是)

2、S1按下,低电平通过D3使MCU的输入脚ON-OFF电平为低,MCU检测到后,通过软件关机(如1所述)

D3用于隔离,不然关机状态时MCU的ON-OFF脚为低电平,Q2将导通。

POWER 是单片机输出开关电源的,低电平是0,高电平等于单片机的供电电压(近似)

ON-OFF是单片机的输入脚,用于单片机检测S1的状态,如果不用S1关机ON-OFF脚可以不用。

来源:电子发烧友网,转载此文目的在于传递更多信息,版权归原作者所有。

围观 44

I/O口是单片机与外界联系的通道。它可对各类外部信号(开关量、模拟量、频率信一号)进行检测、判断、处理,并可控制各类外部设备。单片机通过I/O口感知外界的存在,而外界也通过I/O口感知单片机的存在。


现在的单片机I/O口已经集成了更多的特性和功能。因此,在学习某一款单片机时,需要先了解其I/O口具有哪些特性和特殊的应用功能(不同的单片机是有所差别的),并因地制宜设计外围电路、编写控制软件,充分发挥该I/O口的优势。


1. 输入/输出概念

大多数I/O口都是双向三态的。根据具体应用情况,可以分为输入口和输出口。输人口用来读取外部输人的电平信号,输出口则用于对外输出一个电平信号。

有些单片机(如PIC)允许设置I/O口的输入/输出状态。这样做的好处是可以让I/O口适应更多的应用环境:当I/O口处于输入状态时,对外表现为“高阻态”;而当I/O口处于输出状态时,对外可以提供更大的灌电流或拉电流,这样可以直接驱动一些如LED之类的负载。无需再外扩驱动电路了。

2. 输入门槛电平

对于51系列单片机来说,输入电平低于0.7V就是低电平,高于1. 8 V就是高电平。如果输入的电平介于二者之间,那么CPU在读取该I/O口时可能会得到一个不确定的错误数据。一般来说,我们不希望输入口上出现这种模棱两可的电平状态(除非那个口是ADC检测口)。

3. 最大输出电流

这个特性是针对输出来讲的。最大输出电流包括两种:灌电流和拉电流。灌电流是指当I/O口输出“0”(低电平)时允许灌人(流入)该I/O口的电流;拉电流则是指当I/O口输出“1"(高电平)时允许流出的电流。

4. 输出电平

这个特性是也针对输出来讲的,包括两种:“0”(低电平电压)和“1"(高电平电压)。理想状态上来说,输出高电平应该等于单片机的工作电压Vcc。但是实际由于内阻的关系,输出高电平会略低于Vcc。尤其是当拉电流较大时,高电平会被进一步拉低。同样的道理,输出低电平也往往不是正好等于0V,而是有可能比0V高出一点。

5. I/O口附加功能

许多单片机都为I/O口集成了许多新的功能控制,包括内部上拉/下拉电阻功能、R-op-TION功能以及漏极(或集电极)开路功能。如果能够合理地使用这些功能,就可以简化外围工作电路。

6. I/O口功能的拓展与复用

包括中断、唤醒、ADC检测以及PWM输出等。

本文转自:电工学习网,转载此文目的在于传递更多信息,版权归原作者所有。

围观 122

单片机应用系统中,常有用单片机的I/O口来实现自关机(彻底关机)的功能。一般用单片机的一个I/O口控制一个电子开关来实现,因单片机关电后,失去电源,所以在关机时,实现关机的IO口的电平必须用低电平。

但在这里有一个矛盾,就是在电子开关关闭电源时,因有电源滤波电容的存在,单片机系统的电压不是立即变为0,而是慢慢变低,当电压低到一定电压时,单片机 将进入复位状态、或程序跑飞状态、或不确定状态,此时单片机控制关电的I/O口也可能变回高电平,将使电子开关重新开通。

解决方法:

一般单片机最低工作电压要比正常工作的电压低一些,我们就用这个差别来设计关机电路,就是让电子开关的开通电压必须大于单片机的最低工作压,这样在单片机正常工作时,此控制电压较高,能维持电子开关的正常导通,而当单片机在关电过程中因低压而产生的I/O口的高电平,因电压较低,不足以维持电子开关的导通, 从而实现彻底的关电。

单片机如何通过I/O口实现断电自关机

在关机状态时:

S1按下,Q2导通,单片机工作后,POWER输出高电平,Q1导通,维持Q2的导通实现开机。

在开机状态时:

1、软件关机:MCU的POWER引脚输出低电平,Q1截止,Q2关断,关机。(一般用于延时关机,象数字万用表即是)

2、S1按下,低电平通过D3使MCU的输入脚ON-OFF电平为低,MCU检测到后,通过软件关机(如1所述)

D3用于隔离,不然关机状态时MCU的ON-OFF脚为低电平,Q2将导通。

POWER 是单片机输出开关电源的,低电平是0,高电平等于单片机的供电电压(近似)
ON-OFF是单片机的输入脚,用于单片机检测S1的状态,如果不用S1关机ON-OFF脚可以不用。

转自: 玩转单片机

围观 417

双向IO口的输出:互补推挽

在51单片机的P0口工作在普通IO口模式下,为准双向IO口。而工作在第二功能状态下时,则为标准的双向IO口。由于双向IO口的输出,要求能输出高低电平,通常会采用互补推挽电路。

在第二功能状态下,51单片机P0口采用的是互补推挽的输出方式。何为互补推挽呢?下面是它的等效电路图。

51单片机I/O口的讲解

当P0第二功能作为输出时,K1和K2两个开关轮流打开。K2闭合K1打开,就会输出高电平,并且其驱动能力很大,因为电子开关的阻值小(不像上拉电阻的值那么大)。反之K2打开,K1闭合,就会输出低电平。

两个开关交替导通,互为补充,“挽”是“拉”的意思,两个电子开关分别负责在IO口输出处“推”和“拉”电流,所以称为互补推挽。

这种IO口结构的优点很明显,驱动能力强,稳定可靠。缺点在于实现起来比较困难。在切换输出电平的过程中,例如从低电平切换到高电平,当K1断开时,要求尽可能快的输出高电平,也就是K2应该立即闭合;同时,如果K1还没断开,K2就提前闭合了,相同于两个开关同时导通,会直接短路,后果又会很严重。所以需要用电路控制好两个开关的协调工作。

双向IO口的输入:高阻态、输入电阻

双向IO口的输出,只要求能输出高低电平,因此并不是必须采用互补推挽电路。而采用互补推挽电路的好处在于,这种电路同时又可以实现高阻态的输入,从而实现标准双向IO口。

当图中的K1和K2同时断开时,IO口就可以工作在高阻态的输入状态下。高阻态到底是什么样的一个概念呢?

当IO口处于高阻态时,也将其称为浮空输入状态,其电平是悬浮不定的,既不是高电平也不是低电平。我们可以想象单片机在检测IO口的电平高低时,相当于在CPU里面有一个类似电压表的东西,并且这个电压表内阻很大,例如图中给出的100MΩ。在这里,我们可以把这个电压表的内阻称为P0.0口此时的输入电阻(也可以近似认为是输出阻抗,电阻是对直流电而言,而阻抗是对交流电来说的。这是模拟电路的知识,这里不做细说)。

51单片机I/O口的讲解

现在试想,如果不小心用手碰到了P0.0端口,而由于人体本身就是阻值很大的导体,周围有很多电磁波干扰,手上可能存在一些很微弱的电流,这个时候,电压表的读数就会发生变化,单片机读取的电平高低就会变。高阻态表现出来的结果就是外界很小的干扰,都可能导致读取的电平变化,甚至即使没有碰这个IO口,它每次读取的结果也可能不一样,因为外界的电磁波等可能会干扰到IO口。稍后我们会利用51单片机做个实验,来体验P0口的高阻态。

高阻态的意义、输出电阻

为什么双向IO口输入的时候要求是高阻态呢?

我们假设有一种装置,等效电路如下图。开关上下切换,它就会输出高低电平,通过电压表可以检测出来。但是其驱动能力很弱,连LED也驱动不了。装置里的100kΩ,可以叫做装置的输出电阻(同样也可以近似认为是输出阻抗)。

51单片机I/O口的讲解

让这个装置输出低电平,然后连接51单片机的P1.0口。这时,VCC经过10kΩ上拉电阻到达IO口,再到装置内部的100kΩ电阻,通过开关K接到GND。根据分压原理,P1.0上的电压值大概是4.55V,于是单片机读取的是高电平。而事实是,装置想输出低电平告知51单片机。这里单片机管脚作为输入功能,却干扰了外界装置的输出值,相当于单片机的这个IO口也在输出。
51单片机I/O口的讲解

当单片机的P0口工作在第二功能的输入状态,或者工作在普通IO口的输入状态,且没有外界上下拉电阻,内部的两个电子开关都是断开的,对外部呈现高阻态。从图中可以看出,装置输出的电平能被准确的读取到单片机中。之所以能准确读取,就是因为装置输出电阻比单片机IO口的输入电阻要小。
51单片机I/O口的讲解

有人可能会说,如果把装置中的电阻换成1000MΩ,这个时候这个单片机又不能准确读取电平了。但是一般情况下,我们不需要考虑这么极端。如果是理想的高阻态,其输入阻抗应该是无穷大,而这有点像超导体一样比较特殊。一般情况下认为导线电阻几乎为0,同样也认为高阻态输入电阻是无穷大。

总的来说,就是高阻态情况下,IO口输入电阻很大,而不容易干扰那些输出电阻较大、驱动能力弱的装置输出到IO口上的电平。

出处:玩转单片机

围观 360

浮空,顾名思义就是浮在空中,上面用绳子一拉就上去了,下面用绳子一拉就沉下去了.

开漏,就等于输出口接了个NPN三极管,并且只接了e,b. c极 是开路的,你可以接一个电阻到3.3V,也可以接一个电阻到5V,这样,在输出1的时候,就可以是5V电压,也可以是3.3V电压了.但是不接电阻上拉的时候,这个输出高就不能实现了.

推挽,就是有推有拉,任何时候IO口的电平都是确定的,不需要外接上拉或者下拉电阻.

(1)GPIO_Mode_AIN 模拟输入
(2)GPIO_Mode_IN_FLOATING 浮空输入
(3)GPIO_Mode_IPD 下拉输入
(4)GPIO_Mode_IPU 上拉输入
(5)GPIO_Mode_Out_OD 开漏输出
(6)GPIO_Mode_Out_PP 推挽输出
(7)GPIO_Mode_AF_OD 复用开漏输出
(8)GPIO_Mode_AF_PP 复用推挽输出

推挽电路是两个参数相同的三极管或MOSFET,以推挽方式存在于电路中,各负责正负半周的波形放大任务,电路工作时,两只对称的功率开关管每次只有一个导通,所以导通损耗小、效率高。输出既可以向负载灌电流,也可以从负载抽取电流。推拉式输出级既提高电路的负载能力,又提高开关速度。

开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内).

开漏形式的电路有以下几个特点:

1. 利用外部电路的驱动能力,减少IC内部的驱动。当IC内部MOSFET导通时,驱动电流是从外部的VCC流经R pull-up ,MOSFET到GND。IC内部仅需很下的栅极驱动电流。

2. 一般来说,开漏是用来连接不同电平的器件,匹配电平用的,因为开漏引脚不连接外部的上拉电阻时,只能输出低电平,如果需要同时具备输出高电平的功能,则需要接上拉电阻,很好的一个优点是通过改变上拉电源的电压,便可以改变传输电平。比如加上上拉电阻就可以提供TTL/CMOS电平输出等。(上拉电阻的阻值决定了逻辑电平转换的沿的速度 。阻值越大,速度越低功耗越小,所以负载电阻的选择要兼顾功耗和速度。)

3. OPEN-DRAIN提供了灵活的输出方式,但是也有其弱点,就是带来上升沿的延时。因为上升沿是通过外接上拉无源电阻对负载充电,所以当电阻选择小时延时就小,但功耗大;反之延时大功耗小。所以如果对延时有要求,则建议用下降沿输出。

4. 可以将多个开漏输出的Pin,连接到一条线上。通过一只上拉电阻,在不增加任何器件的情况下,形成“与逻辑”关系。这也是I2C,SMBus等总线判断总线占用状态的原理。补充:什么是“线与”?:

在一个结点(线)上, 连接一个上拉电阻到电源 VCC 或 VDD 和 n 个 NPN 或 NMOS 晶体管的集电极 C 或漏极 D, 这些晶体管的发射极 E 或源极 S 都接到地线上, 只要有一个晶体管饱和, 这个结点(线)就被拉到地线电平上. 因为这些晶体管的基极注入电流(NPN)或栅极加上高电平(NMOS),晶体管就会饱和, 所以这些基极或栅极对这个结点(线)的关系是或非 NOR 逻辑. 如果这个结点后面加一个反相器, 就是或 OR 逻辑.

其实可以简单的理解为:在所有引脚连在一起时,外接一上拉电阻,如果有一个引脚输出为逻辑0,相当于接地,与之并联的回路“相当于被一根导线短路”,所以外电路逻辑电平便为0,只有都为高电平时,与的结果才为逻辑1。

由于浮空输入一般多用于外部按键输入,结合图上的输入部分电路,我理解为浮空输入状态下,IO的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的。

上拉输入/下拉输入/模拟输入:这几个概念很好理解,从字面便能轻易读懂。

复用开漏输出、复用推挽输出:可以理解为GPIO口被用作第二功能时的配置情况(即并非作为通用IO口使用)

最后总结下使用情况:

在STM32中选用IO模式

(1) 浮空输入_IN_FLOATING ——浮空输入,可以做KEY识别,RX1
(2)带上拉输入_IPU——IO内部上拉电阻输入
(3)带下拉输入_IPD—— IO内部下拉电阻输入
(4) 模拟输入_AIN ——应用ADC模拟输入,或者低功耗下省电
(5)开漏输出_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能
(6)推挽输出_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
(7)复用功能的推挽输出_AF_PP ——片内外设功能(I2C的SCL,SDA)
(8)复用功能的开漏输出_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS)

STM32设置实例:

(1)模拟I2C使用开漏输出_OUT_OD,接上拉电阻,能够正确输出0和1;读值时先GPIO_SetBits(GPIOB, GPIO_Pin_0);拉高,然后可以读IO的值;使用GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0);
(2)如果是无上拉电阻,IO默认是高电平;需要读取IO的值,可以使用带上拉输入_IPU和浮空输入_IN_FLOATING和开漏输出_OUT_OD;

来源: http://www.cnblogs.com/mm327596194/articles/6473926.html

围观 402

在做总线通信过程中,我们很少会用到这样方法,一般在我们选择MCU的时候都会带有你所需要的通信接口。但是,对于一些简单的通信应该用的场合,一 般在一些传感器的数据通信过程中,传感器厂商会将通信协议做一些改变,这些通信协议也没有一个标准的协议规定。以至于传感器的兼容性很差,甚至有时候找不 到能够与其通信的MCU,这个时候有一种方法就是用I/O口来模拟通信总线(由于I/O速度的限制一般只适用于低速的通信总线)的时序。之前,用I2C通信做一个温湿度测量的工程,本篇文章就以一个例子来看看如何用I/O口对总线时序进行模拟。

我们平时计算机常用的RS232/485工作在异步工作状态时是有严格的数据时钟限制,也就是我们所说的波特率,通信的两个设备有相同的波特率才能正确的通信。对于同步通信一般没有严格的时间限制,总线通过高低电平来分辨数据是"0"还是"1",有两个关键的时刻:上升沿,下降沿。它 是用过上升沿和下降沿的时刻来读写数据的,也就是说这样的话通信频率不是固定的,因为通信的设备"数"的是上升沿和下降沿的数目,然后读写数据线上的数 据。笔者做过实验,将I2C通信的频率降到了10Hz左右,这样用示波器能够很好的捕捉到每一个时钟,通信的结果也是正确的。

好了,直接来看案例吧。

通常我们的I2C的通信时序应该如下图所示,在时钟线拉高的情况下,将数据线拉低就会产生一个启动信号。但是传感器SHT的启动信号却是一个数据线拉低后,时钟线产生一个脉冲,而后再将数据线拉高,这样做的好处是在一定程度上确保了总线正确的启动,但是几乎与之匹配的MCU。这个时候就需要通过I/O模拟的方式来与SHT11完成通信。

#define IIC_SCL RC0 //I2C时钟线

#define IIC_SDA RC1 //I2C数据线

#define IIC_SCL_DIR TRISC0 //I2C时钟线传输方向

#define IIC_SDA_DIR TRISC1 //I2C数据线传输方向

#define PORT_INPUT 1

#define PORT_OUTPUT 0

#define IIC_SCL_HIGH() IIC_SCL_DIR = PORT_INPUT //时钟线拉高

#define IIC_SCL_LOW() IIC_SCL_DIR = PORT_OUTPUT;IIC_SCL=0//时钟线拉低

#define IIC_SDA_HIGH() IIC_SDA_DIR = PORT_INPUT //数据线拉高

#define IIC_SDA_LOW() IIC_SDA_DIR = PORT_OUTPUT;IIC_SDA=0//数据线拉低

/***************

*SHT11启动时序

***************/

void SHT_START(void)

{

IIC_SCL_HIGH();

IIC_SDA_HIGH();

delay_us(5);

IIC_SDA_LOW();

delay_us(5);

IIC_SCL_LOW();

delay_us(5);

IIC_SCL_HIGH();

delay_us(5);

IIC_SDA_HIGH();

delay_us(5);

IIC_SCL_LOW();

}

/***************

*SHT11发送数据时序

***************/

void SHT_SEND(uchar data)

{uchar i,data1;

for(i=0;i<8;i++)

{

data1=data<

if(!(data1&0x80))

IIC_SDA_LOW();

if(data1&0x80)

IIC_SDA_HIGH();

IIC_SCL_LOW(); //写完1位数据将时钟线拉低,等待发送

delay_us(5);

IIC_SCL_HIGH(); //时钟线上升沿,发送1位数据

delay_us(5); //等待1位数据发送完成

}

IIC_SCL_LOW();

IIC_SDA_HIGH(); //8位数据发送完成,数据线拉高,等待SLAVE器件响应

delay_us(5);

IIC_SCL_HIGH(); //时钟线拉高,产生上升沿读取数据线是否SLAVE器件有响应

//while(IIC_SDA==1);

delay_us(5);

IIC_SCL_LOW();

IIC_SDA_HIGH(); //数据线拉高,时钟线拉低,等待转换完成

}

/***************

*SHT11接收数据时序

***************/

uint SHT_REC(void)

{

uint i;

uint REC1=0,REC0=0,REC=0;

for(i=0;i<8;i++)

{

IIC_SCL_HIGH(); //转换完成,SLAVE器件将数据线拉低,时钟线产生上升沿读取高8位数据

REC1=(REC1<<1)+IIC_SDA;

delay_us(5);

IIC_SCL_LOW(); //将时钟线拉低,等待下一个上升沿的到来

delay_us(5);

}

SHT_ASK(); //高8位数据接收完毕,发送应答信号

for(i=0;i<8;i++)

{

IIC_SCL_HIGH(); //转换完成,SLAVE器件将数据线拉低,时钟线产生上升沿读取低8位数据

REC0=(REC0<<1)+IIC_SDA;

delay_us(5);

IIC_SCL_LOW();

delay_us(5);

}

SHT_STOP(); //低8位数据接收完毕,结束

REC=(REC1<<8)+REC0;

return REC;

}

/***************

*SHT11应答时序

***************/

void SHT_ASK(void)

{

IIC_SCL_LOW();

IIC_SDA_LOW(); //数据线拉低

delay_us(5);

IIC_SCL_HIGH(); //时钟线拉高才生应答信号

delay_us(5);

IIC_SDA_HIGH();

IIC_SCL_LOW();

delay_us(5);

}

/***************

*SHT11停止时序

***************/

void SHT_STOP(void)

{

IIC_SDA_HIGH();

IIC_SCL_LOW();

delay_us(5);

IIC_SCL_HIGH();

delay_us(5);

IIC_SDA_HIGH();

IIC_SCL_LOW();

}

围观 195

页面

订阅 RSS - I/O口