標(biāo)題:
關(guān)于單片機(jī)不同IO口編組程序
[打印本頁]
作者:
xtayxwygqvhj
時(shí)間:
2024-1-8 21:52
標(biāo)題:
關(guān)于單片機(jī)不同IO口編組程序
請問有沒有哪位大神百忙中抽點(diǎn)時(shí)間指點(diǎn)一下這一段代碼,卡了兩天了沒搞懂。
下面是一段異組非順序端口編組的程序
本人業(yè)余愛好者,半路出家沒有系統(tǒng)學(xué)習(xí)過
之前在網(wǎng)上學(xué)了一些89c51皮毛做了一些流水燈,4*4矩陣之類的
最近想做個實(shí)物矩陣鍵盤,但是由于之前用的是89c51,然后想著只做一個矩陣鍵盤帶幾個LED沒必要用那么多引腳的單片機(jī),
就選了個STC15W SOP16的
然后就悲劇了 STC15單組IO最多才6個P1.0-P1.5,4*4鍵盤要用8個口,跟之前學(xué)的0x**就完成掃描的程序不一樣,搞了兩天就只會分開一個一個口的寫代碼
雖然也能用,但是這樣太修飾了,然后就去網(wǎng)上找了一些資料(這方面的資料超級少),研究后發(fā)覺我看不懂代碼了(主要是運(yùn)算符)
單個運(yùn)算符拿出來可以理解,但是放在一起就搞不懂為什么會有這樣的結(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)先級,這里的位移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)制
}
作者:
npn
時(shí)間:
2024-1-9 10:36
十進(jìn)制是給人類看的,無論任何進(jìn)制,在單片機(jī)都是二進(jìn)制處理的。
作者:
lkc8210
時(shí)間:
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ù)
uchar PD()
{
u8 dat = 0;
if(P2&0x10)dat|=0x80;
if(P2&0x04)dat|=0x40;
dat|=P3&0x3F;
return dat;
}
復(fù)制代碼
作者:
18680365301
時(shí)間:
2024-1-9 11:02
能用最簡單易懂的辦法做出就可以了,先沒必要在意復(fù)雜的方式,等你用了幾年C之后再研究研究吧
作者:
xtayxwygqvhj
時(shí)間:
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)什么問題
我的方向錯了
問題1那里是宏定義端口組(就是等于新建一個8位的組),
以原代碼為例
我錯以為是直接把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í)際情況是直接新建一個8位的組,然后把要用的io口運(yùn)算出來再通過位移調(diào)整各個位的io的高低位置再加進(jìn)這個組。
再一個是位移是0(當(dāng)前位)開始,我錯誤當(dāng)作是1開始
問題2
我是直接理解為把位移的步數(shù)轉(zhuǎn)換成2進(jìn)制直接進(jìn)行&運(yùn)算
修改后 我的理解為把宏定義移位到高位的位(2.4 2.2)移位回原來的位并賦值
(不知道有沒理解錯,畢竟宏定義都的IO組為PD,這里的移位的是P2口,有點(diǎn)小迷惘)
最后是修改后測試代碼,我把P2的2.4 2.2改成P1的1.1 1.0(運(yùn)行沒問題,不知道有沒有錯誤)
如有不當(dāng),萬望指正。
另外函數(shù)的那個方法因?yàn)闆]學(xué)到dat,暫時(shí)沒辦法測試了 (不過我保存下來了)
#include "RELA.H"
#include"delay.h"
#define MAIN_Fosc 12000000L //定義內(nèi)部時(shí)鐘為12MHz
#define uchar unsigned char
void DelayXms(unsigned int xms);
#define PD ((P1<<6&0x80)|(P1<<6&0x40)|(P3&0x3f))//宏定義IO口并排列順序
/*********************************************************************************
* P1.1/P1.0 定義IO組并排列順序從高到低位依次為P1.1 1.0 P3.5 3.4 3.3 3.2 3.1 3.0 *
* 把想編組的IO口移動到想要的IO口組的位置重并排列順序 *
* (P1<<6&0x80)相當(dāng)于把P1.1的口移動到編組的第6位,也就是1000 0000 *
* (P1<<6&0x40)相當(dāng)于把P1.0的口移動到編組的第6位,也就是0100 0000 *
**********************************************************************************/
void PX(uchar x)
{
P3&=0xc0; //低6位清0,P3.6、P3.7不變
P3|=(x&0x3f); //P3低6位賦值
P1&=0xfc; //P1.1、P1.0清0,其它位不變
P1|=((x>>6&0x02)|(x>>6&0x01));//P1.1、P1.0賦值,X的取值范圍 0-255
}
/**************************************************************************************
//(x>>6&0x02)等于把宏定義的第7位右移6位0000 0010&0x02運(yùn)算后等P1口的P1.1位置并賦值
//(x>>6&0x01)等于宏定義后的第6位右移6位0000 0001&0x10運(yùn)算后等P1口的P1.0位置并賦值
***************************************************************************************/
/***************************************************************************************
uchar PD()
{
u8 dat = 0;
if(P2&0x10)dat|=0x80;
if(P2&0x04)dat|=0x40;
dat|=P3&0x3F;
return dat;
}
//上函數(shù)為不用宏定義該用函數(shù)方法(未測試)
******************************************************************************************/
void main()
{
unsigned char temp = 0x80;
unsigned char i;
while(1)
{
for(i=0;i<8;i++)
{
PX(~(temp>>i));
DelayXms(3000);
}
}
}
復(fù)制代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1