前面讲过两个常用的串口,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
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;
}
附上stm8s在IAR环境下的项目工程,包括了SPI、IIC、PWM、AWU、USART、EEPROM等片上硬件的初始化代码。
http://download.csdn.NET/detail/devintt/9454188
读操作:开始 -> 发送外设地址 -> 开始 ->发送需要读取的寄存器地址 -> 读一个字节 -> (可能再读一个字节) ->。。。 -> 结束
上一篇:stm8s开发(七) SPI的使用:SPI主机通信!
下一篇:stm8s开发(六) EXIT的使用:做一个外部中断的按钮
推荐阅读
史海拾趣
随着公司实力的不断增强,DDD公司开始积极拓展市场。公司针对不同领域的需求,推出了多种定制化产品,满足了客户的多样化需求。同时,DDD公司还积极参与国内外展览和交流活动,加强与同行的合作与交流,提高了公司的知名度和影响力。这些市场拓展策略的实施,为DDD公司的快速发展奠定了坚实基础。
创新是Advanced Analog公司发展的核心动力。公司始终坚持自主研发和技术创新,不断推出新的产品和技术。这些新产品不仅满足了市场的多样化需求,也进一步巩固了公司在电源管理IC领域的领先地位。同时,Advanced Analog还积极关注行业发展趋势和未来技术走向,为公司的长远发展做好战略布局。
在电子行业的快速发展中,Dremio公司以其独特的数据治理技术崭露头角。他们开发了一种新型的数据处理引擎,能够直接在云数据湖中查询和分析数据,无需将数据复制到专有数据仓库中。这一创新技术大大提高了数据处理效率,降低了成本,并为企业提供了更灵活的数据管理方式。Dremio凭借这一技术,迅速在电子行业中树立了领先地位。
德艺隆自创立之初,就专注于电子开关、插座和连接器的研发与生产。在创始人陈建新的带领下,公司聚集了一批从业多年的设计开发、生产管理等技术人员。他们日夜兼程,不断攻克技术难关,逐渐在行业内树立了技术领先的地位。一次,公司接到一个要求极高精度的连接器订单,技术人员经过反复试验,最终成功研发出符合要求的连接器,赢得了客户的赞誉,也为公司赢得了更多的市场份额。
为了拓展国际市场,德艺隆制定了国际化战略。他们积极参加国际展会,与全球客户建立联系;同时,公司还加大了对海外市场的投入,建立了海外销售网络和售后服务体系。通过多年的努力,德艺隆的产品已经出口到多个国家和地区,赢得了国际市场的认可。
每次换手机,都附送新充电器,不同品牌又有不同款式充电器,结果旧的扔掉,超级不环保。 全球10大手机商,终于同意明年开始,向用户提供统一标准的充电器,预料充电器将在全球步入一统时代。 现在随机送充电器十分浪费,欧洲 ...… 查看全部问答∨ |
|
这几天在看802.11的物理层的FHSS(Frequency Hopping Spread Spectrum , 调频扩频),工作在2.4GHz,使用了79个信道,每个信道的带宽为1MHZ,这里的带宽是这什么意思? 谢谢!… 查看全部问答∨ |
|
这是一个孔深在50米的一个封闭孔,孔的直径大约在60毫米,我想用雷达测距在孔口发射和接收来测孔深不知道可不可行,希望大家给提点建议,看看雷达测距是否可行,或者还有没有别的测距方式能测到孔底,激光测距好像不太可行,因为空不一定是很直的。 ...… 查看全部问答∨ |
|
我想实现这样一个功能,在zigbee组建的网络里面,有一个主设备,一个备份主设备,其他是从设备,当主设备出现故障后,网络自动切换到从设备上工作(即从备份主设备变成主设备,原来的主设备转为 ...… 查看全部问答∨ |