初识C51单片机(STC89C52RC开发板)

2024-01-28 10:10

本文主要是介绍初识C51单片机(STC89C52RC开发板),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、学会创建新工程

(安装Keil 5 教程自行寻找)

选择好保存目录,取好名字

点击Add后即可开始编写第一个程序

二、点亮第一个LED灯

为什么不是高电平?看原理图

因此引脚设置为低电平,才能形成电势差,存在电压才能点亮led

下面讲一下怎么把程序刷入开发板:

首先,用keil5将代码编译成hex文件。

注意:如果在项目目录下的各个文件夹内都没生成hex文件,请看下面的操作步骤

点击ok即可,然后重新编译

再讲解一下将hex文件刷入开发板的方法:

1、使用PZ-ISP软件(打开板子电源开关即可自动下载)

2、使用STC-ISP(官方软件,推荐)需要冷启动

冷启动:板子在掉电状态下点击下载,打开电源后开始下载

三、LED闪烁实验

很简单,点亮,然后循环延时一会再熄灭,重复这个操作就是闪烁了

四、LED流水灯实验

五、蜂鸣器实验

蜂鸣器持续发声,即给蜂鸣器一个脉冲信号,使其不断开关,来持续稳定发声。它不是给一个高电平信号就可以持续响的!

六、数码管(静态/动态)

段码数据计算:

数码管原理图上,让哪根线亮,哪根就是1,按下面的顺序排列,转换成16进制即可,比如

dp g f e d c b a

0 1 1 1 1 1 1 1 -> 0x7F 即亮一个8

所谓动态数码管,本质上是让数码管一位一位点亮,利用人眼的余晖效应,只有30Hz,用高频率刷新,看起来就像同时点亮,在使用上面的nixie()函数时,后面建议加一句P0=0x00;消音以避免会有残影

七、 独立按键实验

我将四个独立按键进行封装,作为函数,便于后续调用。

使用方法:在主函数while(1)里写上if(key() == 1/2/3/4){}即可判断1-4哪个按键被按下

八、 矩阵键盘实验

#include <REGX52.H>
#include "delay.h"#define KEY_MATRIX_PORT	P1/*******************************************************************************
* 函 数 名       : key_matrix_ranks_scan
* 函数功能		 : 使用行列式扫描方法,检测矩阵按键是否按下,按下则返回对应键值
* 输    入       : 无
* 输    出    	 : key_value:1-16,对应S1-S16键,0:按键未按下====实现原理====逐列扫描低八位————>       1、先拉低某一列高|			    2、再检测GPIO 1寄存器中的电平信号来判断某一行八|			    3、不断循环这个过程位|V
*******************************************************************************/
int scankey()
{char key_value=0;KEY_MATRIX_PORT=0xf7;//给第一列赋值0,其余全为1if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下{delay(10);//消抖switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值	{case 0x77: key_value=1;break;case 0xb7: key_value=5;break;case 0xd7: key_value=9;break;case 0xe7: key_value=13;break;}}while(KEY_MATRIX_PORT!=0xf7);//等待按键松开	KEY_MATRIX_PORT=0xfb;//给第二列赋值0,其余全为1if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下{delay(10);//消抖switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值	{case 0x7b: key_value=2;break;case 0xbb: key_value=6;break;case 0xdb: key_value=10;break;case 0xeb: key_value=14;break;}}while(KEY_MATRIX_PORT!=0xfb);//等待按键松开	KEY_MATRIX_PORT=0xfd;//给第三列赋值0,其余全为1if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下{delay(10);//消抖switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值	{case 0x7d: key_value=3;break;case 0xbd: key_value=7;break;case 0xdd: key_value=11;break;case 0xed: key_value=15;break;}}while(KEY_MATRIX_PORT!=0xfd);//等待按键松开	KEY_MATRIX_PORT=0xfe;//给第四列赋值0,其余全为1if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下{delay(10);//消抖switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值	{case 0x7e: key_value=4;break;case 0xbe: key_value=8;break;case 0xde: key_value=12;break;case 0xee: key_value=16;break;}}while(KEY_MATRIX_PORT!=0xfe);//等待按键松开return key_value;		
}/*******************************************************************************
* 函 数 名       : key_matrix_flip_scan
* 函数功能		 : 使用线翻转扫描方法,检测矩阵按键是否按下,按下则返回对应键值
* 输    入       : 无
* 输    出    	 : key_value:1-16,对应S1-S16键,0:按键未按下====原理说明====先扫出行,再扫出列依然是分高八位低八位
先扫描列数据,行为高八位,置0,按键按下后就会将列的低八位拉低为0,此时可以检测出哪一列被按下
再扫描行,低八位置0,按键按下后就会将高八位拉低,检测出哪一行被按下,判断哪个按键即可
第一行,直接输出列
第二行,列+4即可
第三行,列+8
依此类推
*******************************************************************************/
char key_matrix_flip_scan()
{static char key_value=0;KEY_MATRIX_PORT=0x0f;//给所有行赋值0,列全为1if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下{delay(10);//消抖if(KEY_MATRIX_PORT!=0x0f){//测试列KEY_MATRIX_PORT=0x0f;switch(KEY_MATRIX_PORT)//保存行为0,按键按下后的列值	{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_MATRIX_PORT=0xf0;switch(KEY_MATRIX_PORT)//保存列为0,按键按下后的键值	{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_MATRIX_PORT!=0xf0);//等待按键松开	}}elsekey_value=0;		return key_value;		
}

