IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。它是半双工通信方式。
IIC总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。
IIC总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
IIC串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,其时钟信号是由主控器件产生。所有接到IIC总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。对于并联在一条总线上的每个IC都有唯一的地址。
一般情况下,数据线SDA和时钟线SCL都是处于上拉电阻状态。因为:在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。
IIC总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。同时我们还要介绍其空闲状态、数据的有效性、数据传输。
空闲状态
当IIC总线的数据线SDA和时钟线SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
起始信号与停止信号
起始信号:当时钟线SCL为高期间,数据线SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号;
停止信号:当时钟线SCL为高期间,数据线SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
应答信号
发送器每发送一个字节(8个bit),就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节;
应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放数据线SDA,以便主控接收器发送一个停止信号P。
数据有效性
IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定;只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
即:数据在时钟线SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。
代码
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "24cxx.h"
#include "usmart.h"
//ALIENTEK Mini STM32¿ª·¢°å·¶Àý´úÂë19
//IICʵÑé
//¼¼ÊõÖ§³Ö£ºwww.openedv.com
//¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾
//ҪдÈëµ½24c02µÄ×Ö·û´®Êý×é
const u8 TEXT_Buffer[]={"MiniSTM32 IIC TEST"};
#define SIZE sizeof(TEXT_Buffer)
int main(void)
{
u8 key;
u16 i=0;
u8 datatemp[SIZE];
Stm32_Clock_Init(9); //ϵͳʱÖÓÉèÖÃ
uart_init(72,9600); //´®¿Ú³õʼ»¯Îª9600
delay_init(72); //ÑÓʱ³õʼ»¯
LED_Init(); //³õʼ»¯ÓëLEDÁ¬½ÓµÄÓ²¼þ½Ó¿Ú
LCD_Init(); //³õʼ»¯LCD
usmart_dev.init(72); //³õʼ»¯USMART
KEY_Init(); //°´¼ü³õʼ»¯
AT24CXX_Init(); //IIC³õʼ»¯
POINT_COLOR=RED;//ÉèÖÃ×ÖÌåΪºìÉ«
LCD_ShowString(60,50,200,16,16,"Mini STM32");
LCD_ShowString(60,70,200,16,16,"IIC TEST");
LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(60,110,200,16,16,"2014/3/9");
LCD_ShowString(60,130,200,16,16,"WK_UP:Write KEY0:Read"); //ÏÔʾÌáʾÐÅÏ¢
while(AT24CXX_Check())//¼ì²â²»µ½24c02
{
LCD_ShowString(60,150,200,16,16,"24C02 Check Failed!");
delay_ms(500);
LCD_ShowString(60,150,200,16,16,"Please Check! ");
delay_ms(500);
LED0=!LED0;//DS0ÉÁ˸
}
LCD_ShowString(60,150,200,16,16,"24C02 Ready!");
POINT_COLOR=BLUE;//ÉèÖÃ×ÖÌåΪÀ¶É«
while(1)
{
key=KEY_Scan(0);
if(key==WKUP_PRES)//WK_UP °´ÏÂ,дÈë24C02
{
LCD_Fill(0,170,239,319,WHITE);//Çå³ý°ëÆÁ
LCD_ShowString(60,170,200,16,16,"Start Write 24C02....");
AT24CXX_Write(0,(u8*)TEXT_Buffer,SIZE);
LCD_ShowString(60,170,200,16,16,"24C02 Write Finished!");//Ìáʾ´«ËÍÍê³É
}
if(key==KEY0_PRES)//KEY0 °´ÏÂ,¶ÁÈ¡×Ö·û´®²¢ÏÔʾ
{
LCD_ShowString(60,170,200,16,16,"Start Read 24C02.... ");
AT24CXX_Read(0,datatemp,SIZE);
LCD_ShowString(60,170,200,16,16,"The Data Readed Is: ");//Ìáʾ´«ËÍÍê³É
LCD_ShowString(60,190,200,16,16,datatemp);//ÏÔʾ¶Áµ½µÄ×Ö·û´®
}
i++;
delay_ms(10);
if(i==20)
{
LED0=!LED0;//ÌáʾϵͳÕýÔÚÔËÐÐ
i=0;
}
}
}