单片机总复习
一、理论:
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 1100delay_10us(50000);P2=0xf3;//1111 0011delay_10us(50000);P2=0xcf;//1100 1111delay_10us(50000);P2=0x3f;//0011 1111delay_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;elsei--;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 = 1scount = 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为方式1TH0 = (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 = 1scount = 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 P0u8 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) ;}}elsekey_value=0;return key_value;}void main(){u8 key=0;while(1){key=key_scan();if(key!=0)P0=led[key-1];}}