51单片机

基础

最小系统

复位电路

头文件


如上在KEIL编程中并没有使用到头文件 ,如果没有加"sfr P2 =0x80;"这一句,就需要添加头文件"reg52.h"了

巧用宏定义

#define HC(x,y) {P2=P2&0x1f|(x<<5);P0=y;P2=P2&0x1f;}

时钟

振荡周期:也称时钟周期(频率的倒数),单片机提供时钟信号的振荡源周期,频率一般有11.0592MHz,12MHz等
状态周期:是时钟周期的2倍,
机器周期:是包含6个状态周期,机器周期=1/单片机时钟频率
单片机时钟频率:是外部时钟的12分频,如果是12MHz的晶振,机器周期=1/单片机时钟频率=1/(12MHz/12)=12/12M=1us

定时器

TMOD是定时器、计数器模式控制寄存器,它是一个逐位定义的8位寄存器,但只能使用字节寻址。
在这里插入图片描述
GATE:门控制
GATE=0: 仅由TR0,TR1置位分别启动定时器T0、T1
GATE=1:由外部中断引脚INT0、INT1来启动定时器T0、T1
当INT0引脚为高电平时TR0置位,启动定时器T0;
当INT1引脚为高电平时TR1置位,启动定时器T1
C/T:定时器和计数器选择位,0为定时器,1为计数器

定时
这里一个机器周期为1us,若定时时间为1ms,则需要1000个机器周期,计算出初值;如果机器周期为2us,则只需要500个机器周期。
定时器初值计算:初值=(65536-机器周期数量)

数码管

共阳极:
位选为高电平(即1)选中数码管,
各段选为低电平(即0接地时)选中各数码段。

uchar code table[]={
	0xc0//0
	0xf9//1
	0xa4//2
	0xb0//3
	0x99//4
	0x92//5
	0x82//6
	0xf8//7
	0x80//8
	0x90//9
	0x88//A
	0x83//B
	0xc6//C
	0xa1//D
	0x86//E
	0x8e, //F
	0x8c, //P
	0xc1,//U
	0x91,//Y
	0x7c,//L
	0x00,//全亮
	0xff  //熄灭
};

共阴极:
位选为低电平(即0)选中数码管,
各段选为高电平(即1接+5V时)选中各数码段。

uchar code leddata[]={
	0x3F,  //"0"
    0x06,  //"1"
    0x5B,  //"2"
    0x4F,  //"3"
    0x66,  //"4"
    0x6D,  //"5"
    0x7D,  //"6"
    0x07,  //"7"
    0x7F,  //"8"
    0x6F,  //"9"
    0x77,  //"A"
    0x7C,  //"B"
    0x39,  //"C"
    0x5E,  //"D"
    0x79,  //"E"
    0x71,  //"F"
    0x76,  //"H"
    0x38,  //"L"
    0x37,  //"n"
    0x3E,  //"u"
    0x73,  //"P"
    0x5C,  //"o"
    0x40,  //"-"
    0x00  //熄灭
	};

使用数码管小技巧

void display()
{
static u8 d1;
HC(7,0xff);
HC(6,1<<d1);
HC(7,led[znx[d1]]);
d1==7?d1=0:d1++;
}

在定时器服务函数中调用该函数,就可以实现八位数码管的循环点亮;

Keil

编程

优先级的问题
if(P1&0x0f !=0x0f) 是错的
改正后 if((P1&0x0f) !=0x0f)

使用问题

keil注释无法输入汉字,变成“?”

项目

串口通信

串口中断要有定时器T1参加,因为C51是用定时器1来产生波特率的。
因此就需要给 定时器T1 设置初值。

例程1

单片机发送数据到电脑

