高低电平:
数字电路中有两种电平:高/低 电平。
高电平:5V/3.3V,取决于单片机电源。
低电平:0V
十六进制
0-9,a-f。
CPU:由运算和控制逻辑组成,同时还包括中断系统和部分特殊功能寄存器。
I/O:四个8位并行I/O;
T/C:两个定时/计数器;
五个中断源的中断控制系统;
一个全双工UART(通用异步接受发送器)的串行I/O口;
片内震荡器和时钟产生电路;
基本时序: https://www.jianshu.com/p/442f1b7af553;
定时器
8051提供两个16位定时/计数器,分别是Timer 0、Timer 1即T0/T1。
8052为三个16位定时/计数器,多一个Timer 2即T2。
定时器使用步骤:
1、对定时器进行初始化:
①定时器/计数器工作方式寄存器(TMOD)
16进制 | 8位二进制 | 工作方式 |
---|---|---|
0x00 | 0000 0000 | 工作方式0 |
0x01 | 0000 0001 | 工作方式1 |
0x02 | 0000 0010 | 工作方式2 |
0x03 | 0000 0011 | 工作方式3 |
②设定初值
根据晶振计算时钟周期 1/11059200,所以一个机器周期为 12/11059200.
例:定时20ms?
x * 12/11059200 = 0.02;
x=18432;
方法一:
TH0 = (65536-18432)/256;
TL0 = (65536-18432)%256;
方法二:
(65536-18432)转换16进制为B8 00;
所以
TH0 = 0xB8;
TL0 = 0x00;
③开启定时器
TRx=1;
定时时间小于最大值的函数:
void timer(){
TMOD = 0X01;
TH0 = 0XB8;
TL0 = 0;
TR0 =1;
P1=0xfe;
while(1){
if(TF0==1){
TF0 = 0;
TH0 = 0XB8;
TL0 = 0;
P1=_crol_(P1,1);
}
}
}
定时时间大于最大值的函数方法:
void timer(){
unsigned char cnt=0;
TMOD = 0X01;
TH0 = 0XB8;
TL0 = 0;
TR0 =1;
P1=0xfe;
while(1){
if(TF0==1){
TF0 = 0;//计数溢出标志位
TH0 = 0XB8;
TL0 = 0;
cnt++;
}
if(cnt>=50){
cnt = 0;
TF0 = 0;
TH0 = 0XB8;
TL0 = 0;
P1=_crol_(P1,1);
}
}
}
数码管
单位数码管
直接进行位运算。
多位数码管
动态刷新,视觉暂留。
①相同操作
#include<reg52.h>
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
void delay();
int i=0;
int j=0;
int k=0;
unsigned char code num[10] ={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90
};
void main(){
P2_0=0;
while(1){
for(k=0;k<4;k++){
switch(k){
case 0:
P2_0=0;
delay();
case 1:
P2_1=0;
delay();
case 2:
P2_2=0;
delay();
case 3:
P2_3=0;
delay();
}
}
}
}
void delay(){
TMOD = 0X01;
TH0=0XB8;
TL0=0;
TR0=1;
if(TF0=1){
TH0=0XB8;
TL0=0;
j++;
}
if(j==50){
TH0=0XB8;
TL0=0;
i++;
if(i>=10) i=0;
P0 = num[i];
}
}
①不同操作
#include<reg52.h>
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
delay(n){
n--;
}
part1(){
P2_3=1;
P2_0=0;
P0=0xf9;
}
part2(){
P2_0=1;
P2_1=0;
P0=0xa4;
}
part3(){
P2_1=1;
P2_2=0;
P0=0xb0;
}
part4(){
P2_2=1;
P2_3=0;
P0=0x99;
}
void main(){
part1();
delay(100);
part2();
delay(100);
part3();
delay(100);
part4();
delay(100);
}
独立按键
扫描按钮是否被按下,判断操作。
以下代码:独立按键按下,灯光亮,第二次按,灯灭(双按钮控制)--模拟房间灯:
#include <reg52.h>
sbit Init = P3^2;
sbit Init1 = P3^3;
delay(n){
n--;
}
void main(){
P1=0xff;
while(1){
if(Init==0||Init1==0){
delay(10);
if(Init==0||Init1==0){
while(Init==0||Init1==0);
P1=~P1;
}
}
}
}
串口通信
#include <reg52.h>
#define jingzhen 11059200UL /*使用11.0592M晶体*/
#define botelv 9600UL /*波特率定义为9600*/
unsigned char zifuchuan[]="大家好,我是MCU起航!"; //待显示字符。
volatile unsigned char sending;
void delay(unsigned char i)
{
unsigned char j,k;
for(j=i;j>0;j--)
for(k=90;k>0;k--);
}
void init(void) //串口初始化
{
EA=0; //暂时关闭中断
TMOD&=0x0F; //定时器1模式控制在高4位
TMOD|=0x20; //定时器1工作在模式2,自动重装模式
SCON=0x50; //串口工作在模式1
TH1=256-jingzhen/(botelv*12*16); //计算定时器重装值
TL1=256-jingzhen/(botelv*12*16);
PCON|=0x80; //串口波特率加倍
ES=1; //串行中断允许
TR1=1; //启动定时器1
REN=1; //允许接收
EA=1; //允许中断
}
void send(unsigned char d) //发送一个字节的数据,形参d即为待发送数据。
{
SBUF=d; //将数据写入到串口缓冲
sending=1; //设置发送标志
while(sending); //等待发送完毕
}
void sendc(unsigned char * pd)
{
while((*pd)!='\0') //发送字符串,直到遇到0才结束
{
send(*pd); //发送一个字符
pd++; //移动到下一个字符
}
}
int main()
{
init();
while(1)
{
delay(200);
sendc(zifuchuan);
}
return(0);
}
void uart(void) interrupt 4 //串口发送中断
{
if(RI) //收到数据
{
RI=0; //清中断请求
}
else //发送完一字节数据
{
TI=0;
sending=0; //清正在发送标志
}
}