代码及原理解释直接给出,方法二效率更高一些,因为扫描次数更少,讲解看不懂的建议去b站看讲解动画。

封装函数使用方法:在主函数while(1)里面写if(scankey() == 1/2/……16){}与独立按键相同

九、点阵屏实验

与数码管类似,但这里多了74HC595芯片(串行传并行,极大减少io使用)

74HC595是一个8位串行输入、并行输出的位移缓存器:并行输出为三态输出。在SCK 的上升沿,串行数据由SDL输入到内部的8位位移缓存器,并由Q7'输出,而并行输出则是在LCK的上升沿将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低使能时,并行输出端的输出值等于并行输出缓存器所存储的值。

看不懂b站上有动画说明

根据74HC595芯片的工作原理,我们知道,最关键的引脚其实只有三个,分别是串行数据输入引脚DS、移位寄存器时钟输入引脚SHCP、储存寄存器时钟输入引脚STCP;所以代码怎么写,无非就是配置这几个引脚,定义串行数据输入的子函数,以及运行所需要的主函数

下面直接给出代码

/**************************************************************************************
实验名称:LED点阵实验(显示图像)
实验现象:下载程序后,8*8LED点阵显示心形
注意事项:LED点阵旁的J24黄色跳线帽短接到GND一端																				  
***************************************************************************************/
#include "reg51.h"//定义74HC595控制管脚
sbit SRCLK=P3^6;	//移位寄存器时钟输入
sbit RCLK=P3^5;		//存储寄存器时钟输入
sbit SER=P3^4; 		//串行数据输入#define LEDDZ_COL_PORT	P0	//点阵列控制端口char gled_row[8]={0x38,0x7C,0x7E,0x3F,0x3F,0x7E,0x7C,0x38};//LED点阵显示图像的行数据
char gled_col[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//LED点阵显示图像的列数据/*******************************************************************************
* 函 数 名         : hc595_write_data(char dat)
* 函数功能		   : 向74HC595写入一个字节的数据
* 输    入         : dat:数据
* 输    出         : 无
*******************************************************************************/
void hc595_write_data(char dat)
{char i=0;for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中{SER=dat>>7;//优先传输一个字节中的高位dat<<=1;//将低位移动到高位SRCLK=0;delay(1);SRCLK=1;delay(1);//移位寄存器时钟上升沿将端口数据送入寄存器中	}RCLK=1;delay(1);RCLK=0;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出	
}void main()
{	char i=0;while(1){			for(i=0;i<8;i++)//循环8次扫描8行、列{LEDDZ_COL_PORT=gled_col[i];//传送列选数据hc595_write_data(gled_row[i]);//传送行选数据delay(1);//延时一段时间,等待显示稳定hc595_write_data(0x00);//消影	}								}		
}

 十、定时器

        1.CPU时序

                 1) 震荡周期:为单片机提供定时信号的震荡源的周期(晶振周期或外加震荡周期)。

                 2) 状态周期:2个震荡周期为1个状态周期,用S表示。震荡周期又称S周期或时钟周期。

                 3) 机器周期:1个机器周期含6个状态周期,12个震荡周期

                 4) 指令周期:完成1条指令所占用的全部时间,他以机器周期为单位。

  • 例如:外界晶振为12MHz时,51单片机相关周期的具体值为:
  • 震荡周期=1/12us
  • 状态周期=1/6us
  • 机器周期=1us
  • 指令周期=1~4us

        2.定时器初步认识

                ① 51单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器   

                ② 定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程自动完成的,不需要CPU的参与。

                ③ 51单片机中的定时器/计数器是根据机器内部的时钟或者外部的脉冲信号对寄存器中的数据加1

        3.定时器原理

                STC89C5X单片机内有两个可编程的定时/计数器 T0,T1 和一个特殊功能定时器T2。定时/计数的是指是加 1 计数器(16位),由高 8 位到低 8 位两个寄存器 THx 和 TLx 组成。它随着计数器的输入脉冲进行自加 1 ,也就是每来一个脉冲,计数器就自动加 1 ,当加到计数器为全 1 时,再输入一个脉冲就使计数器回零,且计数器的益出相应的中断标志位置 1 ,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。可见,由溢出时计算器的值减去计数初值才是加 1 计数器的计算值。

        4.定时器/计数器控制寄存器TCON

可位寻址:可以对寄存器的某一位进行修改操作,而其它位数据保持不变

上图中常用的几个数据位为:

