1 单片机介绍
1.1 芯片名称
STC 89C52RC 40I-PDIP 0707
➢ STC: 公司名, AT(ATM), P(飞利浦), W(华邦), S(西门子), I(英特尔);
➢ 8: 80C51内核;
➢ 9: RAM型号, 9(Flash E2P-RAM), 0(Mark RAM), 7(EP-RAM);
➢ C: CMOS工艺, LV、 LE(低压产品), S(可串行化编程);
➢ 5: 固定;
➢ 2: 2X4KB, ROM;
➢ RC: 512B大小RAM, RD++(1080B);
➢ 40: 晶振频率40MHZ;
➢ I: I(工业级-40~85℃)、 C(商业级0~70℃)、 A(汽车-40~125℃)、 M(军品-55~150℃);
➢ PDIP: 封装形式, PDIP 双列直插式)、 PLCC(带引线的塑料封装)、 QFP/PFP(方形扁平式)、PGA(插针网格阵列)、 BGA(球栅阵列);
➢ 0707: 07年第07周;
1.2 电平特性
➢ CMOS/TTL: 5V、 3.3V、 2.5V、 1.8V;
➢ STC89C52: TTL电平,高电平5V,低电平0V;
➢ RS-232: 计算机串口,高电平-12V,低电平12V;
➢ MAX232: 实现计算机串口电平与单片机电平转换;
➢ TTL特点: 使用最多, 对于电源要求不高、热损耗低; 直接与集成电路相连不需要价格昂贵的线路驱动; 能够实现数据高速传输; 但是并行数据传输不能超过10英尺,由于并行接口不对称对可靠性有影响;
➢ CMOS特点: 输入端不能悬空,会导致逻辑混乱;电源电压可在大范围变化,不如TTL严格;
1.3 芯片引脚
➢ 第一类:电源与时钟引脚 - VCC(40)、 GND(20)、 XTAL1(19)、 XTAL2(18);
➢ 第二类:编程控制引脚 – RST/VPD(9)、 𝑃𝑆𝐸𝑁(29)、 ATL/PROG(30)、 𝐸𝐴/𝑉𝑃𝑃(31);
➢ 第三类: IO引脚 – P1(1~8)、 P3(10~17)、 P2(21~28)、 P0(32~39);
➢ VCC、 GND: 外接电源,需要使用滤波器过滤信号;
➢ XTAL1、 XTAL2:时钟引脚,外部时钟, XTAL2接地, XTAL1接输入信号,片内振荡,XTAL1输入信号, XTAL2输出信号,外接 电容10~30PF,保证程序能够执行到下一行,外加电容是为了获得交流信号,使其起振;
➢ RST/VPD: 第一功能复位计数器PC=0000H,连续输入两个机器周期以上的高电平有效,第二功能提供临时高电平,备用电源,防止数据丢失;
➢ 𝑷𝑺𝑬𝑵: 程序存储器允许输出控制端,低电平有效,低电平读取外部ROM,一机器周期两个脉冲,与外部ROM的OE口相连;
➢ ATL/PROG: 扩展外部RAM时, ALE控制P0口的输出低8位地址送锁存器,低电平有效;PROG为编程脉冲的输入端 ;
➢ 𝑬𝑨/𝑽𝑷𝑷: 高电平先读内部,再读外部,低电平只读外部ROM;
1.4 最小系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iyNRKssl-1688306214837)(E:\Notes\1. 技术\1. STC89C52RC\images\最小系统.bmp)]
1.5 数据类型和头文件
➢ #include<reg52.h> 头文件比51多一个T2定时器;
➢ <regx52.h>头文件中也定义了特殊功能位 P1_0 = P1^0
➢ srf: 8位特殊功能寄存器声明;
➢ srf16: 16位特殊功能寄存器声明;
➢ sbit:特殊功能位声明;
➢ bit:位变量声明;
➢ short / unsigned short int 2;
➢ Int / unsigned int 2;
➢ long / unsigned long int 4;
➢ float 4 ;
➢ double 8;
➢ char / unsigned char 1;
2 点亮LED
2.1 LED结构原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdqz1XeK-1688306214838)(E:\Notes\1. 技术\1. STC89C52RC\images\LED原理.bmp)]
2.1 代码实现
bsp_delay.h
#ifndef BSP_DELAY_H__
#define BSP_DELAY_H__
#include <REGX52.H>
#include <intrins.h>
/*延迟Xms*/
void Delay(unsigned int ms);
#endif
bsp_delay.c
#include "bsp_delay.h"
void Delay(unsigned int ms){
unsigned char i, j;
while(ms--){
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
bsp_led.h
#ifndef BSP_LED_H__
#define BSP_LED_H__
#include <REGX52.H>
#include "bsp_delay.h"
#include <intrins.h>
/*引脚配置*/
#define LED_Port P2
/*点亮LED*/
#define LED_Pin_0 0xff // 全部熄灭
#define LED_Pin_1 0xfe // 点了第1个
#define LED_Pin_2 0xfd // 点亮第2个
#define LED_Pin_3 0xfb // 点亮第3个
#define LED_Pin_4 0xf7 // 点亮第4个
#define LED_Pin_5 0xef // 点了第5个
#define LED_Pin_6 0xdf // 点亮第6个
#define LED_Pin_7 0xbf // 点亮第7个
#define LED_Pin_8 0x7f // 点亮第8个
#define LED_Pin_9 0x00 // 全部点亮
/*点亮熄灭宏*/
#define ON 1
#define OFF 0
#define LED(X,LED_Pin) if(X) \
LED_Port = LED_Pin; \
else \
LED_Port = 0xff;
/*实现流水灯*/
void LED_Water(void);
#endif
bsp_led.c
#include "bsp_led.h"
void LED_Water(void){
LED_Port = LED_Pin_1;
while(1){
Delay(500);
LED_Port = _crol_(LED_Port,1);
}
}
main.c
#include <REGX52.H>
#include "bsp_led.h"
void main(void){
#if 0
LED_Water();
#endif
while(1){
LED(ON,LED_Pin_1);
}
}
3 独立按键
3.1 独立按键
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vAGsvqVE-1688306214838)(E:\Notes\1. 技术\1. STC89C52RC\images\独立按键原理.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPKQuutZ-1688306214839)(E:\Notes\1. 技术\1. STC89C52RC\images\独立按键开发板.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fo7Hormr-1688306214839)(E:\Notes\1. 技术\1. STC89C52RC\images\按键消除抖动.bmp)]
3.2 代码实现
bsp_skey.h
#ifndef BSP_SKEY_H__
#define BSP_SKEY_H__
#include <REGX52.H>
#include "bsp_delay.h"
/*
获取按键值,1、2、3、4
*/
unsigned char Key_Scan(void);
#endif
bsp_skey.c
#include "bsp_skey.h"
unsigned char Key_Scan(void){
if(P3_1 == 0){
Delay(20); // 消除抖动
while(P3_1 == 0); // 保证到松开
Delay(20); // 消除抖动
return 1;
}
if(P3_0 == 0){
Delay(20);
while(P3_0 == 0);
Delay(20);
return 2;
}
if(P3_2 == 0){
Delay(20);
while(P3_2 == 0);
Delay(20);
return 3;
}
if(P3_3 == 0){
Delay(20);
while(P3_3 == 0);
Delay(20);
return 4;
}
return 0;
}
main.c
#include <REGX52.H>
#include "bsp_led.h"
#include "bsp_skey.h"
#define uint8_t unsigned char
void main(void){
/*
按键点亮对于的灯
*/
uint8_t keyNum = 0;
while(1){
keyNum = Key_Scan();
if(keyNum){
LED(ON,_crol_(LED_Pin_1,keyNum - 1));
}
}
}
4 点亮数码管
4.1 数码管原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iF0voolz-1688306214839)(E:\Notes\1. 技术\1. STC89C52RC\images\数码管驱动方式.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oleAbQsP-1688306214840)(E:\Notes\1. 技术\1. STC89C52RC\images\数码管原理图1.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p25l8iaz-1688306214841)(E:\Notes\1. 技术\1. STC89C52RC\images\数码管原理图1.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fV5Y2x2h-1688306214841)(E:\Notes\1. 技术\1. STC89C52RC\images\点亮数码管TX.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KTqlhzDI-1688306214841)(E:\Notes\1. 技术\1. STC89C52RC\images\数码管动态显示TX.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfzuI65l-1688306214842)(E:\Notes\1. 技术\1. STC89C52RC\images\数码管循环TX.bmp)]
4.2 代码实现
bsp_nixie.h
#ifndef BSP_NIXIE_H__
#define BSP_NIXIE_H__
#include <REGX52.H>
#include "bsp_delay.h"
#define A0 P2_2
#define A1 P2_3
#define A2 P2_4
#define NIXIE_PORT P0
static unsigned char code Nixie_Table[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
// 点了第x个数码管,显示y
void Nixie(unsigned char x,y);
#endif
bsp_nixie.c
#include "bsp_nixie.h"
extern unsigned char code Nixie_Table[10];
void Nixie(unsigned char x,y){
// 先段选
switch(x){
case 8: A0 = 0; A1 = 0; A2 = 0; break;
case 7: A0 = 1; A1 = 0; A2 = 0; break;
case 6: A0 = 0; A1 = 1; A2 = 0; break;
case 5: A0 = 1; A1 = 1; A2 = 0; break;
case 4: A0 = 0; A1 = 0; A2 = 1; break;
case 3: A0 = 1; A1 = 0; A2 = 1; break;
case 2: A0 = 0; A1 = 1; A2 = 1; break;
case 1: A0 = 1; A1 = 1; A2 = 1; break;
}
// 位选
NIXIE_PORT = Nixie_Table[y];
Delay(1); // 消影
NIXIE_PORT = 0x00; // 显示一会再取消
}
main.c
#include <REGX52.H>
#include "bsp_led.h"
#include "bsp_skey.h"
#include "bsp_nixie.h"
#define uint8_t unsigned char
void main(void){
/*
点亮显示123
*/
while(1){
Nixie(1,1);
Nixie(2,2);
Nixie(3,3);
}
}
5 矩阵键盘
5.1 矩阵键盘原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3d0LDtAK-1688306214842)(E:\Notes\1. 技术\1. STC89C52RC\images\矩阵键盘原理图.bmp)]
5.2 代码实现
bsp_matrix.h
#ifndef BSP_MATRIX_H__
#define BSP_MATRIX_H__
#include <REGX52.H>
#include "bsp_delay.h"
// 扫描按键
unsigned char Matrix_Scan(void);
#endif
bsp_matrix.c
#include "bsp_matrix.h"
unsigned char Matrix_Scan(void){
/*
扫描矩阵键盘
1. 先将一行置0;
2. 再扫描当前行;
3. 为0则按下;
*/
unsigned char KeyNum = 0;
P1 = 0xff;
P1_7 = 0;
if(P1_3 == 0){Delay(20); while(P1_3 == 0); Delay(20); KeyNum = 1;}
if(P1_2 == 0){Delay(20); while(P1_2 == 0); Delay(20); KeyNum = 2;}
if(P1_1 == 0){Delay(20); while(P1_1 == 0); Delay(20); KeyNum = 3;}
if(P1_0 == 0){Delay(20); while(P1_0 == 0); Delay(20); KeyNum = 4;}
P1 = 0xff;
P1_6 = 0;
if(P1_3 == 0){Delay(20); while(P1_3 == 0); Delay(20); KeyNum = 5;}
if(P1_2 == 0){Delay(20); while(P1_2 == 0); Delay(20); KeyNum = 6;}
if(P1_1 == 0){Delay(20); while(P1_1 == 0); Delay(20); KeyNum = 7;}
if(P1_0 == 0){Delay(20); while(P1_0 == 0); Delay(20); KeyNum = 8;}
P1 = 0xff;
P1_5 = 0;
if(P1_3 == 0){Delay(20); while(P1_3 == 0); Delay(20); KeyNum = 9;}
if(P1_2 == 0){Delay(20); while(P1_2 == 0); Delay(20); KeyNum = 10;}
if(P1_1 == 0){Delay(20); while(P1_1 == 0); Delay(20); KeyNum = 11;}
if(P1_0 == 0){Delay(20); while(P1_0 == 0); Delay(20); KeyNum = 12;}
P1 = 0xff;
P1_4 = 0;
if(P1_3 == 0){Delay(20); while(P1_3 == 0); Delay(20); KeyNum = 13;}
if(P1_2 == 0){Delay(20); while(P1_2 == 0); Delay(20); KeyNum = 14;}
if(P1_1 == 0){Delay(20); while(P1_1 == 0); Delay(20); KeyNum = 15;}
if(P1_0 == 0){Delay(20); while(P1_0 == 0); Delay(20); KeyNum = 16;}
P1 = 0xff;
return KeyNum;
}
main.c
#include <REGX52.H>
#include "bsp_led.h"
#include "bsp_skey.h"
#include "bsp_nixie.h"
#include "bsp_matrix.h"
#define uint8_t unsigned char
void main(void){
/*
显示按键值
*/
unsigned char KeyNum = 0;
unsigned char Num = 0;
while(1){
KeyNum = Matrix_Scan();
if(KeyNum){
Num = KeyNum;
}
Nixie(1,Num/10);
Nixie(2,Num%10);
}
}
6 LED点阵屏
6.1 LED点阵屏原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kq4IAsiQ-1688306214842)(E:\Notes\1. 技术\1. STC89C52RC\images\点阵屏原理介绍.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pr6d30Gm-1688306214843)(E:\Notes\1. 技术\1. STC89C52RC\images\点阵屏显示原理.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EgjJ6VZj-1688306214843)(E:\Notes\1. 技术\1. STC89C52RC\images\点阵屏显示原理1.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3zN3c9SO-1688306214843)(E:\Notes\1. 技术\1. STC89C52RC\images\74HC595原理.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uUNdVKuk-1688306214843)(E:\Notes\1. 技术\1. STC89C52RC\images\74HC595原理图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8tLNFgPc-1688306214844)(E:\Notes\1. 技术\1. STC89C52RC\images\点阵屏显示原理1.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LSTzHmxb-1688306214844)(E:\Notes\1. 技术\1. STC89C52RC\images\取字模.bmp)]
6.2 代码实现
bsp_matrixled.h
#ifndef BSP_MATRIXLED_H__
#define BSP_MATRIXLED_H__
#include <REGX52.H>
#include "bsp_delay.h"
/*74HC595模块*/
// 引脚配置
#define HC595_SER P3_4 // 串行输入
#define HC595_SRCLK P3_6 // 下降沿数据位移
#define HC595_RCLK P3_5 // 下降沿数据输出
// 写入数据
void HC595_WriteData(unsigned char Data);
/*点阵屏显示*/
void Matrix_ShowColumn(unsigned char Column,Data);
/*图像变换显示*/
static unsigned char code PictureTable[16] = {0x23,0x45,0x51,0x89,0x89,0x51,0x45,0x23,0x80,0x98,0xD4,0xF3,0xF3,0xD4,0x98,0x80};
void Matrix_LED(void);
#endif
bsp_matrixled.c
#include "bsp_matrixled.h"
extern unsigned char code PictureTable[16];
void HC595_WriteData(unsigned char Data){
unsigned char i = 0;
for(;i < 8;i++){
HC595_SER = Data & (0x80 >> i); // 取第i位
HC595_SRCLK = 1;
HC595_SRCLK = 0;
}
HC595_RCLK = 1;
HC595_RCLK = 0;
}
void Matrix_ShowColumn(unsigned char Column,Data){
HC595_WriteData(Data);
P0 = ~(0x80 >> Column);
Delay(1); // 消除闪烁
P0 = 0xff;
}
void Matrix_LED(void){
unsigned char Data = 0;
unsigned char Column = 0;
unsigned char i = 0;
while(1){
for(Column = 0;Column < 8;Column++){
Matrix_ShowColumn(Column,PictureTable[Data + Column]);
}
Delay(500);
Data = (Data + 8) % 16;
}
}
main.c
#include <REGX52.H>
#include "bsp_led.h"
#include "bsp_skey.h"
#include "bsp_nixie.h"
#include "bsp_matrix.h"
#include "bsp_matrixled.h"
#define uint8_t unsigned char
void main(void){
/*
点阵屏动态显示
*/
Matrix_LED();
}
7 LCD1602
7.1 LCD1602原理
- LCD1602:字符型液晶显示器,可以显示ASCII码以及内置特殊字符。
- 显示容量:16 x 2,每个字符是5 x 7点阵。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1LkJasgU-1688306214844)(E:\Notes\1. 技术\1. STC89C52RC\images\LCD1602原理图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kQtOhZQG-1688306214845)(E:\Notes\1. 技术\1. STC89C52RC\images\LCD1602内部框图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K1H9an6s-1688306214845)(E:\Notes\1. 技术\1. STC89C52RC\images\LCD1602存储器结构.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9gxlH7QL-1688306214845)(E:\Notes\1. 技术\1. STC89C52RC\images\LCD1602时序图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWxDkq0v-1688306214845)(E:\Notes\1. 技术\1. STC89C52RC\images\LCD1602指令集.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQmEIPDc-1688306214845)(E:\Notes\1. 技术\1. STC89C52RC\images\LCD1602操作顺序.bmp)]
7.2 代码实现
bsp_lcd1602.h
#ifndef BSP_LCD1602_H__
#define BSP_LCD1602_H__
#include <REGX52.H>
#include "bsp_delay.h"
// 引脚配置
#define LCD1602_RS P2_6
#define LCD1602_RW P2_5
#define LCD1602_EN P2_7
#define LCD1602_DataPort P0
// 写指令
void LCD1602_WriteCommand(unsigned char Command);
// 写数据
void LCD1602_WriteData(unsigned char Data);
// 初始化
void LCD1602_Init(void);
// 设置地址
void LCD1602_SetAddress(unsigned char Line,Column);
// 显示字符
void LCD1602_ShowChar(unsigned char Line,Column,Char);
// 显示字符串
void LCD1602_ShowString(unsigned char Line,Column,char String[]);
// 显示数字
void LCD1602_ShowNum(unsigned char Line,Column,unsigned int Num,unsigned char Len);
// 显示有符号数
void LCD1602_ShowSignedNum(unsigned char Line,Column,int Num,unsigned char Len);
// 显示二进制数字
void LCD1602_ShowBinNum(unsigned char Line,Column,unsigned int Num,unsigned char Len);
#endif
bsp_lcd1602.c
#include "bsp_lcd1602.h"
// 写指令
void LCD1602_WriteCommand(unsigned char Command){
LCD1602_RS = 0; // 1 数据 0 指令
LCD1602_RW = 0; // 1 读 0 写
LCD1602_DataPort = Command; // 将指令放在数据结口
LCD1602_EN = 1; // 高电平使能
Delay(1); // 延迟1ms,需要一定时间
LCD1602_EN = 0; // 下降延写入数据
Delay(1);
}
// 写数据
void LCD1602_WriteData(unsigned char Data){
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DataPort = Data;
LCD1602_EN = 1;
Delay(1);
LCD1602_EN = 0;
Delay(1);
}
// 初始化
void LCD1602_Init(void){
LCD1602_WriteCommand(0x38); // 8位数据线,两行显示,5*7字符
LCD1602_WriteCommand(0x0c); // 显示打开,光标关闭,闪烁关闭
LCD1602_WriteCommand(0x06); // 数据输入和输出AC都会自加1,画面不动
LCD1602_WriteCommand(0x00); // 清屏
}
// 设置地址
void LCD1602_SetAddress(unsigned char Line,Column){
// 设置地址时,最高位需要为1
if(Line == 1){
LCD1602_WriteCommand(0x80 | (Column - 1 + 0x00)); // 0x00 将其最高行为1
}else if(Line == 2){
LCD1602_WriteCommand(0x80 | (Column - 1 + 0x40)); // 0x40
}
}
// 显示字符
void LCD1602_ShowChar(unsigned char Line,Column,Char){
// 写地址
LCD1602_SetAddress(Line,Column);
// 写数据
LCD1602_WriteData(Char);
}
// 显示字符串
void LCD1602_ShowString(unsigned char Line,Column,char String[]){
unsigned char i = 0;
LCD1602_SetAddress(Line,Column);
for(;String[i] != '\0';i++){
LCD1602_WriteData(String[i]);
}
}
// 显示数字
int LCD1602_Pow(int x,y){
// 获取X的Y次方
unsigned char i = 0;
int ret = 1;
for(i = 0;i < y;i++){
ret *= x;
}
return ret;
}
void LCD1602_ShowNum(unsigned char Line,Column,unsigned int Num,unsigned char Len){
unsigned char i = 0;
LCD1602_SetAddress(Line,Column);
for(i = Len;i > 0;i--){
// 从最高位写到最低位
LCD1602_WriteData(Num/LCD1602_Pow(10,i-1)%10 + '0');
}
}
// 显示有符号数
void LCD1602_ShowSignedNum(unsigned char Line,Column,int Num,unsigned char Len){
unsigned char i = 0;
LCD1602_SetAddress(Line,Column);
if(Num > 0){
LCD1602_WriteData('+');
}else if(Num < 0){
LCD1602_WriteData('-');
Num = -Num;
}
for(i = Len;i > 0;i--){
LCD1602_WriteData(Num/LCD1602_Pow(10,i-1)%10 + '0');
}
}
// 显示二进制数字
void LCD1602_ShowBinNum(unsigned char Line,Column,unsigned int Num,unsigned char Len){
unsigned char i = 0;
LCD1602_SetAddress(Line,Column);
for(i = Len;i > 0; i-- ){
LCD1602_WriteData(Num/LCD1602_Pow(2,i-1)%2 + '0');
}
}
main.c
#include <REGX52.H>
#include "bsp_led.h"
#include "bsp_skey.h"
#include "bsp_nixie.h"
#include "bsp_matrix.h"
#include "bsp_matrixled.h"
#include "bsp_lcd1602.h"
#define uint8_t unsigned char
void main(void){
LCD1602_Init();
while(1){
LCD1602_ShowChar(1,1,'A');
LCD1602_ShowNum(1,2,123,3);
LCD1602_ShowSignedNum(2,8,-666,3);
LCD1602_ShowString(2,1,"hello");
LCD1602_ShowBinNum(1,7,11,4);
}
}
8 蜂鸣器
8.1 蜂鸣器原理
8.2 代码实现
9 定时器
9.1 定时器原理
- 定时器:内部资源,T0、T1、T2三个定时器资源,其中T2为新增,主要用途定时或者延时。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WhKBoiW7-1688306214846)(E:\Notes\1. 技术\1. STC89C52RC\images\定时器框图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6V8TSWu-1688306214846)(E:\Notes\1. 技术\1. STC89C52RC\images\中断资源原理.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-86JOBY3a-1688306214846)(E:\Notes\1. 技术\1. STC89C52RC\images\中断优先级.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JmNjrzEJ-1688306214846)(E:\Notes\1. 技术\1. STC89C52RC\images\中断寄存器.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cgcDyztx-1688306214846)(E:\Notes\1. 技术\1. STC89C52RC\images\中断TMOD.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPqFy8Yi-1688306214847)(E:\Notes\1. 技术\1. STC89C52RC\images\中断TCON.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu8pXuKR-1688306214847)(E:\Notes\1. 技术\1. STC89C52RC\images\中断IE.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PVncERdr-1688306214847)(E:\Notes\1. 技术\1. STC89C52RC\images\中断IP.bmp)]
9.2 代码实现
9.2.1 LED闪烁
bsp_timer0.h
#ifndef BSP_TIMER0_H__
#define BSP_TIMER0_H__
#include <REGX52.H>
void Timer0_Init(void);
#endif
bps_timer0.c
#include "bsp_timer0.h"
void Timer0_Init(void){
// 设置TMOD寄存器,16位计数器模式
TMOD &= 0xf0; // 后四位清零
TMOD |= 0x01; // 设置模式1
// 设置计数大小
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
// 设置TCON寄存器
TF0 = 0;
// 打开TR0
TR0 = 1;
// 设置IE寄存器
ET0 = 1;
EA = 1;
// 设置优先级
PT0 = 1;
}
#if 0
void Timer0_Rountine(void) interrupt 1{
static unsigned int i = 0;
// 重置技术单元
TH0 = 64536 /256; // 1000us
TL0 = 64536 % 256 + 1;
i++;
if(i >= 500){
// 500ms后翻转第一个灯
P2_0 = ~P2_0;
// 重置i
i = 0;
}
}
#endif
main.c
#include <REGX52.H>
#include "bsp_timer0.h"
void main(void){
Timer0_Init();
while(1){
}
}
void Timer0_Rountine(void) interrupt 1{
static unsigned int i = 0;
// 重置技术单元
TH0 = 64536 /256;
TL0 = 64536 % 256 + 1;
i++;
if(i >= 500){
// 500ms后翻转第一个灯
P2_0 = ~P2_0;
// 重置i
i = 0;
}
}
9.2.2 按键切换LED模式
main.c
#include <REGX52.H>
#include "bsp_skey.h"
#include "bsp_timer0.h"
#include <intrins.h>
static unsigned char mode = 0;
void main(void){
unsigned char KeyNum = 0;
Timer0_Init();
P2 = 0xfe;
while(1){
KeyNum = Key_Scan();
if(KeyNum){
if(KeyNum == 1){ // 加1
mode = (mode + 1) %2;
}else if(KeyNum == 2){
if(mode == 0){
mode = 1;
}else{
mode --;
}
}
}
}
}
void Timer0_Rountine(void) interrupt 1{
static unsigned int i = 0;
// 重置技术单元
TH0 = 64536 /256;
TL0 = 64536 % 256 + 1;
i++;
if(i >= 1000){
if(mode == 0){
P2 = _crol_(P2,1); // 左移
}else if(mode == 1){
P2 = _cror_(P2,1); // 右移
}
i= 0;
}
}
9.2.3 显示时分秒
main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "bsp_timer0.h"
unsigned int Sec = 0;
unsigned int Minute = 0;
unsigned int Hour = 0;
void main(void){
Timer0_Init();
LCD_Init();
while(1){
LCD1602_ShowString(1,1,"Time: ");
LCD1602_ShowNum(2,1,Hour,2);
LCD1602_ShowChar(2,3,' ');
LCD1602_ShowNum(2,4,Minute,2);
LCD1602_ShowChar(2,6,' ');
LCD1602_ShowNum(2,7,Sec,2);
}
}
void Timer0_Rountine(void) interrupt 1{
static unsigned int i = 0;
// 重置技术单元
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
i++;
if(i >= 1000){
i= 0;
Sec++;
if(Sec >= 60){
Sec = 0;
Minute ++;
if(Minute >= 60){
Minute = 0;
Hour ++;
if(Hour >= 24){
Hour = 0;
}
}
}
}
}
10 UART串口
10.1 UART串口原理
- **UART:**通用异步收发器,两根通信线TXD、RXD交叉接线,电平不一致时加电平转换芯片。
- **TTL电平:**0v – 0,5v – 1。
- RS232电平:-3v~-15v – 1,3v~15v – 0。
- **RS485电平:**两线压差,传输更远。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HwzIo7Uh-1688306214847)(E:\Notes\1. 技术\1. STC89C52RC\images\串口分类.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q7hLTGvW-1688306214847)(E:\Notes\1. 技术\1. STC89C52RC\images\通信术语.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i3PL8Bgo-1688306214848)(E:\Notes\1. 技术\1. STC89C52RC\images\UART原理图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avDGF29K-1688306214848)(E:\Notes\1. 技术\1. STC89C52RC\images\UART内部框图.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r8iPUwX6-1688306214848)(E:\Notes\1. 技术\1. STC89C52RC\images\UART相关寄存器.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cRIHHa8v-1688306214848)(E:\Notes\1. 技术\1. STC89C52RC\images\UART相关寄存器1.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wTdPH32-1688306214848)(E:\Notes\1. 技术\1. STC89C52RC\images\UART相关寄存器2.bmp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3WG1DWzS-1688306214848)(E:\Notes\1. 技术\1. STC89C52RC\images\波特率计算.bmp)]
10.2 代码实现
bsp_uart.h
#ifndef BSP_UART_H__
#define BSP_UART_H__
#include <REGX52.H>
void UART_Init(void);
void UART_SendByte(unsigned char Byte);
#endif
bsp_uart.c
#include "bsp_uart.h"
void UART_Init(void){
// 设置8位重装模式
TMOD &= 0x0f;
TMOD |= 0x20;
// 设置RS的相关寄存器
PCON &= 0x7f; // 将SMOD清零波特率不加倍
SCON = 0x50; // REN = 1 SM0 = 0 SM1 = 1
// 设置计数单元
TH1 = 0xfd;
TL1 = 0xfd;
// 关闭ET1中断
ET1 = 0;
TR1 = 1;
// 打开串行中断
EA = 1;
ES = 1;
}
// 写
void UART_SendByte(unsigned char Byte){
SBUF = Byte;
while(TI == 0); // 发送时会产生TI中断标志
TI = 0; // 最后将TI清零
}
// 中断
/*
void UART_Rountine(void) interrupt 4{ // 输入数据点亮LED
if(RI == 1){
// 开始接受
P2 = SBUF; // led的值为SUBF
UART_SendByte(SBUF); // 发送到接受端
RI = 0; // 清零RI
}
}
*/
main.c
#include <REGX52.H>
#include "bsp_lcd1602.h"
#include "bsp_uart.h"
void main(void){
UART_Init();
while(1){
}
}
void UART_Rountine(void) interrupt 4{
if(RI == 1){
// 开始接受
P2 = SBUF; // led的值为SUBF
UART_SendByte(SBUF); // 发送到接受端
RI = 0; // 清零RI
}
}