音影先锋亚洲天堂网|电影世界尽头的爱完整版播放|国产 熟女 91|高清无码免费观看欧美日韩|韩国一区二区三区黄色录像|美女亚洲加勒比在线|亚洲综合网 开心五月|7x成人在线入口|成人网站免费日韩毛片区|国产黄片?一级?二级?三级

登錄 免費(fèi)注冊(cè) 首頁(yè) | 行業(yè)黑名單 | 幫助
維庫(kù)電子市場(chǎng)網(wǎng)
技術(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ī)
一個(gè)I/O口操作的麻煩問(wèn)題
用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
不要落下,繼續(xù)等待高手
不要落下,繼續(xù)等待高手

3樓: >>參與討論
kimfufree
請(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
有現(xiàn)實(shí)意義嗎?
這樣子左右什么現(xiàn)實(shí)意義嗎?
兩顆線上完全可以掛16個(gè)i2器件!

5樓: >>參與討論
tg.liu
同意xiangyanan的說(shuō)
要知道I2C是總線,既然是總線,當(dāng)然可以接多個(gè)器件

6樓: >>參與討論
yadog
re
是撒

7樓: >>參與討論
wqz
還望高手繼續(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
LZ是指一模一樣的器件懸掛問(wèn)題?
有點(diǎn)不懂撒,換作我可以通過(guò)預(yù)讀器件寫(xiě)入模擬地址,然后再通過(guò)地址區(qū)分,不能實(shí)現(xiàn)嗎?

9樓: >>參與討論
wqz
一個(gè)I/O口操作的麻煩問(wèn)題
這個(gè)器件無(wú)法象24CXX那樣外部可以對(duì)器件設(shè)置地址,所以相同的器件,當(dāng)然地址相同。

10樓: >>參與討論
wqz
看了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
暈,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
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
試試用函數(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
呵呵,如果不j局限于軟件方法那么
兩片CD4067單16通道模擬開(kāi)關(guān)即可解決問(wèn)題

15樓: >>參與討論
wqz
看過(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
看過(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
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
不知道是否還有更妙的點(diǎn)子
 
19樓: >>參與討論
starlite_jason
可惜LZ沒(méi)有明白hunao的指針用法
應(yīng)該說(shuō)使用函數(shù)指針是針對(duì)這個(gè)問(wèn)題最好的辦法,不需要與或的運(yùn)算,而且移植也具有一致性,可惜LZ沒(méi)有明白hunao的指針用法

20樓: >>參與討論
liqimcu
請(qǐng)教!
void delay(void){uchar i;for(i=10;i>0;i--);}對(duì)嗎?i是不是會(huì)一直大于零???

21樓: >>參與討論
WQZ
我想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
WHY?在32個(gè)口線上掛16個(gè)I2C器件
就成本角度來(lái)說(shuō),可能存在浪費(fèi),不如加模擬開(kāi)關(guān)來(lái)切換SDA劃算。

LZ在做理論研究嗎?

參與討論
昵稱(chēng):
討論內(nèi)容:
 
 
相關(guān)帖子
有人知道accesse數(shù)據(jù)庫(kù)最多能放多少條記錄?
用復(fù)位實(shí)現(xiàn)多任務(wù)、看門(mén)狗、抗干擾
數(shù)據(jù)采集 與 頻率計(jì)算
請(qǐng)問(wèn)誰(shuí)有C語(yǔ)言編寫(xiě)的MSC1210單片機(jī)AD轉(zhuǎn)換的程序例子
推薦一款mp3芯片學(xué)習(xí)單片機(jī)資料
免費(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)