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.
484 lines
11 KiB
484 lines
11 KiB
1 year ago
|
//////////////////////////////////////////////////////////////////////////
|
||
|
/// 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_siicx.h"
|
||
|
|
||
|
#include "debug_drv.h"
|
||
|
|
||
|
|
||
|
TS_siic_ xdata ts_siic[D_IIC_NUM];
|
||
|
|
||
|
/*------------------------------------------------
|
||
|
端口定义
|
||
|
在I2C总线传输数据过程中,每传输一个字节,
|
||
|
都要跟一个应答状态位。接收器接收数据的情况
|
||
|
可以通过应答位来告知发送器。应答位的时钟脉冲
|
||
|
仍由主机产生,而应答位的数据状态则遵循“谁
|
||
|
接收谁产生”的原则,即总是由接收器产生应答位,
|
||
|
在响应的时钟脉冲期间接收器必须将SDA 线拉
|
||
|
低,使它在这个时钟脉冲的高电平期间保持稳定的低电平(见图9) ,
|
||
|
当然必须考虑建立和保持时间
|
||
|
(详细请查阅表6) 。主机向从机发送数据时,
|
||
|
应答位由从机产生;主机从从机接收数据时,应答位
|
||
|
由主机产生。
|
||
|
I2C总线标准规定: 应答位为0表示接收器应答 (ACK) ,
|
||
|
常常简记为A; 为1则表示非应答 (NACK) ,
|
||
|
常简记为NA。发送器发送LSB之后,应当释放SDA线(拉高SDA) ,
|
||
|
以等待接收器产生应答位。
|
||
|
如果接收器在接收完最后一个字节的数据,
|
||
|
或者不能再接收更多的数据时,应当产生非应答信
|
||
|
号来通知发送器。发送器如果发现接收器产生了非应答状态,
|
||
|
则应当终止发送。
|
||
|
|
||
|
------------------------------------------------*/
|
||
|
///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
|
||
|
|
||
|
void L0_iicx_INIT(TS_siic_ *p,unsigned char v)
|
||
|
{
|
||
|
TS_siic_ *pp = p;
|
||
|
/// p->pf_init(1);
|
||
|
if (v)///正常工作
|
||
|
{
|
||
|
// p->pf_SDA_set(1);
|
||
|
// p->pf_SCL_set(1);
|
||
|
|
||
|
pp->pf_SDA_out(1);
|
||
|
pp->pf_SCL_out(1);
|
||
|
|
||
|
// //
|
||
|
|
||
|
|
||
|
}else
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned char L0_iicx_SDA_ask(TS_siic_ *p)
|
||
|
{
|
||
|
if(p->pf_SDA_get() != 0)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
///<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
|
||
|
|
||
|
|
||
|
/****************
|
||
|
|
||
|
void L0_iicx_Reset(void)
|
||
|
{
|
||
|
p->pf_SCL_set(1); p->pf_SDA_set(1);//pf_SDA_set(1);; //确认释放总线
|
||
|
}
|
||
|
|
||
|
|
||
|
********************/
|
||
|
|
||
|
//**********************************************
|
||
|
//送起始位 IO_SDA=1->0
|
||
|
void L0_iicx_Start(TS_siic_ *p)
|
||
|
{
|
||
|
#if 0
|
||
|
|
||
|
TS_siic *pp = p;
|
||
|
pp->pf_SDA_set(1);//pf_SDA_set(1);;
|
||
|
pp->pf_SCL_set(1);
|
||
|
pp->pf_SDA_set(0);
|
||
|
pp->pf_SCL_set(0);
|
||
|
|
||
|
#else
|
||
|
|
||
|
p->pf_SDA_set(1);//pf_SDA_set(1);;
|
||
|
p->pf_SCL_set(1);
|
||
|
p->pf_SDA_set(0);
|
||
|
p->pf_SCL_set(0);
|
||
|
#endif
|
||
|
///fixme: cc
|
||
|
L0_slc_1_delay();
|
||
|
L0_slc_1_delay();
|
||
|
L0_slc_1_delay();
|
||
|
}
|
||
|
//************************************************
|
||
|
//送停止位 IO_SDA = 0->1
|
||
|
void L0_iicx_Stop(TS_siic_ *p)
|
||
|
{
|
||
|
p->pf_SDA_set(0);
|
||
|
p->pf_SCL_set(1);
|
||
|
p->pf_SDA_set(1);
|
||
|
/// p->pf_init(0);
|
||
|
}
|
||
|
//************************************************
|
||
|
//主应答(包含ack:IO_SDA = 0和no_ack:IO_SDA = 0)
|
||
|
///主机给从机的ACK
|
||
|
void L0_iicx_Ack(TS_siic_ *p)
|
||
|
{
|
||
|
p->pf_SDA_out(1);//设置SDA 口为输出
|
||
|
p->pf_SCL_set(0);
|
||
|
p->pf_SDA_set(0);
|
||
|
p->pf_SCL_set(1);
|
||
|
p->pf_SCL_set(0);
|
||
|
p->pf_SDA_out(0);
|
||
|
// Lc_delay_ms(2); ///for debug wave easy to see
|
||
|
|
||
|
}
|
||
|
|
||
|
///主机给从机的NOACK
|
||
|
void L0_iicx_NoAck(TS_siic_ *p)
|
||
|
{
|
||
|
p->pf_SDA_out(1);//设置SDA 口为输出
|
||
|
p->pf_SCL_set(0);
|
||
|
p->pf_SDA_set(1);
|
||
|
p->pf_SCL_set(1);
|
||
|
p->pf_SCL_set(0);
|
||
|
p->pf_SDA_out(0);
|
||
|
// Lc_delay_ms(2);
|
||
|
|
||
|
}
|
||
|
|
||
|
/// 从机返回的ack
|
||
|
void L0_iicx_WaitAck(TS_siic_ *p)
|
||
|
{
|
||
|
p->pf_SDA_out(0);
|
||
|
p->pf_SCL_set(1);
|
||
|
////
|
||
|
p->pf_SCL_set(0);
|
||
|
p->pf_SDA_out(1);
|
||
|
/// Lc_delay_ms(2);
|
||
|
}
|
||
|
|
||
|
|
||
|
/******
|
||
|
I2C总线标准规定: 应答位为0表示接收器应答 (ACK) , 常常简记为A;
|
||
|
为1则表示非应答 (NACK) ,常简记为NA。
|
||
|
发送器发送LSB之后,应当释放SDA线(拉高SDA) ,
|
||
|
以等待接收器产生应答位。
|
||
|
如果接收器在接收完最后一个字节的数据,
|
||
|
或者不能再接收更多的数据时,应当产生非应答信
|
||
|
号来通知发送器。发送器如果发现接收器产生了非应答状态,
|
||
|
则应当终止发送。
|
||
|
// 检测 SDA是否回ACK
|
||
|
bit L0_iicx_Test_Ack(void)
|
||
|
{ //设置SDA 口为输入
|
||
|
bit ACK_Flag = 0;
|
||
|
p->pf_SCL_set(0);
|
||
|
p->pf_SDA_set(1);//pf_SDA_set(1);;
|
||
|
p->pf_SCL_set(1);
|
||
|
|
||
|
|
||
|
if(IO_SDA = 0)
|
||
|
ACK_Flag = 1;
|
||
|
else
|
||
|
ACK_Flag = 0;
|
||
|
p->pf_SCL_set(0);
|
||
|
return ACK_Flag;
|
||
|
// return 1;// debug
|
||
|
}
|
||
|
*******/
|
||
|
//*************************************************
|
||
|
//字节发送程序
|
||
|
//发送c(可以是数据也可是地址),送完后接收从应答
|
||
|
//不考虑从应答位
|
||
|
|
||
|
void L0_iicx_SendData(TS_siic_ *p,unsigned char c)
|
||
|
{
|
||
|
TS_siic_ *pp = p;
|
||
|
TS_siic_ *tt = p;
|
||
|
// unsigned char ack=8;
|
||
|
unsigned char BitCnt=8;//一字节8位
|
||
|
//设置SDA 口为输出
|
||
|
for(BitCnt = 0;BitCnt < 8;BitCnt ++) //要传送的数据长度为8位
|
||
|
{
|
||
|
//printf("\r\nBitCnt=%d",(int)BitCnt);
|
||
|
if((c << BitCnt ) & 0x80)
|
||
|
pp->pf_SDA_set(1);//pf_SDA_set(1);; //判断发送位;/// ;//
|
||
|
else
|
||
|
pp->pf_SDA_set(0);
|
||
|
|
||
|
tt->pf_SCL_set(1); //置时钟线为高,通知被控器开始接收数据位
|
||
|
tt->pf_SCL_set(0);
|
||
|
/// printf("\r\nqq=%d",(int)BitCnt);
|
||
|
pp = p;
|
||
|
tt = p;
|
||
|
}//8clk
|
||
|
L0_iicx_WaitAck(tt);
|
||
|
}
|
||
|
//**************************************************
|
||
|
//字节接收程序
|
||
|
//接收器件传来的数据,此程序应配合|主应答函数|i2c_ack_main(void)使用
|
||
|
//return: uchar型1字节
|
||
|
|
||
|
unsigned char L0_iicx_ReceiveData(TS_siic_ *p)
|
||
|
{
|
||
|
unsigned char BitCnt=8,IIC_RX_Data = 0;
|
||
|
p->pf_SDA_out(0);// p->pf_SDA_set(1);//pf_SDA_set(1);; //读入数据 设置SDA 口为输入
|
||
|
for(BitCnt = 0;BitCnt<8;BitCnt++)
|
||
|
{
|
||
|
L0_I2C_delay(1);
|
||
|
p->pf_SCL_set(0); //置时钟线为低,准备接收数据位
|
||
|
p->pf_SCL_set(1); //置时钟线为高使数据线上数据有效
|
||
|
L0_I2C_delay(1);
|
||
|
IIC_RX_Data = IIC_RX_Data << 1;
|
||
|
if(0 != p->pf_SDA_get())//切记 非零和零的区别
|
||
|
IIC_RX_Data = IIC_RX_Data + 1; //读数据位,接收的数据位放入retc中
|
||
|
L0_I2C_delay(1);
|
||
|
}// 8clk up
|
||
|
p->pf_SCL_set(0);
|
||
|
return IIC_RX_Data;
|
||
|
}
|
||
|
/// 读取 n个数据 放入p中
|
||
|
|
||
|
void L0_iicx_ReadNByte(TS_siic_ *p, unsigned char *b,unsigned char n)
|
||
|
{
|
||
|
|
||
|
TS_siic_ *pp = p;
|
||
|
TS_siic_ *tt = p;
|
||
|
unsigned char i;
|
||
|
|
||
|
|
||
|
printf("111 3\r\n");
|
||
|
L0_iicx_Start(pp); // 启动I2C
|
||
|
|
||
|
printf("222 3\r\n");
|
||
|
L0_iicx_SendData(pp,(pp->sal)| 0x01); //发送器件地址
|
||
|
//p->pf_SDA_out(0);
|
||
|
for(i = 0;i<n-1;i++) //读取字节数据
|
||
|
{
|
||
|
*(b + i) = L0_iicx_ReceiveData(pp); //读取数据
|
||
|
L0_iicx_Ack(pp); //__/```\__
|
||
|
|
||
|
pp = p;
|
||
|
tt = p;
|
||
|
}
|
||
|
*(b + n - 1) = L0_iicx_ReceiveData(pp);
|
||
|
L0_iicx_NoAck(pp);
|
||
|
tt->pf_SDA_out(1);
|
||
|
L0_iicx_Stop(tt);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////
|
||
|
///写入一个reg 为后续的写命令或者读取服务
|
||
|
void L1_iicx_Write1Reg(TS_siic_ *p,unsigned char reg)
|
||
|
{
|
||
|
//printf("L1_iicx_Write1Reg 3\r\n");
|
||
|
L0_iicx_Start(p); //启动I2C
|
||
|
|
||
|
//printf("L0_iicx_Start\r\n");
|
||
|
L0_iicx_SendData(p,p->sal);//发送器件地址
|
||
|
|
||
|
///printf("L0_iicx_SendData\r\n");
|
||
|
L0_iicx_SendData(p,reg);
|
||
|
}
|
||
|
|
||
|
void L1_iicx_Write2Reg(TS_siic_ *p,unsigned char reg,unsigned char reg2)
|
||
|
{
|
||
|
L0_iicx_Start(p); //启动I2C
|
||
|
L0_iicx_SendData(p,p->sal);//发送器件地址
|
||
|
L0_iicx_SendData(p,reg);
|
||
|
L0_iicx_SendData(p,reg2);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//读取reg地址(1Byte)的1个数据 sla.(reg) sla.(reg+1). 有返回值的 为了兼容
|
||
|
unsigned char L2_iicx_Read1Reg1DataR(TS_siic_ *p,unsigned char reg)
|
||
|
{
|
||
|
unsigned char d;
|
||
|
// U8 d[1];
|
||
|
//S ADD W A REG A
|
||
|
L1_iicx_Write1Reg(p,reg);
|
||
|
//S ADD R A D1 A D2 A.....DX N P
|
||
|
L0_iicx_ReadNByte(p,&d,1);
|
||
|
return d;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//读取reg地址(1Byte)的1个数据 sla.(reg) sla.(reg+1). 没有返回值的 为了兼容
|
||
|
void L2_iicx_Read1Reg1Data(TS_siic_ *p,unsigned char reg,unsigned char *r)
|
||
|
{
|
||
|
//S ADD W A REG A
|
||
|
L1_iicx_Write1Reg(p,reg);
|
||
|
//S ADD R A D1 A D2 A.....DX N P
|
||
|
L0_iicx_ReadNByte(p,r,1);
|
||
|
}
|
||
|
|
||
|
|
||
|
void L2_iicx_Read1RegNData(TS_siic_ *p,unsigned char reg,
|
||
|
unsigned char *r,unsigned char n)
|
||
|
{
|
||
|
|
||
|
#if 0
|
||
|
|
||
|
///printf("L2_iicx_Read1RegNData\r\n");
|
||
|
|
||
|
p->pf_SDA_set(1);//pf_SDA_set(1);;
|
||
|
|
||
|
|
||
|
///printf("pf_SDA_set\r\n");
|
||
|
|
||
|
p->pf_SCL_set(1);
|
||
|
///p->pf_SDA_set(0);
|
||
|
///p->pf_SCL_set(0);
|
||
|
|
||
|
printf("pf_SCL_set\r\n");
|
||
|
|
||
|
|
||
|
//L0_iicx_Start(p); //启动I2C
|
||
|
//L0_iicx_SendData(p,p->sal);//发送器件地址
|
||
|
//L0_iicx_SendData(p,reg);
|
||
|
|
||
|
#else
|
||
|
printf("L2_iicx_Read1RegNData\r\n");
|
||
|
//S ADD W A REG A
|
||
|
L1_iicx_Write1Reg(p,reg);
|
||
|
|
||
|
printf("L1_iicx_Write1Reg\r\n");
|
||
|
//S ADD R A D1 A D2 A.....DX N P
|
||
|
L0_iicx_ReadNByte(p,r,1);
|
||
|
|
||
|
|
||
|
|
||
|
printf("L0_iicx_ReadNByte\r\n");
|
||
|
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void L2_iicx_Read2RegNdata(TS_siic_ *p,unsigned char H,unsigned char L,
|
||
|
unsigned char *r,unsigned char n)
|
||
|
{
|
||
|
// U8 d[1];
|
||
|
//S ADD W A REG A
|
||
|
/// L1_iicx_Write1Reg(p,H);
|
||
|
/// L0_iicx_SendData(p,L);
|
||
|
L1_iicx_Write2Reg(p,H,L);
|
||
|
//S ADD R A D1 A D2 A.....DX N P
|
||
|
L0_iicx_ReadNByte(p,r,n);
|
||
|
|
||
|
}
|
||
|
/******
|
||
|
// sla.(reg)=cmd
|
||
|
void L2_iicx_Write1Reg1Cmd(TS_siic *p, unsigned char reg,unsigned char cmd)
|
||
|
{
|
||
|
L1_iicx_Write1Reg(p,reg);
|
||
|
L0_iicx_SendData(p,cmd);
|
||
|
L0_iicx_Stop(p);
|
||
|
/*****************
|
||
|
if(gRccUs05 >0)///测试iic有效否 发现没有结果
|
||
|
{
|
||
|
L0_uart0_uc(gRccUs05);gRccUs05 = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
////// S slaW cmd cmd2 S slaR A A NACK P
|
||
|
////// A A A A MSB LSB CRC
|
||
|
void L2_iicx_Read2Cmd(TS_siic *p, unsigned char cmd,unsigned char cmd2,
|
||
|
unsigned char *buf,unsigned char n)
|
||
|
{
|
||
|
L1_iicx_Write1Reg(p,cmd);
|
||
|
L0_iicx_SendData(p,cmd2);
|
||
|
|
||
|
L1_iicx_ReadNByte(p,buf,n);
|
||
|
}
|
||
|
|
||
|
/// I2C设备地址为8bit,其中最低位为读写位,0为写,1为读
|
||
|
////读取两个字节的,先发送两个字节 然后再读取
|
||
|
void L1_iicx_Read2cmd(TS_siic *p, unsigned char *c,unsigned char *b,unsigned char n)
|
||
|
{
|
||
|
unsigned char i;
|
||
|
L0_iicx_Start(p); // 启动I2C
|
||
|
L0_iicx_SendData(p,(p->sal)| 0x01); //发送器件地址
|
||
|
L0_iicx_SendData(p,(*c)); //发送器件地址
|
||
|
L0_iicx_SendData(p,*(c+1));
|
||
|
|
||
|
|
||
|
//p->pf_SDA_out(0);
|
||
|
for(i = 0;i<n-1;i++) //读取字节数据
|
||
|
{
|
||
|
*(b + i) = L0_iicx_ReceiveData(p); //读取数据
|
||
|
L0_iicx_Ack(p); //__/```\__
|
||
|
}
|
||
|
*(b + n - 1) = L0_iicx_ReceiveData(p);
|
||
|
L0_iicx_NoAck(p);
|
||
|
p->pf_SDA_out(1);
|
||
|
L0_iicx_Stop(p);
|
||
|
}
|
||
|
|
||
|
void L2_iicx_Read1RegNData(TS_siic *p,unsigned char reg,
|
||
|
unsigned char *r,unsigned char n)
|
||
|
*********/
|
||
|
|
||
|
void L3_iicx_debug(u8 filter)
|
||
|
{
|
||
|
if(filter == Ts_debug.td->filter)
|
||
|
{
|
||
|
///while(9)
|
||
|
{
|
||
|
printf("\r\n 0x%2x\r\n",(int)Ts_debug.td->ocr);
|
||
|
}
|
||
|
// L0_uart0_uc("A");
|
||
|
// L0_uart0_0d0a();
|
||
|
if(0x10 == Ts_debug.td->ocr)///read reg1 num 读取reg1地址中的num个数据
|
||
|
{
|
||
|
//NUM: 0 1 2 3 4
|
||
|
// Fx R1 R2 R3 ocr
|
||
|
// TS_siic reg1 num
|
||
|
/// f1 00 0x28 06 10
|
||
|
/// f1 00 0x28 06 10
|
||
|
|
||
|
|
||
|
/// while(9)
|
||
|
{
|
||
|
L2_iicx_Read1RegNData(&ts_siic[Ts_debug.td->R1],Ts_debug.td->R2,Ts_debug.d,Ts_debug.td->R3);
|
||
|
L1_uartD_uchexArray(Ts_debug.d,Ts_debug.td->R3);
|
||
|
//
|
||
|
/// printf("\r\n 0x%2x\r\n",(int)Ts_debug.td->ocr);
|
||
|
}
|
||
|
}else if(0x11 == Ts_debug.td->ocr)//read reg1 reg2 num 读取reg1地址中的num个数据
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
}else if(0x12 == Ts_debug.td->ocr)//write
|
||
|
{///设置重量
|
||
|
|
||
|
/// printf("\r\n set[ %d].adc = 0x%04x\r\n",(int)Ts_debug.td->R1, (vU16)tst_weight.out6);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
else
|
||
|
{
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|