IIC通信控制的AD5259------在调试过程中遇到的奇葩问题
首先說(shuō)一下的遇到的問(wèn)題:
1.AD5259按照SCL是100KHz的情況下,可以正常接收上位機(jī)的數(shù)據(jù),但是一段時(shí)間后,就不能正確的按照時(shí)序來(lái)走了
原因在于AD5259在接收到上位機(jī)的數(shù)據(jù)后需要一定的響應(yīng)時(shí)間,而在這個(gè)響應(yīng)時(shí)間內(nèi),scl和sda都不應(yīng)該有任何的活動(dòng),否則會(huì)導(dǎo)致不能準(zhǔn)確接收下一個(gè)數(shù)據(jù)的開(kāi)始信號(hào),但要特別注意的是,這段時(shí)間內(nèi)的SCL以及SDA的設(shè)置也是有一個(gè)說(shuō)法的。
2.斷電后可以保持在正常工作的條件下。
斷電相當(dāng)于是一個(gè)復(fù)位的過(guò)程,也就是說(shuō),復(fù)位后可以正常工作~
3.網(wǎng)上找到的完整的IIC分析
IIC協(xié)議
??IIC協(xié)議是一種多機(jī)通訊,由SDA數(shù)據(jù)線和SCL時(shí)鐘線構(gòu)成串行總線,所有的IIC設(shè)備都可以掛載到總線上,但每個(gè)設(shè)備都有唯一的設(shè)備讀地址和設(shè)備寫(xiě)地址。在使用IIC作為數(shù)字接口的芯片datasheet中都可以看到該設(shè)備的設(shè)備讀/寫(xiě)地址情況,并可以查找到相應(yīng)的讀寫(xiě)時(shí)序,以及對(duì)速率的要求。下圖是一個(gè)通用的IIC協(xié)議時(shí)序:
?
我們可以總結(jié)出五種IIC協(xié)議的時(shí)序狀態(tài):
??1. 空閑狀態(tài),當(dāng)SDA和SCL兩條信號(hào)線都處于高電平時(shí)總線處于空閑狀態(tài)。
??2. 開(kāi)始信號(hào),SCL為高電平期間SDA信號(hào)線上產(chǎn)生了下降沿標(biāo)志著的一次數(shù)據(jù)傳輸?shù)拈_(kāi)始。開(kāi)始信號(hào)應(yīng)當(dāng)由主機(jī)發(fā)起。
??3. 數(shù)據(jù)傳輸,在SCL同步控制下SDA串行的傳送每一位,因此傳送8bits的數(shù)據(jù)需要8個(gè)SCL時(shí)鐘。SCL為高電平時(shí)期SDA電平狀態(tài)必須穩(wěn)定;SCL為低電平期間才允許SDA改變狀態(tài)。
??4. 應(yīng)答信號(hào),IIC總線上每傳送一個(gè)8位字節(jié),第9個(gè)脈沖期間便會(huì)釋放總線,由接收器發(fā)出一個(gè)應(yīng)答信號(hào),反饋有沒(méi)有成功接收。
??5. 停止信號(hào),在SCL保持高電平期間,將SDA信號(hào)線釋放恢復(fù)到高電平,標(biāo)志一次數(shù)據(jù)傳輸?shù)慕Y(jié)束,IIC總線也重新回到了空閑狀態(tài)。
計(jì)數(shù)器控制IIC讀寫(xiě)
??在“FPGA基礎(chǔ)設(shè)計(jì)(三):UART串口通信”中已經(jīng)接觸到了使用計(jì)數(shù)器控制時(shí)序的方法,這個(gè)方法在控制IIC通信時(shí)同樣實(shí)用。一次完整的寫(xiě)入操作如下所示:
case( i )
0: // iic Start
begin
isOut <= 1; //SDA端口輸出
if( C1 == 0 ) rSCL <= 1'b1;
else if( C1 == 200 ) rSCL <= 1'b0; //SCL由高變低
if( C1 == 0 ) rSDA <= 1'b1;
else if( C1 == 100 ) rSDA <= 1'b0; //SDA先由高變低
if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin rData <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
2: // Wirte Word Addr
begin rData <= Addr_Sig; i <= 5'd7; Go <= i + 1'b1; end
3: // Write Data
begin rData <= WrData; i <= 5'd7; Go <= i + 1'b1; end
4: //iic Stop
begin
isOut <= 1'b1;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1; //SCL先由低變高
if( C1 == 0 ) rSDA <= 1'b0;
else if( C1 == 150 ) rSDA <= 1'b1; //SDA由低變高
if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
5:
begin isDone <= 1'b1; i <= i + 1'b1; end //寫(xiě)I2C 結(jié)束
6:
begin isDone <= 1'b0; i <= 5'd0; end
7,8,9,10,11,12,13,14: //發(fā)送Device Addr/Word Addr/Write Data
begin
isOut <= 1'b1;
rSDA <= rData[14-i]; //高位先發(fā)送
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1;
else if( C1 == 150 ) rSCL <= 1'b0;
if( C1 == F250K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
15: // waiting for acknowledge
begin
isOut <= 1'b0; //SDA端口改為輸入
if( C1 == 100 ) isAck <= SDA;
if( C1 == 0 ) rSCL <= 1'b0;
else if( C1 == 50 ) rSCL <= 1'b1;
else if( C1 == 150 ) rSCL <= 1'b0;
if( C1 == F250K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
16:
if( isAck != 0 ) i <= 5'd0;
else i <= Go;
endcase
?向IIC總線寫(xiě)數(shù)據(jù)時(shí),需要依次寫(xiě)入待寫(xiě)入的設(shè)備寫(xiě)地址、設(shè)備中的寫(xiě)地址和待寫(xiě)入的數(shù)據(jù)共3個(gè)8bits字節(jié)數(shù)據(jù)。i代表總線上不同的狀態(tài),通過(guò)計(jì)數(shù)器來(lái)控制狀態(tài)之間的跳轉(zhuǎn)。i為0時(shí)發(fā)出開(kāi)始信號(hào);i為7~14時(shí)控制8bits數(shù)據(jù)的發(fā)送;i為1、2、3時(shí)分別為設(shè)備地址、字節(jié)地址和數(shù)據(jù),依次調(diào)用7-14完成數(shù)據(jù)的傳輸;其余還有停止位、應(yīng)答位、IIC通信完成置位等狀態(tài)。
??從器件中讀取數(shù)據(jù)的方法與此一樣,只不過(guò)通常都需要先向IIC總線寫(xiě)入待讀取的設(shè)備地址和器件地址,之后再讀數(shù)據(jù)。讀數(shù)據(jù)整體過(guò)程比寫(xiě)數(shù)據(jù)要麻煩一點(diǎn),但只要控制好狀態(tài)之間跳轉(zhuǎn)的過(guò)程即可。
分頻時(shí)鐘控制IIC讀寫(xiě)
??由計(jì)數(shù)器控制通信時(shí)序的方法優(yōu)點(diǎn)是很靈活,幾乎所有的時(shí)序方法都可以用這種方法完成;缺點(diǎn)就是太麻煩,需要控制好狀態(tài)之間的跳轉(zhuǎn),時(shí)序越復(fù)雜使用越麻煩,其實(shí)在“FPGA采集-傳輸-顯示系統(tǒng)(二):基于FPGA的溫度采集和以太網(wǎng)傳輸”中,我對(duì)DS18B20的時(shí)序控制就是采用計(jì)數(shù)器控制的方法。DS18B20的時(shí)序要求較多,因此其中的狀態(tài)跳轉(zhuǎn)已經(jīng)相當(dāng)復(fù)雜。
??其實(shí)在控制IIC這種時(shí)鐘速率固定的串行協(xié)議時(shí),還可以在外部分頻或PLL生成一個(gè)低頻的通信時(shí)鐘,用這個(gè)時(shí)鐘來(lái)控制數(shù)據(jù)傳輸過(guò)程。如下所示:
always@(posedge clock_i2c)
begin
if(reset_n==1'b0) begin
tr_end<=0;
ack1<=1;
ack2<=1;
ack3<=1;
sclk<=1;
reg_sdat<=1;
end
else
case(cyc_count)
begin ack1<=1;ack2<=1;tr_end<=0;sclk<=1;reg_sdat<=1;end
reg_sdat<=0; //開(kāi)始傳輸
sclk<=0;
reg_sdat<=i2c_data[23];
reg_sdat<=i2c_data[22];
reg_sdat<=i2c_data[21];
reg_sdat<=i2c_data[20];
reg_sdat<=i2c_data[19];
reg_sdat<=i2c_data[18];
reg_sdat<=i2c_data[17];
reg_sdat<=i2c_data[16];
reg_sdat<=1; //應(yīng)答信號(hào)
begin reg_sdat<=i2c_data[15];ack1<=i2c_sdat;end
reg_sdat<=i2c_data[14];
reg_sdat<=i2c_data[13];
reg_sdat<=i2c_data[12];
reg_sdat<=i2c_data[11];
reg_sdat<=i2c_data[10];
reg_sdat<=i2c_data[9];
reg_sdat<=i2c_data[8];
reg_sdat<=1; //應(yīng)答信號(hào)
begin reg_sdat<=i2c_data[7];ack2<=i2c_sdat;end
reg_sdat<=i2c_data[6];
reg_sdat<=i2c_data[5];
reg_sdat<=i2c_data[4];
reg_sdat<=i2c_data[3];
reg_sdat<=i2c_data[2];
reg_sdat<=i2c_data[1];
reg_sdat<=i2c_data[0];
reg_sdat<=1; //應(yīng)答信號(hào)
begin ack3<=i2c_sdat;sclk<=0;reg_sdat<=0;end
sclk<=1;
begin reg_sdat<=1;tr_end<=1;end //IIC傳輸結(jié)束
endcase
?
轉(zhuǎn)載于:https://www.cnblogs.com/Dinging006/p/9073560.html
總結(jié)
以上是生活随笔為你收集整理的IIC通信控制的AD5259------在调试过程中遇到的奇葩问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 研究生报考费是多少
- 下一篇: 用python创建一个目录