双向IO口.doc
- 格式:doc
- 大小:153.50 KB
- 文档页数:6
单片机P0口是双相口,而P1P2P3是准双相口。
举个例子:相信大家都理解准妈妈,就是怀孕的女人,当然这里也是这样的,就不是真正的双相口了。
为什么P0是双向口,这里的差别是什么呢?最主要原因是:P0没有上拉电阻,所以当P0最IO口的时候一定要加上上拉电阻,否则的话,你输出的1就是无效了,这样T2截止了,那么P0都就是呈现高阻状态了。
下图分别是P0,P1P2P3的读写数据,红线表示输出,蓝线表示输入(读引脚)还有一个就是读锁存器的,没画出来。
在读引脚的时候,有一点注意:每当读引脚的时候要确保场效应管T2是截止的,否则的话1(高电平)外部数据读不出来,T2会把它拉低,所以通过MO V PX,FFH,把T2截止,就完美了。
在单片机学习、开发和应用中,IO口的配置对功能的实现起着重要的作用,下面介绍常见的四种配置,而现在很多单片机都兼有这四种配置,可供选择。
一.准双向口配置如下图,当IO输出为高电平时,其驱动能力很弱,外部负载很容易将其拉至低电平。
当IO 输出为低电平时,其驱动能力很强,可吸收相当大的电流。
准双向口有三个上拉晶体管,一个“极弱上拉”,当端锁存器为逻辑“1”时打开,当端口悬空时,“极弱上拉”将端口上拉至高电平。
第二个上拉晶体管为“弱上拉”,当端口锁存器为逻辑“1”且端口本身也为“1”时打开,此上拉提供的电流,使准双向口输出为“1”。
如果此时端口被外部装置拉到逻辑“0”时,通过施密特触发器,控制“弱上拉”关闭,而“极弱上拉”维持开状态,为了把这个端口拉低,外部装置必须有足够的灌电流能力,使管脚上的电压,降到门槛电以下。
第三个上拉晶体管为“强上拉”,当端口锁存器由“0”跳变到“1”时,这个上拉用来加快端口由逻辑“0”到逻辑“1”的转换速度。
最近有一个项目要用到FPGA,还要用硬件描述语言综合出一个双向IO口用作地址数据总线。
一直没能够实现,在实验过程中遇到了或这或那的问题,终于在今天有所突破!能够正确的读写CAN控制芯片SJA1000的测试寄存器。
在试验中也总结了一些东西,如下:1、Inout口,一般要放在最顶层的V文件中,我试验过放到下面的v文件中,没能够成功(更正一下:inout并非一定要在最顶层,也可以在底层设置。
具体可参见黑金开发板建模篇实验13 DS1302实时时钟驱动。
)。
2、在一个module中,可以将输出定义为reg型,然后直接与要驱动module的wire型输入相连,没有问题。
3、在调试程序的过程中,尽量借助于工具,如quartus内部的Signal Tap。
之前一直不会使用,现在也在慢慢学习。
用来模拟的是intel模式的总线读写其时序图如下:代码包括下面的及部分:can_top.vmodule can_top(CLK,RSTn,Row_scan,Column_scan,can_pin,can_ALE,can_WR,can_RD,can_CS,can_dir,can_rst_out);input CLK;input RSTn;output [7:0] Row_scan;output [1:0] Column_scan;inout [7:0] can_pin;output can_ALE;output can_WR;output can_RD;output can_CS;output can_dir;output can_rst_out;wire [7:0] data_in;wire rmd;wire wmd;wire [7:0] adr;wire [7:0] data_tx;wire [7:0] data_rx;wire rd_flag;wire wr_flag;trans_control U3(.CLK(CLK),.RSTn(RSTn),.data_in(data_in),.Row_scan(Row_scan),.Column_scan(Column_scan) );wire can_rst;can_ctr U1(.CLK(CLK),.RSTn(RSTn),.rd_flag(rd_flag),.wr_flag(wr_flag),.data_rx(data_rx),.data_display(data_in), .rmd(rmd),.wmd(wmd),.adr(adr),.data_tx(data_tx),.can_rst(can_rst));can_op U2(.CLK(CLK),.RSTn(RSTn),.can_rst_in(can_rst),.rmd(rmd),.wmd(wmd),.adr(adr),.data_tx(data_tx),.can_in(can_in_temp),.en_out(en_out),.can_out(can_out),.read_cmd(read_cmd),.data_rx(data_rx),.can_ALE(can_ALE),.can_WR(can_WR),.can_RD(can_RD),.can_CS(can_CS),.can_dir(can_dir),.rd_flag(rd_flag),.wr_flag(wr_flag),.can_rst_out(can_rst_out));wire en_out;wire [7:0] can_out;// wire [7:0] can_in;reg [7:0] can_in_temp;wire read_cmd;always @ ( posedge CLK or negedge RSTn )beginif(!RSTn)can_in_temp<=8'b1000_1001;elsebeginif(read_cmd==1'b1)can_in_temp <= can_pin;endend// assign can_in = can_in_temp;assign can_pin = (en_out==1'b1)?can_out:8'bZZZZZZZZ; //双向口设置endmodulecan_ctr.vmodule can_ctr(CLK,RSTn,rd_flag,wr_flag,data_rx,data_display,rmd,wmd,adr,data_tx,can_rst);input CLK;input RSTn;input rd_flag;input wr_flag;input [7:0] data_rx;output [7:0] data_display;output rmd;output wmd;output [7:0] adr;output [7:0] data_tx;output can_rst;reg [7:0] data_display_temp;reg rmd_temp;reg wmd_temp;reg [7:0] adr_temp;reg [7:0] data_tx_temp;reg can_rst_temp;reg rst_flag;parameter TS = 26'd29_999_999; parameter T1S = 26'd49_999_999;always @ ( posedge CLK or negedge RSTn )beginif(!RSTn)begincan_rst_temp<=1'b1;rst_flag<=1'b1;endelse if (Count_Sec==26'd100 && rst_flag == 1'b1) begincan_rst_temp<=1'b0;rst_flag<=1'b0;endendalways @ ( posedge CLK or negedge RSTn )beginif(!RSTn)beginrmd_temp<=1'b0;wmd_temp<=1'b0;adr_temp<=8'b0000_0000;data_display_temp<= 8'b1000_1000;data_tx_temp<=8'b0000_0000;endelsebeginif (Count_Sec==TS)beginwmd_temp<=1'b1;adr_temp<=8'b0001_0000;data_tx_temp<=8'b0001_0010;endif (Count_Sec==T1S)beginrmd_temp<=1'b1;adr_temp<=8'b0001_0000; //读测试寄存器endif (wr_flag==1'b1)beginwmd_temp<=1'b0;endif (rd_flag==1'b1)beginrmd_temp<=1'b0;data_display_temp<= data_rx;endendendreg [25:0]Count_Sec;always @ ( posedge CLK or negedge RSTn ) if( !RSTn )Count_Sec <= 26'd0;else if( Count_Sec == T1S )Count_Sec <= 26'd0;elseCount_Sec <= Count_Sec + 1'b1;assign data_display=data_display_temp; assign rmd=rmd_temp;assign wmd=wmd_temp;assign adr=adr_temp;assign data_tx=data_tx_temp;assign can_rst=can_rst_temp;endmodulecan_op.vmodule can_op(CLK,RSTn,can_rst_in,rmd,wmd,adr,data_tx,can_in,en_out,can_out,read_cmd,data_rx,can_ALE,can_WR,can_RD,can_CS,can_dir,rd_flag,wr_flag,can_rst_out);input CLK;input RSTn;input can_rst_in;input rmd;input wmd;input [7:0]adr;input [7:0]data_tx;input [7:0]can_in;output en_out;output [7:0] can_out;output read_cmd;output [7:0]data_rx;output can_ALE;output can_WR;output can_RD;output can_CS;output can_dir;output rd_flag;output wr_flag;output can_rst_out;reg [7:0] can_out_temp;reg en_out_temp; //这两个变量来组成双向口输出控制reg read_cmd_temp;reg [7:0] data_rx_temp;reg can_ALE_temp;reg can_WR_temp;reg can_RD_temp;reg can_CS_temp;reg can_dir_temp;reg rd_flag_temp;reg wr_flag_temp;reg [3:0] count;always @ ( posedge CLK or negedge RSTn ) beginif ( !RSTn )beginrd_flag_temp<=1'b0;wr_flag_temp<=1'b0;can_WR_temp<=1'b1;can_RD_temp<=1'b1;can_CS_temp<=1'b1;can_dir_temp<=1'b0;data_rx_temp<=8'd221;count<= 4'd0;en_out_temp<=1'b1;can_out_temp<=8'd0;read_cmd_temp<=1'b0;endelsebeginif (rmd)begincase(count)4'd0,4'd1,4'd6: count<= count+1'b1; 4'd2:begincan_out_temp<= adr;en_out_temp<=1'b1;can_ALE_temp<= 1'b1;count<= count+1'b1;end4'd3:begincan_ALE_temp<=1'b0;count<= count+1'b1;end4'd4:begincan_CS_temp<= 1'b0;count<= count+1'b1;en_out_temp<=1'b0;end4'd5:begincan_RD_temp<= 1'b0;can_dir_temp=1'b1;count<= count+1'b1;end4'd7:beginread_cmd_temp<=1'b1;count<= count+1'b1;end4'd8:begincount<= count+1'b1;read_cmd_temp<=1'b0;end4'd9:begindata_rx_temp <= can_in;can_RD_temp<= 1'b1;count<= count+1'b1;can_dir_temp <= 1'b0;en_out_temp<=1'b1;end4'd10:begincan_CS_temp<= 1'b1;count<= count+1'b1;rd_flag_temp<=1'b1;end4'd11:begincount<=4'd0;rd_flag_temp<=1'b0;endendcaseendif (wmd)begincase(count)4'd0,4'd1: count<= count+1'b1; 4'd2:begincan_out_temp<= adr;en_out_temp<=1'b1;can_ALE_temp<= 1'b1;count<= count+1'b1;end4'd3:begincan_ALE_temp<=1'b0;count<= count+1'b1;end4'd4:begincan_CS_temp<= 1'b0;count<= count+1'b1;end4'd5:begincan_WR_temp<= 1'b0;count<= count+1'b1;end4'd6:begincan_out_temp<= data_tx;count<= count+1'b1; end4'd7:begincount<= count+1'b1;end4'd8:begincan_WR_temp<= 1'b1;count<= count+1'b1;end4'd9:begincan_CS_temp<= 1'b1;can_ALE_temp<=1'b1;count<= count+1'b1;wr_flag_temp<=1'b1;end4'd10:begincount<= 1'b0;wr_flag_temp<=1'b0; endendcaseendendendassign data_rx=data_rx_temp;assign can_ALE=can_ALE_temp;assign can_WR=can_WR_temp;assign can_RD=can_RD_temp;assign can_CS=can_CS_temp;assign can_dir=can_dir_temp;assign wr_flag=wr_flag_temp;assign rd_flag=rd_flag_temp;assign can_rst_out=can_rst_in;assign can_out=can_out_temp;assign en_out=en_out_temp;assign read_cmd=read_cmd_temp;endmoduletrans_control.v 这个与下面两个v文件是用来将接收到的数据显示到数码管上module trans_control(CLK,RSTn,data_in,Row_scan,Column_scan);input CLK;input RSTn;input [7:0] data_in;output [7:0] Row_scan;output [1:0] Column_scan;wire [7:0] data1_temp;wire [7:0] data2_temp;trans_module U1(.CLK (CLK),.RSTn (RSTn),.data_in (data_in),.out_data1 (data1_temp), .out_data2 (data2_temp) );scan_module U2(.CLK (CLK),.RSTn (RSTn),.scan_data1 (data1_temp), .scan_data2 (data2_temp), .Row_scan (Row_scan),.Column_scan (Column_scan) );endmoduletrans_module.vmodule trans_module(CLK,RSTn,data_in,out_data1,out_data2);input CLK;input RSTn;input [7:0] data_in;output [7:0] out_data1; output [7:0] out_data2;reg [7:0] out_data1_temp; reg [7:0] out_data2_temp;reg [3:0] temp1;reg [3:0] temp2;parameter _0 = 8'b1100_0000, _1 = 8'b1111_1001, _2 = 8'b1010_0100, _3 = 8'b1011_0000, _4 = 8'b1001_1001, _5 = 8'b1001_0010, _6 = 8'b1000_0010, _7 = 8'b1111_1000, _8 = 8'b1000_0000,_9 = 8'b1001_0000, _A = 8'b1000_1000, _B = 8'b1000_0011,_C = 8'b1100_0110, _D = 8'b1010_0001, _E = 8'b1000_0100,_F = 8'b1000_1110;always @ ( posedge CLK or negedge RSTn )if( !RSTn )beginout_data1_temp<= 8'b1100_0000;out_data2_temp<= 8'b1100_0000;temp1 <= 4'd0;temp2 <= 4'd0;endelsebegintemp1 <= data_in[3:0];temp2 <= data_in[7:4];case(temp1)4'h0 : out_data1_temp <= _0;4'h1 : out_data1_temp <= _1;4'h2 : out_data1_temp <= _2;4'h3 : out_data1_temp <= _3;4'h4 : out_data1_temp <= _4;4'h5 : out_data1_temp <= _5;4'h6 : out_data1_temp <= _6;4'h7 : out_data1_temp <= _7;4'h8 : out_data1_temp <= _8;4'h9 : out_data1_temp <= _9;4'hA : out_data1_temp <= _A;4'hB : out_data1_temp <= _B;4'hC : out_data1_temp <= _C;4'hD : out_data1_temp <= _D;4'hE : out_data1_temp <= _E;4'hF : out_data1_temp <= _F;endcasecase(temp2)4'h0 : out_data2_temp <= _0;4'h1 : out_data2_temp <= _1;4'h2 : out_data2_temp <= _2;4'h3 : out_data2_temp <= _3;4'h4 : out_data2_temp <= _4;4'h5 : out_data2_temp <= _5;4'h6 : out_data2_temp <= _6;4'h7 : out_data2_temp <= _7;4'h8 : out_data2_temp <= _8;4'h9 : out_data2_temp <= _9;4'hA : out_data2_temp <= _A;4'hB : out_data2_temp <= _B;4'hC : out_data2_temp <= _C;4'hD : out_data2_temp <= _D;4'hE : out_data2_temp <= _E;4'hF : out_data2_temp <= _F;endcaseendassign out_data1 = out_data1_temp;assign out_data2 = out_data2_temp;endmodulescan_module.vmodule scan_module(CLK,RSTn,scan_data1,scan_data2,Column_scan,Row_scan);input CLK;input RSTn;input [7:0] scan_data1;input [7:0] scan_data2;output [7:0] Row_scan;output [1:0] Column_scan;parameter T10MS = 19'd499_999;//50M*0.01-1=499_999reg [18:0]Count1;always @ ( posedge CLK or negedge RSTn )if( !RSTn )Count1 <= 19'd0;else if( Count1 == T10MS )Count1 <= 19'd0;elseCount1 <= Count1 + 19'b1;reg [1:0]t;always @ ( posedge CLK or negedge RSTn )if( !RSTn )t <= 2'd0;else if( t == 2'd2 )t <= 2'd0;else if( Count1 == T10MS )t <= t + 1'b1;reg [7:0] Row_scan_temp;reg [1:0] Column_scan_temp;always @ ( posedge CLK or negedge RSTn )if( !RSTn )beginColumn_scan_temp <= 2'b01;Row_scan_temp <= 8'hd0;endelse if( Count1 == T10MS )case( t )2'd0 : begin Column_scan_temp <= 2'b01; Row_scan_temp <= scan_data1; end 2'd1 : begin Column_scan_temp <= 2'b10; Row_scan_temp <= scan_data2; end endcaseassign Column_scan = Column_scan_temp;assign Row_scan = Row_scan_temp;endmodule代码就这些,还有TCL引脚说明#------------------GLOBAL--------------------#set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" set_global_assignment -name ENABLE_INIT_DONE_OUTPUT OFF#复位引脚set_location_assignment PIN_M1 -to RSTn#时钟引脚set_location_assignment PIN_R9 -to CLK#数码管对应的引脚set_location_assignment PIN_M8 -to Row_scan[0]set_location_assignment PIN_L7 -to Row_scan[1]set_location_assignment PIN_P9 -to Row_scan[2]set_location_assignment PIN_N9 -to Row_scan[3]set_location_assignment PIN_M9 -to Row_scan[4]set_location_assignment PIN_M10 -to Row_scan[5]set_location_assignment PIN_P11 -to Row_scan[6]set_location_assignment PIN_N11 -to Row_scan[7]set_location_assignment PIN_N8 -to Column_scan[0]set_location_assignment PIN_P8 -to Column_scan[1]#CAN控制信号对应引脚set_location_assignment PIN_R1 -to can_pin[0]set_location_assignment PIN_R3 -to can_pin[1]set_location_assignment PIN_L3 -to can_pin[2]set_location_assignment PIN_K5 -to can_pin[3]set_location_assignment PIN_P3 -to can_pin[4]set_location_assignment PIN_L8 -to can_pin[5]set_location_assignment PIN_N5 -to can_pin[6]set_location_assignment PIN_K6 -to can_pin[7]set_location_assignment PIN_L6 -to can_ALEset_location_assignment PIN_T3 -to can_WRset_location_assignment PIN_L4 -to can_RDset_location_assignment PIN_N3 -to can_CSset_location_assignment PIN_T2 -to can_dirset_location_assignment PIN_P2 -to can_rst_out。
单片机IO端口工作原理(P0端口,漏极开路,推挽,上拉电阻,准双向口)一、P0端口的结构及工作原理P0端口8位中的一位结构图见下图:输入缓冲器:在P0口中,有两个三态的缓冲器,三态门有三个状态,即在其的输出端可以是高电平、低电平,同时还有一种就是高阻状态。
图中有一个是读锁存器的缓冲器,也就是说,要读取D锁存器输出端Q的数据,那就得使读锁存器的这个缓冲器的三态控制端(上图中标号为‘读锁存器’端)有效。
图中另一个是读引脚的缓冲器,要读取P0.X引脚上的数据,也要使标号为‘读引脚’的这个三态缓冲器的控制端有效,引脚上的数据才会传输到我们单片机的内部数据总线上。
D锁存器:一个触发器可以保存一位的二进制数(即具有保持功能),在51单片机的32根I/O口线中都是用一个D触发器来构成锁存器的。
图中的锁存器,D 端是数据输入端,CP是控制端(也就是时序控制信号输入端),Q是输出端,Q 非是反向输出端。
对于D触发器来讲,当D输入端有一个输入信号,如果这时控制端CP没有信号(也就是时序脉冲没有到来),这时输入端D的数据是无法传输到输出端Q及反向输出端Q非的。
如果时序控制端CP的时序脉冲一旦到了,这时D端输入的数据就会传输到Q及Q非端。
数据传送过来后,当CP时序控制端的时序信号消失了,这时,输出端还会保持着上次输入端D的数据(即把上次的数据锁存起来了)。
如果下一个时序控制脉冲信号来了,这时D端的数据才再次传送到Q端,从而改变Q端的状态。
多路开关:在51单片机中,当内部的存储器够用(也就是不需要外扩展存储器时,这里讲的存储器包括数据存储器及程序存储器)时,P0口可以作为通用的输入输出端口(即I/O)使用,对于8031(内部没有ROM)的单片机或者编写的程序超过了单片机内部的存储器容量,需要外扩存储器时,P0口就作为‘地址/数据’总线使用。
那么这个多路选择开关就是用于选择是做为普通I/O口使用还是作为‘数据/地址’总线使用的选择开关了。
单片机IO端口工作原理(P0端口,漏极开路,推挽,上拉电阻,准双向口)一、P0端口的结构及工作原理P0端口8位中的一位结构图见下图:输入缓冲器:在P0口中,有两个三态的缓冲器,三态门有三个状态,即在其的输出端可以是高电平、低电平,同时还有一种就是高阻状态。
图中有一个是读锁存器的缓冲器,也就是说,要读取D锁存器输出端Q的数据,那就得使读锁存器的这个缓冲器的三态控制端(上图中标号为‘读锁存器’端)有效。
图中另一个是读引脚的缓冲器,要读取P0.X引脚上的数据,也要使标号为‘读引脚’的这个三态缓冲器的控制端有效,引脚上的数据才会传输到我们单片机的内部数据总线上。
D锁存器:一个触发器可以保存一位的二进制数(即具有保持功能),在51单片机的32根I/O口线中都是用一个D触发器来构成锁存器的。
图中的锁存器,D 端是数据输入端,CP是控制端(也就是时序控制信号输入端),Q是输出端,Q 非是反向输出端。
对于D触发器来讲,当D输入端有一个输入信号,如果这时控制端CP没有信号(也就是时序脉冲没有到来),这时输入端D的数据是无法传输到输出端Q及反向输出端Q非的。
如果时序控制端CP的时序脉冲一旦到了,这时D端输入的数据就会传输到Q及Q非端。
数据传送过来后,当CP时序控制端的时序信号消失了,这时,输出端还会保持着上次输入端D的数据(即把上次的数据锁存起来了)。
如果下一个时序控制脉冲信号来了,这时D端的数据才再次传送到Q端,从而改变Q端的状态。
多路开关:在51单片机中,当内部的存储器够用(也就是不需要外扩展存储器时,这里讲的存储器包括数据存储器及程序存储器)时,P0口可以作为通用的输入输出端口(即I/O)使用,对于8031(内部没有ROM)的单片机或者编写的程序超过了单片机内部的存储器容量,需要外扩存储器时,P0口就作为‘地址/数据’总线使用。
那么这个多路选择开关就是用于选择是做为普通I/O口使用还是作为‘数据/地址’总线使用的选择开关了。
准双向io口构成原理准双向IO口是指可以在输入和输出之间切换的IO口。
在单片机中,IO口是非常重要的,它可以连接外部设备,实现数据的输入和输出。
准双向IO口的构成原理是通过控制寄存器来实现输入和输出的切换。
在单片机中,每个IO口都有一个对应的寄存器,称为控制寄存器。
控制寄存器中的位可以控制IO口的输入和输出状态。
当控制寄存器中的某一位被设置为1时,IO口就被设置为输出状态,可以向外部设备输出数据;当控制寄存器中的某一位被设置为0时,IO口就被设置为输入状态,可以从外部设备读取数据。
准双向IO口的实现原理是通过控制寄存器中的位来实现输入和输出的切换。
当需要将IO口设置为输出状态时,将控制寄存器中对应的位设置为1;当需要将IO口设置为输入状态时,将控制寄存器中对应的位设置为0。
这样就可以实现在输入和输出之间的切换。
准双向IO口的优点是可以节省IO口的数量,同时也可以减少外部设备的数量。
在某些应用中,需要同时进行输入和输出操作,如果使用普通的IO口,就需要使用两个IO口,一个用于输入,一个用于输出。
而使用准双向IO口,只需要一个IO口就可以实现输入和输出的切换,可以节省IO口的数量,减少外部设备的数量。
准双向IO口的应用非常广泛,例如在数字电路中,可以使用准双向IO口来实现数据的输入和输出;在控制系统中,可以使用准双向IO口来控制外部设备的状态;在通信系统中,可以使用准双向IO口来实现数据的传输和接收。
总之,准双向IO口是一种非常实用的IO口类型,它可以实现输入和输出的切换,节省IO口的数量,减少外部设备的数量,应用非常广泛。
在单片机的开发中,需要根据具体的应用场景选择合适的IO口类型,以实现最佳的性能和功能。
单片机IO口推挽、开漏输出、准双向IO详解加入论坛的方式:在公众号对话框内,输入数字“1”,即可进入论坛,无需注册,就是这么简单。
诚邀您的加入。
在学单片机和选用逻辑器件的时候我们常别人说这款芯片是推挽输出驱动能力强,这个引脚是开漏输出需要加上拉电阻。
是不是有时候感觉一头雾水?今天就详解一下推挽和开漏,以后你买芯片的时候就可以和别人大声理论了。
1. 什么是推挽输出推挽输出既可以输出低电平,也可以输出高电平,可以直接驱动功耗不大的数字器件。
2. 推挽输出电路的结构推挽电路是由两个三极管或MOSFET,以推挽方式存在于电路中,电路工作时,两只对称的开关管每次只有一个导通,所以导通损耗小、效率高、既提高电路的负载能力,又提高开关速度。
其示意结构如下图所示:1. 当内部输出1电平时,上边的MOS管导通同时下边的MOS管截至,IO口输出高电平;2. 当内部输出0电平时,上边的MOS管截至同时下边的MOS管导通,IO口输出低电平;3. 什么是开漏输出开漏输出只能输出低电平,如果要输出高电平必须通过上拉电阻才能实现。
就类似于三极管的集电极输出。
4. 开漏输出电路的结构如上图:1. 内部输出1时MOS管截止,输出与地断开,这时候IO口其实是没有驱动能力的,需要外部连接上拉电阻才能输出高电平,才能驱动数字器件;2. 内部输出0时MOS管导通,输出低电平,所以开漏能输出低电平;5. 准双向IO在学51单片机的时候老师告诉我们,51单片机的IO口是准双向的,什么是准双向的?示意如下:其结构类似于开漏输出,只不过是把上拉电阻集成到了单片机内部。
6. IO口如何应用对于推挽输出的IO口可以直接输出高低电平驱动功耗较小的数字器件,但对于开漏输出的话必须要在外部接上拉电阻才行。
比如说LPC11C14单片机的片上I2C资源就是开漏输出的,如果要使用这两个引脚做输出就必须加上拉电阻,如下图所示:进入论坛的方式:在公众号对话框内,输入数字“1”,即可进入论坛,无需注册,就是这么简单。
图1双向端口的硬件图当z=0时,上面输出的管子开通,此时数据可以从上面的管子中输出,这时双向端口就作为输出口;当z =1时,上面的管子被置为高阻态,数据不能从上面的管子输出,此时数据只可以从下面的管子由外向内输入,这时的双向端口是输入口。
限于篇幅,我们做一个简单的模型来说明双向端口的设计。
下面我们用V e r i l o g 硬件语言进行双向端口的程序设计,为了看出双向端口分别作为输!"入端口和输出端口的功能,我们的模块分别定义一个数据输入口d i n 和一个数据输出口d o u t ,一个三态门选通信号z ,触发时钟c l k ,还有双向端口d i -n o u t。
我们设数据为8位宽。
图2为该模块图:图2定义的模块图输入口d i n 定义:i n pu t [7:0]d i n ;当双向端口d i n o u t 作为输出口时,我们从d i n 端口输入数据到模块中,让数据从d i n o u t 口出来。
输出口d o u t 定义:o u t pu t [7:0]d o u t ;当双向端口d i n o u t 作为输入口时,我们让数据从d i n o u t 口输入,从输出口d o u t 输出。
双向端口di n o u t 定义:i n o u t [7:0]d i n o u t ; 三态门选通信号z :i n p u t z ; 当z=1时,把三态门置为高阻态,这时d i n o u t 作为输入口用;当z =0时,开通三态门,这时d i n o u t 作为输出口用。
三态门控制语句为:a s s i g nd i n o u t =(!z )?d i n _r e g :8'b z ; 总的完整程序如下:mo d u l e d i n o u t (d i n ,z ,c l k ,d o u t ,d i n o u t ); i n p u t [7:0]d i n ; i n pu t z ; i n pu t c l k ; o u t pu t [7:0]d o u t ;i n o u t [7:0]d i n o u t ; r e g [7:0]d o u t ; r e g [7:0]d i n _r e g; a s s i g nd i n o u t =(!z )?d i n _r e g:8'b z ; a l w a y s @(p o s e d g e c l k ) b e gi n i f (!z)d i n _r e g =d i n ;e l s ed o u t =d i n o u t ;e n dEn d m o d u l e 2 仿真及初始化双向端口下面我们对上述程序进行时序仿真。
单片机P0口是双相口,而P1P2P3是准双相口。
举个例子:相信大家都理解准妈妈,就是怀孕的女人,当然这里也是这样的,就不是真正的双相口了。
为什么P0是双向口,这里的差别是什么呢?最主要原因是:P0没有上拉电阻,所以当P0最IO口的时候一定要加上上拉电阻,否则的话,你输出的1就是无效了,这样T2截止了,那么P0都就是呈现高阻状态了。
下图分别是P0,P1P2P3的读写数据,红线表示输出,蓝线表示输入(读引脚)还有一个就是读锁存器的,没画出来。
在读引脚的时候,有一点注意:每当读引脚的时候要确保场效应管T2是截止的,否则的话1(高电平)外部数据读不出来,T2会把它拉低,所以通过MOV PX,FFH,把T2截止,就完美了。
在单片机学习、开发和应用中,IO口的配置对功能的实现起着重要的作用,下面介绍常见的四种配置,而现在很多单片机都兼有这四种配置,可供选择。
一.准双向口配置如下图,当IO输出为高电平时,其驱动能力很弱,外部负载很容易将其拉至低电平。
当IO 输出为低电平时,其驱动能力很强,可吸收相当大的电流。
准双向口有三个上拉晶体管,一个“极弱上拉”,当端锁存器为逻辑“1”时打开,当端口悬空时,“极弱上拉”将端口上拉至高电平。
第二个上拉晶体管为“弱上拉”,当端口锁存器为逻辑“1”且端口本身也为“1”时打开,此上拉提供的电流,使准双向口输出为“1”。
如果此时端口被外部装置拉到逻辑“0”时,通过施密特触发器,控制“弱上拉”关闭,而“极弱上拉”维持开状态,为了把这个端口拉低,外部装置必须有足够的灌电流能力,使管脚上的电压,降到门槛电以下。
第三个上拉晶体管为“强上拉”,当端口锁存器由“0”跳变到“1”时,这个上拉用来加快端口由逻辑“0”到逻辑“1”的转换速度。
准双向口做为输入时,通个一个施密特触如器和一个非门,用以干扰和滤波。
准双向口用作输入时,可对地接按键,如下图1,当然也可以去掉R1直接接按键,当按键闭合时,端口被拉至低电平,当按键松开时,端口被内部“极弱上拉”晶体管拉至高电平。
io口原理-概述说明以及解释1.引言1.1 概述IO口(Input/Output port)是计算机系统中与外部设备进行信息传输的接口。
它是计算机系统中最主要的通信手段之一。
通过IO口,计算机可以与各类输入输出设备进行数据交互,实现信息的输入和输出。
IO口的作用是将计算机内部处理好的数据传送到外部设备,或接受外部设备传来的数据并传送给计算机内部进行处理。
在计算机系统中,各种外部设备(如显示器、键盘、鼠标、打印机、硬盘等)都需要通过IO口与计算机进行数据交互,以完成各自的功能。
可以说,没有IO口,计算机与外部设备之间的信息交流就无法进行。
IO口的工作原理是通过发送和接收电信号来实现数据传输。
计算机通过控制IO口的电平(高电平或低电平)来控制外部设备的工作状态,通过读取和解析外部设备发送的电信号来获取外部设备传来的数据。
这样,计算机与外部设备之间就建立了一种双向的数据传输通道。
IO口的应用领域非常广泛。
它在个人电脑、嵌入式系统、通信设备、工业自动化等领域都有着重要的应用。
在个人电脑中,各种外设如键盘、鼠标、摄像头等都是通过IO口与计算机进行连接和通信的。
在嵌入式系统中,各种传感器、执行器等设备也需要通过IO口与主控制器进行数据交互。
在通信设备和工业自动化领域,IO口可以与外部设备进行高速数据传输,实现各种通信和控制功能。
总之,IO口在计算机领域的应用非常广泛,它是计算机与外部设备之间信息交流的重要通道。
综上所述,IO口在计算机系统中具有重要的作用。
它是计算机与外部设备进行数据交换的接口,通过发送和接收电信号实现数据传输。
在各种应用领域中都存在着IO口的应用,其重要性不可忽视。
随着科技的不断发展,IO口也在不断地进化和改进,未来它将继续发挥着重要的作用,并带来更多的应用和创新。
1.2文章结构2. 正文2.1 IO口的定义和作用IO口(Input/Output port),简称IO口,是计算机系统中的一个重要组成部分。
:准双向一般只能用于数字输入输出,输入时为弱上拉状态(约50K上拉),端口只有两种状态:高或低。
2:双向除用于数字输入输出外还可用于模拟输入输出,模拟输入时端口通过方向控制设置成为高阻输入状态。
双向端口有三种状态:高、低或高阻。
3:初始状态和复位状态下准双向口为1,双向口为高阻状态.有带些比较器的单片机,比较器的输入端只能做在双向口,不能做在准双向口.所以软件设计的第一步就是对 I/O 口的设置.
标准51内核单片机的IO口,P0口则为双向三态输入输出口,P1\P2\P3是准双向IO口,没有方向控制,做输入时需要先往端口数据寄存器写1才行(也可看作此时为输出,端口输出高电平)。
对单片机的控制,其实就是对I/O口的控制,无论单片机对外界进行何种控制,或接受外部的何种控制,都是通过I/O口进行的。
51单片机总共有P0、P1、P2、P3四个8位双向输入输出端口,每个端口都有锁存器、输出驱动器和输入缓冲器。
4个I/O端口都能作输入输出口用,其中P0和P2通常用于对外部存储器的访问。
51系列单片机有4个I/O端口,每个端口都是8位准双向口,共占32根引脚。
每个端口都包括一个锁存器(即专用寄存器P0~P3)、一个输出驱动器和输入缓冲器。
通常把4个端口笼统地表示为P0~P3。
在无片外扩展存储器的系统中,这4个端口的每一位都可以作为准双向通用I/O 端口使用。
在具有片外扩展存储器的系统中,P2口作为高8位地址线,P0口分时作为低8位地址线和双向数据总线。
51单片机4个I/O端口线路设计的非常巧妙,学习I/O端口逻辑电路,不但有利于正确合理地使用端口,而且会给设计单片机外围逻辑电路有所启发。
下面简单介绍一下输入/输出端口结构。
1.P0口和P2的结构
1.1 P0口的结构:下图为P0口的某位P0.n(n=0~7)结构图,它由一个输出锁存器、两个三态输入缓冲器和输出驱动电路及控制电路组成。
从图中可以看出,P0口既可以作为I/O用,也可以作为地址/数据线用。
.2 P0口作为普通I/O口:
①输出时,CPU发出控制电平“0”封锁“与”门,将输出上拉场效应管T1截止,同时使多路开关MUX把锁存器与输出驱动场效应管T2栅极接通。
故内部总线与P0口同相。
由于输出驱动级是漏极开路电路,若驱动NMOS或其它拉流负载时,需要外接上拉电阻。
P0的输出级可驱动8个LSTTL负载。
②输入时----分读引脚或读锁存器
读引脚:由传送指令(MOV)实现;
下面一个缓冲器用于读端口引脚数据,当执行一条由端口输入的指令时,读脉冲把该三态缓冲器打开,这样端口引脚上的数据经过缓冲器读入到内部总线。
读锁存器:有些指令如:ANL P0,A称为“读-改-写”
指令,需要读锁存器。
上面一个缓冲器用于读端口锁存器数据。
**原因:如果此时该端口的负载恰是一个晶体管基极,且原端口输出值为1,那么导通了的PN结会把端口引脚高电平拉低;若此时直接读端口引脚信号,将会把原输出的“1”电平误读为“0”电平。
现采用读输出锁存器代替读引脚,图中,上面的三态缓冲器就为读锁存器Q端信号而设,读输出锁存器可避免上述可能发生的错误。
**
说明:
⏹
P0口必须接上拉电阻;
⏹
在读信号之前数据之前,先要向相应的锁存器做写1操作的I/O口称为准双向口;
⏹
三态输入缓冲器的作用:
⏹
(ANL P0,A)
准双向口:
从图中可以看出,在读入端口数据时,由于输出驱动FET并接在引脚上,如果T2导通,就会将输入的高电平拉成低电平,产生误读。
所以在端口进行输入操作前,应先向端口锁存器写“1”,使T2截止,引脚处于悬浮状态,变为高阻抗
输入。
这就是所谓的准双向口。
2、P0作为地址/数据总线
在系统扩展时,P0端口作为地址/数据总线使用时,分为:
(1) P0引脚输出地址/数据信息: CPU发出控制电平“1”,打开“与”门,又使多路开关MUX把CPU的地址/数据总线与T2栅极反相接通,输出地址或数据。
由图上可以看出,上下两个FET处于反相,构成了推拉式的输出电路,其负载能
力大大增强。
P0作为地址/数据总线----真正的双向口
(2)P0引脚输出地址/输入数据:
输入信号是从引脚通过输入缓冲器进入内部总线。
此时,CPU自动使MUX向下,并向P0口写“1”,“读引脚”控制信号有效,下面的缓冲器打开,外部数据读
入内部总线。
二、P2的内部结构
2.1 .P2口作为普通I/O口:CPU发出控制电平“0”,使多路开关MUX倒向锁
存器
输出Q端,构成一个准双向口。
其功能与P1相同。
2.2 .P2口作为地址总线:在系统扩展片外程序存储器扩展数据存储器且容量超过256B (用MOVX @DPTR指令)时,CPU发出控制电平“1”,使多路开关MUX 倒内部地址线。
此时,P2输出高8位地址。
三.P1口、P3口的内部结构
①P1口的一位的结构
它由一个输出锁存器、两个三态输入缓冲器和输出驱动电路组成----准双向口。
②P3的内部结构
一、作为通用I/O口与P1口类似----准双向口(W=1)
二、P3第二功能(Q=1)
此时引脚部分输入(Q=1、W=1) ,部分输出(Q=1、W输出) 。
P3第二功能各引脚功能定义:
P3.0:RXD串行口输入
P3.1:TXD串行口输出
P3.2:INT0外部中断0输入
P3.3:INT1外部中断1输入
P3.4:T0定时器0外部输入
P3.5:T1定时器1外部输入
P3.6:WR外部写控制
P3.7:RD外部读控制
综上所述:当P0作为I/O口使用时,特别是作为输出时,输出级属于开漏电路,必须外接上拉电阻才会有高电平输出;如果作为输入,必须先向相应的锁存器写“1”,才不会影响输入电平。
当CPU内部控制信号为“1”时,P0口作为地址/数据总线使用,这时,P0口就无法再作为I/O口使用了。
P1、P2 和P3 口为准双向口, 在内部差别不大, 但使用功能有所不同。
P1口是用户专用 8 位准双向I/O口, 具有通用输入/输出功能, 每一位都能独立地设定为输入或输出。
当有输出方式变为输入方式时, 该位的锁存器必须写入“1”, 然后才能进入输入操作。
P2口是 8 位准双向I/O口。
外接I/O设备时, 可作为扩展系统的地址总线, 输出高8位地址, 与P0 口一起组成 16 位地址总线。
对于 8031 而言, P2 口一般只作为地址总线使用, 而不作为I/O线直接与外部设备相连。