TF0 / TF1  ——  定时器/计数器 T1溢出标志。 当最高位产生溢出时由硬件置“1”,向CPU请求中断。 一直保持到 CPU 响应中断时,才由硬件清 “0 ”。
TR0 / TR1 ——   定时器 T0的运行控制位。 TRX=1 时就允许TX 开始计数。

        5.定时器/计数器工作模式寄存器TMOD

不可位寻址 : 必须对整个寄存器的每一位数据进行覆盖。此处可以利用“TMOD &= 0xF0”来保持高位不变,低位清0,也可以利用“TMOD |= 0xXX”来实现更多的修改操作

这里用定时器0的16位模式演示

按照手册,TMOD = 0x01;

#include <REGX52.H>sbit LED1 = P2^0;//将P2寄存器按位寻址第一位赋给LED1void t0_init(void)
{TMOD=0x10; //设置定时器0模式为16位 TF0=0; // 溢出位 置零TH0=0xFC; // 高位  1111 1100TL0=0x18; // 低位  0001 1000//1ms  FC18(16) -> 64536(10) 距离65536差1000(us) 即1ms后中断一次ET0=1;//打开定时器0中断允许EA=1;//打开总中断TR0=1;//定时器开始计时
}void main()
{t0_init();//初始化while(1){}
}void t0() interrupt 1 //定时器0中断函数  interrupt 中断次序号 越小优先级越高
{static int i;//定义静态变量i//重新赋初值,为下次计时准备TH0=0XFC;TL0=0X18;i++;if(i==1000)//1000ms = 1s{LED1=!LED1;	//电平反转i=0;}						
}

实验效果:第一个LED灯先暗1s然后亮1s,依次循环 

十一、外部中断

等待更新…… 

这篇关于初识C51单片机(STC89C52RC开发板)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/653313

相关文章

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

Linux操作系统 初识

在认识操作系统之前,我们首先来了解一下计算机的发展: 计算机的发展 世界上第一台计算机名叫埃尼阿克,诞生在1945年2月14日,用于军事用途。 后来因为计算机的优势和潜力巨大,计算机开始飞速发展,并产生了一个当时一直有效的定律:摩尔定律--当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍。 那么相应的,计算机就会变得越来越快,越来越小型化。

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

开发板NFS挂载文件目录

文章目录 序NFS1. 安装 NFS 服务器和客户端在服务器上(NFS 服务器端)在客户端上(NFS 客户端) 2. 配置 NFS 服务器创建共享目录编辑 `/etc/exports` 文件启动 NFS 服务 3. 在客户端挂载 NFS 共享创建挂载点挂载 NFS 共享验证挂载 4. 设置开机自动挂载5. 解决权限问题 序 本节主要实现虚拟机(服务器)与开发板(客户端)通过N

docker学习系列(一)初识docker

在第一版本上线之后公司,我们决定将之前使用的开源api文档项目转移到本公司的服务器之上,之前用的是showdoc,showdoc利用的是php技术,作为java程序员表示需要快速部署php环境以及apach容器都需要时间,所以采用第二种方法,即利用docker进行快速部署(虽然学习成本也不比php少)。 一、docker简介 docker的官网是https://www.docker.com,

基于stm32的河流检测系统-单片机毕业设计

文章目录 前言资料获取设计介绍功能介绍具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机设计精品

框架template初识

框架初识 框架就是一个别人帮我们搭好的舞台,造好了很多现成的工具供我们使用,让开发过程更快速、简洁。 Gin框架介绍 Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。 Gin是一个用Go语言编写的web框架。它是一个类似于martini 但拥有更好性能的API框架, 由于使用了 httprouter,速度提高了近40倍。 第一个Gin示例 package mai

安卓开发板_联发科MTK开发评估套件串口调试

串口调试 如果正在进行lk(little kernel ) 或内核开发,USB 串口适配器( USB 转串口 TTL 适配器的简称)对于检查系统启动日志非常有用,特别是在没有图形桌面显示的情况下。 1.选购适配器 常用的许多 USB 转串口的适配器,按芯片来分,有以下几种: CH340PL2303CP2104FT232 一般来说,采用 CH340 芯片的适配器,性能比较稳定,价

VB和51单片机串口通信讲解(只针对VB部分)

标记:该篇文章全部搬自如下网址:http://www.crystalradio.cn/thread-321839-1-1.html,谢谢啦            里面关于中文接收的部分,大家可以好好学习下,题主也在研究中................... Commport;设置或返回串口号。 SettingS:以字符串的形式设置或返回串口通信参数。 Portopen:设置或返回串口

MCU5.51单片机的最小系统

1.最小系统的组成部分 晶振电路(时钟),复位电路,电源电路(控制电压,保持稳定),下载电路(外加的,用于烧录程序) 烧录: 通过下载电路,把程序下载到单片机中用于运行 2.晶振电路 电路图: 是晶振 是电容 为了防止晶振起振时产生影响,因此加电容 3.复位电路 电路图: 按按钮RSTK1(保持一段时间的高电平)即可实现STC芯片的复位 4.电源电路 电路图: