gec210 i2c程序io模拟方式实现
来源:互联网 发布:李涛疯狂淘宝上市 编辑:程序博客网 时间:2024/05/16 14:18
开发环境:ubuntu arm-linux-gcc4.4.1
开发板: GEC210开发板
原理图
i2c芯片:FM24CL04
与cpu的连接,GPD1的0,1号引脚。0号引脚对应SDA功能,1号引脚对应SCL引脚
实现:
io方式模拟i2c通信,没有使用i2c控制器
需要使用io引脚输出高低电平模拟i2c信号
或者需要改变为输入模式服务数据
//宏定义
#define GPD1DAT (*(volatile unsigned long*)0xe02000c4)
#define GPD1CON (*(volatile unsigned long*)0xe02000c0)#define UTXH0 (*(volatile unsigned char*)0xe2900020)
#define UTRSTAT0 (*(volatile unsigned long*)0xe2900010)
//函数声明
void scl_set(unsigned char x);
void delay(int n);
void i2c_start(void);
void i2c_stop(void);
void sda_input(void);
void sda_output(void);
void scl_output(void);
unsigned char read_sda(void);
unsigned char wait_ack(void);
void send_ack(unsigned char ack);
unsigned char data_read(unsigned char ack_flag);
unsigned char data_write(unsigned char buf);
unsigned char data_write_buf(unsigned short addr,unsigned char*buf,int len);
unsigned char rand_read_buf(unsigned short addr,unsigned char*buf,int len);
void print_hex(int n);
void print_string(char *);
//测试程序
void i2c_main(void)
{
unsigned char buf[32];
int i;
sda_output();
scl_output();
print_string("2017\n\r");
for(i=0;i<32;i++)
{
buf[i] = i + 0x20;
}
data_write_buf(0x0,buf,30); //向0地址写入30个值
rand_read_buf(10,buf,20); //从10地址读取20个值
for(i=0;i<20;i++)
{
print_hex(buf[i]);
}
print_string("i2c io test over\n\r");
return;
}
//SDA输出高或低电平
//参数 x非0时输出高电平,x为0时输出低电平
void sda_set(unsigned char x)
{
if(x)
{
GPD1DAT |= 1; //输出高电平
}
else
{
GPD1DAT &= ~1; //输出低电平
}
}
//SCL信号输出高电平或低电平
//参数 x非0时输出高电平,x为0时输出低电平
void scl_set(unsigned char x)
{
if(x)
{
GPD1DAT |= 1<<1; //输出高电平
}
else
{
GPD1DAT &= ~(1<<1); //输出低电平
}
}
//延时函数
void delay(int n)
{
n = 100*n;
while(n--); //直到n减为0
}
//i2c的开始时序
//在SCL为高电平时,SDA由高变为低电平
//尽量保证所有的函数进入时SCL为0,函数返回时SCL也为低
void i2c_start(void)
{
scl_set(0); //SCL = 0
sda_set(1); //SDA = 1
scl_set(1); //SCL = 1
delay(1);
sda_set(0); //SDA = 0
delay(1);
scl_set(0); //SCL = 0
}
//i2c的停止时序
//在SCL为高电平时,SDA由低变为高电平
//最后进入空闲状态,SCL和SDA都保持为高电平
void i2c_stop(void)
{
scl_set(0); //SCL = 0
sda_set(0); //SDA = 0;
scl_set(1); //SCL = 1;
delay(1);
sda_set(1); //SDA = 1
scl_set(1); //SCL = 1
}
//SDA切换为输入模式
//在接收数据或接收应答的时候
//SDA为GPD1 io引脚的0号引脚
void sda_input(void)
{
GPD1CON &= ~0xf; //输入模式
}
//SDA切换为输入模式
//在发送数据的时候
//SDA为GPD1 io引脚的0号引脚
void sda_output(void)
{
GPD1CON &= ~0xf;
GPD1CON |= 1; //输出模式
}
//SCL作为主机模式的时候,只需要设置为输出模式
//SCL为GPD1 io引脚的1号引脚
void scl_output(void)
{
GPD1CON &= ~0xf0;
GPD1CON |= 1<<4; //输出模式
}
//在输入模式时,读取SDA引脚的信号
//只需要最低位,因为最低位才是SDA引脚的对应信号
unsigned char read_sda(void)
{
return GPD1DAT & 1;
}
//主机读取从机发回的应答信号
//
unsigned char wait_ack(void)
{
unsigned char tmp;
scl_set(0); //SCL = 0;
sda_set(1); //SDA = 1 ,释放SDA总线
sda_input(); //SDA切换为输入模式
delay(1);
scl_set(1); //SCL = 1;
delay(1);
tmp = read_sda(); //读取SDA信号
scl_set(0);
delay(1);
sda_output(); //SDA切换为输出模式
return tmp;
}
//主机发送应答信号
//参数ack为0时表示需要应答,为1时不应答
//ack是一个时序过程,就是数据发完的第9位,不管主机要不要发送应答
//这个第9位的时序都要出现在8个数据位之后
void send_ack(unsigned char ack)
{
scl_set(0); //SCL = 0;
delay(1);
sda_set(ack & 1); //SDA = 0;
delay(1);
scl_set(1);
delay(3);
scl_set(0);
}
//写8bits数据时序
unsigned char data_write(unsigned char buf)
{
unsigned char i;
scl_set(0); //SCL = 0;
delay(1);
for(i=0;i<8;i++)
{
sda_set((buf>>(7-i)) & 1);
delay(1);
scl_set(1); //SCL = 1;
delay(5);
scl_set(0); //SCL = 0;
delay(1);
}
return wait_ack(); //应答时序
}
//当前地址读操作
//fm24cl04读取数据的操作,当前地址的话,重新上电后的当前地址为0
//所以调试的时候注意以下,尽量断电重启
unsigned char data_read(unsigned char ack_flag)
{
unsigned char i;
unsigned char buf = 0;
scl_set(0); //SCL = 0;
sda_input(); //sda输入模式
delay(1);
for(i=0;i<8;i++)
{
buf<<=1;
scl_set(1); //SCL = 1;
delay(1);
buf |= read_sda();
// delay(1);
scl_set(0); //SCL = 0;
delay(1);
}
sda_output(); //sda输出模式
send_ack(ack_flag); //发送应答
return buf; //返回收到的数据
}
void i2c_read_buf(unsigned char page,unsigned char*buf,int len)
{
int i;
i2c_start(); //起始信号
while(data_write(0xa1 | (page<<1)) != 0); //设备地址,读操作,页选择
for(i=0;i<len;i++)
{
buf[i] = data_read(i==len-1); //只有i=9才传入1,其他情况为0
}
i2c_stop();
return;
}
//写操作
//fm24cl04写数据的操作
unsigned char data_write_buf(unsigned short addr,unsigned char*buf,int len)
{
int i;
unsigned char page = addr>>8; //第9位为fm24cl04的页选择
i2c_start(); //起始信号
while(data_write(0xa0 | (page << 1)) != 0); //设备地址,写操作
data_write(addr & 0xff); //发送空间地址
if(len == 0) //为随机读创造时序,参看随机读函数
{
return;
}
for(i=0;i<len;i++)
{
data_write(buf[i]); //写入数据
}
i2c_stop();
}
//随机读函数操作,与当前地址读的差异
//fm24cl04写数据的操作
unsigned char rand_read_buf(unsigned short addr,unsigned char*buf,int len)
{
data_write_buf(addr,buf,0);
i2c_read_buf(addr>>8,buf,len);
}
/*******************************************************************************************/
/*
分割线
以下为串口打印函数,不完整。但是使用uboot的换是可以使用的。
暂时不做详细介绍
*/
void uart0_send_byte(unsigned char buf)
{
while((UTRSTAT0 & (1<<2)) == 0); //靠靠靠靠靠靠靠靠
UTXH0 = buf;
}
void print_string(char*str)
{
while(*str)
{
uart0_send_byte(*str++);
}
}
void print_hex(int n)
{
unsigned char arr[8];
unsigned char i;
unsigned char tmp;
for(i=0;i<8;i++)
{
tmp = n & 0xf; //靠靠靠靠4靠靠靠?6靠靠靠靠靠靠靠
if(tmp > 9)
{
arr[i] = tmp + 'a' - 10; //靠靠靠ASCII?
}
else
{
arr[i] = tmp + '0';
}
n >>= 4;
}
print_string("0x");
for(i=0;i<8;i++)
{
uart0_send_byte(arr[7-i]);
}
print_string("\n\r");
}
阅读全文
0 0
- gec210 i2c程序io模拟方式实现
- io模拟i2c程序
- GPIO模拟I2C程序实现
- GPIO模拟I2C程序实现.
- GPIO模拟I2C程序实现
- GPIO模拟I2C程序实现
- GPIO模拟I2C程序实现
- IO模拟I2C代码
- IO模拟I2C
- 普通IO口模拟实现I2C通信及应用解析
- 笔记四:linux下IO口模拟实现I2C协议
- STM32模拟I2C程序
- STM8S 模拟I2C程序
- 51单片机IO模拟I2C
- STM32 IO 模拟IIC I2C
- 普通IO模拟i2c总线
- GPIO模拟I2C快速入门 与程序实现+软件模拟I2C时序
- GEC210 LED裸机开发 c语言实现 ADS方式
- 交换机的基础知识
- Foreach与迭代器
- 排序--直接插入排序
- UGUI(七)界面拖动和焦点界面
- 【七日牧函】基督教传统中的友谊
- gec210 i2c程序io模拟方式实现
- shiro-helloworld(1)
- Shell教程
- 排序--冒泡排序
- vb.net 教程 5-7 Bitmap类 2
- JAVA——IO流 之 节点流和处理流以及流的关闭顺序(5)
- Java中字符串截取使用
- 服务器测试包含的主要测试
- Strings Homomorphism