找回密码
 注册
搜索
查看: 1894|回复: 9

[讨论] GPIO问题

[复制链接]
发表于 2006-1-21 14:26:00 | 显示全部楼层 |阅读模式
请问一般在什么情况下使用GPIO,怎么使用?为什么有的处理器那么多GPIO?都用来干什么?还望各位大侠不嫌问题简单给予解答,谢谢
发表于 2006-1-21 16:26:00 | 显示全部楼层
通用可编程输入/输出口,很多芯片具有很多功能模块,很多功能模块的引脚除了具有本模块特有的功能外,都有第二功能,就是可以作为通用的可编程输入/输出口,数字的。这种GPIO可用来作为外部芯片的控制信号等等。当然有的芯片还有那种通用可编程输入/输出口,只有一个功能,没有第二功能的。[br]<p align=right><font color=red>+3 RD币</font></p>
点评回复

使用道具 举报

 楼主| 发表于 2006-1-23 11:41:00 | 显示全部楼层
GPIO用来对外部芯片进行控制,怎么设置它的工作方式呢?是写内部Registor吗?
点评回复

使用道具 举报

发表于 2006-1-23 12:41:00 | 显示全部楼层
<P>GPIO不光用于外部芯片控制,他是CPU与外部功能单元信息互通的一个桥梁。</P><P>GPIO有专门的控制寄存器,用于控制GPIO的工作方式,包括工作状态(输入还是输出)、中断等。</P>[br]<p align=right><font color=red>+3 RD币</font></p>
点评回复

使用道具 举报

发表于 2006-1-23 15:52:00 | 显示全部楼层
CPU对每个GPIO都有寄存器可以控制它的工作方式,输出还是输入、是否做为中断信号、中断是否可以屏蔽、中断优先级、边沿触发、电平触发、事件捕获、第二功能选择等等,具体功能要参考相应芯片的spec,不能一概而论,芯片的大部分引脚都可以作为GPIO来使用。同时很多GPIO又具有第二功能,我们使用这些芯片的主要目的就是为了使用某些引脚的第二功能。[br]<p align=right><font color=red>+3 RD币</font></p>
点评回复

使用道具 举报

 楼主| 发表于 2006-1-23 16:50:00 | 显示全部楼层
<P>cxin2说的很有道理,单你所说的基本都是瞬时信号,我还看到有些电路把GPIO用作IIC信号(SDA,SCL)的周期信号,这是怎么实现的呢?</P>
点评回复

使用道具 举报

