I2C总线的软件程序模拟—基于Niso II处理器
1、I2C的特点
I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。I2C总线的另一个优点是,它支持多主控(multimastering),其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。
2、I2C信号种类
I2C有3种类型的信号,分别是开始信号、结束信号、应答信号。
开始信号:SCL为高电平,SDA由高电平向低电平跳变,开始传输数据;
结束信号:SCL为高电平,SDA由低电平向高电平跳变,结束传输数据;
应答信号:SCL为高电平,SDA为低电平,表示一个字节数据接收或发送完毕;
还有一种是非应答信号,即SCL为高电平,SDA为高电平,一般应用于数据读操作结束。
3、I2C读写时序
写时序:①向总线发出需要写数据器件地址和写信号并等待应答信号;②向总线发送写地址并等待应答信号;③向总线发送所要写的数据并等待应答信号;④主节点产生结束信号,完成写操作。
读时序:①主节点向总线发送需要读取数据器件的地址和写信号并等待应答信号;②主节点向总线发送随机的数据地址并等待应答信号;③主节点向总线发送需要读取数据器件的地址和读信号并等待应答信号;④接收数据,接收完成后产生非应答信号与结束信号,完成读操作。
4、具体程序分析
/********************************
* 函数名称: start()
* 函数功能: I2C启动
* 输入参数:无
* 返回值 :无
*******************************/
staticvoid start(void)
{
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SDA_BASE, 1); //1指‘写’0指‘读’
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 1);
usleep(10);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE, 0);
usleep(5);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
}
/************************
* 函数名称: stop()
* 函数功能: I2C停止
* 输入参数:无
* 返回值 :无
*********************/
staticvoid stop(void)
{
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SDA_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE, 0);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 1);
usleep(10);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE, 1);
usleep(5);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
usleep(10);
}
/************************
* 函数名称: ack()
* 函数功能: I2C应答信号检测
* 输入参数:无
* 返回值 :无
*********************/
staticvoid ack(void)
{
alt_u8 tmp;
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SDA_BASE, 0);
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 1);
usleep(5);
tmp = IORD_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE);
while(tmp==0x01);
usleep(5);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
usleep(10);
}
/************************
* 函数名称: send_ack()
* 函数功能:发送应答信号,主要是非应答信号
* 输入参数: unsigned char
* 返回值 :无
*********************/
staticvoid send_ack(unsigned char ack)
{
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SDA_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE, ack);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 1);
usleep(10);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
}
/************************
* 函数名称: iic_write()
* 函数功能: I2C写一个字节的数据
* 输入参数: dat
* 返回值 :无
*********************/
void iic_write(alt_u8 dat)
{
alt_u8 i, tmp;
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SDA_BASE, 1);
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 1);
for(i=0; i<8; i++){
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
usleep(5);
tmp = (dat & 0x80) ? 1 : 0;
dat <<= 1;
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE, tmp);
usleep(5);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 1);
usleep(10);
}
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 0);
usleep(10);
}
/************************
* 函数名称: iic_read()
* 函数功能: I2C读取一个字节的数据
* 输入参数:无
* 返回值 : dat(即读取到的数据)
*********************/
static alt_u8 iic_read(void)
{
alt_u8 i, dat = 0;
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SDA_BASE, 0);
IOWR_ALTERA_AVALON_PIO_DIRECTION(RTC_SCL_BASE, 1);
for(i=0; i<8; i++){
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
usleep(10);
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 1);
usleep(5);
dat <<= 1;
dat |= IORD_ALTERA_AVALON_PIO_DATA(RTC_SDA_BASE);
usleep(5);
}
IOWR_ALTERA_AVALON_PIO_DATA(RTC_SCL_BASE, 0);
usleep(10);
return dat;
}
/************************
* 函数名称: write_byte()
* 函数功能:向ds1307写一个字节addr地址写入数据dat
* 输入参数: alt_u16 addr, alt_u8 dat
* 返回值 :无
************************/
staticvoid write_byte(alt_u16 addr, alt_u8 dat)
{
alt_u8 cmdwrite;
cmdwrite=0xD0;
start();
iic_write(cmdwrite);
ack();
iic_write(addr);
ack();
iic_write(dat);
ack();
stop();
}
/************************
* 函数名称: read_byte()
* 函数功能:从ds1307的addr地址读取一个字节数据
* 输入参数: alt_u16 addr
* 返回值 : alt_u8 dat
***********************/
static alt_u8 read_byte(alt_u16 addr)
{
alt_u8 cmdread, cmdwrite ,dat;
cmdwrite=0xD0;
cmdread= 0xD1;
start();
iic_write(cmdwrite);
ack();
iic_write(addr);
ack();
/*********************/
start();
iic_write(cmdread);
ack();
dat = iic_read();
send_ack(0x01);
stop();
return dat;
}
转载自原文链接, 如需删除请联系管理员。
原文链接:I2C总线的软件程序模拟—基于Niso II处理器,转载请注明来源!