久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: C語言如何將多個位變量轉換成一個變量來存儲 [打印本頁]

作者: dyx811    時間: 2024-1-17 12:19
標題: C語言如何將多個位變量轉換成一個變量來存儲
平時利用多個按鍵,往往都是一個按鍵一個位變量表示,在單片機C語言中要么是0,要么是1,就好像按鍵一樣,
程序中為了判斷狀態,要寫很多語句,特別是多個按鍵的情況,占用很多程序空間。
為了計算方便,利用存儲空間,有沒有什么好辦法把他們集中在一起組成一個單字節的,判斷這個數值的內容,就能方便的
判斷出多個位變量的狀態。
比如有6個獨立按鍵,占用了分散的不同的IO口,每個按鍵都要用到短按、長按、組合等控制功能,如果每個按鍵都寫一次
這樣子的判斷,那么將有6個這樣子的似乎重復的語句,各種變量,大量占據存儲空間。

想請教各位老師,如何利用程序強大的運算功能,高效利用程序儲存空間,
有什么好的算法使這6個位變量通過哪種方法組合成一個單字節的變量。



作者: 雷歐庫珀    時間: 2024-1-17 14:46
用bit類型
一個bit變量只占一位
作者: yzw846562238    時間: 2024-1-17 14:48
支持位帶操作的單片機可以用結構體位域寫法
作者: Hephaestus    時間: 2024-1-17 16:08
不同平臺做法完全不一樣。

不支持位操作的單片機以及編譯器,只能用“位域”來實現,具體使用方法自己搜。

支持位操作的單片機及編譯器查手冊,以Keil C51為例,定義字節變量的時候加上bdata屬性,然后用sbit定義就行了。

  1. unsigned char bdata datum;
  2. sbit bd0=datum^0;
  3. sbit bd1=datum^1;
復制代碼

作者: Hephaestus    時間: 2024-1-17 19:44
支持bit-band的ARM比如cortex-m3可以這么寫,不過不建議,bit-band訪問1位需要32位地址,如果不是特殊功能寄存器,只是通用內存,這生意太不劃算了。
  1. #define DEVICE_REG0 ((volatile unsigned long *) (0x40000000))
  2. #define DEVICE_REG0_BIT0 ((volatile unsigned long *) (0x42000000))
  3. #define DEVICE_REG0_BIT1 ((volatile unsigned long *) (0x42000004))
復制代碼

作者: dyx811    時間: 2024-1-17 22:23
總共6個按鍵位變量,我把它合在一起了,成了一個字節,只是想讓它在后面的判斷和調用方便。沒想到還有點難處理。有了返回值,判斷起來就方便多了,組合判斷非常有優勢。
unsigned char KeyScan(unsigned char KeyFlag)
{
        static unsigned char da=0xff;
        if(KeyFlag==1)
        {
                if(key1==0)da &= 0xfe;else da |= 0x01;
                if(key2==0)da &= 0xfd;else da |= 0x02;
                if(key3==0)da &= 0xfb;else da |= 0x04;
                if(key4==0)da &= 0xf7;else da |= 0x08;
                if(key5==0)da &= 0xef;else da |= 0x16;
                if(key6==0)da &= 0xdf;else da |= 0x32;
         }
         return da;
}
作者: Hephaestus    時間: 2024-1-18 01:43
dyx811 發表于 2024-1-17 22:23
總共6個按鍵位變量,我把它合在一起了,成了一個字節,只是想讓它在后面的判斷和調用方便。沒想到還有點難 ...

你這代碼轉換成機器碼,執行效率跟我在地板發的代碼差了十萬八千里,好好學習吧。
作者: wulin    時間: 2024-1-18 08:26
dyx811 發表于 2024-1-17 22:23
總共6個按鍵位變量,我把它合在一起了,成了一個字節,只是想讓它在后面的判斷和調用方便。沒想到還有點難 ...

假設6個按鍵分別接P2.3、2.4,P1.1~1.4
#define KeyFlag P2<<1&0x30|P1>>1&0x0f

