目录
(5)课堂作业:编程控制16个LED灯排队逐一出场,指导全部出现,最后逐一从另外一边排队退场。
前言:
一、最小系统板
1.电路图
2.PCB图
3.下载线
二、流水灯
1.电路图
2.PCB图
3.编程
(1)顺序结构编程
芯片选择:At89c52
未写延迟函数
Stc助手写延迟函数
3.下载代码
(a)出现问题:无法下载
解决办法:更改STC芯片选择
(b)出现问题:不符合想要的状况,速度过慢,只有上半亮起
解决方案:更改延迟函数,检查系统板的电路图
(c)出现问题:有3个灯不亮
解决方案:①板子上有塑料隔绝电(错误的),接3条线到电阻处
②实际上是三个灯是坏的(错误的),换上新的灯即可
③代码问题(被老师坑了,没细看视频,哭唧唧),改一改代码
#include <REGX52.H>
void Dealy100ms() //@11.0592MHz
{
unsigned char data i, j, k;
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
// P0=1;//测试代码
// P2=1;
P0=0xfe;Dealy100ms();
P0=0xfd;Dealy100ms();
P0=0xfb;Dealy100ms();
P0=0xf7;Dealy100ms();
P0=0xef;Dealy100ms();
P0=0xdf;Dealy100ms();
P0=0xbf;Dealy100ms();
P0=0x7f;Dealy100ms();
P0=0xff;Dealy100ms();
P2=0x7f;Dealy100ms();
P2=0xbf;Dealy100ms();
P2=0xdf;Dealy100ms();
P2=0xef;Dealy100ms();
P2=0xf7;Dealy100ms();
P2=0xfb;Dealy100ms();
P2=0xfd;Dealy100ms();
P2=0xfe;Dealy100ms();
P2=0xff;Dealy100ms();
}
}
成功案例
(2)循环结构编程
代码
#include <REGX52.H>
void Dealy100ms() //@11.0592MHz 100毫秒
{
unsigned char data i, j, k;
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
unsigned char i;
while(1)
{
for(i=0;i<8;i++)//i初始值为0,i<8时,i+1
{
P0=~(1<<i); //~是按位取反运算 =是赋值运算 <<是按位左移运算
/*意思是:假设i=3,将二进制数1左移3位,得到二进制数1000。
对1000取反,得到0111。将0111赋值给P0*/
Dealy100ms();
}
P0=0xff;
for(i=0;i<8;i++)
{
P2=~(0x80>>i);
Dealy100ms();
}
P2=0xff;
}
}
拓展:P0=~(1<<i);
~是按位取反运算 =是赋值运算 <<是按位左移运算
意思是:将二进制数1左移3位,得到二进制数1000。对1000取反,得到0111。将0111赋值给P0
成功案例
(3)模块化编程
#include <REGX52.H>
void Dealy100ms() //@11.0592MHz 100毫秒
{
unsigned char data i, j, k;
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void LED1()
{
unsigned char i;
for(i=0;i<8;i++)
{
P0=~(1<<i);
Dealy100ms();
}
P0=0xff;
}
void LED2()
{
unsigned char j;
for(j=0;j<8;j++)
{
P2=~(0x80>>j);
Dealy100ms();
}
P2=0xff;
}
void main()
{
while(1)
{
LED1();
LED2();
}
}
(4)4种模式流水灯
从上往下
从下往上
两端往中间
中间往两边
代码
#include <REGX52.H>
void Dealy100ms() //@11.0592MHz 50毫秒
{
unsigned char data i, j, k;
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void LED11()//从上而下
{
unsigned char i;
for(i=0;i<8;i++)
{
P0=~(1<<i);
Dealy100ms();
}
}
void LED12()//从下而上
{
unsigned char i;
for(i=0;i<8;i++)
{
P0=~(0x80>>i);
Dealy100ms();
}
}
void LED21()//从上而下
{
unsigned char j;
for(j=0;j<8;j++)
{
P2=~(0x80>>j);
Dealy100ms();
}
}
void LED22()//从下而上
{
unsigned char j;
for(j=0;j<8;j++)
{
P2=~(1<<j);
Dealy100ms();
}
}
void hou1()//从上而下
{
LED11();
P0=0xff;
LED21();
P2=0xff;
}
void hou2()//从下而上
{
LED22();
P2=0xff;
LED12();
P0=0xff;
}
void hou3()//从外到中间
{ unsigned char i,j;
for(i=0,j=0;i<8&&j<8;i++,j++)
{
P0=~(1<<i);
P2=~(1<<j);
Dealy100ms();
}
}
void hou4()//从中间到外
{unsigned char i,j;
for(i=0,j=0;i<8&&j<8;i++,j++)
{
P0=~(0x80>>i);
P2=~(0x80>>j);
Dealy100ms();
}
}
void main()
{
while(1)
{
hou1();
hou2();
hou3();
hou4();
P2=0xff;
}
}
示例
(5)课堂作业:16个灯逐一出现 然后从另一边逐一退场
二进制 | 八进制 | 十进制 | 十六进制 |
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
10 | 2 | 2 | 2 |
11 | 3 | 3 | 3 |
100 | 4 | 4 | 4 |
101 | 5 | 5 | 5 |
110 | 6 | 6 | 6 |
111 | 7 | 7 | 7 |
1000 | 10 | 8 | 8 |
1001 | 11 | 9 | 9 |
1010 | 12 | 10 | A |
1011 | 13 | 11 | B |
1100 | 14 | 12 | C |
1101 | 15 | 13 | D |
1110 | 16 | 14 | E |
1111 | 17 | 15 | F |
原理:当P0.0输出一个高电平的时候,相当于跟VCC一样的5V电压,此时整个电路路无电压差无电流,LED熄灭。当P0.0输出一个低电平的时候,相当于跟GND一样的0V电压,此时整个电路接通,LED点亮。可以P0.0输出电平可以通过程序控制。
0000 0000=0x00 → 全亮
1000 0000=0x80
1100 0000=0xc0
1110 0000=0xe0
1111 0000=0xf0
1111 1000=0xf8
1111 1100=0xfc
1111 1110=0xfe
1111 1111=0xff → 全灭
0111 1111=0x7f
0011 1111=0x3f
0001 1111=0x1f
0000 1111=0x0f
0000 0111=0x07
0000 0011=0x03
0000 0001=0x01
代码
#include <REGX52.H>
void Dealy100ms() //@11.0592MHz 50毫秒
{
unsigned char data i, j, k;
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
unsigned char Led1[9]={0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00};
unsigned char Led2[9]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
void hou5() //一个一个亮
{
unsigned char i,j;
for(i=0;i<=8;i++)
{
P0=Led1[i];
Dealy100ms();
}
// P0=Led2[8];
for(j=8;j>=0&&j<=8;j--)
{
P2=Led2[j];
Dealy100ms();
}
}
void hou6() //一个一个灭
{
unsigned char i,j;
for(j=0;j<=8;j++)
{
P0=0x00;
P2=Led2[j];
Dealy100ms();
}
for(i=8;i>=0&&i<=8;i--)
{
P2=0xff;
P0=Led1[i];
Dealy100ms();
}
}
void main()
{
while(1)
{
hou5();
Dealy100ms();
hou6();
//P2=0x01;
}
}
示例
(6)呼吸灯 PWM调节亮度
PWM调节亮度
单片机输出占空比从小到大变化,再从大变小的PWM
#include <REGX52.H>
void Delay() //@12.000MHz
{
unsigned char i;
i = 57;
while (--i);
}
unsigned char duty,x;
void PWM()
{
for (x=0;x<100;x++)
{
if(x<duty)
{
P0=0;
P2=0;
}
else
{
P0=0xff;
P2=0xff;
}
Delay();
}
}
void main()
{
while (1)
{
for (duty=0;duty<100;duty++)
{
PWM();
}
for (duty=100;duty>0;duty--)
{
PWM();
}
}
}
三、独立按键
1.电路图
2.PCB图
3,编程
(1)原理:
按键是机械弹性开关,当开关闭合时,线路导通,高电平;当开关断开时,线路断开,低电平。
(2)注意!按键抖动
按键按下和弹起会发生电平抖动。如下图所示。
(3)消抖
硬件消抖:在硬件设计上想办法降低抖动的幅度及时间,这是一种主动消抖。如按键并联电容。
软件消抖:硬件上不可能完全消除抖动,软件上可以绕开抖动的那一段,这是一种逃避式的消抖。
也就是通过延时消抖,延时时间一般为10-15毫秒。
原文链接:https://blog.csdn.net/weixin_42727214/article/details/127913068
(4)课堂作业:按键切换流水灯的花样
不按键,LED灯不亮
按K1,LED灯从上到下点亮一次然后自动熄灭
按K2,LED灯从下到上点亮一次然后自动熄灭
按K3,LED灯从两端到中间一次然后自动熄灭
按K4,LED灯从中间到两头跑,然后自动熄灭
#include <REGX52.H>
sbit K1=P1^0;
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
/*中间关于灯的代码详见[二,3,(4)]*/
void main()
{
while(1)
{
if(K1==0) hou1();
if(K2==0) hou2();
if(K3==0) hou3();
if(K4==0) hou4();
}
}
案例
四,延迟函数
附加题:调制两个按键,课控制流水灯的速度
延迟函数的解释:c语言的单片机delay延时函数详解_延时函数delay-CSDN博客
时钟周期、机器周期、指令周期的概念及三者之间的关系-CSDN博客
unsigned int xms;
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void speed_k()//快速
{
xms=100;
}
void speed_z()//中速
{
xms=300;
}
void speed_m()//快速
{
xms=500;
}