发表于 2006-1-24 09:31:00 | 显示全部楼层
这是通过GPIO软件模拟I2C实现的,网上有很多源码可以借鉴的,这里我也贴两个别人的代码
I2C总线驱动程序(用两个普通IO模拟I2C总线)--(免费)
文件: PCF8563T.C
1 /**————————————————————
2 〖说明〗I2C总线驱动程序(用两个普通IO模拟I2C总线)
3 包括100Khz(T=10us)的标准模式(慢速模式)选择,
4 和400Khz(T=2.5us)的快速模式选择,
5 默认11.0592Mhz的晶振。

10 —————————————————————*/
11
12 #ifndef SDA
13 #define SDA P0_0
14 #define SCL P0_1
15 #endif
16
17 extern uchar SystemError;
18
19 #define uchar unsigned char
20 #define uint unsigned int
21 #define Byte unsigned char
22 #define Word unsigned int
23 #define bool bit
24 #define true 1
25 #define false 0
26
27 #define SomeNOP(); _nop_();_nop_();_nop_();_nop_();
28
29 /**--------------------------------------------------------------------------------
30 调用方式:void I2CStart(void) ﹫2001/07/0 4
31 函数说明:私有函数,I2C专用
32 ---------------------------------------------------------------------------------*/
33 void I2CStart(void)
34 {
35 EA=0;
36 SDA=1; SCL=1; SomeNOP();//INI
37 SDA=0; SomeNOP(); //START
38 SCL=0;
39 }
40
41 /**--------------------------------------------------------------------------------
42 调用方式:void I2CStop(void) ﹫2001/07/0 4
43 函数说明:私有函数,I2C专用
44 ---------------------------------------------------------------------------------*/
45 void I2CStop(void)
46 {
47 SCL=0; SDA=0; SomeNOP(); //INI
48 SCL=1; SomeNOP(); SDA=1; //STOP
49 EA=1;
50 }
51
52 /**--------------------------------------------------------------------------------
53 调用方式:bit I2CAck(void) ﹫2001/07/0 4
54 函数说明:私有函数,I2C专用,等待从器件接收方的应答
55 ---------------------------------------------------------------------------------*/
56 bool WaitAck(void)
57 {
58 uchar errtime=255;//因故障接收方无ACK,超时值为255。
59 SDA=1;SomeNOP();
60 SCL=1;SomeNOP();
61 while(SDA) {errtime--; if (!errtime) {I2CStop();SystemError=0x11;return false;}}
62 SCL=0;
63 return true;
第1 页
文件: PCF8563T.C 2001-11-27, 18:39:20
64 }
65
66 /**--------------------------------------------------------------------------------
67 调用方式:void SendAck(void) ﹫2001/07/0 4
68 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
69 ---------------------------------------------------------------------------------*/
70 void SendAck(void)
71 {
72 SDA=0; SomeNOP();
73 SCL=1; SomeNOP();
74 SCL=0;
75 }
76
77 /**--------------------------------------------------------------------------------
78 调用方式:void SendAck(void) ﹫2001/07/0 4
79 函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。
80 }**--------------------------------------------------------------------------------
81 void SendNotAck(void)
82 {
83 SDA=1; SomeNOP();
84 SCL=1; SomeNOP();
85 SCL=0;
86 }
87
88 /**--------------------------------------------------------------------------------
89 调用方式:void I2CSend(uchar ch) ﹫2001/07/0 5
90 函数说明:私有函数,I2C专用
91 ---------------------------------------------------------------------------------*/
92 void I2CSendByte(Byte ch)
93 {
94 uchar i=8;
95 while (i--)
96 {
97 SCL=0;_nop_();
98 SDA=(bit)(ch&0x80); ch<<=1; SomeNOP();
99 SCL=1; SomeNOP();
100 }
101 SCL=0;
102 }
103
104 /**--------------------------------------------------------------------------------
105 调用方式:uchar I2CReceive(void) ﹫2001/07/0 5
106 函数说明:私有函数,I2C专用
107 ---------------------------------------------------------------------------------*/
108 Byte I2CReceiveByte(void)
109 {
110 uchar i=8;
111 Byte ddata=0;
112 SDA=1;
113 while (i--)
114 {
115 ddata<<=1;
116 SCL=0;SomeNOP();
117 SCL=1;SomeNOP();
118 ddata|=SDA;
119 }
120 SCL=0;
121 return ddata;
122 }
123
124
125 //---------------------------------------------------------------------------
126 //开始PCF8563T驱动程序
第2 页
文件: PCF8563T.C 2001-11-27, 18:39:20
127 /**--------------------------------------------------------------------------------
128 调用方式:void GetPCF8563(uchar firsttype,uchar count,uchar *buff) ﹫2001/08/0 7
129 函数说明:读取时钟芯片PCF8563的时间,设置要读的第一个时间类型firsttype,并设置读取
130 的字节数,则会一次把时间读取到buff中。顺序是:
131 0x02:秒/0x03:分/0x04:小时/0x05:日/0x06:星期/0x07:月(世纪)/0x08:年
132 ---------------------------------------------------------------------------------*/
133 void GetPCF8563(uchar firsttype,uchar count,uchar *buff)
134 {
135 uchar i;
136 I2CStart();
137 I2CSendByte(0xA2);
138 WaitAck();
139 I2CSendByte(firsttype);
140 WaitAck();
141
142 I2CStart();
143 I2CSendByte(0xA3);
144 WaitAck();
145
146 for (i=0;i147 {
148 buff=I2CReceiveByte();
149 if (i!=count-1) SendAck();//除最后一个字节外,其他都要从MASTER发应答。
150 }
151
152 SendNotAck();
153 I2CStop();
154 }
155
156
157 /**--------------------------------------------------------------------------------
158 调用方式:void SetPCF8563(uchar timetype,uchar value) ﹫2001/08/0 7
159 函数说明:调整时钟。timetype是要改的时间类型,value是新设置的时间值(BCD格式)。
160 0x02:秒/0x03:分/0x04:小时/0x05:日/0x06:星期/0x07:月(世纪)/0x08:年
161 ---------------------------------------------------------------------------------*/
162 void SetPCF8563(uchar timetype,uchar value)
163 {
164 I2CStart();
165 I2CSendByte(0xA2);
166 WaitAck();
167 I2CSendByte(timetype);
168 WaitAck();
169 I2CSendByte(value);
170 WaitAck();
171 I2CStop();
172 }
173
174 /**--------------------------------------------------------------------------------
175 调用方式:void SetAlarmHour(uchar count) ﹫2001/08/0 7
176 函数说明:设置报警闹钟在一天的第count点报警。例如:count=23,则在晚上11点报警。
177 ---------------------------------------------------------------------------------*/
178 void SetAlarm(uchar alarmtype,uchar count)
179 {
180 SetPCF8563(0x01,0x02);
181 SetPCF8563(alarmtype,count);
182 }
183
184 /**--------------------------------------------------------------------------------
185 调用方式:void CleanAlarm(void) ﹫2001/08/0 7
186 函数说明:清除所有报警设置。
187 ---------------------------------------------------------------------------------*/
188 void CleanAlarm(void)
189 {
第3 页
文件: PCF8563T.C 2001-11-27, 18:39:20
190 SetPCF8563(0x01,0x00);
191 SetPCF8563(0x09,0x80);
192 SetPCF8563(0x0A,0x80);
193 SetPCF8563(0x0B,0x80);
194 SetPCF8563(0x0C,0x80);
195 // SetPCF8563(0x0D,0x00);
196 // SetPCF8563(0x0E,0x03);
197 }
198
199
200 /*--------------------------------------------------------------------------------
201 调用方式:uchar read1380(uchar command )
202 函数说明:read1380()返回当前时间, command指要返回的时间类型。
203 秒:81H 分钟:83H 小时:85H 日期:87H 星期:89H 星期几:8BH 年:8D H
204 ---------------------------------------------------------------------------------*/
205 uchar read1380 (uchar command)
206 {
207 uchar time;
208 GetPCF8563(command,1,&time);
209 return time;
210 }
211
212 /*--------------------------------------------------------------------------------
213 调用方式:void write1380(uchar command ,uchar time )
214 函数说明:write1380()往HT1380写命令和数据,command是命令字, time是后写入的数据
215 ---------------------------------------------------------------------------------*/
216 void write1380(uchar command ,uchar time)
217 {
218 SetPCF8563(command,time);
219 }
220
221
222 /*--------------------------------------------------------------------------------
223 调用方式:void time_display(uchar x0,uchar y0 )
224 函数说明:time_display()在指定的x0,y0坐标,以00:00:00格式显示当前时间。
225 ---------------------------------------------------------------------------------*/
226 //uchar time[]="00:11:11";
227
228 void time_display(uchar x0,uchar y0,bit type) //液晶时间显示
229 {
230 uchar time[]="00:00:00";
231 uchar con[3];
232 uchar time_type;
233 GetPCF8563(0x02,3,con);
234
235 time[0]=(con[2]>>4)+'0';
236 time[1]=(con[2]&0x0f)+'0';
237 time[3]=(con[1]>>4)+'0';
238 time[4]=(con[1]&0x0f)+'0';
239 time[6]=(con[0]>>4)+'0';
240 time[7]=(con[0]&0x0f)+'0';
241
242 time[8]=0;
243 if(type==1)
244 {
245 time_type=0xff;
246 }
247 else
248 {
249 time_type=0;
250 }
251 dipchar0(x0,y0,F57,1,time_type,time);
252 }[
点评回复

使用道具 举报

发表于 2006-1-24 09:31:00 | 显示全部楼层
代码,移植到ARM上只要修改define定义,函数后面去掉small,提供页写模式(burst write),效率非常高
#include <w77c32.h>
#include <intrins.h>
#define LOW 0
#define HIGH 1
#define FALSE 0
#define TRUE 1
typedef unsigned char INT8U;
typedef unsigned int INT16U;
sbit SCL=P1^6;
sbit SDA=P1^7;
INT8U E2PRomPageBuf[256];
/*
*******************************************************************
******************************
*/
void Delay10ms(void) small
{
//put ur delay func here,for debug use
}
/*
*******************************************************************
******************************
*/
void I2CInit(void) small
{
    SDA=HIGH;
    SCL=HIGH;
}
/*
*******************************************************************
******************************
*/
static void I2CStart(void) small
{
    SDA=HIGH;
    SCL=HIGH;
    SDA=LOW;
    _nop_();
    SCL=LOW;
}
/*
*******************************************************************
******************************
*/
static void I2CStop(void) small
{
    SCL=LOW;
    SDA=LOW;
    SCL=HIGH;
    SDA=HIGH;
}
/*
*******************************************************************
******************************
*/
static bit I2CSend(INT8U ch) small
{
    INT8U i;
    for(i=0;i<8;i++)
    {
        SDA=(bit)(ch&0x80);
        SCL=HIGH;
        ch<<=1;
        SCL=LOW;
    }
    SDA=HIGH;
    SCL=HIGH;
    _nop_(); /* wait slave-ACK */
    //_nop_();_nop_();_nop_();
    if(SDA) {SCL=LOW;return(FALSE);}
    else {SCL=LOW;return(TRUE);}
}
/*
*******************************************************************
******************************
*/
static INT8U I2CReceive(void) small
{
    INT8U i,ch=0;
    for(i=0;i<8;i++)
    {
        ch<<=1;
        SCL=HIGH;
        ch|=SDA;
        SCL=LOW;
    }
    SDA=HIGH; /* to reduce IO power consunption */
    return(ch);
}
/*
*******************************************************************
******************************
*/
static void I2CAck(void) small
{
    SDA=LOW;
    SCL=HIGH;
    _nop_();
    _nop_();
    SCL=LOW;
    SDA=HIGH; /* to reduce IO power consunption */
}
/*
*******************************************************************
******************************
*/
static void I2CNoAck(void) small
{
    SDA=HIGH;
    SCL=HIGH;
    _nop_();
    _nop_();
    SCL=LOW;
}
/*
*******************************************************************
******************************
*/
bit E2PRomByteWrite(INT8U romnum,INT16U address,INT8U ch) small
{
    romnum<<1;
    romnum&=0x06;
    romnum|=0xA0;
    I2CStart();
    if(!I2CSend(romnum))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(address>>8)))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(address&0x00FF)))
        {I2CStop();return(FALSE);};
    if(!I2CSend(ch))
        {I2CStop();return(FALSE);};
    I2CStop();
    return(TRUE);
}
/*
*******************************************************************
******************************
*/
bit E2PRomPageWrite(INT16U page) small
{
    INT8U i;
    page<<=7;
    I2CStart();
    if(!I2CSend(0xA0))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page>>8)))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page&0x00FF)))
        {I2CStop();return(FALSE);};
    for(i=0;i<128;i++)
        if(!I2CSend(E2PRomPageBuf))
             {I2CStop();return(FALSE);};
    I2CStart();
    if(!I2CSend(0xA2))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page>>8)))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page&0x00FF)))
        {I2CStop();return(FALSE);};
    for(i=128;i<256;i++)
        if(!I2CSend(E2PRomPageBuf))
             {I2CStop();return(FALSE);};
    I2CStop();
    return(TRUE);
}
/*
*******************************************************************
******************************
*/
bit E2PRomPageRead(INT16U page) small
{
    INT8U i;
    page<<=7;
    I2CStart();
    if(!I2CSend(0xA0))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page>>8)))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page&0x00FF)))
        {I2CStop();return(FALSE);};
    I2CStart();
    if(!I2CSend(0xA1))
        {I2CStop();return(FALSE);};
    for(i=0;i<127;i++)
    {
        E2PRomPageBuf=I2CReceive();
        I2CAck();
    }
    E2PRomPageBuf=I2CReceive();
    I2CNoAck();
    I2CStop();
    I2CStart();
    if(!I2CSend(0xA2))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page>>8)))
        {I2CStop();return(FALSE);};
    if(!I2CSend((INT8U)(page&0x00FF)))
        {I2CStop();return(FALSE);};
    I2CStart();
    if(!I2CSend(0xA3))
        {I2CStop();return(FALSE);};
    for(i=127;i<256;i++)
    {
        E2PRomPageBuf=I2CReceive();
        I2CAck();
    }
    E2PRomPageBuf=I2CReceive();
    I2CNoAck();
    I2CStop();
    return(TRUE);
}[br]<p align=right><font color=red>+3 RD币</font></p>
点评回复