unsigned char KeyScan(unsigned char da)
{
        switch(da)
        {
                case 0x3e: da=1; break;
                case 0x3d: da=2; break;
                case 0x3b: da=3; break;
                case 0x37: da=4; break;
                case 0x2f: da=5; break;
                case 0x1f: da=6; break;
                default:   da=0; break;
        }       
        return da;
}
作者: ydatou    時間: 2024-1-18 08:40
dyx811 發表于 2024-1-17 22:23
總共6個按鍵位變量,我把它合在一起了,成了一個字節,只是想讓它在后面的判斷和調用方便。沒想到還有點難 ...

你這段代碼可優化。節省一個全局變量,代碼也可簡短些。

  1. unsigned char KeyScan(unsigned char KeyFlag)
  2. {
  3.         unsigned char da=0xff;
  4.         if(KeyFlag==1)
  5.         {
  6.                 if(key1==0)da &= 0xfe;
  7.                 if(key2==0)da &= 0xfd;
  8.                 if(key3==0)da &= 0xfb;
  9.                 if(key4==0)da &= 0xf7;
  10.                 if(key5==0)da &= 0xef;
  11.                 if(key6==0)da &= 0xdf;
  12.          }
  13.          return da;
  14. }
復制代碼



作者: yzw846562238    時間: 2024-1-18 08:57
wulin 發表于 2024-1-18 08:26
假設6個按鍵分別接P2.3、2.4,P1.1~1.4
#define KeyFlag P21&0x0f

typedef struct
{
    unsigned int key1 : 1;
    unsigned int key2 : 1;
    unsigned int key3 : 1;
    unsigned int key4 : 1;
    unsigned int key5 : 1;
    unsigned int key6 : 1;
}TsMAIN_h_KeyValueStatType;

typedef union
{
    TsMAIN_h_KeyValueStatType keyStat;
    unsigned char             keyValue;
}TuMAIN_h_KeyValueUnionType;

TuMAIN_h_KeyValueUnionType SsMAIN_h_KeyValue;

