本帖最后由 Alvanbai 于 2017-4-5 13:02 编辑
各位前辈好,请教一下。我用的模拟I2C,发送一个字节8bit的数据,发现只要最后一位数据为1,SDA就异常。最后一位为0的话是正常的,请教一下可能的原因,谢谢。
图中分别发送的是0xFE和0xFF黄线是SDA,红线是SDL。经过测试,发现规律只要是最后一位数据为1,波形就拉不下去。
0xFE
0xFF
驱动代码参考了这位前辈,感谢。
http://www.openedv.com/posts/list/61112.htm
I2C.C
[mw_shl_code=c,true]/**
******************************************************************************
* @file IIC.c
* @brief simulation function
* @CPU STM32F10x
*
@compiler Keil uVision V4.74
* @author Alex.fang(china shenzhen)
* @copyright GPL
* @version V1.0.0
* @date 02-Sept-2015
******************************************************************************
* @attention
*/
GPIO_InitTypeDef GPIO_InitStructure;
void IIC_Init(void)
{
RCC_APB2PeriphClockCmd(IIC_RCC_APB2Periph_GPIOx, ENABLE);
GPIO_InitStructure.GPIO_Pin = IIC_SDA_GPIO_Pin | IIC_SCL_GPIO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);
GPIO_SetBits(IIC_GPIOx,IIC_SDA_GPIO_Pin | IIC_SCL_GPIO_Pin); //PB10,PB11 输出高
}
void SDA_OUT(void)
{
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IIC_SDA_GPIO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 //推挽输出 //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);
}
void SDA_IN(void)
{
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = IIC_SDA_GPIO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IIC_GPIOx, &GPIO_InitStructure);
}
unsigned char SDA_READ(void)
{
return GPIO_ReadInputDataBit(IIC_GPIOx, IIC_SDA_GPIO_Pin);
}
void IIC_SDA_1(void)
{
GPIO_SetBits(IIC_GPIOx, IIC_SDA_GPIO_Pin);
}
void IIC_SDA_0(void)
{
GPIO_ResetBits(IIC_GPIOx, IIC_SDA_GPIO_Pin);
}
void IIC_SCL_1(void)
{
GPIO_SetBits(IIC_GPIOx, IIC_SCL_GPIO_Pin);
}
void IIC_SCL_0(void)
{
GPIO_ResetBits(IIC_GPIOx, IIC_SCL_GPIO_Pin);
}
void IIC_Start(void)
{
SDA_OUT(); //sda output
IIC_SDA_1();
IIC_SCL_1();
delay_us(4);
IIC_SDA_0(); //START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL_0(); //hold scl line, prepare to transmit data
}
void IIC_Stop(void)
{
SDA_OUT(); //sda output mode
IIC_SCL_0();
IIC_SDA_0(); //STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL_1();
IIC_SDA_1(); //indicate transmit over
delay_us(4);
}
unsigned char IIC_Wait_Ack(void)
{
unsigned char ucErrTime = 0;
SDA_IN(); //set as input mode
IIC_SDA_1();
delay_us(1);
IIC_SCL_1();
delay_us(1);
while(SDA_READ())
{
ucErrTime++;
if(ucErrTime > 250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL_0(); //release scl line
return 0;
}
void IIC_Ack(void)
{
IIC_SCL_0();
SDA_OUT();
IIC_SDA_0();
delay_us(2);
IIC_SCL_1();
delay_us(2);
IIC_SCL_0();
}
void IIC_NAck(void)
{
IIC_SCL_0();
SDA_OUT();
IIC_SDA_1();
delay_us(2);
IIC_SCL_1();
delay_us(2);
IIC_SCL_0();
}
void IIC_Send_Byte(unsigned char txd)
{
unsigned char i;
SDA_OUT();
IIC_SCL_0();//push down scl to start transmit data
for(i = 0; i < 8; ++i)
{
if(txd & 0x80)
{
IIC_SDA_1();
}
else
{
IIC_SDA_0();
}
txd <<= 1;
delay_us(2);
IIC_SCL_1();
delay_us(2);
IIC_SCL_0();
delay_us(2);
}
}
unsigned char IIC_Read_Byte(unsigned char ack)
{
unsigned char i, res = 0;
SDA_IN(); //SDA input mode
for(i = 0; i < 8; ++i ){
IIC_SCL_0();
delay_us(2);
IIC_SCL_1();
res <<= 1;
if(SDA_READ()){
res++;
}
delay_us(1);
}
if (!ack){
IIC_NAck();//make NACK
}
else {
IIC_Ack(); //make ACK
}
return res;
} [/mw_shl_code]
I2C.H
[mw_shl_code=c,true]#define IIC_SDA_GPIO_Pin GPIO_Pin_12
#define IIC_SCL_GPIO_Pin GPIO_Pin_15
#define IIC_GPIOx GPIOB
#define IIC_RCC_APB2Periph_GPIOx RCC_AHBPeriph_GPIOB
void IIC_Init(void);
void SDA_OUT(void);
void SDA_IN(void);
unsigned char SDA_READ(void);
void IIC_SDA_1(void);
void IIC_SDA_0(void);
void IIC_SCL_1(void);
void IIC_SCL_0(void);
void IIC_Start(void);
void IIC_Stop(void);
unsigned char IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);
void IIC_Send_Byte(unsigned char txd);
unsigned char IIC_Read_Byte(unsigned char ack);
#endif[/mw_shl_code]
谢谢,试过改变IO口mode了,不起作用。当前就是开漏输出。
一周热门 更多>