标签:
在学习单片机的时候就听说过I2c,不过那时候听的一团糟,什么都不会,而且51上面没有集成真正的I2c,只能用IO口模拟它的时序来实现。I2c总线是一种用于Ic器件之间连接的双向二进制总线。所谓总线,就是它上面可以挂多个器件,并且通过两根线连接,占用空间非常小。 其中SDA是数据线,SCL是时钟线。
I2c的几种信号状态:
空闲状态:SCL 高 SDA 高
开始条件: SCL 高 SDA 高-->低
结束条件: SCL 高 SDA 低-->高
数据有效: SCL 高 SDA 稳定
I2c最重要的是时序的掌握,这点和Nandflash有点像,就是要严格按照手册上面的时序图操作。
#include"stdio.h"
#define u8 unsigned char
//IO口的配置
#define GPD1CON (*(volatile unsigned long *)0xE02000C0)
#define GPD1PUD (*(volatile unsigned long *) 0xE02000C8)
#define IICCON (*(volatile unsigned long *)0xE1800000)
#define IICSTAT (*(volatile unsigned long *)0xE1800004)
#define IICDS (*(volatile unsigned long *)0xE180000C)
//i2c 的中断源控制器,VIC1 的14 号中断
#define VIC1INTENCLEAR (*(volatile unsigned long *)0xF2100014)
int init_i2c(void)
{
//端口配置
//GPD1PUD &= 0xfff0; //Pull-up/ down disabled
//端口配置成i2c的SDA 和SCL
GPD1CON &= 0xffffff00;
GPD1CON |=0x22;
//关闭i2c0 的中断源 读取的过程中会不断产生中断,只要关闭总的中断,就不会上报给CPU了
VIC1INTENCLEAR |= (1<<14);
// 产生应答 使能中断控制位
IICCON = (1<<7) |(0<<6) |(1<<5) |0xf;
//使能传输端口
IICSTAT = (1<<4);
return 0;
}
int write_i2c(u8 data, u8 addr) //地址和数据都是八位的
{
int num;
int i;
//发送设备的地址 和写命令(最后一位是0)
IICSTAT = 0xf0; //产生start 信号
IICDS = 0xa0;
//wait_i2c_finish();
WaitOprFinish();
//发送写的地址
IICDS = addr;
//for(i=0; i<20; i++);
IICCON &= ~(1<<4);
//wait_i2c_finish();
WaitOprFinish();
//发送数据
IICDS = data;
//for(i=0; i<20; i++);
IICCON &= ~(1<<4);
//wait_i2c_finish();
WaitOprFinish();
IICSTAT &= ~(1<<5); //产生stop 信号
IICCON &= ~(1<<4);
for(num=0; num<10000; num++); //加延时
return 0;
}
int read_i2c(u8 addr,u8 *data)
{
u8 buf =0;
int num;
IICDS =0xa0;//设备地址发送给移位寄存器
IICSTAT =0xf0;//产生start信号 主发送模式
//wait_i2c_finish();
WaitOprFinish();
IICDS =addr; //写的数据的地址
IICCON =0xaf;
//wait_i2c_finish();
WaitOprFinish();
IICDS = 0xa0; // 设备地址发送给移位寄存器
IICSTAT = 0xb0; // 产生start信号, 主接收模式
IICCON = 0xaf; // resume IIC Operation
//wait_i2c_finish();
WaitOprFinish();
IICCON = 0x2f; //无应答
//wait_i2c_finish();
WaitOprFinish();
buf = IICDS;
IICSTAT = 0x90;//产生停止信号
IICCON = 0xaf;
for(num=0; num<10000; num++);
*data=buf;
}
void WaitOprFinish(void)
{
unsigned int uIICConReg = 0;
unsigned int uRes = 0;
do
{
uIICConReg = IICCON;
//取出第四位,当传输结束时会产生中断信号1
uRes = uIICConReg & 0x10;
}while(uRes == 0); //祍却钡酱渫瓿?
return ;
}
//最后是测试函数,先写后读
int test_i2c(void)
{
int i;
volatile int j;
u8 buf = 0;
int num;
init_i2c();
printf("write...:\r\n");
for(i = 0; i<20; i++)
{
write_i2c(i*2, i);
for(j = 0;j < 10000;j++);
}
for(num=0; num<10000; num++);
printf("read.....:\r\n");
for(i = 0; i<20; i++)
{
read_i2c(i,&buf);
printf("%d\r\n", buf);
}
}
标签:
原文地址:http://www.cnblogs.com/ygy1784717631/p/4830197.html