#include "reg52.h"
void UartInit(void)		//9600bps@11.0592MHz
{
	SCON = 0x50;        //串口方式1
	TMOD = 0x20;        // 定时器使用方式2自动重载
	TH1 = 0xFD;    //9600波特率对应的预设数,定时器方式2下,TH1=TL1
	TL1 = 0xFD;
	TR1 = 1;//开启定时器,开始产生波特率
}
void delay(unsigned int n)
{
	while (n--);
}

void main(void)
{
	UartInit(); 
	P0 =0x00;
	while(1)
	{
		SBUF = 0x30;       //把数据放到SBUF中
		while (TI == 0);//未发送完毕就等待
		TI = 0;    //发送完毕后,要把TI重新置0
		delay(20000) ;
	}
}

例程2

#include "stdio.h"
#include "stdarg.h"
#include "reg52.h"
void UartInit(void)		//9600bps@11.0592MHz
{
	SCON = 0x50;        //串口方式1
	TMOD = 0x20;        // 定时器使用方式2自动重载
	TH1 = 0xFD;    //9600波特率对应的预设数,定时器方式2下,TH1=TL1
	TL1 = 0xFD;
	TR1 = 1;//开启定时器,开始产生波特率
}
void delay(unsigned int n)
{
	while (n--);
}
void UsartPrintf(char *fmt,...)
{
    unsigned char UsartPrintfBuf[30];
    va_list ap;
    unsigned char *pStr = UsartPrintfBuf;
    
    va_start(ap, fmt);
    vsprintf((char *)UsartPrintfBuf, fmt, ap);                         
    va_end(ap);
    
    while(*pStr != 0) {
				SBUF = *pStr++ ;
        while(TI == 0);
				TI = 0;				
    }
}

void main(void)
{
int inumber = 30;

char string[4] = "qy";
	UartInit(); 
	P0 =0x00;
	while(1)
	{
		UsartPrintf("yy%d %s", inumber, string);
		
		inumber++ ;
		delay(20000) ;
		delay(20000) ;
		delay(20000) ;
		delay(20000) ;
	}
}

SCON

串口工作方式寄存器SCON
在这里插入图片描述
RI:接收中断标志位,数据接收结束时,标志位会自动置1,需要通过程序将其置0
TI:发送中断标志位,数据发送结束时,标志位会自动置1,需要通过程序将其置0
RB8:存放发送数据的第9位
TB8:存放接收数据的第9位
REN:串行接收允许位,0允许串行接收,1禁止串行接收
SM2:多机控制位
SM1,SM0:串行工作方式
其中,​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ ​​fosc为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。
在这里插入图片描述

波特率计算

如果SCON已经确定,波特率取决于晶振频率

当串口工作在工作方式0和2是,波特率固定,方式0时fosc/12;方式2时fosc/32或fosc/64(根据SMOD判断)。
当串口工作在方式1时,定时器1工作在方式2时,波特率=(2^SMOD/32)*(单片机时钟频率/(256-X)),X是初值 。

可以使用波特率计算软件提取码: g8cc

设置定时计数器1的工作方式

TMOD寄存器
在这里插入图片描述
高四位为定时计数器1的设置,串口通信波特率设置占用定时计数器1,D7置0,D6置0 。

在这里插入图片描述

LCD1602

举个栗子 :比如我们需要在LCD1602的第二排第一个位置显示数字6,在程序中,我们先要初始化, 写指令函数(参数为0xc0),写数据函数(‘数字6的ASCII码’)//注意十六进制,END。

初始化(三条必加指令):写指令0x38(功能指令);写指令0x06(模式设置指令);写指令0x0c(显示开关控制指令);延时大概1ms;

写指令函数:指令控制字给P0口;RS=0;RW=0;(参数设定)EN=0;EN=1;延时1ms;EN=0;(模拟有效时序段)

写数据函数:数据给P0口;RS=1;RW=0;EN=0;EN=1;延时1ms;EN=0;

在这里插入图片描述

清屏指令 writecmd(0x01)

写第一行的第一个 writecmd(0x80) 写第二行的第一个 writecmd(0xc0)

STC89C52引脚图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值