好久没有在csdn上面做笔记了,主要是最近琐碎的事情太多,乱七八糟的事情让自己不能坚定下来做自己喜欢做的事情。上了星期花了两天的时间模拟了I2C的主机和从机通信。一般都是主机模拟,从机直接用硬件I2C的,但是由于所谓的项目里面没有I2C,但是要用到I2C了,因此就不得不用I/O口去模拟I2C了。
1、I2C协议
I2C的协议相信网上已经有很多资料了,这里就不做详细介绍,只做简单说明即可。
a、I2C协议有两根总线:SDA和SCL。SDA为数据线,而SCL就是主机的时钟线。
b、I2C是主机控制从机,时钟线只能主机改变。
c、每个从机都有唯一的地址,主机通过发送从机地址来选择从机。
d、I2C开始信号:SCL为高电平的时候,SDA由高电平向低电平跳变。
e、I2C结束信号:SCL为高电平的时候,SDA由低电平向高电平跳变。
f、主机传输信号的时候,SCL为高电平的时候,传输信号,SCL为低电平的时候改变信号。
g、主机接收信号的时候,SCL为高电平的时候,接收信号。
2、如果用I/O模拟I2C的时候,一定要记住,是主机控制从机,从机根据主机SCL信号的改变而改变。
3、主机代码:
/****************************************************************************
I2C模拟条件:
1、HOST先发地址和控制命令给SLAVE;
2、地址和控制命令占一个字节;
3、字节格式:
7~2 1 0
地址 单/多字节(0/1) 读/写(1/0)
4、发送多字节时候,第一个字节是地址和控制命令、第二个字节是长度、接下来是数据
5、发送多字节时候,第一个字节是地址和控制命令、第二个字节是要发送的
******************************************************************************/
#include "ioCC1110.h"
#include "hal.h"
#define SCL P1_2
#define SDA P1_3
#define IN 0
#define OUT 1
BYTE ACK_Flag = 0;
BYTE I2C_count;//计数器
BYTE receive_slave[100] = {0x00}; //接收从机的字节
BYTE send_slave[5] = {0xaa,0x55,0xbb,0x55,0xaa}; //发送字节给从机
/*初始化I2C*/
void SDA_(BYTE input)
{
if(input == 1) //SDA输出,p1.3
P1DIR |= 0X08;
else
P1DIR &= 0XF7; //SDA输入,p1.3
}
void SCL_(BYTE input)
{
if(input == 1) //SCL输出,P1.2
P1DIR |= 0X04;
else //SCL输入,P1.2
P1DIR &= 0XFB;
}
/*启动I2C工作*/
void START_I2C(void)
{
SDA = 1;
SCL = 0;
// Delay_us(20); //这个没有多大影响,可以不要
SCL = 1;
Delay_us(10); //最开始50,5us太短了,不能判断,10us可以。
SDA = 0;
Delay_us(2); //最开始50,
SCL = 0;
Delay_us(5); //最开始50,这个延时和上面的延时可以不要,但是为了SLAVE有足够时间退出中断,就加上
}
/*停止I2C工作*/
void STOP_I2C(void)
{
// SDA_OUT;
SDA = 0;
Delay_us(50);;
SCL = 1;
Delay_us(50);;
SDA = 1;
Delay_us(50);;
SCL = 0;