unsigned char GetKeyValue( unsigned char KeyFlag )
{
    if( 1== KeyFlag )
    {
        SsMAIN_h_KeyValue.keyStat.key1 = (!key1) ? 0 : 1;
        SsMAIN_h_KeyValue.keyStat.key2 = (!key2) ? 0 : 1;
        SsMAIN_h_KeyValue.keyStat.key3 = (!key3) ? 0 : 1;
        SsMAIN_h_KeyValue.keyStat.key4 = (!key4) ? 0 : 1;
        SsMAIN_h_KeyValue.keyStat.key5 = (!key5) ? 0 : 1;
        SsMAIN_h_KeyValue.keyStat.key6 = (!key6) ? 0 : 1;
    }
}
作者: yzw846562238    時間: 2024-1-18 09:19
yzw846562238 發表于 2024-1-18 08:57
typedef struct
{
    unsigned int key1 : 1;

return SsMAIN_h_KeyValue.KeyValue;
作者: Hephaestus    時間: 2024-1-18 14:28
yzw846562238 發表于 2024-1-18 08:57
typedef struct
{
    unsigned int key1 : 1;

這算是個通用的做法,在有特殊位尋址功能的平臺上,比如51的效率就非常差勁了。

加強知識的學習吧。
作者: 18680365301    時間: 2024-1-18 15:34
void Key_Scan()                //按鍵檢測 1ms調用
{
        u8 i;
        u8 Loop_Bit = 0x01;
    u8 Key = 0;
       
        if(KEY1_IO == 0)
        {
                Key |= KEY_BIG;
    }
   
    if(KEY2_IO == 0)
        {
                Key |= KEY_SMALL;
    }
   
        for(i = 0; i < KEYNUM; i++)
        {
                if((Key_Lock & Loop_Bit) == 0)                                                        //唯一按鍵
                {
                        if(Key & Loop_Bit)
                        {
                                if(++Key_Count[i] >= 50)                        //消抖50ms
                                {
                                        Key_Count[i] = 0;
                                        Key_Down |= Loop_Bit;        //按鍵觸發
                                        Key_Lock |= Loop_Bit;                        //按鍵鎖住         
                                }
                        }
                        else
                        {
                                Key_Count[i] = 0;
                        }
                }
                else
                {
                        if((Key & Loop_Bit) == 0)
                        {
                                if(++Key_Count[i] >= 40)                        //消抖50ms
                                {
                                        Key_Count[i] = 0;
                                        Key_Lock &= ~Loop_Bit;                        //按鍵鎖解除
                                        Key_Up |= Loop_Bit;
                                }
                        }
                        else
                        {
                                Key_Count[i] = 0;
                        }
                }
                Loop_Bit <<= 1;
        }
}

作者: dyx811    時間: 2024-1-18 17:22
ydatou 發表于 2024-1-18 08:40
你這段代碼可優化。節省一個全局變量,代碼也可簡短些。

利用了靜態變量可以不用每次都初始化da,這樣子不能做多鍵同時按下的準確判斷。
作者: dyx811    時間: 2024-1-18 17:35
yzw846562238 發表于 2024-1-18 09:19
return SsMAIN_h_KeyValue.KeyValue;

差點以為結構體可以自動返回呢,不過這種寫法看的頭暈。變量名字好長好長。但是非常的新穎!
現在就去驗證該語句對空間占用,機器周期耗費情況。
作者: dyx811    時間: 2024-1-18 17:57
wulin 發表于 2024-1-18 08:26
假設6個按鍵分別接P2.3、2.4,P1.1~1.4
#define KeyFlag P21&0x0f

這個還沒有看得懂。同時按住兩個按鍵返回值是如何變化的呢 ?
作者: dyx811    時間: 2024-1-18 18:02
Hephaestus 發表于 2024-1-18 01:43
你這代碼轉換成機器碼,執行效率跟我在地板發的代碼差了十萬八千里,好好學習吧。

一定好好學習。主要是高級點的單片機還沒有咋個會呢。你發的代碼是帶指針的嗎?一時半會還理解不透。

事實上,我是想把一堆的位變量,(我舉的例子是6個,來自于不同的地方),放在一個字節里面,用8位分別代表其中各位的狀態,方便后期僅對該字節的判斷就知道哪些位有效,哪些組合滿足要求,同時還有濾波,長按的判斷等等。主要目的是不用分別對每個位變量判斷短按長按等等。
作者: dyx811    時間: 2024-1-18 19:53
18680365301 發表于 2024-1-18 15:34
void Key_Scan()                //按鍵檢測 1ms調用
{
        u8 i;

這是咋玩的啊,開頭幾句就卡殼了
作者: Hephaestus    時間: 2024-1-18 22:27
dyx811 發表于 2024-1-18 18:02
一定好好學習。主要是高級點的單片機還沒有咋個會呢。你發的代碼是帶指針的嗎?一時半會還理解不透。

...

8051內存地址20h~27h這8個字節每位都是可以直接訪問的,具體使用方法參加我在地板位的代碼。
作者: 188610329    時間: 2024-1-18 23:05
dyx811 發表于 2024-1-17 22:23
總共6個按鍵位變量,我把它合在一起了,成了一個字節,只是想讓它在后面的判斷和調用方便。沒想到還有點難 ...

sbit Temp1 = ACC^0;
sbit Temp2 = ACC^1;
sbit Temp3 = ACC^2;
sbit Temp4 = ACC^3;
sbit Temp5 = ACC^4;
sbit Temp6 = ACC^5;

unsigned char KeyScan(unsigned char KeyFlag)
{
        ACC = 0xff;
        if(KeyFlag==1)
        {
                Temp1 = key1;
                Temp2 = key2;
                Temp3 = key3;
                Temp4 = key4;
                Temp5 = key5;
                Temp6 = key6;
         }
         return ACC;
}

作者: Hephaestus    時間: 2024-1-18 23:59
188610329 發表于 2024-1-18 23:05
sbit Temp1 = ACC^0;
sbit Temp2 = ACC^1;
sbit Temp3 = ACC^2;

你的代碼太想當然了。

        ACC = 0xff;
        if(KeyFlag==1)
后面這一句執行的時候,前面那一句的結果已經被破壞掉了。
作者: ydatou    時間: 2024-1-19 14:29
dyx811 發表于 2024-1-18 17:22
利用了靜態變量可以不用每次都初始化da,這樣子不能做多鍵同時按下的準確判斷。

請仔細分析下我給你的優化代碼。
1:因為有這變量的初始換,才省了你代碼中的一堆else。
2:臨時變量和全局變量相比,代碼空間更小,執行速度更快。計算越復雜,用臨時變量優化效果越明顯。你就是一定要使用全局變量,也應該先用臨時變量獲得計算結果,之后賦值給全局變量。
3.靜態變量是全局變量的一種,但限制了使用范圍。從你的代碼看,使用靜態變量無意義。
作者: dyx811    時間: 2024-1-19 15:33
ydatou 發表于 2024-1-19 14:29
請仔細分析下我給你的優化代碼。
1:因為有這變量的初始換,才省了你代碼中的一堆else。
2:臨時變量和 ...

謝謝指點,突然恍然大悟了!!我居然把把&運算算錯了。。。光想著怎么復原該Bit位了。
這樣子確實精簡了好多代碼。非常感謝。
作者: Hephaestus    時間: 2024-1-19 16:23
dyx811 發表于 2024-1-19 15:33
謝謝指點,突然恍然大悟了!!我居然把把&運算算錯了。。。光想著怎么復原該Bit位了。
這樣子確實精簡了 ...

都不對。

代碼是否被簡化,以c語言的簡潔程度來判斷是錯誤的。

只有匯編碼,也就單片機執行的機器碼,變簡潔了,才是真的優化。

你們搞的都是假優化。
作者: ydatou    時間: 2024-1-19 16:36
ydatou 發表于 2024-1-19 14:29
請仔細分析下我給你的優化代碼。
1:因為有這變量的初始換,才省了你代碼中的一堆else。
2:臨時變量和 ...

再看了下樓主代碼,當KeyFlag 不為1時,要返回上一次的key值,這確實需要一個全局變量,我給的優化代碼沒做到這點。
修改如下
  1. unsigned char KeyScan(unsigned char KeyFlag)
  2. {
  3.         static unsigned char old=0xff;
  4.         if (KeyFlag == 1)
  5.         {
  6.                 unsigned char da = 0xff;
  7.                 if (key1 == 0)
  8.                         da &= 0xfe;
  9.                 if (key2 == 0)
  10.                         da &= 0xfd;
  11.                 if (key3 == 0)
  12.                         da &= 0xfb;
  13.                 if (key4 == 0)
  14.                         da &= 0xf7;
  15.                 if (key5 == 0)
  16.                         da &= 0xef;
  17.                 if (key6 == 0)
  18.                         da &= 0xdf;
  19.                 old=da;
  20.         }
  21.         return old;
  22. }
復制代碼


假如是使用51MCU,使用位變量更好,如下
  1. unsigned char bdata gKey = 0xff;
  2. sbit bKey1 = gKey ^ 0;
  3. sbit bKey2 = gKey ^ 1;
  4. sbit bKey3 = gKey ^ 2;
  5. sbit bKey4 = gKey ^ 3;
  6. sbit bKey5 = gKey ^ 4;
  7. sbit bKey6 = gKey ^ 5;
  8. unsigned char KeyScan(unsigned char KeyFlag)
  9. {
  10.         if (KeyFlag == 1)
  11.         {
  12.                 bKey1 = key1;
  13.                 bKey2 = key2;
  14.                 bKey3 = key3;
  15.                 bKey4 = key4;
  16.                 bKey5 = key5;
  17.                 bKey6 = key6;
  18.         }
  19.         return gKey;
  20. }
復制代碼



作者: dyx811    時間: 2024-1-20 21:22
ydatou 發表于 2024-1-19 16:36
再看了下樓主代碼,當KeyFlag 不為1時,要返回上一次的key值,這確實需要一個全局變量,我給的優化代碼沒 ...

bdta太好用了!不光完全實現了一堆位變量的整合,經過實驗,不光實現了既定要求,程序上還節省了大量空間。
我采用了  ydatou 大哥的編程思路,簡單,高效!
在此,感謝各位大佬們的熱心幫助!
期望大家在單片機領域有更深的造詣,在編程道路上技術越來越精湛!
祝愿各位在龍年   {“龍騰虎躍!心想事成!”}


作者: Hephaestus    時間: 2024-1-20 21:38
dyx811 發表于 2024-1-20 21:22
bdta太好用了!不光完全實現了一堆位變量的整合,經過實驗,不光實現了既定要求,程序上還節省了大量空間 ...

我早就告訴你了你不看。
作者: zy0818    時間: 2024-1-21 00:34
學習各大佬的編程思路,深受啟發
作者: nearsea    時間: 2024-1-21 08:31
我們追求效率肯定是沒有錯的。對于現在的處理器來說,內存空間和運行速度基本上都是能滿足一般運行要求的,對于項目來說,可靠健壯的代碼和清晰明了的結構,是當前需要重點關注的。
作者: nearsea    時間: 2024-1-21 08:34
我們追求效率肯定是沒有錯的。
對于現在的處理器來說,內存空間和運行速度基本上都是能滿足一般運行要求的,對于項目來說,可靠健壯的代碼和清晰明了的文件架構,也許我們需要更重點關注的。


作者: TTQ001    時間: 2024-1-21 09:06
一個字節由 8 位組成。 字節的按位操作廣泛用于數字變量,例如開關狀態、標志和數字輸出。
作者: Hephaestus    時間: 2024-1-21 12:31
TTQ001 發表于 2024-1-21 09:06
一個字節由 8 位組成。 字節的按位操作廣泛用于數字變量,例如開關狀態、標志和數字輸出。

字節的概念多了去了,早年計算機一個字節6、7、8位的都有,TI C2000系列DSP一個字節16位,不存在8位操作,你還是見識的太少了。
作者: dyx811    時間: 2024-1-21 18:12
Hephaestus 發表于 2024-1-20 21:38
我早就告訴你了你不看。

我看了,當時沒有想到能這么用。主要看來還是學習少了!
以后定向大佬們學習!請受小弟一拜!!!!
作者: 老董    時間: 2024-2-9 22:58
可以 用一個8位的io端口啊 用6位 寫程序時判斷io端口的狀態 如P1=0xc0 就是“”11000000“” 就是一起按了6個按鍵




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 成年人免费网站 | 亚洲精品久久久久久国产精华液 | 亚洲自拍偷拍欧美 | 中文字幕日韩三级 | 国产精品免费一区二区三区 | 伊久在线| 国产中文字幕在线观看 | 亚洲免费视频网址 | 亚洲精选一区二区 | 国产一区二区在线视频 | 免费观看黄色一级片 | 久久久片 | 天堂久久天堂综合色 | 国产精品毛片一区二区在线看 | 国产精品99久久久久久宅男 | 一区二区三区四区免费在线观看 | 亚洲第一福利视频 | 免费中文字幕日韩欧美 | 国产精品乱码一区二区三区 | 欧洲高清转码区一二区 | 国产视频亚洲视频 | 免费国产一区 | 99资源站| 中文字幕在线网 | 欧美二区三区 | 亚洲一区二区在线视频 | 91精品国产91久久久久久吃药 | 亚洲36d大奶网 | 成人高清视频在线观看 | 国产丝袜一区二区三区免费视频 | 综合二区 | 日韩欧美三区 | 亚洲三级免费看 | 成人精品免费视频 | av手机免费在线观看 | 精品一区二区三区视频在线观看 | 久久激情视频 | 欧美亚洲视频 | 91久久精品国产91久久 | 久久久久久国产精品免费免费 | 福利成人 |