这是我敲的代码,但无法实现实验效果
一个开关控制两个程序,一个为霹雳灯,一个为灯的奇偶变换
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar tab[] = { 0x7e,0xbd,0xdb,0xe7,0xdb,0xbd };
sbit key = P0 ^ 7;
uchar a;
void delay(uint b)
{
uchar t;
while (b--)
{
for (t = 0; t < 120; t++);
}
}
void main()
{
unsigned char zt = 0;
P1 = 0x55;
while (1)
{
if (key == 0) {
delay(100);
if (key == 0) {
zt = !zt;
if (zt == 0) P1 = 0x55;
}
while (!key);
}
switch (zt)
{
case 0:
delay(500);
P1 = crol(P1, 1);
break;
case 1:
for (a = 0; a < 6; a++)
{
P1 = tab[a];
delay(500);
}
break;
}
}
}
:你的代码中,在奇偶变换的case 1中,你只是将P1赋值为预先定义的一个字符数组中的值,并没有做出奇偶变换的操作。你需要在循环中根据奇偶性对P1进行操作。
参考一下
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar tab[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xdb, 0xbd };
sbit key = P0 ^ 7;
void delay(uint b)
{
uchar t;
while (b--)
{
for (t = 0; t < 120; t++);
}
}
void main()
{
unsigned char zt = 0;
P1 = 0x55;
while (1)
{
if (key == 0)
{
delay(100);
if (key == 0)
{
zt = !zt;
if (zt == 0) P1 = 0x55;
}
while (!key);
}
switch (zt)
{
case 0:
delay(500);
P1 = _crol_(P1, 1); // 使用函数_crol_对P1进行循环移位
break;
case 1:
for (uchar i = 0; i < 8; i++)
{
if ((P1 & 0x01) == 0) // 判断奇偶性
{
P1 = P1 >> 1;
P1 = P1 | 0x80;
}
else
{
P1 = P1 >> 1;
}
delay(500);
}
break;
}
}
}
现在可以回到正文开头的代码中了。这个10us的函数是怎么得出来的呢?
这个我之前查过很多资料,比如执行while语句需要多少个机器周期。赋值需要多少个周期。也就是查这个占用了我很大一部分时间。直到最后将上面的延时函数直接调到main函数中debug调试,才明白,问题其实很简单啊。
无论是执行什么语句,最终都会回到汇编上来,debug里单步调试,所有的指令周期就会明明白白了。
我用main函数直接调用延时函数,如下:
void Delay10us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 27;
while (--i);
}
main
{
Delay10us();
}
我用的keil软件,将上述build之后,点击debug,开始调试
.
看图片上,开始debug,程序的起始就在C:0x0183 020171 LJMP Delay10us(C:0171),
这里有个长转移指令LJMP,它要转移到C:0171行去执行Delay10us这个函数。
那执行LJMP这个指令需要多长时间呢,查找STC数据手册,在1T模式下,此条指令在单片机上运行需要4个时钟周期。
接下来,按单步调试F11键,如下图:
程序成功转移到C:0171行,跳转到Delay10us函数中,此行程序执行NOP指令,空操作。查STC数据手册,NOP指令占用1个时钟周期。
接下来C:0172行,依然是NOP指令,1个时钟周期。
接下来C:0173行,此行执行 MOV R7,#0x1B,将立即数送入寄存器。是将27赋值给i。依然查手册,此条指令2个时钟周期。
继续:
此时执行到while语句了,这里执行的指令时 DJNZ R7,C:0175,寄存器减1非0转移。此条指令执行1次4个时钟周期。
上面已经将寄存器填入27了,因此这条指令将执行27次。
继续:
循环了27次,终于到0了,程序继续向下执行,此行指令RET,子程序返回。此条指令4个时钟周期。
继续:
程序又回到了起点。
好了,可以计算一下此次延时的时间了。1个LJMP,4时钟;2个NOP,2时钟;1个MOV,2时钟;27个DJNZ,108时钟;1个RET,4时钟。
4+2+2+108+4=120。
单片机的时钟周期是:1(S)/12MHz = 1/12(us)
此次延时的时间是:120 × 1/12(us)= 10(us)