微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM8S105S4 I2C

STM8S105S4 I2C

时间:12-02 来源:互联网 点击:
STM8S105S4 I2C这样配置可以从机发数据,从机接数据就不行,是什么问题
//I2C端口初始化
GPIO_Init(GPIOE,GPIO_PIN_1|GPIO_PIN_2, GPIO_MODE_OUT_OD_HIZ_SLOW);
void I2C_init(void)
{
I2C_CCRH = 0; //标准I2C接口
I2C_CCRL = 80 ;
I2C_FREQR = 16;
I2C_OARL = (I2CAddr<1);
I2C_OARH= 0x40;
I2C_ITR =0x06;
I2C_CR1 =0x01;
I2C_CR2 |=0x04;
}
@far @interrupt void I2C_Handler (void)
{
u8 state1,state2,state3;
state1 = I2C_SR1;
state2 = I2C_SR2;
state3 = I2C_SR3;
//地址匹配
if((state1&0x02)!=0){I2C_CR2 |= 0x04;}
//接收到数据,需要处理
if( (state1& 0x40) != 0)
{
I2C_CR2|= 0x04;
temp1= I2C_DR;
SetOutput(temp1);
}
//从机需要发送数据
if((state1 & 0x80) != 0)
{
I2C_DR = num++;
}
if((state2 & 0x04) != 0)I2C_SR2 &= ~0x04; //应答失败,清除该位
if((state1 & 0x10) != 0)
{
I2C_CR2 = 0x02;
}
}
我写成这样子,发现现在是从机发数据是没问题,从机接收数据不行,没有进入中断。

成功传输一次正确的数据后就进不去了。程序还正常运行

#define I2CAddr 0x01
在主机
//主机写数据,从机接,这个不行
Soft_I2C_Start();
Soft_I2C_Write(0x02);
Soft_I2C_Write(0xAA);
Soft_I2C_Stop();
//主机接收数据。没有运行上一段程序,主机可以接收数据,运行上段,主机接收数据都是255
Soft_I2C_Start();
Soft_I2C_Write(0x03);
var0=Soft_I2C_Read(1);
Soft_I2C_Stop();
这个软I2C在控制其它设备是没有问题的,主机用的芯片是STM32。应该是没有问题的

解决问题:

这就是了,你第一次成功后了,你把应答给关掉了,还怎么接收啊。。。以后配寄存器要多一个心眼才是。

问题就在这里I2C_CR2 = 0x02; 修改为I2C_CR2 |= 0x02;原因是修改了,第一次成功后,没有再回复

1.PC0,PC1初始化,GPIO_Init(GPIOC, GPIO_Pin_1 | GPIO_Pin_0, GPIO_Mode_Out_OD_HiZ_Fast);
2.必须连接硬件
3.总线不能busy,一定要空闲
初始化代码如下:
GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_Out_OD_HiZ_Slow);
GPIO_Init(GPIOC, GPIO_Pin_1, GPIO_Mode_Out_OD_HiZ_Slow);
CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE);
I2C_Init(I2C1, 50000, 0xA5, I2C_Mode_I2C, I2C_DutyCycle_2,
I2C_Ack_Enable, I2C_AcknowledgedAddress_7bit);
//注:I2C_Init()里已经使能了I2C,所以可以不用I2C_Cmd(I2C1, ENABLE);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

stm8 自带I2C终于调试成功。

1,此次调试I2C受益多多,首先证明官方的那个写EEPROM的程序是对的。
2,这次调试TW8816开始调不通的原因是误以为寄存器地址是16位的(芯片公司的业务也是这么说的,我相信了),才让我看到的数据不同,但我想,有数据了,而且用WHILE等待的方法,程序跑通了,说明连上了从机。
3, I2C的GPIO不要配置,我看到有些同仁把GPIO配置了。
4,为了大家用好STM8的I2C,我把程序烤下来。

void IIC_Init(void)
{
UCHAR temp;

CLK_PCKENR1 |= 0x01;

I2C_FREQR |= 0x10; //输入外设时钟频率为1MHz
I2C_CR1 = 0x00; //禁止I2C外设
I2C_CCRH&= ~0xcf;
I2C_CCRL&= ~0xff;
I2C_TRISER = 0x11;
I2C_CCRL = 0x10;
I2C_CCRH = 0x00;
I2C_CR1 |= 0x01; //开启I2C外设
I2C_CR2 |= 0x04; //当前接收字节返回应答
I2C_CR2 &= 0x08;
I2C_OARL = 0x86; //自身地址
I2C_OARH = 0x40;
}

void Read_8816(UCHAR *pBuffer, UCHAR index, UCHAR NumByteToRead)
{
UCHAR temp;

while(I2C_SR3 & 0x02); //等待总线空闲
I2C_CR2 |= 0x01; //产生起始位
while(!(I2C_SR1 & 0x01)); //等待START发送完
I2C_DR = 0x8a; //发送8816器件地址
while(!(I2C_SR1 & 0x02)); //等特7位器件地址发送完
temp = I2C_SR1;
temp = I2C_SR3;
I2C_DR = (UCHAR)(index);
while(!(I2C_SR1 & 0x84));

I2C_CR2 |= 0x01; //产生重复起始位
while(!(I2C_SR1 & 0x01)); //等待START发送完
I2C_DR = 0x8b; //读
while(!(I2C_SR1 & 0x02)); //等特7位器件地址发送完
temp = I2C_SR1;
temp = I2C_SR3;
while(NumByteToRead) //要读几个字节
{
if(NumByteToRead == 1)
{
I2C_CR2 &= ~0x04; //不返回应答
I2C_CR2 |= 0x02; //产生停止位
}
if(I2C_SR1 & 0x40)
{
temp = I2C_SR1;
Buff[8-NumByteToRead]=I2C_DR;
*pBuffer = Buff[8-NumByteToRead];
pBuffer++;
NumByteToRead--;
}
}
I2C_CR2 |= 0x04;
I2C_CR2 &= ~0x08; //为下一次接收使能应答
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top