stm8s开发(八) IIC的使用:IIC主机通信!

前面讲过两个常用的串口,UART和SPI,这次这次讲解一下另一个常用的串口:IIC(I2C)通信

 

科普IIC:一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。

 

通信过程:
主模式时,IIC接口启动数据传输并产生时钟信号。串行数据传输总是以起始条件开始并以停止条件结束。起始条件和停止条件都是在主模式下由软件控制产生。
从模式时,IIC接口能识别它自己的地址(7位或10位)和广播呼叫地址。软件能够控制开启或禁止广播呼叫地址的识别。
数据和地址按8位/字节进行传输,高位在前。跟在起始条件后的1或2个字节是地址(7位模式为1个字节,10位模式为2个字节)。地址只在主模式发送。
在一个字节传输的8个时钟后的第9个时钟期间,接收器必须回送一个应答位(ACK)给发送器。参考下图。

详细协议可以参考:http://blog.csdn.net/subkiller/article/details/6854910

 

和SPI差不多,使用IIC无非就一个初始化,一个数据发送,一个数据接收,三大功能。

初始化分初始化为主机、从机,不过一般和外部芯片通信单片机都是作为主机。

 

 

void IIC_Master_Init(void)

{

CLK_PCKENR1 |= 0x01; //使能IIC外设时钟

 

PB_DDR &= 0xcf;

PB_CR1 &= 0xcf;

PB_CR2 &= 0xcf;

 

I2C_CR1 = 0x00; //允许时钟延展,禁止广播呼叫,禁止iic

I2C_FREQR = 0x01; //输入时钟频率8MHz(应该是1MHZ才对,可能是原创者之笔误)

I2C_OARH = 0x40; //七位地址模式

I2C_OARL = 0xa0; //自身地址0xa0

I2C_CCRL = 0xff; //

I2C_CCRH = 0x00; //标准模式

I2C_TRISER = 0x02;

I2C_CR1 |= 0x01; //使能iic外设

}


这里使用的是STM8S105片上的IIC引脚PB4、PB5。另外就是需要使能IIC的时钟。

 

发送和接收数据这里只给出一个最简单的例子,因为不同的外部芯片的通信方式不一样,不过一般都是:

读操作:开始  -> 发送外设地址 -> 开始  ->发送需要读取的寄存器地址 -> 读一个字节  -> (可能再读一个字节)  ->。。。  -> 结束
写操作:开始  -> 发送外设地址 -> 发送需要写入的寄存器地址 -> 写一个字节  -> (可能再写一个字节)  ->。。。  -> 结束

 

 

 

void IIC_Write_Byte(u8 DeviceAddress, u8 Address, u8 Data)

{

vu8 temp = 0;

while((I2C_SR3 & 0x02) != 0); //等待IIC总线空闲

IIC_Start();

while((I2C_SR1 & 0x01) == 0); //EV5,起始信号已经发送

I2C_DR = (DeviceAddress & 0xfe); // 发送iic从器件物理地址,最低位0,写操作

while((I2C_SR1 & 0x02) == 0); //地址已经被发送

temp = I2C_SR1; //清除ADDR标志位

temp = I2C_SR3;

while((I2C_SR1 & 0x80) == 0); //等待发送寄存器为空

I2C_DR = Address; //发送要写入的寄存器地址

while((I2C_SR1 & 0x04) == 0); //等待发送完成

while((I2C_SR1 & 0x80) == 0); //等待发送寄存器为空

I2C_DR = Data; //发送要写入的数据

while((I2C_SR1 & 0x04) == 0); //等待发送完成

temp = I2C_SR1; //清零BTF标志位

temp = I2C_DR;

IIC_Stop(); //发送停止信号

}

 

unsigned char IIC_Read_Byte(u8 DeviceAddress, u8 Address)

{

vu8 temp = 0;

short read_data = 0;

while((I2C_SR3 & 0x02) != 0); //等待IIC总线空闲

I2C_CR2 |= 0x04; //使能ACK

IIC_Start();

while((I2C_SR1 & 0x01) == 0); //EV5,起始信号已经发送

I2C_DR = (DeviceAddress & 0xfe); // 发送iic从器件物理地址,最低位0,写操作

while((I2C_SR1 & 0x02) == 0); //地址已经被发送

temp = I2C_SR1; //清除ADDR标志位

temp = I2C_SR3;

while((I2C_SR1 & 0x80) == 0); //等待发送寄存器为空

I2C_DR = Address; // 发送要读取的寄存器地址

while((I2C_SR1 & 0x04) == 0); //等待数据发送完成

 

IIC_Start();

while((I2C_SR1 & 0x01) == 0); //EV5,起始信号已经发送

I2C_DR = (DeviceAddress | 0x01); // 发送iic从器件物理地址,最低位1,读操作

while((I2C_SR1 & 0x02) == 0); //地址已经被发送

temp = I2C_SR1; //清除ADDR标志位

temp = I2C_SR3;

while((I2C_SR1 & 0x40) == 0); //等待接收数据寄存器非空

read_data = I2C_DR;

I2C_CR2 &= 0xfb; //读取数据下,发送stop必须禁止ack,才能释放从机

temp = I2C_SR1; //清零BTF标志位

temp = I2C_DR;

IIC_Stop();

return read_data;

}

附:频率寄存器详细资料

  • 0
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值