使用道具 举报

发表于 2006-4-26 10:24:00 | 显示全部楼层
<P 0cm 0cm 0pt; TEXT-INDENT: 26.25pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align=left>它一般用于逻辑控制,当它作为输出端口时,通过高低电平控制外围器件,当它作为输入端口时,通过检测到的高低电平来判定外围器件的工作状态。<p></p></P><P 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left>例如1.GPIO口用于键盘矩阵电路:将按键排列成矩阵形式,每条水平线和垂直线在交叉处不直接连通, 而是通过一个按键加以连接。判断键盘中有无键按下 将全部行线置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下。若所有列线均为高电平,则键盘中无键 按下。在确认有键按下后,即可进入确定具体闭合键 的过程。依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。CPU通过检测到的GPIO口的高低电平确定那个键被按下。GPIO还用于键盘背光电路,通过把GPIO置高置低来导通或关闭三极管,从而控制背光的开与关。<p></p></P><P 0cm 0cm 0pt; TEXT-INDENT: 21pt; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-char-indent-count: 2.0; mso-char-indent-size: 10.5pt" align=left>同时GPIO口还用于UIM卡电路部份,USB接口部分,LCD显示电路,同时他还可以通过置低置高来控制红绿指示灯的显示,检测电池电压,控制扬声器的工作模式等等. <p></p></P><P 0cm 0cm 0pt; TEXT-INDENT: 26.25pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align=left> <p></p></P>[br]<p align=right><font color=red>+3 RD币</font></p>
点评回复

使用道具 举报

发表于 2006-7-6 14:22:00 | 显示全部楼层
<P>GPIO和普通的port有什么区别(如8051上的P0~P3)?</P>
点评回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

Archiver|手机版|小黑屋|52RD我爱研发网 ( 沪ICP备2022007804号-2 )

GMT+8, 2024-12-25 01:24 , Processed in 0.053875 second(s), 16 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表