找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1131|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

關(guān)于單片機(jī)不同IO口編組程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1054576 發(fā)表于 2024-1-8 21:52 | 只看該作者 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式
請(qǐng)問有沒有哪位大神百忙中抽點(diǎn)時(shí)間指點(diǎn)一下這一段代碼,卡了兩天了沒搞懂。下面是一段異組非順序端口編組的程序
本人業(yè)余愛好者,半路出家沒有系統(tǒng)學(xué)習(xí)過之前在網(wǎng)上學(xué)了一些89c51皮毛做了一些流水燈,4*4矩陣之類的
最近想做個(gè)實(shí)物矩陣鍵盤,但是由于之前用的是89c51,然后想著只做一個(gè)矩陣鍵盤帶幾個(gè)LED沒必要用那么多引腳的單片機(jī),
就選了個(gè)STC15W SOP16的
然后就悲劇了 STC15單組IO最多才6個(gè)P1.0-P1.5,4*4鍵盤要用8個(gè)口,跟之前學(xué)的0x**就完成掃描的程序不一樣,搞了兩天就只會(huì)分開一個(gè)一個(gè)口的寫代碼
雖然也能用,但是這樣太修飾了,然后就去網(wǎng)上找了一些資料(這方面的資料超級(jí)少),研究后發(fā)覺我看不懂代碼了(主要是運(yùn)算符)
單個(gè)運(yùn)算符拿出來可以理解,但是放在一起就搞不懂為什么會(huì)有這樣的結(jié)果。

#define PD ((P2<<3&0x80)|(P2<<4&0x40)|(P3&0x3f)) //P2.4/P2.2


不懂1:宏定義 P2向左移3位跟0x80進(jìn)行按位與......
       根據(jù)運(yùn)算優(yōu)先級(jí),這里的位移3位是指P2口低位往高位移3位后的結(jié)果是2.2口嗎?(P2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7)
        既:P2=0X04(0000 0100) & 0x80(1000 0000) 結(jié)果為0x00 (0000 0000) ??
        P2向左移4位跟0x40進(jìn)行按位與..... .這里的位移4位是指P2口低位往高位移3位后的結(jié)果是2.3口嗎??
    之后
          P2=0X08(0000 1000) & 0x40(0100 0000)  結(jié)果為0x00 (0000 0000) ??
再之后
                   不算P3的情況 按位或結(jié)果  0000 0000 | 0000 0000 = 0000 0000   那就跟程序運(yùn)行的結(jié)果就不一樣了

void PX(uchar x)
{
        P3&=0xc0;                //低6位清0,P3.6、P3.7不變
        P3|=(x&0x3f);        //P3低6位賦值
        P2&=0xeb;                //P2.4、P2.2清0,其它位不變
        P2|=((x>>3&0x10)|(x>>4&0x04)); //P2.4、P2.2賦值

不懂2:  無字符型變量X 取值范圍是 0-255   這里的X移位是怎么移?0 1 2 3 -255  位移3位是2嗎?移位后的值是10進(jìn)制還是2進(jìn)制或者16進(jìn)制

}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

5#
ID:1054576 發(fā)表于 2024-1-9 18:23 | 只看該作者
lkc8210 發(fā)表于 2024-1-9 11:02
不懂1:
位數(shù)弄反了
正確順序:P2.7/6/5/4/3/2/1/0

大致搞明白了,用流水燈正反測試了一下沒發(fā)現(xiàn)什么問題
我的方向錯(cuò)了
問題1那里是宏定義端口組(就是等于新建一個(gè)8位的組),
以原代碼為例
我錯(cuò)以為是直接把P2口的2.4 2.2運(yùn)算出來,然后跟P3口的P3.5-3.0或運(yùn)算取出要用的io后再調(diào)用。
所以我一直以為位移之后的位置是2.4或者2.2,而不是把2.4 2.2的低位移到高位
而實(shí)際情況是直接新建一個(gè)8位的組,然后把要用的io口運(yùn)算出來再通過位移調(diào)整各個(gè)位的io的高低位置再加進(jìn)這個(gè)組。
再一個(gè)是位移是0(當(dāng)前位)開始,我錯(cuò)誤當(dāng)作是1開始

問題2
我是直接理解為把位移的步數(shù)轉(zhuǎn)換成2進(jìn)制直接進(jìn)行&運(yùn)算
修改后 我的理解為把宏定義移位到高位的位(2.4 2.2)移位回原來的位并賦值
(不知道有沒理解錯(cuò),畢竟宏定義都的IO組為PD,這里的移位的是P2口,有點(diǎn)小迷惘)

