//-------------------------------------------------------------------------------------
#include "reg24le1.h"
#include "stdint.h"
#include "stdbool.h"
#include "zho_i2c.h"
#include "zho_delay.h"
#include "zho_io.h"
#include <intrins.h>
//-------------------------------------------------------------------------------------
//定义I2C地址
//-------------------------------------------------------------------------------------
#define SlaveAddress (0x30 << 1)
//-------------------------------------------------------------------------------------
//定义IO口
//-------------------------------------------------------------------------------------
#define SCL P16
#define SDA P15
#define SCL_OUTPUT() zho_output_P16()
#define SDA_OUTPUT() zho_output_P15()
#define SDA_INPUT() zho_input_P15()
//-------------------------------------------------------------------------------------
//连续读出时的数据缓冲区
//-------------------------------------------------------------------------------------
uint8_t zho_i2c_buf[6];
//-------------------------------------------------------------------------------------
//延时
//-------------------------------------------------------------------------------------
void zho_i2c_wait()
{
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
}
//-------------------------------------------------------------------------------------
//I2C Start
//-------------------------------------------------------------------------------------
void zho_i2c_start()
{
SCL_OUTPUT(); //SCL的IO设置为输出
SDA_OUTPUT(); //SDA的IO设置为输出
zho_i2c_wait(); //延时,避免和上一次的stop间隔太近
SDA = 1; //拉高数据线
SCL = 1; //拉高时钟线
zho_i2c_wait(); //延时
SDA = 0; //产生下降沿
zho_i2c_wait(); //延时
SCL = 0; //拉低时钟线
}
//-------------------------------------------------------------------------------------
//I2C Stop
//-------------------------------------------------------------------------------------
void zho_i2c_stop()
{
SDA_OUTPUT(); //SDA的IO设置为输出
SDA = 0; //拉低数据线
SCL = 1; //拉高时钟线
zho_i2c_wait(); //延时
SDA = 1; //产生上升沿
zho_i2c_wait(); //延时
}
//-------------------------------------------------------------------------------------
//I2C ACK
//-------------------------------------------------------------------------------------
void zho_i2c_send_ack(bit ack)
{
SDA_OUTPUT(); //SDA的IO设置为输出
SDA = ack; //写应答信号
SCL = 1; //拉高时钟线
zho_i2c_wait(); //延时
SCL = 0; //拉低时钟线
zho_i2c_wait(); //延时
}
//-------------------------------------------------------------------------------------
//I2C RecvACK
//-------------------------------------------------------------------------------------
uint8_t zho_i2c_recv_ack(void)
{
SDA_INPUT(); //SDA的IO设置为输入
SCL = 1; //拉高时钟线
zho_i2c_wait(); //延时
CY = SDA; //读应答信号
SCL = 0; //拉低时钟线
zho_i2c_wait(); //延时
return CY; //返回
}
//-------------------------------------------------------------------------------------
//I2C Send Byte
//-------------------------------------------------------------------------------------
void zho_i2c_send_byte(uint8_t dat)
{
uint8_t i;
SDA_OUTPUT(); //SDA的IO设置为输出
for(i = 0; i < 8; i++) //8位计数器
{
dat <<= 1; //移出数据的最高位
SDA = CY; //送数据口
SCL = 1; //拉高时钟线
zho_i2c_wait(); //延时
SCL = 0; //拉低时钟线
zho_i2c_wait(); //延时
}
zho_i2c_recv_ack(); //读取回应
}
//-------------------------------------------------------------------------------------
//I2C Recv Byte
//-------------------------------------------------------------------------------------
uint8_t zho_i2c_recv_byte()
{
uint8_t i;
uint8_t dat = 0;
SDA_INPUT(); //SDA的IO设置为输入
SDA = 1; //使能内部上拉,准备读取数据,
for(i = 0; i < 8; i++) //8位计数器
{
dat <<= 1;
SCL = 1; //拉高时钟线
zho_i2c_wait(); //延时
dat |= SDA; //读数据
SCL = 0; //拉低时钟线
zho_i2c_wait(); //延时
}
return dat; //返回
}
//-------------------------------------------------------------------------------------
//写寄存器
//-------------------------------------------------------------------------------------
void zho_i2c_write_reg(uint8_t REG_Address, uint8_t REG_data)
{
zho_i2c_start(); //起始信号
zho_i2c_send_byte(SlaveAddress); //发送设备地址+写信号
zho_i2c_send_byte(REG_Address); //内部寄存器地址,请参考中文pdf
zho_i2c_send_byte(REG_data); //内部寄存器数据,请参考中文pdf
zho_i2c_stop(); //发送停止信号
}
//-------------------------------------------------------------------------------------
//读寄存器
//-------------------------------------------------------------------------------------
uint8_t zho_i2c_read_reg(uint8_t REG_Address)
{
uint8_t REG_data;
zho_i2c_start(); //起始信号
zho_i2c_send_byte(SlaveAddress); //发送设备地址+写信号
zho_i2c_send_byte(REG_Address); //发送存储单元地址
zho_i2c_start(); //起始信号
zho_i2c_send_byte(SlaveAddress + 1); //发送设备地址+读信号
REG_data = zho_i2c_recv_byte(); //读出寄存器数据
zho_i2c_send_ack(1); //发送回应
zho_i2c_stop(); //停止信号
return REG_data; //返回
}
//-------------------------------------------------------------------------------------
//连续读出6个寄存器,数据存放在zho_i2c_buf[]
//-------------------------------------------------------------------------------------
void zho_i2c_read_6_reg(uint8_t REG_Address)
{
uint8_t i;
zho_i2c_start(); //起始信号
zho_i2c_send_byte(SlaveAddress); //发送设备地址+写信号
zho_i2c_send_byte(REG_Address); //发送起始存储单元地址
zho_i2c_start(); //起始信号
zho_i2c_send_byte(SlaveAddress + 1); //发送设备地址+读信号
for(i = 0; i < 6; i++) //连续读取6个地址数据
{
zho_i2c_buf[i] = zho_i2c_recv_byte(); //存储数据
if (i == 5) {zho_i2c_send_ack(1);} //最后一个数据需要回NOACK
else {zho_i2c_send_ack(0);} //回应ACK
}
zho_i2c_stop(); //停止信号
}
//-------------------------------------------------------------------------------------