给个程序你参考一下,只需要关注几个程序即可
/*_____________________________________________________________________________________________
*_____________________________________________________________________________________________
*
* 优 利 德 科 技(中国)有 限 公 司
* UNIT-TREND TECHNOLOGY(CHINA) LIMITED
* http: //www.uni-trend.com.cn
* 东莞松山湖**技术产业开发区工业北一路6号
*
*_____________________________________________________________________________________________
* 文 件 名: IIC.C
* 创 建 人: 艾艳斌(E-mail:1109706098@qq.com)
* 版 本: V1.00 / 2006-06-02
* 描 述: 通用IIC模拟驱动程序,通过头文件可以进行配置(只包括基本程序)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版 本: V1.01 / 2006-06-25
* 描 述: 增加IIC_RECEIVE_EN定义,快速屏蔽iic_receive函数(有些情况不用,如PCF8576)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版 本: V1.02 / 2006-07-19
* 描 述: 改进IIC延时函数,使之能适应多种速度IIC器件共存(false=0方式效率高)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版 本: V1.03 / 2006-07-20
* 描 述: 增加iic_query函数(更加通用,适用于多IIC器件查询)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版 本: V1.04 / 2006-07-29
* 描 述: 修改延时程序结构,使SCL高低电平周期容易相等,有利于最大限度利用总线频率(基于_nopx),
* 增加iic_query函数另外二个高效代码版本
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版 本: V1.04 / 2012-08-23
* 描 述: 只保留一个iic_query函数
*_____________________________________________________________________________________________
*_____________________________________________________________________________________________
*/
#define __I2C_C
#include "HEADER.H"
#include "I2C.H"
/* 改进记录 / abin 2012-09-20
________________________________________________________________
2013-08-22:
2014-04-14:
-- 完整支持LSB模式,
-- 增加函数i2c_send_lsb,i2c_receive_lsb,
适应某些非I2C标准器件.
-- 优化延时宏(程序)结构,便于维护.
-- 增加函数i2c_send_repeat_n_bytes.
-- 增加函数i2c_send_n_bytes,i2c_receive_n_bytes,提高效率.
-- iic_query_general更名为iic_query,原iic_query函数去掉.
-- 优化程序,方便移植到不同架构的MCU上.
-- 返回时总线SDA,SCL总是为高,iic_send程序优化,待测试.
-- 增加iic_query_general函数,严格按照手册时序图执行.
用以取代iic_query函数,iic_query针对有些器件有BUG.
-- 为方便移植,改造程序。
-- 精确控制IIC时序延时,更优化,更合理。
-- 优化程序结构,简化配置,原多速度配置是错误的。
-- 增加函数i2c_receive_ack,i2c_receive_nack
________________________________________________________________
2015-02-04:
-- 优化i2c_query函数,支持任何时候调用,不会死机。
________________________________________________________________
2015-05-04:
-- 修正了i2c_query的小BUG。
________________________________________________________________
*/
//______________________________________________________________
// i2c_init();
//______________________________________________________________
//
// IIC总线初始化
//
#if EN_i2c_init > 0
bit i2c_init(void)
{
GPIO_ON(GPIO_I2C_WP);
GPIO_OFF(GPIO_I2C_SCL);
GPIO_OFF(GPIO_I2C_SDA);
GPIO_OUTPUT(GPIO_I2C_WP);
GPIO_OUTPUT(GPIO_I2C_SCL);
GPIO_OUTPUT(GPIO_I2C_SDA);
GPIO_ON(GPIO_I2C_WP);
GPIO_OFF(GPIO_I2C_SCL);
GPIO_OFF(GPIO_I2C_SDA);
i2c_delay_std();
i2c_stop();
return true;
}
#endif
//______________________________________________________________
// i2c_start();
//______________________________________________________________
//
// I2C开始信号,注意结束时GPIO_IIC_SCL=0,GPIO_IIC_SDA=1
//
#if EN_i2c_start > 0
void i2c_start(void)
{
SCL_0();
i2c_delay_std();
SDA_1();
SDA_OUTPUT();
SDA_1();
i2c_delay_std();
SCL_1();
i2c_delay_std();
SDA_0();
i2c_delay_std();
SCL_0(); // SCL = 0, SDA = 1
i2c_delay_std();
SDA_1();
}
#endif
//______________________________________________________________
// i2c_stop();
//______________________________________________________________
//
// I2C停止信号,结束时SDA=1,SCL=1,确保I2C总线在停止状态
//
#if EN_i2c_stop > 0
void i2c_stop(void)
{
SCL_0();
i2c_delay_std();
SDA_0();
SDA_OUTPUT();
SDA_0();
i2c_delay_std();
SCL_1();
i2c_delay_std();
SDA_1();
i2c_delay_std();
}
#endif
//______________________________________________________________
// if(true != i2c_send(PCF8576_WRITE))...
//______________________________________________________________
//
// 发送一个字节,失败后会自动停止总线(发送stop)
// byte = 数据
// 返回: false = 失败, true = 成功
//
#if EN_i2c_send > 0
bit i2c_send(U8 byte)
{
U8 i;
SDA_OUTPUT();
for(i=8; i; i--){
byte <<= 1, SDA_OUT(PSW_CY); // GPIO_IIC_SDA = CY;
i2c_delay_da();
SCL_1();
i2c_delay_ck1();
SCL_0();
i2c_delay_ck0();
}
SDA_OUT(1);
SDA_INPUT();
i2c_delay_da();
SCL_1();
i2c_delay_std();
//___________________________________
// 等待从机应答,超时失败自动退出
for(i=16; i; i--){
if(!SDA_IN()){
SCL_0();
return true;
}else{
// __debug();
}
}
//________________
// 失败停止总线
i2c_stop();
return false;
}
#endif
//______________________________________________________________
// x = i2c_receive(NACK);
//______________________________________________________________
//
// 接收一个字节
// ack : 应答信号ACK或NACK
// 返回: 接收的字节
// 注: 软件模拟方式无法判断是否成功或失败,所以总是成功
//
#if EN_i2c_receive > 0
U8 i2c_receive(U8 ack)
{
U8 i;
U8 temp;
SDA_1();
SDA_INPUT();
temp = 0;
for(i=8; i; i--){
temp <<= 1;
SCL_1();
i2c_delay_ck1();
if(SDA_IN()){
temp++;
}
SCL_0();
i2c_delay_ck0();
}
//________________
// 主机应答从机
SDA_OUTPUT();
SDA_OUT(ack);
i2c_delay_da();
SCL_1();
i2c_delay_std();
SCL_0();
i2c_delay_std();
SDA_1(); // 接收结束时GPIO_IIC_SDA=1
return temp;
}
#endif
//______________________________________________________________
// x = i2c_receive_ack();
//______________________________________________________________
//
// 接收一个字节,并应答
//
#if EN_i2c_receive_ack > 0
U8 i2c_receive_ack(void)
{
U8 i;
U8 temp = 0;
SDA_INPUT();
for(i=0; i<8; i++){
SCL_1();
i2c_delay_ck1();
temp <<= 1;
if(SDA_IN()){
temp++;
}
SCL_0();
i2c_delay_ck0();
}
//________________
// 主机应答从机
SDA_OUTPUT();
SDA_OUT(I2C_ACK); // I2C_NACK
i2c_delay_da();
SCL_1();
i2c_delay_std();
SCL_0();
i2c_delay_std();
SDA_1(); // 接收结束时GPIO_I2C_SDA=1
return temp;
}
#endif
//______________________________________________________________
// x = i2c_receive_nack();
//______________________________________________________________
//
// 接收一个字节,并非应答
//
#if EN_i2c_receive_nack > 0
U8 i2c_receive_nack(void)
{
U8 i;
U8 temp = 0;
SDA_INPUT();
for(i=0; i<8; i++){
SCL_1();
i2c_delay_ck1();
temp <<= 1;
if(SDA_IN()){
temp++;
}
SCL_0();
i2c_delay_ck0();
}
//________________
// 主机应答从机
SDA_OUTPUT();
SDA_OUT(I2C_NACK); // I2C_ACK
i2c_delay_da();
SCL_1();
i2c_delay_std();
SCL_0();
i2c_delay_std();
SDA_1(); // 接收结束时GPIO_I2C_SDA=1
return temp;
}
#endif
//______________________________________________________________
// i2c_send_repeat_n_bytes
//______________________________________________________________
//
// 发送多个重复的字节(主要用于初始化).
//
#if EN_i2c_send_repeat_n_bytes > 0
bit i2c_send_repeat_n_bytes(const U8 d, U8 n)
{
for(__null; n; n--){
if(i2c_send(d) == false){
return false;
}
}
return true;
}
#endif
//______________________________________________________________
// i2c_send_n_bytes
//______________________________________________________________
//
// 发送多个字节
//
#if EN_i2c_send_n_bytes > 0
bit i2c_send_n_bytes(void* p, U8 n)
{
U8* p2;
p2 = (U8*)p;
for(__null; n; n--,p2++){
if(i2c_send(p2[0]) == false){
return false;
}
}
return true;
}
#endif
//______________________________________________________________
// i2c_receive_n_bytes
//______________________________________________________________
//
// 接收多个字节
//
#if EN_i2c_receive_n_bytes > 0
bit i2c_receive_n_bytes(void* p, U8 n)
{
U8* p2;
p2 = (U8*)p;
for(__null; n; n--,p2++){
if(n == 1){
p2[0] = i2c_receive(I2C_NACK);
}else{
p2[0] = i2c_receive(I2C_ACK);
}
}
return true;
}
#endif
//______________________________________________________________
// if(true != i2c_query(PCF8576_WRITE, 10ms))...
//______________________________________________________________
//
// 查询IIC器件操作是否完成
// device = 器件选择(建议写操作,主机主动)
// timeout = 超时间
// 返回: false = 未完成, true = 完成
//
// 注意: 可能不同的设备需要定制查询程序
//
#if EN_iic_query > 0
bit i2c_query(U8 device, U8 timeout)
{
U8 t0;
//________________
// 简化算法
// sys_delay(timeout);
// return true;
//________________
// 正常算法
if(IEN0_EAL && TCON_TR0){
t0 = ayb_isr_inc_get();
for(;;){
i2c_start(); // !!!
if(i2c_send(device) == true){
i2c_stop();
return true;
}
if(ayb_isr_inc_get() - t0 >= timeout){ // timeout
// i2c_stop();
return false;
}
}
}else{
for(;;){
i2c_start(); // !!!
if(i2c_send(device) == true){
i2c_stop();
return true;
}
ayb_delay(1ms);
if(--timeout == 0){
// i2c_stop();
return false;
}
}
}
}
#endif
/*
//______________________________________________________________
// 完整的LSB方式
//______________________________________________________________
*/
//______________________________________________________________
// if(true != i2c_send_lsb(PCF8576_WRITE))...
//______________________________________________________________
//
// 发送一个字节,失败后会自动停止总线(发送stop)
// byte = 数据
// 返回: false = 失败, true = 成功
//
#if EN_i2c_send_lsb > 0
bit i2c_send_lsb(U8 byte)
{
U8 i;
SDA_OUTPUT();
for(i=8; i; i--){
byte >>= 1, SDA_OUT(PSW_CY); // GPIO_IIC_SDA = CY;
i2c_delay_da();
SCL_1();
i2c_delay_ck1();
SCL_0();
i2c_delay_ck0();
}
SDA_INPUT();
i2c_delay_da();
SCL_1();
i2c_delay_std();
//___________________________________
// 等待从机应答,超时失败自动退出
for(i=16; i; i--){
if(!SDA_IN() == 1){
SCL_0();
return true;
}else{
// __debug();
}
}
//________________
// 失败停止总线
i2c_stop();
return false;
}
#endif
//______________________________________________________________
// x = i2c_receive_lsb(NACK);
//______________________________________________________________
//
// 接收一个字节
// ack : 应答信号ACK或NACK
// 返回: 接收的字节
// 注: 软件模拟方式无法判断是否成功或失败,所以总是成功
//
#if EN_i2c_receive_lsb > 0
U8 i2c_receive_lsb(U8 ack)
{
U8 i;
U8 temp;
SDA_INPUT();
temp = 0;
for(i=8; i; i--){
temp >>= 1;
SCL_1();
i2c_delay_ck1();
if(SDA_IN() == 1){
temp |= BIT7;
}
SCL_0();
i2c_delay_ck0();
}
//________________
// 主机应答从机
SDA_OUTPUT();
SDA_OUT(ack);
i2c_delay_da();
SCL_1();
i2c_delay_std();
SCL_0();
i2c_delay_std();
SDA_1(); // 接收结束时GPIO_IIC_SDA=1
return temp;
}
#endif
//______________________________________________________________
// i2c_send_lsb_n_bytes
//______________________________________________________________
//
// 发送多个字节
//
#if EN_i2c_send_lsb_n_bytes > 0
bit i2c_send_lsb_n_bytes(void* p, U8 n)
{
U8* p2;
p2 = (U8*)p;
for(__null; n; n--,p2++){
if(i2c_send_lsb(p2[0]) == false){
return false;
}
}
return true;
}
#endif
//______________________________________________________________
// i2c_receive_lsb_n_bytes
//______________________________________________________________
//
// 接收多个字节
//
#if EN_i2c_receive_lsb_n_bytes > 0
bit i2c_receive_lsb_n_bytes(void* p, U8 n)
{
U8* p2;
p2 = (U8*)p;
for(__null; n; n--,p2++){
if(n == 1){
p2[0] = i2c_receive_lsb(I2C_NACK);
}else{
p2[0] = i2c_receive_lsb(I2C_ACK);
}
}
return true;
}
#endif
/*
//______________________________________________________________
// 函数延时方式
//______________________________________________________________
*/
#if I2C_DELAY_MODE != 0
//______________________________________________________________
// i2c_delay_ss,i2c_delay_da,i2c_delay_ck1,i2c_delay_ck0
//______________________________________________________________
//
// iic延时函数
//
static void i2c_delay_std(void)
{
__nops(NOPS_i2c_delay_std);
}
static void i2c_delay_da(void)
{
__nops(NOPS_i2c_delay_da);
}
static void i2c_delay_ck1(void)
{
__nops(NOPS_i2c_delay_ck1);
}
static void i2c_delay_ck0(void)
{
__nops(NOPS_i2c_delay_ck0);
}
#endif // #if IIC_DELAY_MODE != 0
//______________________________________________________________
// @End
//______________________________________________________________ |