////////////////////////////////////////////////////////////////////////// /// 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;ipf_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;ipf_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 { } } }