标题:
关于单片机不同IO口编组程序
[打印本页]
作者:
xtayxwygqvhj
时间:
2024-1-8 21:52
标题:
关于单片机不同IO口编组程序
请问有没有哪位大神百忙中抽点时间指点一下这一段代码,卡了两天了没搞懂。
下面是一段异组非顺序端口编组的程序
本人业余爱好者,半路出家没有系统学习过
之前在网上学了一些89c51皮毛做了一些流水灯,4*4矩阵之类的
最近想做个实物矩阵键盘,但是由于之前用的是89c51,然后想着只做一个矩阵键盘带几个LED没必要用那么多引脚的单片机,
就选了个STC15W SOP16的
然后就悲剧了 STC15单组IO最多才6个P1.0-P1.5,4*4键盘要用8个口,跟之前学的0x**就完成扫描的程序不一样,搞了两天就只会分开一个一个口的写代码
虽然也能用,但是这样太修饰了,然后就去网上找了一些资料(这方面的资料超级少),研究后发觉我看不懂代码了(主要是运算符)
单个运算符拿出来可以理解,但是放在一起就搞不懂为什么会有这样的结果。
#define PD ((P2<<3&0x80)|(P2<<4&0x40)|(P3&0x3f)) //P2.4/P2.2
不懂1
:宏定义 P2向左移3位跟0x80进行按位与......
根据运算优先级,这里的位移3位是指P2口低位往高位移3位后的结果是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) 结果为0x00 (0000 0000) ??
P2向左移4位跟0x40进行按位与..... .这里的位移4位是指P2口低位往高位移3位后的结果是2.3口吗??
之后
P2=0X08(0000 1000) & 0x40(0100 0000) 结果为0x00 (0000 0000) ??
再之后
不算P3的情况 按位或结果 0000 0000 | 0000 0000 = 0000 0000 那就跟程序运行的结果就不一样了
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进制还是2进制或者16进制
}
作者:
npn
时间:
2024-1-9 10:36
十进制是给人类看的,无论任何进制,在单片机都是二进制处理的。
作者:
lkc8210
时间:
2024-1-9 11:02
不懂1:
位数弄反了
正确顺序: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:
楼上说了,所有计算都是2进制
不用宏定义改用函数
uchar PD()
{
u8 dat = 0;
if(P2&0x10)dat|=0x80;
if(P2&0x04)dat|=0x40;
dat|=P3&0x3F;
return dat;
}
复制代码
作者:
18680365301
时间:
2024-1-9 11:02
能用最简单易懂的办法做出就可以了,先没必要在意复杂的方式,等你用了几年C之后再研究研究吧
作者:
xtayxwygqvhj
时间:
2024-1-9 18:23
lkc8210 发表于 2024-1-9 11:02
不懂1:
位数弄反了
正确顺序:P2.7/6/5/4/3/2/1/0
大致搞明白了,用流水灯正反测试了一下没发现什么问题
我的方向错了
问题1那里是宏定义端口组(就是等于新建一个8位的组),
以原代码为例
我错以为是直接把P2口的2.4 2.2运算出来,然后跟P3口的P3.5-3.0或运算取出要用的io后再调用。
所以我一直以为位移之后的位置是2.4或者2.2,而不是把2.4 2.2的低位移到高位
而实际情况是直接新建一个8位的组,然后把要用的io口运算出来再通过位移调整各个位的io的高低位置再加进这个组。
再一个是位移是0(当前位)开始,我错误当作是1开始
问题2
我是直接理解为把位移的步数转换成2进制直接进行&运算
修改后 我的理解为把宏定义移位到高位的位(2.4 2.2)移位回原来的位并赋值
(不知道有没理解错,毕竟宏定义都的IO组为PD,这里的移位的是P2口,有点小迷惘)
最后是修改后测试代码,我把P2的2.4 2.2改成P1的1.1 1.0(运行没问题,不知道有没有错误)
如有不当,万望指正。
另外函数的那个方法因为没学到dat,暂时没办法测试了 (不过我保存下来了)
#include "RELA.H"
#include"delay.h"
#define MAIN_Fosc 12000000L //定义内部时钟为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)相当于把P1.1的口移动到编组的第6位,也就是1000 0000 *
* (P1<<6&0x40)相当于把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运算后等P1口的P1.1位置并赋值
//(x>>6&0x01)等于宏定义后的第6位右移6位0000 0001&0x10运算后等P1口的P1.0位置并赋值
***************************************************************************************/
/***************************************************************************************
uchar PD()
{
u8 dat = 0;
if(P2&0x10)dat|=0x80;
if(P2&0x04)dat|=0x40;
dat|=P3&0x3F;
return dat;
}
//上函数为不用宏定义该用函数方法(未测试)
******************************************************************************************/
void main()
{
unsigned char temp = 0x80;
unsigned char i;
while(1)
{
for(i=0;i<8;i++)
{
PX(~(temp>>i));
DelayXms(3000);
}
}
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1