i2c通信控制器侧设置linux gpio模拟i2c设置什么模式

MDIO、GPIO、I2C、EEPROMD概念
MDIO(Management Data Input/Output),对G比特而言,称为管理数据输入输出 (MDIO)。该由IEEE通过标准IEEE
802.3的若干条款加以定义。MDIO是一种简单的双线,将管理器件(如MAC控制器、)与具备管理功能的收发器(如多端口吉比特以太网收发器或 10GbE
XAUI收发器)相连接,从而控制收发器并从收发器收集状态信息。可收集的信息包括链接状态、传输速度与选择、断电、低功率、TX/RX模式选择、自动协商控制、环回模式控制等。除了拥有 IEEE
要求的功能之外,收发器厂商还可添加更多的信息收集功能。
88E1111是一个phy,它具备符合IEEE802.3u标准22款所规定的标准管理接口,它包含2个管脚:MDC和MDIO。MDC是管理数据的时钟输入,最高速率可达8.3MHz。MDIO是管理数据的输入输出双向接口,数据是与MDC的。MDIO的工作流程为:
MDIO接口在没有传输数据的空闲状态(IDLE)数据线MDIO处于高阻态。
MDIO出现一个2bit的开始标识码(01)一个读/写操作开始。
MDIO出现一个2bit数据来标识是读操作(10)还是写操作(01)。 MDIO出现一个5bit数据标识PHY的地址。
MDIO出现一个5bitPHY地址。
MDIO需要2个时钟的访问时间。 MDIO串行读出/写入16bit的数据。
MDIO恢复成IDLE状态,同时MDIO进入高阻状态。
General Purpose Input Output
(通用输入/输出)简称为GPIO,或总线扩展器,利用工业标准I2C、SMBus或SPI接口简化了I/O口的扩展。当微控制器或芯片组没有足够的I/O端口,或当系统需要采用远端或控制时,GPIO产品能够提供额外的控制和监视功能。
GPIO是相对于芯片本身而言的,如某个管脚是芯片的GPIO脚,则该脚可作为输入或输出高或低电平使用,当然某个脚具有复用的功能,即可做GPIO也可做其他用途。
温度的例子,其实温度采集最终都得转换成电压信号,通过GPIO口给某个脚。
输出可用于控制继电器、蜂呤器、LED等&输入可以获取传感器状态、高低电平、低速信号等
也就是说你可以把这些引脚拿来用作任何一般用途的输入输出,例如用一根引脚连到led的一极来控制它的亮灭,也可以用一根(一些)引脚连到一个传感器上以获得该传感器的状态,这给cpu提供了一个方便的控制周边设备的途经。如果没有足够多的gpio管脚,在控制一些外围设备时就会力有不逮,这时可采取的方案是使用CPLD来帮助管理。
与单片机类似,GPIO就是芯片的引脚,管脚是可编程的
可对引脚的工作模式进行设置:输入模式(检测输入信号),输出模式(输出0或1),
高阻状态(常用于AD转换),还有禁止或允许上内部下拉电阻(上拉:管脚通过电阻接高电平,
下拉:管脚通过电阻接地,也可以外部接上拉或下拉电阻),还要管脚复用等功能,即通过
对内部寄存器的设置使引脚既可以工作在一般模式,作为普通的GPIO口使用,
也可已工作在特殊模式,比如作为外部中断信号输入引脚等等。如果不设置GPIO引脚,CPU
工作时有一个初始化模式,可以从datasheet上了解,对于管脚相关的内部硬件的工作原理
请从简单的单片机内部结构了解,原理是一样的
I2C&即 I2C总线 。
I2C(Inter-Integrated Circuit)总线是由公司开发的两线式串行总线,用于连接及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。
I2C 总线支持任何&生产过程(CMOS、双极性)。通过串行数据(SDA)线和串行时钟(SCL)线在连接到总线的器件间传递信息。每个器件都有一个唯一的地址识别(无论是——MCU、&驱动器、存储器或键盘接口),而且都可以作为一个发送器或接收器(由器件的功能决定)。
1、只要求两条总线线路:一条串行数据线SDA,一条串行时钟线SCL;
2、每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;
3、它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;
4、串行的8
位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;
5、连接到相同总线的IC 数量只受到总线的最大电容400pF 限制。
发送器:发送数据到总线的器件;
接收器:从总线接收数据的器件;
主机:启动数据传送并产生时钟信号的设备;
从机:被主机寻址的器件;
多主机:同时有多于一个主机尝试控制总线但不破坏传输;
主模式:用I2CNDAT支持自动字节计数的模式;位I2CRM,I2CSTT,I2CSTP控制数据的接收和发送;
从模式:发送和接收操作都是由I2C模块自动控制的;
仲裁:是一个在有多个主机同时尝试控制总线但只允许其中一个控制总线并使传输不被破坏
同步:两个或多个器件同步时钟信号的过程 。
eeprom是非易失存储器的一种,掉电可以保持数据,如果你有一些设置的参数,想掉电复位后可以用,就放到eeprom里,这是最常用的啦,其他的就看你具体的需求了。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。stm8s I2C总线总是处于忙状态 - STM8 - 意法半导体STM32/STM8技术社区
后使用快捷导航没有帐号?
查看: 6002|回复: 14
stm8s I2C总线总是处于忙状态
在线时间3 小时
主题帖子好友
新手上路, 积分 18, 距离下一级还需 32 积分
新手上路, 积分 18, 距离下一级还需 32 积分
求助各位大大,我使用的是STM8S103K3,想要使用stm8通过I2C控制一个LCD的驱动芯片,在I2C写的时候,判断bus是否处于忙状态的循环无法跳出,通过示波器量I2C总线的时候是高电平。目前怀疑是自己I2C初始化不正确,但网上有的说要设置GPIO PIN,有的说不需要,请问一下I2C的初始化到底要怎么初始化?下面是我的代码:#define I2C_SLAVE_ADDRESS& & & & 0x7C
#define I2C_PORT& & & &&&GPIOB
#define I2C_SDA_PIN& & & &&&GPIO_PIN_4
#define I2C_SCL_PIN& & & &&&GPIO_PIN_5
void main(void)
{
& & GPIO_Init(I2C_PORT, I2C_SDA_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);
& & GPIO_Init(I2C_PORT, I2C_SCL_PIN, GPIO_MODE_OUT_OD_HIZ_SLOW);
& & CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
& & I2C_EEInit();
}复制代码void Init_I2C(void)
{
& & & & /* 复位设备 */
& & & & I2C_DeInit();
& & & & /* 初始化设备 */
& & & & I2C_EEInit();
}复制代码void I2C_EEInit(void)
{
& & & & u8 Input_Clock = 0x0;
& & & & Input_Clock = CLK_GetClockFreq() / 1000000;
& & & & /* I2C Peripheral Enable */
& & & & I2C_Cmd(ENABLE);
& & & & /* Apply I2C configuration after enabling it */
& & & & I2C_Init(I2C_MAX_STANDARD_FREQ, I2C_SLAVE_ADDRESS,
& & & & & & & & & & & &&&I2C_DUTYCYCLE_2, I2C_ACK_CURR,
& & & & & & & & & & & &&&I2C_ADDMODE_7BIT, Input_Clock);
}复制代码void I2C_EE_ByteWrite(u8 u8CmdType, u8 *pu8Buffer, u8 u8WriteAddr)
{
& & & & /* while the bus is busy */
& & & & while (I2C_GetFlagStatus(I2C_FLAG_BUSBUSY))
& & & & {
& & & & }
& & & & /* Send start condition */
& & & & I2C_GenerateSTART(ENABLE);
& & & &
& & & & /* Test on EV5 and clear it */
& & & & while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT))
& & & & {
& & & & }
& & & &
& & & & /* Send devices address for write */
& & & & I2C_Send7bitAddress(I2C_SLAVE_ADDRESS, I2C_DIRECTION_TX);
& & & & /* Test on EV6 and clear it */
& & & & while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
& & & & {
& & & & }
& & & & /* Send cmd type be written */
& & & & I2C_SendData(u8CmdType);
& & & & /* Test on EV8 and clear it */
& & & & while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
& & & & {
& & & & }
& & & & /* Send Address to be written & wait event detection */
& & & & I2C_SendData(u8WriteAddr);
& & & & /* Test on EV8 and clear it */
& & & & while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
& & & & {
& & & &
& & & & if (u8CmdType == 0x80)
& & & & {
& & & & & & & & /* Send the byte to be written */
& & & & & & & & I2C_SendData(*pu8Buffer);
& & & & & & & & /* Test on EV3 and clear it */
& & & & & & & & while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING))
& & & & & & & & {
& & & & & & & &
& & & & & & & & }
& & & & }
& & & & /* Send stop condition */
& & & & I2C_GenerateSTOP(ENABLE);
& & & &
}复制代码这个问题困扰我好久了,请大家帮忙看一下,谢谢各位了!!!
在线时间16 小时
主题帖子好友
中级会员, 积分 258, 距离下一级还需 242 积分
中级会员, 积分 258, 距离下一级还需 242 积分
终于搞清楚了,是在仿真或烧写的OPTIONS中配置复用功能,不需要在程序中写配置代码,好大一个坑啊,花了我一天时间
在线时间3 小时
主题帖子好友
新手上路, 积分 18, 距离下一级还需 32 积分
新手上路, 积分 18, 距离下一级还需 32 积分
问题已经解决了...I2C是复用的GPIO的管脚,我没有设置这个GPIO为I2C导致的...
在线时间191 小时
ST金币1927
主题帖子好友
金牌会员, 积分 3616, 距离下一级还需 1384 积分
金牌会员, 积分 3616, 距离下一级还需 1384 积分
ST的硬件I2C让人很头痛。还是用模拟的吧。简单的来而且还方便
在线时间42 小时
主题帖子好友
中级会员, 积分 442, 距离下一级还需 58 积分
中级会员, 积分 442, 距离下一级还需 58 积分
在线时间206 小时
ST金币1165
主题帖子好友
金牌会员, 积分 3288, 距离下一级还需 1712 积分
金牌会员, 积分 3288, 距离下一级还需 1712 积分
直接模拟吧
在线时间13 小时
主题帖子好友
初级会员, 积分 185, 距离下一级还需 15 积分
初级会员, 积分 185, 距离下一级还需 15 积分
问题已经解决了...I2C是复用的GPIO的管脚,我没有设置这个GPIO为I2C导致的...
请问具体怎么解决,遇到同样的问题。一直忙~~~
在线时间188 小时
主题帖子好友
高级会员, 积分 993, 距离下一级还需 7 积分
高级会员, 积分 993, 距离下一级还需 7 积分
没有设置这个GPIO为I2C导致的
在线时间5 小时
主题帖子好友
初级会员, 积分 77, 距离下一级还需 123 积分
初级会员, 积分 77, 距离下一级还需 123 积分
直接在配置字中设置端口为I2C.然后不需要再进行GPIO设置
在线时间238 小时
ST金币1489
主题帖子好友
对于STM8S103K来说 PB4/5做 I2C并不用特别的选项字配置。相关I2C配置好就能用的。
楼主说 “I2C是复用的GPIO的管脚,我没有设置这个GPIO为I2C导致的” 很费解。
楼主说“判断bus是否处于忙状态的循环无法跳出,通过示波器量I2C总线的时候是高电平。”
高电平并非是忙的提示,相反是空闲的提示。不知楼主要表达什么。
在线时间118 小时
ST金币2299
主题帖子好友
金牌会员, 积分 2364, 距离下一级还需 2636 积分
金牌会员, 积分 2364, 距离下一级还需 2636 积分
站长推荐 /2
Tel: 3-8064
备案号: 苏ICP备号-2
|||意法半导体STM32/STM8技术社区
Powered by查看: 2212|回复: 0
STM32 MCU GPIO双向口使用的话题
本文的作者是milershao关于STMCU的GPIO的双向使用话题不新鲜了,好像还经常有人在此遇点麻烦。这可能跟总有新人接触STMCU不无关系。几天前一个研究生MM使用STM32的GPIO模拟I2C通信,读取一时钟芯片的时钟的过程中遇到麻烦。查看其代码,看到其在SDA数据线读写代码时,发现其来回做SDA脚的GPIO模式切换。那样写虽然没有错,但那样写多少有点累或繁琐。 无独有偶,昨天一广州工程师也是用某STM32芯片的GPIO模拟I2C通信。他发现通信程序总是堵塞在代码某地方。后来发现将那2根通信线的GPIO模式由输入改为OD或PP就正常了。程序正是正常了,但有点不知所以然的意味,如鲠在喉。 其实,STMCU的GPIO是支持双向通信的。如果希望某GPIO做双向传输,将其配制为OD输出模式,将相应输出寄存器位写1就可以了,不用在程序代码里往返切换。 至于第二个案例,他用GPIO模拟I2C通信,其SDA应是双向数据口,只是把他定义为输入肯定是不行的,那样的话完全没法做输出了。如果这样,通信自然无法正常。他把SDA口配置为OD才是合理的。下图是GPIO配置为输入时的情况。如果把GPIO配置为PP是否可以做双向口呢,很多人发现有时可行有时不可行。我们不妨先看看STMCU GPIO配置为输出时的原理框图。
对于OD配置,结合上拉,输出电平的高低确定。当给端口输出寄存器写1时,端口对外成高阻态。外部电平真实反映在端口上,输入电平不受内部输出控制电路的影响,而且GPIO管脚相对安全。 对于PP配置端口,跟OD配置相比,差别就大了。首先对于PP配置,总有一边管子导通,对外来电平会有些影响。若给PP配置端口输出寄存器写0,只有下方的N-MOS导通到地,端口不论外部电平如何变化都会锁定在低电平,当外来输入高电平时有管脚烧坏风险。如果给PP配置端口输出寄存器写1,只让上方P-MOS导通。如果外来电平为高没什么问题,如果外来电平是低,也有可能管脚过流烧掉。当然到底烧不烧还得结合外围电路的配置。整体而言,对于PP配置输出口不合适作输入的读取,所以不建议使用PP做双向口用。关于STMCU的GPIO的双向使用话题不新鲜了,好像还经常有人在此遇点麻烦。这可能跟总有新人接触STMCU不无关系。几天前一个研究生MM使用STM32的GPIO模拟I2C通信,读取一时钟芯片的时钟的过程中遇到麻烦。查看其代码,看到其在SDA数据线读写代码时,发现其来回做SDA脚的GPIO模式切换。那样写虽然没有错,但那样写多少有点累或繁琐。 无独有偶,昨天一广州工程师也是用某STM32芯片的GPIO模拟I2C通信。他发现通信程序总是堵塞在代码某地方。后来发现将那2根通信线的GPIO模式由输入改为OD或PP就正常了。程序正是正常了,但有点不知所以然的意味,如鲠在喉。 其实,STMCU的GPIO是支持双向通信的。如果希望某GPIO做双向传输,将其配制为OD输出模式,将相应输出寄存器位写1就可以了,不用在程序代码里往返切换。 至于第二个案例,他用GPIO模拟I2C通信,其SDA应是双向数据口,只是把他定义为输入肯定是不行的,那样的话完全没法做输出了。如果这样,通信自然无法正常。他把SDA口配置为OD才是合理的。下图是GPIO配置为输入时的情况。如果把GPIO配置为PP是否可以做双向口呢,很多人发现有时可行有时不可行。我们不妨先看看STMCU GPIO配置为输出时的原理框图。
对于OD配置,结合上拉,输出电平的高低确定。当给端口输出寄存器写1时,端口对外成高阻态。外部电平真实反映在端口上,输入电平不受内部输出控制电路的影响,而且GPIO管脚相对安全。 对于PP配置端口,跟OD配置相比,差别就大了。首先对于PP配置,总有一边管子导通,对外来电平会有些影响。若给PP配置端口输出寄存器写0,只有下方的N-MOS导通到地,端口不论外部电平如何变化都会锁定在低电平,当外来输入高电平时有管脚烧坏风险。如果给PP配置端口输出寄存器写1,只让上方P-MOS导通。如果外来电平为高没什么问题,如果外来电平是低,也有可能管脚过流烧掉。当然到底烧不烧还得结合外围电路的配置。整体而言,对于PP配置输出口不合适作输入的读取,所以不建议使用PP做双向口用。
Powered by你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
新手提问,勿喷
GPIO_Mode_Out_OD
#define SCL_SET()
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_SET)
#define SCL_RESET()
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_9,GPIO_PIN_RESET)
#define SDA_SET()
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_10,GPIO_PIN_SET)
#define SDA_RESET()
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_10,GPIO_PIN_RESET)
#define READ_SDA()
HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_10)
//***************[i][b][/i][i][b][/i]以下是模拟I2C函数[/b][/b]************************//
/*================================================================
【名 称】void I2CDelay (unsigned char t)
【功 能】模拟IIC用的短延时
================================================================*/
void I2CDelay (unsigned char t)
while(t--);
/*================================================================
【名 称】void I2CInit(void)
【功 能】I2C初始化,空闲状态
================================================================*/
void I2CInit(void)
SDA_SET();
SCL_SET();
/*================================================================
【名 称】void I2CStart(void)
【功 能】I2C起始信号
【备 注】SCL、SDA同为高,SDA跳变成低之后,SCL跳变成低
================================================================*/
void I2CStart(void)
SDA_SET();
SCL_SET();
I2CDelay(10);
SDA_RESET();
I2CDelay(20);
SCL_RESET();
I2CDelay(20);
/*================================================================
【名 称】void I2CStop(void)
【功 能】I2C停止信号
【备 注】SCL、SDA同为低,SCL跳变成高之后,SDA跳变成高
================================================================*/
void I2CStop(void)
SDA_RESET();
SCL_RESET();
I2CDelay(10);
SCL_SET();
I2CDelay(10);
SDA_SET();
I2CDelay(10);
/*================================================================
【名 称】unsigned char I2CWRByte(unsigned char WRByte)
【功 能】I2C写一个字节数据,返回ACK或者NACK
【备 注】从高到低,依次发送
================================================================*/
unsigned char I2CWRByte(unsigned char WRByte)
SCL_RESET();
for(i=0;i&8;i++)
if(WRByte&0x80)
SDA_SET();
SDA_RESET();
I2CDelay(10);
SCL_SET();
//输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
I2CDelay(50);
SCL_RESET();
I2CDelay(10);
WRByte &&= 1;
SDA_SET();
SCL_SET();
I2CDelay(20);
if(READ_SDA()==1)
//SDA为高,收到NACK
SCL_RESET();
I2CDelay(50);
return NACK;
//SDA为低,收到ACK
SCL_RESET();
I2CDelay(50);
return ACK;
/*================================================================
【名 称】unsigned char I2CRDByte(unsigned char AckValue)
【功 能】I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
【备 注】从高到低,依次接收
================================================================*/
unsigned char I2CRDByte(unsigned char AckValue)
unsigned char i,RDByte=0;
SCL_RESET();
SDA_SET();
//释放总线
for (i=0;i&8;i++)
RDByte &&= 1; //移位
SCL_SET();
//给出上升沿
I2CDelay(30); //延时等待信号稳定
if(READ_SDA()==1)
//采样获取数据
RDByte |= 0x01;
RDByte &= 0
SCL_RESET();
//下降沿,从机给出下一位值
I2CDelay(10);
if(AckValue )//应答状态
SDA_SET();
SDA_RESET();
I2CDelay(10);
SCL_SET();
I2CDelay(50);
SCL_RESET();
SDA_SET();
I2CDelay(1);
return RDB
默认配置为开漏输出 ,外部上拉,是可以直接读端口的!
亲,我好像见过你!
(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复用推挽输出我们平时接触的最多的也就是推挽输出、开漏输出、上拉输入这三种,
一般模拟IIC的时候是在要读的时候改GPIO的寄存器改为输入要输出的时候改GPIO寄存器到输出
要回复问题请先或
浏览: 1674
关注: 7 人

我要回帖

更多关于 i2c gpio custom 的文章

 

随机推荐