最后是修改后測試代碼,我把P2的2.4 2.2改成P1的1.1 1.0(運(yùn)行沒問題,不知道有沒有錯(cuò)誤)
如有不當(dāng),萬望指正。

另外函數(shù)的那個(gè)方法因?yàn)闆]學(xué)到dat,暫時(shí)沒辦法測試了 (不過我保存下來了)


  1. #include "RELA.H"
  2. #include"delay.h"

  3. #define MAIN_Fosc  12000000L //定義內(nèi)部時(shí)鐘為12MHz
  4. #define uchar unsigned char
  5. void DelayXms(unsigned int xms);       

  6. #define PD ((P1<<6&0x80)|(P1<<6&0x40)|(P3&0x3f))//宏定義IO口并排列順序           
  7. /*********************************************************************************
  8. * P1.1/P1.0 定義IO組并排列順序從高到低位依次為P1.1 1.0 P3.5 3.4 3.3 3.2 3.1 3.0  *
  9. * 把想編組的IO口移動(dòng)到想要的IO口組的位置重并排列順序                             *
  10. * (P1<<6&0x80)相當(dāng)于把P1.1的口移動(dòng)到編組的第6位,也就是1000 0000                 *
  11. * (P1<<6&0x40)相當(dāng)于把P1.0的口移動(dòng)到編組的第6位,也就是0100 0000                 *
  12. **********************************************************************************/

  13. void PX(uchar x)
  14. {
  15.         P3&=0xc0;                //低6位清0,P3.6、P3.7不變
  16.         P3|=(x&0x3f);        //P3低6位賦值
  17.         P1&=0xfc;                //P1.1、P1.0清0,其它位不變
  18.         P1|=((x>>6&0x02)|(x>>6&0x01));//P1.1、P1.0賦值,X的取值范圍 0-255
  19.         }
  20. /**************************************************************************************       
  21.         //(x>>6&0x02)等于把宏定義的第7位右移6位0000 0010&0x02運(yùn)算后等P1口的P1.1位置并賦值
  22.         //(x>>6&0x01)等于宏定義后的第6位右移6位0000 0001&0x10運(yùn)算后等P1口的P1.0位置并賦值
  23. ***************************************************************************************/

  24. /***************************************************************************************
  25. uchar PD()
  26. {
  27.         u8 dat = 0;
  28.         if(P2&0x10)dat|=0x80;
  29.         if(P2&0x04)dat|=0x40;
  30.         dat|=P3&0x3F;
  31.         return dat;
  32. }
  33. //上函數(shù)為不用宏定義該用函數(shù)方法(未測試)
  34. ******************************************************************************************/       
  35. void main()
  36. {  
  37.         unsigned char temp = 0x80;
  38.         unsigned char i;
  39.         while(1)
  40.         {
  41.                 for(i=0;i<8;i++)
  42.                 {
  43.       PX(~(temp>>i));  
  44.                   DelayXms(3000);
  45.                 }
  46.   }
  47. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

地板
ID:485350 發(fā)表于 2024-1-9 11:02 | 只看該作者
能用最簡單易懂的辦法做出就可以了,先沒必要在意復(fù)雜的方式,等你用了幾年C之后再研究研究吧
回復(fù)

使用道具 舉報(bào)

板凳
ID:161164 發(fā)表于 2024-1-9 11:02 | 只看該作者
不懂1:
位數(shù)弄反了
正確順序:P2.7/6/5/4/3/2/1/0
P24取值放到第7位:
P2<<3 & 0x80 = 0B00010000<<3 & 0x80 = 0B10000000 & 0x80
P22取值放到第6位:
P2<<4 & 0x40 = 0B00000100<<4 & 0x40 = 0B01000000 & 0x40

不懂2:
樓上說了,所有計(jì)算都是2進(jìn)制

不用宏定義改用函數(shù)
  1. uchar PD()
  2. {
  3.         u8 dat = 0;
  4.         if(P2&0x10)dat|=0x80;
  5.         if(P2&0x04)dat|=0x40;
  6.         dat|=P3&0x3F;
  7.         return dat;
  8. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:57657 發(fā)表于 2024-1-9 10:36 | 只看該作者
十進(jìn)制是給人類看的,無論任何進(jìn)制,在單片機(jī)都是二進(jìn)制處理的。
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表