51单片机学习记录04
一、独立按键控制LED单向移动
代码分为两个部分:“主函数”+“延时函数”,此处列出整体框架,填充部分见下文
include <REGX52.H> //添加头文件
void Delay(unsigned int xms); //延时函数声明
void main()
{
//此处待填充
}
void Delay(unsigned int xms) //@12.000MHz延时函数(固定的)
{
unsigned char i, j;
while(xms)
{
i = 12;
j = 169;
do
{
while (--j);
}
while (--i);
xms--;
}
}
单项右移
LEDnum定义为unsigned char是因为这个数据类型正好是8位,对应P2八位寄存器
填充代码如下:
unsigned char LEDnum; //移位自增or自减
P2=0xFE; //初始化使第一个灯亮
while(1)
{
if(P3_1==0) //判断独立按键的开关
{
Delay(20); //延迟消抖
while(P3_1==0); //判断松手
Delay(20); //延迟消抖
LEDnum++;
if(LEDnum>=8) //8位寄存器且没有负值
{
LEDnum=0; //回到起点,超过8程序失效
}
P2=~(0x01<<LEDnum); //'<<'为左移符号,取反保证只有一个灯亮,但由于本人开发板上的LED灯是01~08从左至右,故显示出是向右移
}
}
}
单项左移
LEDnum定义为unsigned char时,取值不能为负。
- 第一次选择定义为unsigned char时,判断是否为0,若是则对LEDnum赋值8,从头开始向左移,但最后一个LED总是不能正常亮。
- 可能原因1:与自增不同,需要先判断是否为0才能自减
- 第二次LEDnum数据类型不变,依旧为unsigned char,将条件语句补充完整,结果正常
填充代码如下:
unsigned char LEDnum;
P2=0x7F; //初始化使右侧第一个灯亮,从右至左移动
while(1)
{
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
if(LEDnum==0)
{
LEDnum=7;
}
else
LEDnum--;
P2=~(0x01<<LEDnum);
}
}
- 可能原因2:LEDnum在左侧第二个灯处就自减到0了,重新开始了新的一轮,说明在左侧第一个(即从右至左最后一个)处应该做一个是否为负的判断
- 第三次选择判断是否为负数,改变LEDnum为int数据类型,判断是否为负值,若是则对LEDnum赋值7(如果为8则会在一轮的结尾空一个),重新测试,可以正常显示。
填充代码如下:
int LEDnum=8; //移位上限,自减变量
P2=0x7F; //初始化使右侧第一个灯亮,从右至左移动
while(1)
{
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
LEDnum--;
if(LEDnum<0)
{
LEDnum=7;
}
P2=~(0x01<<LEDnum);
}
}
二、独立按键控制LED移动
整体代码如下:
#include <REGX52.H>
void Delay(unsigned int xms); //函数声明
void main()
{
unsigned char LEDnum; //移位自增or自减
P2=0xFE; //初始化使第一个灯亮
while(1)
{
if(P3_1==0) //判断独立按键的开关
{
Delay(20); //延迟消抖
while(P3_1==0); //判断松手
Delay(20); //延迟消抖
LEDnum++;
if(LEDnum>=8) //8位寄存器且没有负值
{
LEDnum=0; //回到起点,超过8程序失效
}
P2=~(0x01<<LEDnum); //右移
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
if(LEDnum==0)
{
LEDnum=7;
}
else
LEDnum--;
P2=~(0x01<<LEDnum); //左移
}
}
}
void Delay(unsigned int xms) //@12.000MHz延时函数(固定的)
{
unsigned char i, j;
while(xms)
{
i = 12;
j = 169;
do
{
while (--j);
}
while (--i);
xms--;
}
}
总结
- 硬件电路与寄存器编辑:寄存器避免人为改换电路的繁琐过程,而是切换输出电平,达到切换导线的目的。与VCC连接是输出1,与GND连接是输出0
- unsigned char 8位 int 16位
- 不论左移右移都使用了<<左移符号,因为LEDnum是一个自增自减的量。若<<在自加前提下运行时为左移,则自增为左移,自减为左移少一位,可以看作右移
- 运行时定义LEDnum总是出错,发现它必须放在主函数的一开始的位置,否则无法创建运行
- P2口需要初始化,使它从第一个LED开始亮(P2=~0x01取反更方便,当然写P2=0xFE也是正确的)