单片机学习总结
Lesson1 预备知识与点亮一个二极管
一、预备知识与流水灯
1、CPU ROM RAM STC I/O口
2、电平特性:高与低,TTL电平:高+5v,低0v;RS232电平:高-12v,低+12v,计算机与单片机通讯时要加电平转换芯片max232(实验板上左下角)
3、二进制:遇二进一;十六进制:十进制中的0-15分别表示为十六进制的0、1....9、A、B、C、D、E、F,一般把四个二进制数放在一起转换为一个十六进制数,转换时先把二进制数转换成十进制数,再把十进制数转换成十六进制数。0001B>1H;1010B>AH;0010 1100>2CH(这里B表示的是二进制,H表示的十六进制)。0x表示十六进制。
4、二进制的逻辑运算:“与”、“?”、“&”;“或”、“+”、“|”;“非”“”;“异或”“?”,相同为0,不同为1。按位与&,按位或|,按位异或~,按位取反~
5、芯片缺口方向,芯片插反会导致短路。
二、80C51系列介绍
1、80C51的引脚封装:总线型:有4组 非总线型:只有20个引脚,送数据时,数据在总线上跑
2、C51知识:sfr,特殊功能寄存器声明;sfr16,sfr的16位数据声明;sbit,特殊功能位声明;bit,位变量声明。例如sfr SCON=0X98,sfr16 T2=0xCC,sbit 0V=PSW^2(第2位定义为ov)。单片机都是从0开始记值。
3、C-51的运算符:
4、单片机掌握几点:
5、stc-isp的使用
就德飞莱单片机而言,单片机类型为stc90c516RD+,com类型为com4,在下载程序时,一定要先把开发板上的电源断掉,过2秒钟再打开,顺序不能颠倒。
如果此界面长期没有变化,考虑以下几点:
6、Keil的使用:
(1)、先建工程,文件名没有后缀名,保存,选择atmel中的80c52
(2)、再建文件,有后缀名,后缀名.c(c语言)或.asm(汇编语言)
(3)、将文件添加在工程里,在左方,右击
(4)、建一个工程,就要建一个文件名
(5)、先下载程序,后打开电源
(6)、注释的方式有两种,一是//,换行无效;二是/* */,但是注释的语句不编译。
(7)、c语言区分大小写,默认端口P是大写字母;c语言的任何语句和标点都是在英文状态下书写的,中文符号是不能识别的,中文仅仅能作为注释使用。
(8)、建立工程时,选择芯片类型为AT89c52即可。
(9)、c语言中数值不区分大小写,标识符一定区分大小写。
(10)、一个函数由两部分组成:函数首部与函数体。函数首部包括函数名max,函数类型int,函数参数x、y,函数参数类型int,比如int max (int x,int y),也可以没有参数,如void main()。函数体包括声明部分(对变量和所调用函数)和执行部分。
6、自己动手需要的硬件材料
7、在字母上加上划线表示低电平有效。51单片机所有i/o口上电平默认为高电平
8、用位操作与总线操作两种方法写程序
(1)、位操作 (2)总线操作
#include <reg52.h> #include <reg52.h>
sbit D1=P1^0; void main()
void main() {P1=0xfd;
{ D1=0; }
}
9、课后练习
对照TX-1C单片机学习板原理图写程序
用位操作和总线操作两种方法完成以下题目
1.熟练建立KEIL工程
2.点亮第一个发光管.
3.点亮最后一个发光管
4.点亮1、3、5、7
5.点亮二、四、五、六
6.尝试让第一个发光管闪烁
法一:#include<reg52.h>
sbit P1_1=P1^0;
void main()
{unsigned int i;
while(1)
{P1_1=0;
for(i=1;i<10000;i++);
P1_1=1;
for(i=1;i<10000;i++);
}}
法二:#include<reg52.h>
sbit P1_1=P1^0;
void yanshi();
void main()
{while(1)
{P1_1=0;
yanshi();
P1_1=1;
yanshi();}}
void yanshi()
{unsigned int i;
for(i=0;i<10000;i++);}
法三:#include<reg52.h>
void main()
{while(1)
{
int i;i=50000;
P1=0xfe;
while(i--);
P1=0xff;
i=50000;
while(i--);
}
}
7.尝试设计出流水灯程序
法一:直接法
#include<reg52.h>
//sbit P1_1=P1^0;
void yanshi();
void main()
{while(1)
{P1=0xfe;
yanshi();
P1=0xfd;
yanshi();
P1=0xfb;
yanshi();
P1=0xf7;
yanshi();
P1=0xef;
yanshi();
P1=0xdf;
yanshi();
P1=0xbf;
yanshi();
P1=0x7f;
yanshi();
}}
void yanshi()
{unsigned int i;
for(i=0;i<10000;i++);}
法二:使用数组
#include<reg52.h>
unsigned char table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void yanshi();
void main()
{unsigned int i;
while(1)
{
for(i=0;i<8;i++)
{P1=table[i]; (注意,在这里的大括号是一定要加的,否则)
yanshi();
}}}
void yanshi()
{unsigned int i;
for(i=0;i<10000;i++);}
法三:左移右移
#include<reg52.h>
unsigned char table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned int i;
void yanshi();
void main()
{P1=0xfe;
while(1)
{P1=P1<<1;
P1=P1|0x01;(因为是左移而不是循环左移,所以要末位置一,这样的结果也会导致最后只挨个量一次)
yanshi();}
}
void yanshi()
{unsigned int i;
for(i=0;i<10000;i++);}
8、双灯左移右移闪烁(双灯左移7次,右移7次,然后全闪7次)
#include<reg52.h>
void main()
{unsigned char i;
unsigned char temp;
while(1)
{temp=0xfc;
P1=temp;
for(i=0;i<7;i++)
Delay(50000);
{temp<<=1;
temp=temp|0x01;
P1=temp;}之所以加入temp做中间变量,防止直接操作端口造成的短暂闪烁
Temp=0x3f;
P1=temp;
For(i=0;i<7;i++)
{Delay(50000);
Temp>>=1;
Temp|=0x80;
P1=temp;}
For(i=0;i<3;i++)
P1=0xff;
Delay(50000);
P1=0x00;
Delay(50000);}
} }
9、花样灯
10、PWM调光
三、流水灯
1、在使用总线操作点亮发光二极管时,注意顺序,比如从左往右依次为12345678个二极管,要想让246亮。系统默认高电平不亮低电平亮,即1010 1011,但是在赋值时要倒过来,即11010101,十六进制为d5,这样就可以了。
2、LED发光二极管,单向导电性,电源电压减去LED的正向压降的值除以工作电流即为LED的电阻。LED正常压降1.5v,正常工作电流10mA。
J9端低电平时LED亮,高电平时LED灭。具体解释如下:
A点就相当于单片机的I/O口,接5v相当于高电平1,灯不亮;接地相当于低电平0,灯亮。
3、单片机端口是标准双向口,可作为输出控制端,如控制灯亮灭;可作为输入信号端,如按键信号输入。
4、给端口赋值
(1)、SETB P1.1等价于sbit P1_1=P1^1,P1_1=1。
(2)、CLR P1.1等价于sbit P1_1=P1^1,P1_1=0。因为在C51中,没有P1_1这个表示,所以要预先定义。
(3)、while语句的两种形式:do语句while(条件);或while(条件)语句;。当循环条件为真即条件不为0时,循环会一直执行大括号中的语句。要想进行大循环时,用while(1),要想停留在某句,用while(1);。
(4)、宏定义#define uint unsigned int 函数声明void Delay(unsigned int t );
(5)、for循环
(6)、调用函数时一定要提前声明;带参数的子函数调用;C51库函数的调用(可以实现流水灯)
(7)、蜂鸣器
四、共阳二极管
1、dp-a,这个小数点是最高位,a是最低位,若接在P1口,a所对应的应该是P1.0,dp对应的是P1.7.
2、一个共阳数码管显示数字变化
#include<reg52.h>
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void Delay(unsigned int i);
void main(void)
{unsigned char i;
while(1)
{
for(i=0;i<16;i++)
{
P1=table[i];
Delay(60000);
}
}
}
void Delay(unsigned int t)
{
while(--t);
}
3、单个数码管模拟水流
#include<reg52.h>
void Delay(unsigned int t);//函数声明时的格式
void main()
{
unsigned char i;
while(1)
{
P1=0xfe; 如果在while之前就只会闪烁一次
for(i=0;i<6;i++)
{
Delay(10000); 如果没有延时会怎样
P1<<=1;
P1|=0x01;
}
}
}
void Delay(unsigned int t)//注意格式
{
while(--t);
}
4、8位数码管显一个数字
#include<reg52.h>
#define Port P0
void Delay(unsigned int i);
sbit Duan_LATCH1=P2^2;
sbit Wei_LATCH2=P2^3;
void main()
{
P0=0xfe;
Wei_LATCH2=1;
Wei_LATCH2=0;
P0=0x3f;
Duan_LATCH1=1;
Duan_LATCH1=0;
Delay(60000);
while(1)
{
}
}
4、8位数码管显示两个不同的数字
#include<reg52.h>
#define Port P0
void Delay(unsigned int i);
sbit Duan_LATCH1=P2^2;
sbit Wei_LATCH2=P2^3;
void main()
{
while(1)
{
P0=0xfe;
Wei_LATCH2=1;
Wei_LATCH2=0;
P0=0x3f;
Duan_LATCH1=1;
Duan_LATCH1=0;
Delay(60000);
P0=0xfd;
Wei_LATCH2=1;
Wei_LATCH2=0;
P0=0x06;
Duan_LATCH1=1;
Duan_LATCH1=0;
Delay(60000);
}
}
void Delay(unsigned int i)
{
while(--i);
}
5、8位数码管动态扫描
#include<reg52.h>
#define Port P0
void Delay(unsigned int i);
unsigned char code Duan_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code Wei_table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
sbit Duan_LATCH1=P2^2;
sbit Wei_LATCH2=P2^3;
void main()
{int i;
while(1)
{
for(i=0;i<8;i++)
{
P0=Wei_table[i];
Wei_LATCH2=1;
Wei_LATCH2=0;
P0=Duan_table[i];
Duan_LATCH1=1;
Duan_LATCH1=0;
Delay(60000);
}
}
}
void Delay(unsigned int i)
{
while(--i);
}
6、显示3位
#include<reg52.h>
#define Port P0
void Delay(unsigned int i);
unsigned char code Duan_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code Wei_table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
sbit Duan_LATCH1=P2^2;
sbit Wei_LATCH2=P2^3;
unsigned char temp[8];
void main()
{unsigned char i,j;
while(1)
{
j++;
for(i=0;i<8;i++)
{
temp[0]=Duan_table[j/100];
temp[1]=Duan_table[(j/10)%10];
temp[2]=Duan_table[j%10];
P0=Wei_table[i];
Wei_LATCH2=1;
Wei_LATCH2=0;
P0=temp[i];
Duan_LATCH1=1;
Duan_LATCH1=0;
Delay(60000);
}
}
}
void Delay(unsigned int i)
{
while(--i);
}
Lesson2 简单的延时程序及蜂鸣器
1、简单的延时程序:
一个机器周期等于12个时钟周期。用软件仿真进行调试,设定时间。
2、子程序调用:
(1)、宏定义:#define uint unsigned int(不加分号,注意先后顺序)以后出现uint就是unsigned int
(2)、无参子函数的设计:声明时,函数类型名 函数名 参数类型名,没有可不写,如void delay()
(3)、含参子函数的设计:
#include<reg52.h>
#define uint unsigned int
sbit D1=P1^0;
void delay(uint z);
void main()
{
while(1)
{
D1=0;
delay(600);
D1=1;
delay(600);
}
}
void delay(uint z)
{
uint x,y;
for(x=100;x>0;x--)
for(z=y;y>0;y--);
}
(4)、c51库函数的调用
#include<reg52.h>
#include <intrins.h>把所用库函数的函数名调用上
#define uint unsigned int
#define uchar unsigned char
uchar temp;
sbit D1=P1^0;
void delay(uint z);
void main()
{temp=0xfe;
P1=temp;
while(1)
{
temp=_crol_(temp,1);
delay(600);
P1=temp;
delay(600);
}
}
void delay(uint z)
{
uint x,y;
for(x=100;x>0;x--)
for(z=y;y>0;y--);
}
(5)蜂鸣器
P2^3即是
Lesson 3数码显示器以及定时器
1、锁存器:一个下降沿可以把输入的数据保持在输出端。8个数码管的公共端都是位选端,位选低电平有效;段选是高电平有效。
#include<reg52.h>
sbit duan=P2^2;
sbit wei=P2^3;
void main()
{
wei=1;
P0=0x00;
wei=0xbf;(此条语句结果为第7位数码管亮,显示4)
duan=1;
P0=0x66;
duan=1;
while(1);
}
2、多个数码管静态显示
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit duan=P2^2;
sbit wei=P2^3;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay (uint z);
void main()
{wei=1;
P0=0xea;
wei=0;
while(1)
{uint num;
for(num=0;num<16;num++)
{
duan=1;
P0=table[num];
duan=0;
delay(1000);
}
}
}
void delay (uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
3、中断系统
(1)、中断响应条件:
中断源有中断请求;
此中断源的中断允许位为1;
CPU开中断(即EA=1)。
以上三条同时满足时,CPU才有可能响应中断。
(2)、TCON的中断标志
IT0(TCON.0),外部中断0触发方式控制位。
当IT0=0时,为电平触发方式。
当IT0=1时,为边沿触发方式(下降沿有效)。
IE0(TCON.1),外部中断0中断请求标志位。
IT1(TCON.2),外部中断1触发方式控制位。
IE1(TCON.3),外部中断1中断请求标志位。
TF0(TCON.5),定时/计数器T0溢出中断请求标志位。
TF1(TCON.7),定时/计数器T1溢出中断请求标志位。
(3)、中断允许控制
EX0(IE.0),外部中断0允许位;
ET0(IE.1),定时/计数器T0中断允许位;
EX1(IE.2),外部中断0允许位;
ET1(IE.3),定时/计数器T1中断允许位;
ES(IE.4),串行口中断允许位;
EA (IE.7), CPU中断允许(总允许)位。
4、定时器初始化程序应完成如下工作:
(1)、对TMOD赋值,以确定T0和T1的工作方式。
(2)、计算初值,并将其写入TH0、TL0或TH1、TL1。
(3)、中断方式时,则对IE赋值,开放中断。
(4)、使TR0或TR1置位,启动定时/计数器定时或计数。
5、中断函数不需要声明28= 2828=256,
void exter0()interrupt 0(01234分别对应的是外部中断0、定时器/计数器T0、外部中断1、定时器/计数器T1、串行口中断)
{
d1=0;
}
单片机中各种周期的关系与定时器原理