You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

382 lines
9.6 KiB

//////////////////////////////////////////////////////////////////////////
/// COPYRIGHT NOTICE
/// Copyright (c) 2018, 传控科技
/// All rights reserved.
///
/// @file iic_sim
/// @brief iic 模拟io 版本, 和cpu无关,唯一需要修改的就是头函数中的管脚定义
/// @info 如无必要请勿修改
///(本文件实现的功能的详述)
///
/// @version 1.1 CCsens technology
/// @author CC
/// @date 20180102
//
//////////////////////////////////////////////////////////////////////////
#include "msp_iicM1.h"
/*------------------------------------------------
端口定义
在I2C总线传输数据过程中,每传输一个字节,
都要跟一个应答状态位。接收器接收数据的情况
可以通过应答位来告知发送器。应答位的时钟脉冲
仍由主机产生,而应答位的数据状态则遵循“谁
接收谁产生”的原则,即总是由接收器产生应答位,
在响应的时钟脉冲期间接收器必须将SDA 线拉
低,使它在这个时钟脉冲的高电平期间保持稳定的低电平(见图9) ,
当然必须考虑建立和保持时间
(详细请查阅表6) 。主机向从机发送数据时,
应答位由从机产生;主机从从机接收数据时,应答位
由主机产生。
I2C总线标准规定: 应答位为0表示接收器应答 (ACK) ,
常常简记为A; 为1则表示非应答 (NACK) ,
常简记为NA。发送器发送LSB之后,应当释放SDA线(拉高SDA) ,
以等待接收器产生应答位。
如果接收器在接收完最后一个字节的数据,
或者不能再接收更多的数据时,应当产生非应答信
号来通知发送器。发送器如果发现接收器产生了非应答状态,
则应当终止发送。
------------------------------------------------*/
///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void L0_IICM1_SCL(unsigned char v)
{
if(v)
{
L0_IICM1_SCL_ON();/// L0_SCL_ON();
L0_slc_1_delay();
}
else
{
L0_IICM1_SCL_OFF();///L0_SCL_OFF();
L0_slc_0_delay();
}
}
void L0_IICM1_SDA(unsigned char v)
{
if(v)
{
L0_IICM1_SDA_ON();
L0_slc_1_delay();
}
else
{
L0_IICM1_SDA_OFF();
L0_slc_0_delay();
}
}
void L0_IICM1_INIT(unsigned char v)
{
if (v)
{
//L0_IIC_SIM_INIT();
L0_IICM1_SCL_init();
L0_IICM1_SDA_init();
L0_IICM1_SDA(1);
L0_IICM1_SCL(1);
}else
{
}
}
unsigned char L0_IICM1_SDA_ask(void)
{
return L0_IICM1_SDA_AT();
}
///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/****************
void L0_I2C_Reset(void)
{
L0_I2C_SCL(1); L0_I2C_SDA(1); //确认释放总线
}
********************/
#define L0_IIC_SIM_INIT()
#define L0_IIC_SIM_close()
//**********************************************
//送起始位 IO_SDA=1->0
void L0_IICM1_Start(void)
{
///L0_IIC_SIM_INIT();
L0_IICM1_SDA(1);
L0_IICM1_SCL(1);
L0_IICM1_SDA(0);
L0_IICM1_SCL(0);
}
//************************************************
//送停止位 IO_SDA = 0->1
void L0_IICM1_Stop(void)
{
L0_IICM1_SDA(0);
L0_IICM1_SCL(1);
L0_IICM1_SDA(1);
L0_IIC_SIM_INIT();
L0_IIC_SIM_close();
}
//************************************************
//主应答(包含ack:IO_SDA = 0和no_ack:IO_SDA = 0)
void L0_IICM1_Ack(void)
{ //设置SDA 口为输出
L0_IICM1_SCL(0);
L0_IICM1_SDA(0);
L0_IICM1_SCL(1);
L0_IICM1_SCL(0);
L0_IICM1_SDA(1);
}
void L0_IICM1_NoAck(void)
{ //设置SDA 口为输出
L0_IICM1_SCL(0);
L0_IICM1_SDA(1);
L0_IICM1_SCL(1);
L0_IICM1_SCL(0);
}
/******
I2C总线标准规定: 应答位为0表示接收器应答 (ACK) , 常常简记为A;
为1则表示非应答 (NACK) ,常简记为NA。
发送器发送LSB之后,应当释放SDA线(拉高SDA) ,
以等待接收器产生应答位。
如果接收器在接收完最后一个字节的数据,
或者不能再接收更多的数据时,应当产生非应答信
号来通知发送器。发送器如果发现接收器产生了非应答状态,
则应当终止发送。
// 检测 SDA是否回ACK
bit L0_I2C_Test_Ack(void)
{ //设置SDA 口为输入
bit ACK_Flag = 0;
L0_I2C_SCL(0);
L0_I2C_SDA(1);
L0_I2C_SCL(1);
if(IO_SDA = 0)
ACK_Flag = 1;
else
ACK_Flag = 0;
L0_I2C_SCL(0);
return ACK_Flag;
// return 1;// debug
}
*******/
//*************************************************
//字节发送程序
//发送c(可以是数据也可是地址),送完后接收从应答
//不考虑从应答位
void L0_IICM1_SendData(unsigned char c)
{
unsigned char ack=8;
unsigned char BitCnt=8;//一字节8位
//设置SDA 口为输出
for(BitCnt = 0;BitCnt < 8;BitCnt ++) //要传送的数据长度为8位
{
if((c << BitCnt ) & 0x80)
L0_IICM1_SDA(1); //判断发送位
else
L0_IICM1_SDA(0);
L0_IICM1_SCL(1); //置时钟线为高,通知被控器开始接收数据位
L0_IICM1_SCL(0);
}//8clk
L0_IICM1_SDA(1); //8位发送完后释放数据线,准备接收应答位
L0_IICM1_SCL(1);
///gRccUs05 += L0_I2C_SDA_ask();
L0_IICM1_SCL(0);
L0_IICM1_delay();
}
//**************************************************
//字节接收程序
//接收器件传来的数据,此程序应配合|主应答函数|i2c_ack_main(void)使用
//return: uchar型1字节
unsigned char L0_IICM1_ReceiveData(void)
{
unsigned char BitCnt=8,IIC_RX_Data = 0;
L0_IICM1_SDA(1); //读入数据 设置SDA 口为输入
for(BitCnt = 0;BitCnt<8;BitCnt++)
{
L0_IICM1_delay(1);
L0_IICM1_SCL(0); //置时钟线为低,准备接收数据位
L0_IICM1_SCL(1); //置时钟线为高使数据线上数据有效
L0_IICM1_delay(1);
IIC_RX_Data = IIC_RX_Data << 1;
if(1 == L0_IICM1_SDA_ask())
IIC_RX_Data = IIC_RX_Data + 1; //读数据位,接收的数据位放入retc中
L0_IICM1_delay(1);
}// 8clk up
L0_IICM1_SCL(0);
return IIC_RX_Data;
}
/// 读取 n个数据 放入p中
void L1_IICM1_ReadNByte(unsigned char Sal, unsigned char *p,unsigned char n)
{
unsigned char i;
L0_IICM1_Start(); // 启动I2C
L0_IICM1_SendData((Sal)| 0x01); //发送器件地址
for(i = 0;i < n-1;i ++) //读取字节数据
{
*(p + i) = L0_IICM1_ReceiveData(); //读取数据
///printf("%x ",(int)(*(p + i)));
L0_IICM1_Ack(); //__/```\__
}
*(p + n - 1) = L0_IICM1_ReceiveData();
L0_IICM1_NoAck();
L0_IICM1_Stop();
}
#if 0
主机从从设备读取多个字节
Master ST SAD+W SUB SR SAD+R MAK MAK NMAK SP
Slave SAK SAK SAK DATA DATA DATA
0x19
0001 1001
0011 001R
#endif
///////////////////////////////
///写入一个reg 为后续的写命令或者读取服务
void L1_IICM1_WriteReg(unsigned char sla,unsigned char reg)
{
L0_IICM1_Start(); //启动I2C
L0_IICM1_SendData(sla);//发送器件地址
L0_IICM1_SendData(reg);
}
// sla.(reg)=cmd
void L2_IICM1_WriteCmd(unsigned char sla,unsigned char reg,unsigned char cmd)
{
L1_IICM1_WriteReg(sla,reg);
L0_IICM1_SendData(cmd);
L0_IICM1_Stop();
/*****************
if(gRccUs05 >0)///测试iic有效否 发现没有结果
{
L0_uart0_uc(gRccUs05);gRccUs05 = 0;
}
***************/
}
//读取reg地址的n个数据 sla.(reg) sla.(reg+1)................ sla.(reg+n)
void L2_IICM1_ReadReg(unsigned char sla,unsigned char reg,
unsigned char *r,unsigned char n)
{
// U8 d[1];
//S ADD W A REG A
L1_IICM1_WriteReg(sla,reg);
//S ADD R A D1 A D2 A.....DX N P
L1_IICM1_ReadNByte(sla,r,n);
}
//读取reg地址的n个数据 sla.(reg) sla.(reg+1)................ sla.(reg+n)
unsigned char L2_IICM1_Read1Reg1D(unsigned char sla,unsigned char reg)
{
U8 d;
// U8 d[1];
//S ADD W A REG A
L1_IICM1_WriteReg(sla,reg);
//S ADD R A D1 A D2 A.....DX N P
L1_IICM1_ReadNByte(sla,&d,1);
return d;
}
#if 0////不可删除
///S 80H A Register Address A S 81H A Data NA P
void L2_tws_ReadReg000(unsigned char sla,unsigned char reg,
unsigned char *v)
{
unsigned char ack=8;
unsigned char BitCnt=8;//一字节8位
// U8 d[1];
//S ADD W A REG A
//// L1_I2C_WriteReg(sla,reg);
//step 1----
L0_I2C_Start(); //启动I2C
//step 2----L0_I2C_SendData(sla);//发送器件地址
//设置SDA 口为输出
for(BitCnt = 0;BitCnt < 8;BitCnt ++) //要传送的数据长度为8位
{
if((sla << BitCnt ) & 0x80)
L0_I2C_SDA(1); //判断发送位
else
L0_I2C_SDA(0);
L0_I2C_SCL(1); //置时钟线为高,通知被控器开始接收数据位
L0_I2C_SCL(0);
}//8clk
L0_I2C_SDA(1); //8位发送完后释放数据线,准备接收应答位
L0_I2C_SCL(1);
L0_I2C_SCL(0);
//step 3---L0_I2C_SendData(reg);
for(BitCnt = 0;BitCnt < 8;BitCnt ++) //要传送的数据长度为8位
{
if((reg << BitCnt ) & 0x80)
L0_I2C_SDA(1); //判断发送位
else
L0_I2C_SDA(0);
L0_I2C_SCL(1); //置时钟线为高,通知被控器开始接收数据位
L0_I2C_SCL(0);
}//8clk
L0_I2C_SDA(1); //8位发送完后释放数据线,准备接收应答位
L0_I2C_SCL(1);
L0_I2C_SCL(0);
//step 4----
L0_I2C_Start(); //启动I2C
//step 5---
//设置SDA 口为输出
sla|=0x01;
for(BitCnt = 0;BitCnt < 8;BitCnt ++) //要传送的数据长度为8位
{
if((sla << BitCnt ) & 0x80)
L0_I2C_SDA(1); //判断发送位
else
L0_I2C_SDA(0);
L0_I2C_SCL(1); //置时钟线为高,通知被控器开始接收数据位
L0_I2C_SCL(0);
}//8clk
L0_I2C_SDA(1); //8位发送完后释放数据线,准备接收应答位
L0_I2C_SCL(1);
L0_I2C_SCL(0);
//step 6---receive data
//设置SDA 口为输出
*v = L0_I2C_ReceiveData();
L0_I2C_SCL(1);
L0_I2C_SCL(0);/// send NA
//step 7--- P
L0_I2C_Stop();
}
///S 80H A Register Address A S 81H A Data NA P
#endif