|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測(cè)控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
一個(gè)I/O口操作的麻煩問(wèn)題 |
| 作者:wqz 欄目:單片機(jī) |
用I2C舉個(gè)例子(當(dāng)然不是應(yīng)用在I2C里): 1.在32個(gè)口線上掛16個(gè)I2C器件 2.我很吝嗇,不想為每個(gè)器件都準(zhǔn)備一套I2C協(xié)議,想共用協(xié)議。 3.顯然下面“傳遞口線”的寫(xiě)法是錯(cuò)誤的,KEIL C不接受; void I2CSendByte(uchar ch;uchar sdata){ //ch:表示要傳送通道號(hào)(及16個(gè)器件中的一個(gè)) //sdata:表示要發(fā)送的一個(gè)字節(jié)數(shù)據(jù) SWITCH(ch){ case 0:{Sbit SDA=P1^0;Sbit SCL=P1^1;};break; case 1:{Sbit SDA=P1^2;Sbit SCL=P1^3;};break; case 2:{Sbit SDA=P3^6;Sbit SCL=P3^7;};break; case 3:{Sbit SDA=P2^0;Sbit SCL=P2^1;};break; …… } ……//這些是對(duì)“目標(biāo)”口線進(jìn)行“讀寫(xiě)”的操作語(yǔ)句 } 4.當(dāng)然有種方法是可行的,用“與”對(duì)某位清零,用“或”對(duì)某位置高,但 這種方法需要通過(guò)運(yùn)算得到結(jié)果,反應(yīng)速度慢了一些,特別要對(duì)某個(gè)口線 進(jìn)行判斷高電平或低電平判斷時(shí)。 因?yàn),我才疏學(xué)淺,無(wú)法參出如何在KEIL C里進(jìn)行“口線傳遞”方法,所以貼上來(lái)請(qǐng)高手前來(lái)解決。謝謝! * - 本貼最后修改時(shí)間:2006-4-5 17:22:17 修改者:wqz |
| 2樓: | >>參與討論 |
| 作者: wqz 于 2006/4/6 11:31:00 發(fā)布:
不要落下,繼續(xù)等待高手 不要落下,繼續(xù)等待高手 |
|
| 3樓: | >>參與討論 |
| 作者: kimfufree 于 2006/4/6 16:14:00 發(fā)布:
請(qǐng)你測(cè)試一下這個(gè)程序。 我測(cè)了兩個(gè)口是可以的。你再測(cè)測(cè)。 bit SDA,SCL; sbit P1_0=P1^0; sbit P1_1=P1^1; sbit P1_2=P1^2; sbit P1_3=P1^3; 。。。。。。//你自己定吧。 void I2CSendByte(uchar ch,uchar sdata){//你之前是分號(hào)也能編譯過(guò)嗎? //ch:表示要傳送通道號(hào)(及16個(gè)器件中的一個(gè)) //sdata:表示要發(fā)送的一個(gè)字節(jié)數(shù)據(jù) SWITCH(ch){ #if 1 case 0:{ SDA=P1_0; SCL=P1_1;};break; case 1:{ SDA=P1_2; SCL=P1_3;}break; ... ... //不能用SDA=P1^0這種方式; #else case 0:{Sbit SDA=P1^0;Sbit SCL=P1^1;};break; case 1:{Sbit SDA=P1^2;Sbit SCL=P1^3;};break; case 2:{Sbit SDA=P3^6;Sbit SCL=P3^7;};break; case 3:{Sbit SDA=P2^0;Sbit SCL=P2^1;};break; …… #endif } ……//這些是對(duì)“目標(biāo)”口線進(jìn)行“讀寫(xiě)”的操作語(yǔ)句 } |
|
| 4樓: | >>參與討論 |
| 作者: xiangyanan 于 2006/4/6 16:28:00 發(fā)布:
有現(xiàn)實(shí)意義嗎? 這樣子左右什么現(xiàn)實(shí)意義嗎? 兩顆線上完全可以掛16個(gè)i2器件! |
|
| 5樓: | >>參與討論 |
| 作者: tg.liu 于 2006/4/6 19:01:00 發(fā)布:
同意xiangyanan的說(shuō) 要知道I2C是總線,既然是總線,當(dāng)然可以接多個(gè)器件 |
|
| 6樓: | >>參與討論 |
| 作者: yadog 于 2006/4/6 21:20:00 發(fā)布:
re 是撒 |
|
| 7樓: | >>參與討論 |
| 作者: wqz 于 2006/4/7 10:24:00 發(fā)布:
還望高手繼續(xù)參與。 非常謝謝kimfufree,我一定好好試一下。至于分號(hào)是輸入錯(cuò)誤,見(jiàn)笑了。 另外,對(duì)參與本次討論的朋友我再表述一下,之前可能我沒(méi)有表達(dá)清楚。 1.不同地址的I2C器件可以掛在同一總線上,但這次不同,所有器件一樣,地址一樣。所以,無(wú)法掛在同一總線。 2.本次發(fā)貼的目的:想實(shí)現(xiàn)通過(guò)函數(shù)的參數(shù)傳遞要操作的器件的編號(hào),然后在函數(shù)里面選擇不同的I/O口(因?yàn)槠骷煌許DA,SCL掛的口不同)進(jìn)行讀寫(xiě)。 還望高手繼續(xù)參與。 |
|
| 8樓: | >>參與討論 |
| 作者: alan903 于 2006/4/7 11:06:00 發(fā)布:
LZ是指一模一樣的器件懸掛問(wèn)題? 有點(diǎn)不懂撒,換作我可以通過(guò)預(yù)讀器件寫(xiě)入模擬地址,然后再通過(guò)地址區(qū)分,不能實(shí)現(xiàn)嗎? |
|
| 9樓: | >>參與討論 |
| 作者: wqz 于 2006/4/8 16:35:00 發(fā)布:
一個(gè)I/O口操作的麻煩問(wèn)題 這個(gè)器件無(wú)法象24CXX那樣外部可以對(duì)器件設(shè)置地址,所以相同的器件,當(dāng)然地址相同。 |
|
| 10樓: | >>參與討論 |
| 作者: wqz 于 2006/4/9 18:37:00 發(fā)布:
看了kimfufree的回復(fù)后 看了kimfufree的回復(fù)后,我寫(xiě)了下面的測(cè)試程序,發(fā)現(xiàn)還是無(wú)法對(duì)I/O動(dòng)作,后面所動(dòng)作的只是位變量“Plus_Pin”,希望,有辦法的朋友可以繼續(xù)解決這個(gè)問(wèn)題。 #include <reg52.h> #define uint unsigned int #define uCHAR unsigned CHAR bit Plus_Pin; sbit P1_0=P1^0; sbit P1_1=P1^1; sbit P1_2=P1^2; sbit P1_3=P1^3; void delay(void){uCHAR i;for(i=10;i>0;i--);} void delayms(void){uCHAR j;for(j=100;j>0;j--){delay();}} void CLK_Plus(uCHAR ch,uCHAR CPN){ SWITCH(ch){ #if 1 case 0:Plus_Pin=P1_0;break; case 1:Plus_Pin=P1_1;break; case 2:Plus_Pin=P1_2;break; case 3:Plus_Pin=P1_3;break; default: break; #endif } Plus_Pin=1; for(CPN;CPN>0;CPN--){ Plus_Pin=0; delay(); Plus_Pin=1; delay(); } } void main(){ while(1){ CLK_Plus(0,4); delayms(); CLK_Plus(1,56); delayms(); CLK_Plus(2,32); delayms(); CLK_Plus(3,71); delayms(); } } |
|
| 11樓: | >>參與討論 |
| 作者: xwj 于 2006/4/9 19:04:00 發(fā)布:
暈,LZ連C語(yǔ)言賦值的方向都沒(méi)搞清? 在C語(yǔ)言中,用“=來(lái)”賦值,不過(guò)賦值的方向是把=右邊的值Copy到左邊! SDA=P1^0(應(yīng)為P_0);或Plus_Pin=P1_0;的意思是把P1_0的值復(fù)制到Plus_Pin,相當(dāng)于匯編中的 MOV C,P1_0 MOV Plus_Pin,C 結(jié)果當(dāng)然變化的是Plus_Pin變量! |
|
| 12樓: | >>參與討論 |
| 作者: xwj 于 2006/4/9 19:33:00 發(fā)布:
LZ 的意思重寫(xiě)了一下,只是每個(gè)通道發(fā)n個(gè)脈沖 //仔細(xì)想想用于I2C不管是共用SDA還是共用SCL都有弊端, //如果每片都用2個(gè)IO,那16通道豈不是要32個(gè)IO?暈... #include <reg52.h> #include<INTRINS.H> #define uint unsigned int #define uCHAR unsigned CHAR bit Plus; sbit Plus_Pin1=P1^0; sbit Plus_Pin2=P1^1; sbit Plus_Pin3=P1^2; sbit Plus_Pin4=P1^3; void delay(void){uCHAR i;for(i=10;i>0;i--);} //#define delay(); _nop_(); void delayms(void){uint j;for(j=1000;j>0;j--);} void CLK_Plus(uCHAR ch,uCHAR CPN){ for(CPN;CPN>0;CPN--){ SWITCH(ch){ case 0:Plus_Pin1=0;delay();Plus_Pin1=1;break; case 1:Plus_Pin2=0;delay();Plus_Pin2=1;break; case 2:Plus_Pin3=0;delay();Plus_Pin3=1;break; case 3:Plus_Pin4=0;delay();Plus_Pin4=1;break; default: break; } } } void main(){ Plus_Pin1=1;Plus_Pin2=1;Plus_Pin3=1;Plus_Pin4=1; while(1){ CLK_Plus(0,4); //通道0發(fā)4個(gè)脈沖 delayms(); CLK_Plus(1,56); //通道1發(fā)4個(gè)脈沖 delayms(); CLK_Plus(2,32); delayms(); CLK_Plus(3,71); delayms(); } } //本程序由xwj設(shè)計(jì)的ultraedit腳本加亮顯示,如需要腳本請(qǐng)?jiān)L問(wèn)我的blog |
|
| 13樓: | >>參與討論 |
| 作者: hunao 于 2006/4/10 14:29:00 發(fā)布:
試試用函數(shù)指針數(shù)組 sbit SDA_0 = P1 ^ 0; sbit SCL_0 = P1 ^ 1; void SetSDA0(void) { SDA_0 = 1; } void ClrSDA0(void) { SDA_0 = 0; } bit GetSDA0(void) { SDA_0 = 1; reutrn SDA_0; } void SetSCL0(void) { SCL_0 = 1; } void ClrSCL0(void) { SCL_0 = 0; } sbit SDA_1 = P1 ^ 2; sbit SCL_1 = P1 ^ 3; void SetSDA1(void) { SDA_1 = 1; } void ClrSDA1(void) { SDA_1 = 0; } bit GetSDA1(void) { SDA_1 = 1; reutrn SDA_1; } void SetSCL1(void) { SCL_ = 1; } void ClrSCL1(void) { SCL_1 = 0; } sbit SDA_2 = P1 ^ 4; sbit SCL_2 = P1 ^ 5; /* 函數(shù)同上*/ ...... sbit SDA_15 = Px ^ x; sbit SCL_15 = Px ^ x; typedef void (code *SETBIT)(void); typedef bit (code *GETBIT)(void); SETBIT code SetSDA[16] = {SetSDA0,SetSDA2,....,SetSDA15}; SETBIT code ClrSDA[16] = {ClrSDA0,ClrSDA2,....,ClrSDA15}; SETBIT code SetSCL[16] = {SetSCL0,SetSCL1,....,SetSCL15}; SETBIT code ClrSCL[16] = {ClrSCL0,ClsSCL1,....,ClrSCL15}; GETBIT code GetSDA[16] = {GetSDA0,GetSDA2,....,GetSDA15}; 在協(xié)議中,index 表示 總線索引 所有 "SDA = 1;"的地方,用 SetSDA[index]();代替 所有 "SDA = 0;"的地方,用 ClrSDA[index]();代替 所有 "SCL = 1;"的地方,用 SetSCL[index]();代替 所有 "SCL = 0;"的地方,用 ClrSCL[index]();代替 所有 "xxx = SDA"的地方,用 xxx = GetSDA[index]();代替 不知道我說(shuō)明白了沒(méi)有 |
|
| 14樓: | >>參與討論 |
| 作者: xwj 于 2006/4/10 19:32:00 發(fā)布:
呵呵,如果不j局限于軟件方法那么 兩片CD4067單16通道模擬開(kāi)關(guān)即可解決問(wèn)題 |
|
| 15樓: | >>參與討論 |
| 作者: wqz 于 2006/4/11 10:25:00 發(fā)布:
看過(guò)hunao朋友的貼后 看了hunao朋友的貼后,認(rèn)為這種方法是可行的,比準(zhǔn)備16套協(xié)議好多了。不過(guò)繁長(zhǎng)的一點(diǎn),另外,因?yàn)樾枰楸淼,所以?zhí)行反應(yīng)時(shí)間也長(zhǎng)了一點(diǎn)(不過(guò)應(yīng)付I2C足夠了)。 我在發(fā)貼的當(dāng)初已經(jīng)說(shuō)過(guò)速度還是要緊的,要不然可以用“與”和“或”來(lái)解決,F(xiàn)在,我將我寫(xiě)的測(cè)試程序(已經(jīng)編譯過(guò)關(guān),并用UV3帶的邏輯分析儀仿真過(guò))貼出來(lái): #include <reg52.h> #include <INTRINS.H> #define uint unsigned int #define uCHAR unsigned CHAR #define Set_ P1|= //可以選擇其他口,這里僅做舉例,P1口可以掛4路 #define Clr_ P1&=~ #define SomeNOP(); {_nop_();_nop_();_nop_();_nop_();_nop_();} void I2CSendByte(uCHAR ch,uCHAR sdata){ uCHAR i=8,SDA,SCL; SWITCH(ch){ //當(dāng)然也可以做成表格的方式(如果掛得多的話,這里只舉例兩路) case 0: SCL=0x1;SDA=0x2;break; //對(duì)第一路作用 case 1: SCL=0x4;SDA=0x8;break; //對(duì)第二路作用 case 2: SCL=0x5;SDA=0xa;break; //同時(shí)對(duì)兩路作用 default: break; } Set_ SDA; Set_ SCL; SomeNOP();//I2C開(kāi)始,注意在Set_或Clr后面要留空格 Clr_ SDA; SomeNOP(); Clr_ SCL; …… } 另外回答xwj朋友,硬件解決方法有很多種,但不在這里討論。 謝謝各位回貼的朋友,希望可以有更多的高手參與進(jìn)來(lái),找到更好的解決的方案。 |
|
| 16樓: | >>參與討論 |
| 作者: hunao 于 2006/4/12 3:13:00 發(fā)布:
看過(guò)wqz朋友的回貼,說(shuō)說(shuō)我的考慮 一.從速度上考慮,可以再加一個(gè)函數(shù)指針變量,在函數(shù)開(kāi)始的時(shí)候只查表一次: void I2CSendByte(uchar ch,uchar sdata,uchar index){ SETBIT Set_SDA = SetSDA[index]; SETBIT Clr_SDA = ClrSDA[index]; ...... Set_SDA(); ...... } 時(shí)間上的開(kāi)銷(xiāo)剛好可以作為延時(shí),不用再插入 nop 另外,看看編譯器對(duì)端口“與”“或”的處理,P1 &= SDA;是不是用的 讀-修改-寫(xiě) 指令 具體指令我記不清了 ANL P1,SDA ; 讀寄存器,與SDA ,寫(xiě)寄存器 如果用的是下面的指令就要小心點(diǎn)了。。。 MOV A,P1 ; 讀口線 ANL A,SDA MOV P1,A ; 寫(xiě)寄存器 |
|
| 17樓: | >>參與討論 |
| 作者: WQZ 于 2006/4/12 22:36:00 發(fā)布:
C里的無(wú)奈 hunao朋友不愧為老手,考慮事情總那么細(xì)致,你所說(shuō)的“小心點(diǎn)了”應(yīng)該是指如果編譯的不是用“讀-修改-寫(xiě)”指令,而是用多條指令完成,擔(dān)心在“ANL A,SDA”P(pán)1出現(xiàn)了變化,導(dǎo)致結(jié)果會(huì)影響P1口其他位的變化是嗎。 以下是生成SRC文件后提出來(lái)的: ;---- Variable 'SDA?043' assigned to Register 'R3' ---- ;Clr_ SDA;(即P1&=~SDA) MOV A,R3 CPL A ANL P1,A 另外“再加一個(gè)函數(shù)指針變量”確實(shí)整個(gè)程序清晰許多,不過(guò)需要執(zhí)行的時(shí)間應(yīng)該不會(huì)有變化。 如果只是用做I2C應(yīng)該足夠了。 C里對(duì)I/O口線的操作確實(shí)麻煩,要象對(duì)位變量賦值那么方便就好了。 寫(xiě)底層的口線操作還是匯編好 JB JNB JBC用起來(lái)順手多了,不過(guò)維護(hù)起來(lái)就麻煩了許多。 末了,謝謝hunao朋友參與討論 |
|
| 18樓: | >>參與討論 |
| 作者: wqz 于 2006/4/26 8:38:00 發(fā)布:
不知道是否還有更妙的點(diǎn)子 |
|
| 19樓: | >>參與討論 |
| 作者: starlite_jason 于 2006/4/26 9:38:00 發(fā)布:
可惜LZ沒(méi)有明白hunao的指針用法 應(yīng)該說(shuō)使用函數(shù)指針是針對(duì)這個(gè)問(wèn)題最好的辦法,不需要與或的運(yùn)算,而且移植也具有一致性,可惜LZ沒(méi)有明白hunao的指針用法 |
|
| 20樓: | >>參與討論 |
| 作者: liqimcu 于 2006/4/26 16:43:00 發(fā)布:
請(qǐng)教! void delay(void){uchar i;for(i=10;i>0;i--);}對(duì)嗎?i是不是會(huì)一直大于零??? |
|
| 21樓: | >>參與討論 |
| 作者: WQZ 于 2006/4/28 14:36:00 發(fā)布:
我想starlite_jason朋友可能誤會(huì)我的本意了 不管是發(fā)脈沖還是I2C都不是發(fā)這個(gè)貼的本意。 目的:解決多組相同作用功能I/O口進(jìn)行切換后繁雜的讀寫(xiě)操作。 方向:程序結(jié)構(gòu)清晰簡(jiǎn)短,執(zhí)行周期短。 可以肯定hunao朋友方法是個(gè)很好的方法。 這里,只是為了探討一個(gè)問(wèn)題的多種解決方法,或更好的方法。 有個(gè)極端的例子: 在一年多前,我碰到一個(gè)設(shè)備的鍵盤(pán)輸入壞了。因?yàn)槭抢显O(shè)備,已經(jīng)買(mǎi)不到配件。當(dāng)然,因?yàn)檫@個(gè)去開(kāi)發(fā)一個(gè)鍵盤(pán),不是很現(xiàn)實(shí)的。 然后,我嘗試用其他的鍵盤(pán)替代(當(dāng)然行列方式不一樣),保留原CPU程序。 解決的思路是:用一個(gè)I/O去判斷該行掃描電平的到來(lái),然后拉低相應(yīng)的讀口。 sbit row1=P2^0; sbit row2=P2^1; sbit row3=P2^2; sbit row4=P2^3; sbit col1=P3^1; sbit col2=P3^2; sbit col3=P3^3; …… #define Fun01 col2=row1; #define Fun02 col2=row2; #define Fun03 col1=row1; #define Fun04 col1=row2; #define Fun05 col3=row1; #define Fun06 col3=row2; #define Fun07 col1=row4; #define Fun08 col1=row3; #define Fun09 col3=row3; …… bit keyon; SWITCH(Funnumber){ case0: while(keyon)Fun09;//只要keyon=1,就反復(fù)的把行口的值賦給列 …… } 用上列C的語(yǔ)句去跟行口,還是無(wú)法很好的跟到。有大概一大半的按鍵無(wú)法如愿。 后來(lái),用C里嵌入?yún)R編去跟,問(wèn)題才解決。 當(dāng)然,上面用模擬開(kāi)關(guān)或用高速的片去做更方便一些。 當(dāng)初,也只是為了一時(shí)興起才想一定要用軟件解決。 |
|
| 22樓: | >>參與討論 |
| 作者: avrx007 于 2006/4/29 10:39:00 發(fā)布:
WHY?在32個(gè)口線上掛16個(gè)I2C器件 就成本角度來(lái)說(shuō),可能存在浪費(fèi),不如加模擬開(kāi)關(guān)來(lái)切換SDA劃算。 LZ在做理論研究嗎? |
|
| 免費(fèi)注冊(cè)為維庫(kù)電子開(kāi)發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號(hào) |