一、理论:
1.进制转化:
十进制转成二进制:除以2取余,从右向左写。
二进制转成十进制:从右向左每位依次为2的0次方,2的1次方,2的2次方,依次递增,再加起来。
二进制转成十六进制:从右向左,每四位一划分。
2.四个周期:
(1)振荡周期:
晶振频率分之一。
(2)状态周期:
振荡周期*2.
(3)机器周期:
振荡周期*12.
(4)指令周期:
(1~4)*机器周期
3.定时原理:
二、实验:
1.让一个LED点亮
#include <REGX51.H>
void main()
{
while(1)
{
P2=0xfb;//1111 1011
}
}
2.让一个LED闪烁
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
P2=0xfe;//1111 1110
delay_10us(50000);
P2=0xff;
delay_10us(50000);
}
3.实现流水灯
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
u8 i=0;
P2=~(0x01);
for(i=0;i<8;i++)
{
P2=~(0x01<<i);
delay_10us(50000);
}
}
4.
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
while(1)
{
P2=0xfc;//1111 1100
delay_10us(50000);
P2=0xf3;//1111 0011
delay_10us(50000);
P2=0xcf;//1100 1111
delay_10us(50000);
P2=0x3f;//0011 1111
delay_10us(50000);
}
}
5.
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
while(1)
{
P2=0x7e;//0111 1110
delay_10us(50000);
P2=0xbd;//1011 1101
delay_10us(50000);
P2=0xdb;//1101 1011
delay_10us(50000);
P2=0xe7;//1110 0111
delay_10us(50000);
P2=0xdb;//1101 1011
delay_10us(50000);
P2=0xbd;//1011 1101
delay_10us(50000);
}
}
6.
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
u8 i=0;
while(1)
{
P2=~(i++);
delay_10us(200000);
}
}
7.独立按键实验
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
P2_0=0;
while(1)
{
if(P3_1==0)
{
delay_10us(50000);
while(P3_1==0)
delay_10us(50000);
P2_0=~P2_0;
}
}
}
8.
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void main()
{
u8 i=0;
P2=~0x01;
while(1)
{
if(P3_1==0)
{
delay_10us(50000);
while(P3_1==0)
delay_10us(50000);
i++;
if(i>=8)
i=0;
P2=~(0x01<<i);
}
if(P3_0==0)
{
delay_10us(50000);
while(P3_0==0)
delay_10us(50000);
if(i==0)
i=7;
else
i--;
P2=~(0x01<<i);
}
}
}
9.静态数码管
第一步:定位哪个LED亮:给P2_2.3.4赋值。注意顺序:P2_4是高位,即如果P2_4=1,P2_3=1,P2_2=0,那就是110,即Y6---LED7亮。
看每个LED灯,假设LED7亮E,即afged亮,也就是P0_7---P0_0赋予0111 1001.(注意顺序是从P0_7---P0_0,从下往上,亮的给1)即P0=0x79。
#include <REGX51.H>
void main()
{
P2_4=1 ;
P2_3=1 ;
P2_2=0 ;
P0=0x79;
}
10.动态数码管
注意:1.先定义数码管数组。
2.注意延时函数的写法。
3.亮某数码管用Switch,一定要注意数码管的顺序。
4.亮P0之后要消影。
#include <REGX51.H>
unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};//0.1.2.3.4.5.6.7.8.9.A.B.C.D.E.F.空
void delay(unsigned int xms)
{
unsigned char i,j;
while(xms--)
{
i=2;
j=239;
do
{
while(--j);
}
while(--i);
}
}
void light(unsigned char location,number)
{
switch (location)
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=led[number];
delay(1);
P0=0x00;
}
void main()
{
while(1)
{
light(1,2);
light(2,0);
light(3,0);
light(4,6);
light(5,0);
light(6,7);
light(7,2);
light(8,6);
}
}
11.
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
u8 led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07};//0.1.2.3.4.5.6.7
u16 count=0;
void delay(unsigned int xms)
{
unsigned char i,j;
while(xms--)
{
i=2;
j=239;
do
{
while(--j);
}
while(--i);
}
}
void main()
{
P2_4=1;
P2_3=1;
P2_2=1;
P0=led[0];
delay(1);
P0=led[0];
while(1)
{
if(P3_1==0)
{
delay(500);
while(P3_1==0)
delay(500);
count++;
P0=led[count];
if(count>7)
P0=led[7];
}
if(P3_0==0)
{
delay(500);
while(P3_0==0)
delay(500);
P0=led[0];
}
}
}
12.外部中断实验按下后灯翻转
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
void delay_10us(u16 t)
{
while(t--);
}
void Timer0_Init()
{
TMOD=TMOD&0xF0;
TMOD=TMOD|0x01;
TH0=64535 /256;
TL0=64535%256;
TF0=0;
TR0=1;
ET0=1;
EX1=1;
EA=1;
}
void main()
{
Timer0_Init();
while(1)
{
}
}
void Timer0_Routine() interrupt 1
{
delay_10us(1000);
if(P3_0==0)
{
delay_10us(1000);
while(P3_0==0)
delay_10us(1000);
P2_0=~P2_0;
}
}
13.定时器实验定时后1s,led翻转
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
u16 count=0;
void Timer0_Init()
{
TMOD=TMOD&0xF0;
TMOD=TMOD|0x01;
TH0=(65536 - 9216) /256;
TL0=(65536 - 9216)%256;
TF0=0;
TR0=1;
ET0=1;
EX1=1;
EA=1;
}
void main()
{
Timer0_Init();
while(1)
{
}
}
void Timer0_Routine() interrupt 1
{
TH0 = (65536 - 9216) / 256; // 重新赋值初值
TL0 = (65536 - 9216) % 256;
count++;
if (count >= 100) { // 10ms * 100 = 1s
count = 0;
P2_0 = ~P2_0; // LED状态翻转
}
}
14.
typedef unsigned char u8;
u8 num = 0;
u16 count=0;
void Timer0_Init()
{
TMOD=TMOD&0xF0;
TMOD=TMOD|0x00;
TH0=(8192 - 9216)>> 5;
TL0=(8192 - 9216) & 0x1F;
TF0=0;
TR0=1;
ET0=1;
EX1=1;
EA=1;
}
void main()
{
Timer0_Init();
while(1)
{
}
}
void Timer0_Routine() interrupt 1
{
TH0 = (8192 - 9216) >> 5; // 重新赋值初值
TL0 = (8192 - 9216) & 0x1F;
count++;
if (count >= 40) {
count = 0;
num++;
if(num>15)
{
num=0;
}
P2 =~num;
}
}
15.
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
bit key_flag = 0; // 按键按下标志位
u16 count = 0; // 定时器计数变量
// 10微秒延时函数,用于消抖
void delay_10us(u16 t) {
while (t--);
}
// 定时器0初始化函数
void Timer0_Init() {
TMOD &= 0xF0;
TMOD |= 0x01; // 设置定时器0为方式1
TH0 = (65536 - 9216) / 256; // 定时10ms初值,11.0592MHz晶振下
TL0 = (65536 - 9216) % 256;
TF0 = 0;
TR0 = 0; // 先不启动定时器,等按键按下再启动
ET0 = 1;
EA = 1;
}
// 外部中断0初始化函数
void EX0_Init() {
IT0 = 1; // 设置外部中断0为下降沿触发
EX0 = 1;
EA = 1;
}
void main() {
P2_0 = 0; // 初始LED亮
Timer0_Init();
EX0_Init();
while (1);
}
// 外部中断0服务函数
void EX0_Routine() interrupt 0 {
delay_10us(5000); // 消抖
if (P3_2 == 0) { // 确认按键按下
key_flag = 1; // 设置按键按下标志
P2_0 = 1; // LED熄灭
count = 0; // 计数清零
TR0 = 1; // 启动定时器
while (P3_2 == 0); // 等待按键释放
}
}
// 定时器0服务函数
void Timer0_Routine() interrupt 1 {
TH0 = (65536 - 9216) / 256;
TL0 = (65536 - 9216) % 256;
if (key_flag) { // 只有按键按下后才计数
count++;
if (count >= 100) { // 10ms * 100 = 1s
count = 0;
key_flag = 0; // 标志位清零
P2_0 = 0; // LED亮
TR0 = 0; // 停止定时器
}
}
}
16.
#include <REGX51.H>
// 外部中断0初始化函数
void EX0_Init() {
IT0 = 1; // 设置外部中断0为下降沿触发
EX0 = 1;
EA = 1;
}
void main() {
P1 = 0x00; // LED全灭
EX0_Init();
while (1)
{
}
}
// 外部中断0服务函数
void EX0_Routine() interrupt 0 {
if (P1_0 == 1) {
P1_3 = 1; // 若X1为高电平,点亮LED1
}
if (P1_1 == 1) {
P1_4 = 1; // 若X2为高电平,点亮LED2
}
if (P1_2 == 1) {
P1_5 = 1; // 若X3为高电平,点亮LED3
}
}
17.矩阵按键实验
按下“矩阵按键”模块中S1-S16键,对应数码管最左边显示0-F
#include <REGX51.H>
typedef unsigned int u16;
typedef unsigned char u8;
#define KEY P1
#define light P0
u8 led[]={0x3f,0x06,0x5b,0x4f,0x6b,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
u8 key_scan()
{
static u8 key_value=0;
KEY=0X0F;
if( KEY!=0X0F )
{
delay_10us(1000);
if( KEY!=0X0F )
{
KEY=0X0F;
switch(KEY)
{
case 0x07:key_value=1;break;
case 0x0b:key_value=2;break;
case 0x0d:key_value=3;break;
case 0x0e:key_value=4;break;
}
KEY=0XF0;
switch(KEY)
{
case 0x70:key_value=key_value;break;
case 0xb0:key_value=key_value+4;break;
case 0xd0:key_value=key_value+8;break;
case 0xe0:key_value=key_value+12;break;
}
while( KEY!=0xf0) ;
}
}
else
key_value=0;
return key_value;
}
void main()
{
u8 key=0;
while(1)
{
key=key_scan();
if(key!=0)
P0=led[key-1];
}
}