今天有时间研究了AD7745的IIC读写问题。
打算用Arduino做单片机这个决定导致我没什么太多资料可以参考。Github上面没有AD7745的库。国内文章搜了一下,罗列了一些资料可以参考:
51的:XXXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXml
STM32的:XXXXXXXXXXXXXXXXXXXXXX/XXXXXXXXp?mod=viewthread&tid=70502
树莓派的:XXXXXXXXXXXXXXXXXXXX/bbs/XXXXXXXXXXXXXXXml
我一开始尝试用Arduino自带的IIC库,读取不出数据,做了地址扫描,发现有返回值的设备地址是0x48,十进制72,但是返回值也都是固定的数字,对于这个程序信心不高,于是放弃。等会儿上图。
后来根据51那个教程尝试做一个直接控制引脚电平来读取数据的实验,抄写了一会儿,发现它的程序里有点似乎非常非常(可能是故意的)恶心人的一段,随后放弃,并未尝试。有空也会上图。
最后找到一个树莓派的通用c写的AD7746库(7745差不多)
略微一看发现和arduino有惊人的相似之处。随即决定用这套程序,抄写翻译了一遍。
对于它的等待ack信号的处理不甚理解,但是应该不影响,其它时序似乎都对了。
先上程序:
#define CapDacvalue 4.97 #define SCL 21 #define SDA 20 byte SCLState = LOW; byte IIC_Flag=0; byte interval = 1; int previousMillis = 0; void IIC_Init(void) { /* GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
GPIO_XXXXXXXXXXXXXXXXIO_Pin = GPIO_Pin_12|GPIO_Pin_11; GPIO_XXXXXXXXXXXXXXXXIO_Mode = GPIO_Mode_Out_PP ; GPIO_XXXXXXXXXXXXXXXXIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); */ digitalWrite(SCL,1);//IIC_SCL=1; digitalWrite(SDA,1);//IIC_SDA=1; } void IIC_Start(void) { pinMode(SDA, OUTPUT); digitalWrite(SDA,1);//IIC_SDA=1; digitalWrite(SCL,1);//IIC_SCL=1; delayMicroseconds(4);//uS digitalWrite(SDA,0);//IIC_SDA=0; delayMicroseconds(4); digitalWrite(SCL,0);//IIC_SCL=0; } void IIC_Stop(void) { pinMode(SDA, OUTPUT); digitalWrite(SCL,0);//IIC_SCL=0; digitalWrite(SDA,0);//IIC_SDA=0; delayMicroseconds(4);//uS digitalWrite(SCL,1); digitalWrite(SDA,1); delayMicroseconds(4);//uS } byte IIC_Wait_Ack(void) { byte ucErrTime=0; pinMode(SDA, INPUT); digitalWrite(SDA,1); delayMicroseconds(1);//uS digitalWrite(SCL,1); delayMicroseconds(1);//uS while(digitalRead(SDA)) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } digitalWrite(SCL,0);//IIC_SCL=0; return 0; } void IIC_Ack(void) { digitalWrite(SCL,0);//IIC_SCL=0; pinMode(SDA, OUTPUT);//SDA_OUT(); digitalWrite(SDA,0);//IIC_SDA=0; delayMicroseconds(2);//uS digitalWrite(SCL,1); delayMicroseconds(2);//uS digitalWrite(SCL,0); }
void IIC_NAck(void) { digitalWrite(SCL,0);//IIC_SCL=0; pinMode(SDA, OUTPUT);//SDA_OUT(); digitalWrite(SDA,1);//IIC_SDA=1; delayMicroseconds(2);//uS digitalWrite(SCL,1);//IIC_SCL=1; delayMicroseconds(2);//uS digitalWrite(SCL,0);//IIC_SCL=0; }
void IIC_Send_Byte(byte txd) { byte t; pinMode(SDA, OUTPUT);//SDA_OUT(); digitalWrite(SCL,0);//IIC_SCL=0; for(t=0;t<8;t++) { digitalWrite(SDA,(txd&0x80)>>7);//IIC_SDA=(txd&0x80)>>7; txd<<=1; delayMicroseconds(2);//uS digitalWrite(SCL,1);//IIC_SCL=1; delayMicroseconds(2);//uS digitalWrite(SCL,0);//IIC_SCL=0; delayMicroseconds(2);//uS } } u8 IIC_Read_Byte(unsigned char ack) { unsigned char i,receive=0; pinMode(SDA, INPUT); for(i=0;i<8;i++ ) { digitalWrite(SCL,0);//IIC_SCL=0 delayMicroseconds(2);//uS digitalWrite(SCL,1);//IIC_SCL=1; receive<<=1; if(digitalRead(SDA))receive++; delayMicroseconds(1);//delay_us(1); } if (!ack) IIC_NAck(); else IIC_Ack(); return receive; } unsigned char IICWatask2(void) ///????,master wait for the ack, { unsigned char i=0; unsigned char flag=0x01; digitalWrite(SCL,0);//IIC_SCL=0; delayMicroseconds(2);//uS digitalWrite(SDA,1);//IIC_SDA=1; digitalWrite(SCL,1);//IIC_SCL=1; delayMicroseconds(6);//delay_us(6); while(digitalRead(SDA)&&(i<250))///????while((IIC_SDA==1)&&(i<250)) could just use a delay? i++; flag=digitalRead(SDA);//flag=IIC_SDA; digitalWrite(SCL,0);//IIC_SCL=0; return(flag); } void IICSendask(void) { digitalWrite(SDA,0);//IIC_SDA=0; delayMicroseconds(3);//delay_us(3); digitalWrite(SCL,1);//IIC_SCL=1; delayMicroseconds(6);//delay_us(6); delayMicroseconds(2);//delay_us(2); digitalWrite(SCL,0);//IIC_SCL=0; digitalWrite(SDA,1);//IIC_SDA=1; delayMicroseconds(3);//delay_us(3); } unsigned char IICRECVbyte(void) { unsigned char i; unsigned char temp=0; digitalWrite(SCL,0);//IIC_SCL=0; digitalWrite(SDA,1);//IIC_SDA=1; for (i=0;i<8;i++) { digitalWrite(SCL,1);//IIC_SCL=1; delayMicroseconds(5);//delay_us(5); temp=temp<<1; if(digitalRead(SDA)==1)//IIC_SDA==1 temp=temp|0x01; else temp=temp&0xfe; digitalWrite(SCL,0);//IIC_SCL=0; } return(temp); } void AD7745_RESET(void) { IIC_Start(); IIC_Send_Byte(0xBF); // accroding to the reset method IIC_Stop(); } unsigned char SETUP_7745(unsigned char addr,unsigned char value) { unsigned char flag; flag=0x01; IIC_Start(); IIC_Send_Byte(0x90); if(IICWatask2()!=0) flag=1; else flag=0; IIC_Send_Byte(addr); if(IICWatask2()!=0) flag=1; else flag=0; IIC_Send_Byte(value); if(IICWatask2()!=0) flag=1; else flag=0; IIC_Stop(); return(flag); } void GET7745value(unsigned char *p,unsigned char addr,unsigned char n)// get a series of value { unsigned char i; unsigned char flagw; IIC_Start(); IIC_Send_Byte(0x90); flagw=IICWatask2(); IIC_Send_Byte(addr); //从 Cap Data H开始读取0x01, addr 自定义开始读取的寄存器地址 flagw=IICWatask2(); IIC_Start(); IIC_Send_Byte(0x91); flagw=IICWatask2(); for(i=0;i<n;i++) { *p=IICRECVbyte(); if(i!=n-1) IICSendask(); else IICSendask(); p++; } IIC_Stop(); } // #define CapDacvalue 4. // capdacreg=(int)((CapDacvalue*0x7F)/17 // capdacreg=0x80|capdacre // AD7745_RESET( // SETUP_7745(0x07,0x80 // SETUP_7745(0x09,0x2B // SETUP_7745(0x0A,0xA1 // SETUP_7745(0x0B,capdacreg); // GET7745value(MRD,3); void setup() { XXXXXXXXXgin(9600); // initialize digital pin as an output. pinMode(SCL, OUTPUT); AD7745_RESET(); delay(100); XXXXXXXXXintln("Reset"); //SETUP_7745(0x07,0x80); //SETUP_7745(0x09,0x2B); //SETUP_7745(0x0A,0xA1); //int capdacreg=(int)((CapDacvalue*0x7F)/17); //capdacreg=0x80|capdacreg; //SETUP_7745(0x0B,capdacreg); XXXXXXXXXintln("Setup done"); } // the loop function runs over and over again forever void loop() { byte n=18;//先取1个字节试试 byte buff[17];//*p指向的缓存区,准备1个字节的空间 unsigned char addr; addr=0x01; GET7745value(buff,addr,n); for(byte j=0;j<n;j++) { XXXXXXXXXint(j);//从地址开始的位置为0 XXXXXXXXXint(" "); XXXXXXXXXintln(buff[j],HEX); } delay(5000); } |
更新了一下程序。
上机测试,数据是读出来了没错。因为IIC如果不读出来,会出现卡住的现象,什么都显示不出来。可是现在我收到的结果是:
对应于AD7745寄存器的:
怀疑是Rest的问题,陷入窘境。
上一张连线图(应该不是这个问题):
使用中我还是比较注意静电防护的,手拿电路板的时候,我用下面这层气泡袋防护一下。
时段 | 个数 |
---|---|
{{f.startingTime}}点 - {{f.endTime}}点 | {{f.fileCount}} |