STM8S105S4 I2C
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; //为下一次接收使能应答
}
STM8S105S4I2 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)