解析下列程序#include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit EN=P1^2 ; sbit RS=P1^0 ; sbit RW=P1^1 ; sbit dula=P2^6; sbit wela=P2^7; uchar idata rdata[8]; uchar n=0; bit p=0; void delay (unsigned int t) { char j; while(t--) for(j=0;j<125;j++); } void wcmd(uchar cmd) { RS=0; RW=0; P0=cmd; delay(5); EN=1; delay(5); EN=0; delay(5); } void wdat(uchar dat) { RS=1; RW=0; P0=dat; delay(5); EN=1; delay(5); EN=0; delay(5); } void init_1602() { EN=0; wcmd(0x06); delay(5); wcmd(0x01); delay(5); wcmd(0x0c); delay(5); wcmd(0x38); delay(5); } main () { uchar i; init_1602(); SCON=0x50; PCON=0; TR1=1; TMOD=0x20; TH1=0xE8; TL1=0xE8; EA=1; ES=1; while(1) { wcmd(0x80); for(i=0;i<8;i++) { wdat(rdata[i]); } } } void ss()interrupt 4 { if(RI==1) { RI=0; if(p==1) { rdata[n]=SBUF; n++; if(n==8) { n=0; p=0; delay(20); } } else {if(SBUF==0x00)p=1;} } }
时间: 2023-07-14 08:14:19 浏览: 98
这是一个使用 8051 单片机控制的 1602 液晶显示屏的程序,并通过串口通信接收数据进行显示。具体解析如下:
1. 头文件和宏定义:
```c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
```
- `reg52.h` 是 8051 单片机的头文件。
- `uchar` 和 `uint` 是定义无符号字符和无符号整型数据类型的宏定义。
- 程序中使用的 `sbit` 是单片机特有的宏定义,表示单片机 I/O 引脚。
2. 定义液晶显示屏控制引脚:
```c
sbit EN=P1^2 ;
sbit RS=P1^0 ;
sbit RW=P1^1 ;
sbit dula=P2^6;
sbit wela=P2^7;
```
- `EN`、`RS`、`RW` 分别代表液晶显示屏的使能、读写、数据命令选择引脚。
- `dula`、`wela` 分别代表数码管的位选和位锁存使能引脚。
3. 定义全局变量和函数:
```c
uchar idata rdata[8]; // 用于存储接收到的数据
uchar n=0; // 接收到的数据数量
bit p=0; // 标志位,判断是否连续接收到一串数据
void delay (unsigned int t); // 延时函数
void wcmd(uchar cmd); // 写命令函数
void wdat(uchar dat); // 写数据函数
void init_1602(); // 初始化液晶显示屏
void ss()interrupt 4; // 中断服务函数
```
- `rdata` 是用于存储通过串口接收到的数据的数组。
- `n` 是记录接收到的数据数量。
- `p` 是标志位,用于判断接收到的数据是否是连续的一串数据。
- `delay` 是延时函数,用于产生一定时间的延时。
- `wcmd` 是写命令函数,用于向液晶显示屏发送命令。
- `wdat` 是写数据函数,用于向液晶显示屏发送数据。
- `init_1602` 是初始化液晶显示屏的函数。
- `ss` 是中断服务函数,在程序中被定义为串口中断函数。
4. 初始化液晶显示屏:
```c
void init_1602() {
EN=0;
wcmd(0x06); // 光标右移,不移动屏幕
delay(5);
wcmd(0x01); // 清除屏幕
delay(5);
wcmd(0x0c); // 显示开,不显示光标,不闪烁
delay(5);
wcmd(0x38); // 显示模式设置,16x2显示,8位数据接口,5x7点阵字符
delay(5);
}
```
- 初始化液晶显示屏的步骤通常为先发送一系列的命令,再发送数据。
- `wcmd` 函数用于向液晶显示屏发送命令,这里发送的命令包括光标右移、清除屏幕、显示开、显示模式设置等。
5. 主函数:
```c
main () {
uchar i;
init_1602(); // 初始化液晶显示屏
SCON=0x50; // 串口工作模式设置
PCON=0;
TR1=1; // 开启定时器1
TMOD=0x20;
TH1=0xE8;
TL1=0xE8;
EA=1; // 开启总中断
ES=1; // 开启串口中断
while(1) { // 死循环,不断更新液晶显示屏内容
wcmd(0x80); // 写入第一行
for(i=0;i<8;i++) {
wdat(rdata[i]); // 写入接收到的数据
}
}
}
```
- `SCON` 是串口控制寄存器,用于设置串口工作模式。
- `PCON` 是功率控制寄存器,这里将其设置为 0。
- `TR1` 是定时器 1 的开关控制位,这里将其设置为 1。
- `TMOD` 是定时器模式寄存器,这里设置为 0x20,代表定时器 1 工作在方式 2,即 8 位自动重装计数器模式。
- `TH1` 和 `TL1` 是定时器 1 的计数初值,这里设置为 0xE8。
- `EA` 是总中断控制位,这里将其设置为 1,开启总中断。
- `ES` 是串口中断控制位,这里将其设置为 1,开启串口中断。
- 在 `while` 循环中,先将光标定位到第一行,然后将接收到的数据写入液晶显示屏。
6. 中断服务函数:
```c
void ss()interrupt 4 {
if(RI==1) { // 判断是否接收到数据
RI=0; // 接收标志位清零
if(p==1) { // 判断是否连续接收到一串数据
rdata[n]=SBUF; // 将接收到的数据存储到数组中
n++; // 计数器加 1
if(n==8) { // 接收完一串数据
n=0; // 计数器清零
p=0; // 标志位清零
delay(20); // 延时 20 毫秒
}
}
else { // 接收到数据
if(SBUF==0x00) // 判断开始接收数据的标志
p=1; // 设置标志位,开始连续接收数据
}
}
}
```
- `ss` 是中断服务函数,在程序中被定义为串口中断函数。
- `RI` 是接收中断标志位,这里先判断是否接收到数据。
- 如果连续接收到一串数据,则将接收到的数据存储到数组中,并且计数器加 1,判断是否接收完一串数据。
- 如果没有连续接收到一串数据,则判断是否接收到开始接收数据的标志,如果接收到,则设置标志位,开始连续接收数据。
阅读全文