【单片机语言C51程序设计入门指南】:零基础入门,轻松掌握C51编程
发布时间: 2024-07-07 16:23:10 阅读量: 184 订阅数: 36
(175797816)华南理工大学信号与系统Signal and Systems期末考试试卷及答案
![【单片机语言C51程序设计入门指南】:零基础入门,轻松掌握C51编程](https://img-blog.csdnimg.cn/8ab760fd5b2e4a85b78e7be15a1906ff.png)
# 1. 单片机C51语言简介
单片机C51语言是一种专为8051系列单片机设计的汇编语言。它是一种低级语言,直接操作单片机的寄存器和内存,具有执行效率高、代码体积小等优点。C51语言广泛应用于嵌入式系统开发,如工业控制、仪器仪表、消费电子等领域。
C51语言采用模块化结构,由指令集、伪指令和宏组成。指令集定义了单片机可以执行的基本操作,伪指令用于控制程序的编译和链接,宏用于简化代码编写。C51语言还提供了丰富的库函数,方便开发者调用常用的功能。
# 2. C51语言基础语法
### 2.1 数据类型和变量
#### 2.1.1 数据类型
C51语言支持多种数据类型,用于表示不同范围和类型的数值。主要数据类型包括:
- **整数类型:**`char`(8位有符号整数)、`int`(16位有符号整数)、`long`(32位有符号整数)
- **浮点类型:**`float`(32位浮点数)、`double`(64位浮点数)
- **布尔类型:**`bit`(1位布尔值)
- **字符类型:**`char`(8位字符)
#### 2.1.2 变量定义和赋值
变量用于存储数据,在使用前需要定义其类型和名称。变量定义的语法如下:
```c
<数据类型> <变量名>;
```
例如:
```c
int num;
char ch;
```
变量赋值是将值存储到变量中,语法如下:
```c
<变量名> = <值>;
```
例如:
```c
num = 10;
ch = 'a';
```
### 2.2 运算符和表达式
#### 2.2.1 算术运算符
算术运算符用于执行算术运算,包括加法(+)、减法(-)、乘法(*)、除法(/)和取余(%)。
| 运算符 | 描述 |
|---|---|
| + | 加法 |
| - | 减法 |
| * | 乘法 |
| / | 除法 |
| % | 取余 |
#### 2.2.2 关系运算符
关系运算符用于比较两个值,返回一个布尔值(真或假)。
| 运算符 | 描述 |
|---|---|
| == | 等于 |
| != | 不等于 |
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
### 2.3 流程控制语句
#### 2.3.1 条件语句
条件语句用于根据条件执行不同的代码块。C51语言支持以下条件语句:
- **if语句:**如果条件为真,执行代码块。
- **if-else语句:**如果条件为真,执行第一个代码块;否则,执行第二个代码块。
- **switch-case语句:**根据变量的值执行不同的代码块。
#### 2.3.2 循环语句
循环语句用于重复执行代码块。C51语言支持以下循环语句:
- **for循环:**重复执行代码块,直到满足指定的条件。
- **while循环:**重复执行代码块,只要条件为真。
- **do-while循环:**先执行代码块,然后再检查条件。
# 3.1 函数和数组
#### 3.1.1 函数定义和调用
**函数定义**
在 C51 中,函数定义使用以下语法:
```c
returnType functionName(parameterList) {
// 函数体
}
```
其中:
* `returnType`:函数的返回值类型,可以是 `void`(无返回值)或其他数据类型。
* `functionName`:函数的名称。
* `parameterList`:函数的参数列表,可以为空。
**函数调用**
要调用函数,只需使用其名称并传递适当的参数即可:
```c
functionName(arguments);
```
其中:
* `arguments`:传递给函数的参数列表。
**示例**
以下代码定义了一个计算两个数之和的函数:
```c
int sum(int a, int b) {
return a + b;
}
```
要调用此函数,可以使用以下代码:
```c
int result = sum(10, 20);
```
#### 3.1.2 数组定义和使用
**数组定义**
在 C51 中,数组使用以下语法定义:
```c
dataType arrayName[size];
```
其中:
* `dataType`:数组元素的数据类型。
* `arrayName`:数组的名称。
* `size`:数组的大小(元素数)。
**数组使用**
要访问数组元素,可以使用以下语法:
```c
arrayName[index]
```
其中:
* `index`:数组索引(从 0 开始)。
**示例**
以下代码定义了一个包含 5 个整数元素的数组:
```c
int numbers[5];
```
要访问数组的第一个元素,可以使用以下代码:
```c
int firstNumber = numbers[0];
```
### 3.2 指针和结构体
#### 3.2.1 指针概念和操作
**指针概念**
指针是一个变量,它存储另一个变量的地址。通过指针,可以间接访问该变量。
**指针操作**
C51 中的指针操作符有:
* `&`:取地址运算符,返回变量的地址。
* `*`:解引用运算符,返回指针指向的变量的值。
**示例**
以下代码定义了一个指向整数变量 `number` 的指针:
```c
int *ptr = &number;
```
要访问 `number` 变量的值,可以使用以下代码:
```c
int value = *ptr;
```
#### 3.2.2 结构体定义和使用
**结构体定义**
结构体是一种复合数据类型,它可以包含不同类型的数据成员。
**结构体定义**
在 C51 中,结构体使用以下语法定义:
```c
struct structName {
memberType memberName;
// 其他成员
};
```
其中:
* `structName`:结构体的名称。
* `memberType`:成员的数据类型。
* `memberName`:成员的名称。
**结构体使用**
要访问结构体的成员,可以使用以下语法:
```c
structName.memberName
```
其中:
* `structName`:结构体的名称。
* `memberName`:成员的名称。
**示例**
以下代码定义了一个包含姓名和年龄两个成员的结构体:
```c
struct person {
char name[20];
int age;
};
```
要访问结构体的 `name` 成员,可以使用以下代码:
```c
char *name = person.name;
```
### 3.3 中断和定时器
#### 3.3.1 中断概念和类型
**中断概念**
中断是一种硬件机制,它允许外围设备在发生特定事件时暂停正在执行的程序。
**中断类型**
C51 支持以下中断类型:
* 外部中断
* 定时器中断
* 串口中断
#### 3.3.2 定时器配置和使用
**定时器配置**
在 C51 中,定时器使用以下寄存器进行配置:
* `TMOD`:定时器模式寄存器
* `TL0`:定时器 0 低字节寄存器
* `TH0`:定时器 0 高字节寄存器
**定时器使用**
要使用定时器,需要执行以下步骤:
1. 配置定时器模式(`TMOD` 寄存器)。
2. 设置定时器初值(`TL0` 和 `TH0` 寄存器)。
3. 启用定时器中断(`IE` 寄存器)。
**示例**
以下代码配置定时器 0 为 16 位自动重装模式:
```c
TMOD |= 0x01;
```
以下代码设置定时器 0 的初值为 65535:
```c
TL0 = 0xFF;
TH0 = 0xFF;
```
以下代码启用定时器 0 中断:
```c
IE |= 0x82;
```
# 4. C51语言实践应用
### 4.1 LED灯控制
#### 4.1.1 I/O口配置
**代码块:**
```c
#define P1 0x90
#define P2 0xA0
void main()
{
P1 = 0xFF; // 设置P1口为输出
P2 = 0x00; // 设置P2口为输入
}
```
**逻辑分析:**
- `P1` 和 `P2` 分别是 8051 单片机上的两个 I/O 口。
- `P1 = 0xFF` 表示将 P1 口的所有位设置为高电平(1),将其配置为输出口。
- `P2 = 0x00` 表示将 P2 口的所有位设置为低电平(0),将其配置为输入口。
#### 4.1.2 LED灯控制程序
**代码块:**
```c
#define LED_PORT P1
#define LED_PIN 0
void main()
{
LED_PORT &= ~(1 << LED_PIN); // 打开LED灯
delay(1000); // 延时1秒
LED_PORT |= (1 << LED_PIN); // 关闭LED灯
delay(1000); // 延时1秒
}
```
**逻辑分析:**
- `LED_PORT` 和 `LED_PIN` 分别表示 LED 灯连接的 I/O 口和引脚。
- `LED_PORT &= ~(1 << LED_PIN)` 表示将 LED 灯引脚对应的位清零,打开 LED 灯。
- `delay(1000)` 表示延时 1 秒。
- `LED_PORT |= (1 << LED_PIN)` 表示将 LED 灯引脚对应的位置 1,关闭 LED 灯。
### 4.2 键盘输入
#### 4.2.1 键盘扫描原理
键盘扫描原理是通过轮询的方式,依次检测每个按键是否被按下。具体步骤如下:
1. 设置键盘接口引脚为输入模式。
2. 将所有键盘行引脚置为高电平。
3. 依次将每列引脚置为低电平。
4. 检测每行引脚是否为低电平,如果为低电平,则表示该行对应的按键被按下。
5. 重复步骤 3 和步骤 4,直到扫描完所有列。
#### 4.2.2 键盘输入程序
**代码块:**
```c
#define KEY_PORT P2
#define KEY_ROW 4
#define KEY_COL 4
char key_scan()
{
unsigned char row, col;
for (row = 0; row < KEY_ROW; row++)
{
KEY_PORT |= (1 << row); // 将该行置为高电平
for (col = 0; col < KEY_COL; col++)
{
if (!(KEY_PORT & (1 << (col + 4)))) // 检测该列是否为低电平
{
return (row * KEY_COL + col); // 返回按键值
}
}
KEY_PORT &= ~(1 << row); // 将该行置为低电平
}
return 0; // 没有按键被按下
}
```
**逻辑分析:**
- `KEY_PORT`、`KEY_ROW` 和 `KEY_COL` 分别表示键盘接口引脚、行数和列数。
- `key_scan()` 函数用于扫描键盘,并返回被按下的按键值。
- 循环嵌套用于扫描每一行和每一列,检测按键是否被按下。
- 如果检测到按键被按下,则返回按键值。
- 如果没有按键被按下,则返回 0。
### 4.3 串口通信
#### 4.3.1 串口配置
**代码块:**
```c
#define SBUF 0x99
#define SCON 0x98
#define PCON 0x87
void serial_init()
{
PCON |= 0x80; // 开启串口时钟
SCON = 0x50; // 设置串口模式为 8 位数据位、1 位停止位、无校验
TMOD |= 0x20; // 设置定时器 1 为串口模式
TH1 = 0xFD; // 设置波特率为 9600
}
```
**逻辑分析:**
- `SBUF`、`SCON` 和 `PCON` 分别是串口数据寄存器、串口控制寄存器和时钟控制寄存器。
- `serial_init()` 函数用于初始化串口。
- `PCON |= 0x80` 表示开启串口时钟。
- `SCON = 0x50` 表示设置串口模式为 8 位数据位、1 位停止位、无校验。
- `TMOD |= 0x20` 表示设置定时器 1 为串口模式。
- `TH1 = 0xFD` 表示设置波特率为 9600。
#### 4.3.2 串口通信程序
**代码块:**
```c
void serial_send(char data)
{
while (!(SCON & 0x02)); // 等待发送缓冲区为空
SBUF = data; // 将数据写入发送缓冲区
}
char serial_recv()
{
while (!(SCON & 0x01)); // 等待接收缓冲区有数据
return SBUF; // 读取接收缓冲区中的数据
}
```
**逻辑分析:**
- `serial_send()` 函数用于发送数据。
- `while (!(SCON & 0x02))` 表示等待发送缓冲区为空。
- `SBUF = data` 表示将数据写入发送缓冲区。
- `serial_recv()` 函数用于接收数据。
- `while (!(SCON & 0x01))` 表示等待接收缓冲区有数据。
- `return SBUF` 表示读取接收缓冲区中的数据。
# 5. C51语言项目实战
### 5.1 数字时钟
#### 5.1.1 时钟显示原理
数字时钟的显示原理相对简单,主要通过定时器中断来更新时间。C51单片机具有多个定时器,其中定时器0(T0)常用于时钟显示。T0是一个8位定时器,其时钟源可以是内部时钟或外部晶振。
当T0作为时钟源时,其计数频率为:
```
F_T0 = F_osc / 12
```
其中:
* `F_T0` 为 T0 的计数频率
* `F_osc` 为单片机的时钟频率
通过设置 T0 的重装载值,可以控制 T0 的中断周期。当 T0 计数到重装载值时,会产生一个中断,从而更新时间显示。
#### 5.1.2 数字时钟程序
```c
#include <reg51.h>
unsigned char hour, minute, second;
void main() {
TMOD = 0x01; // 设置 T0 为模式 1
TH0 = 0xFF; // 设置 T0 重装载值为 255
TL0 = 0x00; // 设置 T0 初始值为 0
TR0 = 1; // 启动 T0
while (1) {
if (TF0 == 1) { // T0 中断标志位为 1
TF0 = 0; // 清除 T0 中断标志位
second++; // 秒数加 1
if (second == 60) { // 秒数达到 60
second = 0; // 秒数归零
minute++; // 分钟数加 1
if (minute == 60) { // 分钟数达到 60
minute = 0; // 分钟数归零
hour++; // 小时数加 1
if (hour == 24) { // 小时数达到 24
hour = 0; // 小时数归零
}
}
}
// 更新时间显示
}
}
}
```
**代码逻辑分析:**
1. 设置 T0 为模式 1,即 16 位定时器模式。
2. 设置 T0 的重装载值为 255,即 T0 的计数频率为 1MHz/12 = 83333Hz。
3. 设置 T0 的初始值为 0。
4. 启动 T0。
5. 在主循环中,当 T0 中断标志位为 1 时,执行中断处理程序。
6. 在中断处理程序中,清除 T0 中断标志位,并更新时间。
7. 更新时间显示。
### 5.2 温湿度监测
#### 5.2.1 传感器接口
温湿度监测需要使用温湿度传感器,如 DHT11 或 DHT22。这些传感器通过 I2C 或单总线与单片机通信。
**I2C 接口:**
```c
#include <reg51.h>
#include <i2c.h>
void main() {
I2C_Init(); // 初始化 I2C 接口
while (1) {
// 读取温湿度数据
}
}
```
**单总线接口:**
```c
#include <reg51.h>
#include <onewire.h>
void main() {
OneWire_Init(); // 初始化单总线接口
while (1) {
// 读取温湿度数据
}
}
```
#### 5.2.2 温湿度监测程序
```c
#include <reg51.h>
#include <i2c.h>
#include <dht11.h>
unsigned char temperature, humidity;
void main() {
I2C_Init(); // 初始化 I2C 接口
while (1) {
DHT11_ReadData(&temperature, &humidity); // 读取温湿度数据
// 显示温湿度数据
}
}
```
**代码逻辑分析:**
1. 初始化 I2C 接口。
2. 在主循环中,调用 `DHT11_ReadData()` 函数读取温湿度数据。
3. 显示温湿度数据。
### 5.3 电机控制
#### 5.3.1 电机驱动原理
电机控制需要使用电机驱动器,如 L298N 或 TB6612。这些电机驱动器通过 PWM 信号控制电机的转速和方向。
**PWM 信号:**
```c
#include <reg51.h>
#include <pwm.h>
void main() {
PWM_Init(); // 初始化 PWM
while (1) {
// 设置 PWM 占空比
}
}
```
#### 5.3.2 电机控制程序
```c
#include <reg51.h>
#include <pwm.h>
#include <motor.h>
void main() {
Motor_Init(); // 初始化电机
while (1) {
// 设置电机转速和方向
}
}
```
**代码逻辑分析:**
1. 初始化电机。
2. 在主循环中,设置电机转速和方向。
# 6.1 嵌入式操作系统
### 6.1.1 嵌入式操作系统简介
嵌入式操作系统(RTOS)是一种专门为嵌入式系统设计的操作系统。嵌入式系统通常具有资源受限、实时性要求高的特点,因此需要专门的操作系统来满足其特殊需求。
RTOS通常提供以下功能:
- **任务管理:**创建、调度和同步任务。
- **内存管理:**管理系统中的内存资源。
- **设备驱动:**为硬件设备提供接口。
- **通信:**支持任务之间的通信和与外部设备的通信。
- **实时性:**确保系统能够及时响应事件。
### 6.1.2 嵌入式操作系统应用
RTOS广泛应用于各种嵌入式系统中,包括:
- **工业自动化:**PLC、DCS等。
- **消费电子:**智能手机、平板电脑等。
- **汽车电子:**发动机控制、仪表盘等。
- **医疗器械:**监护仪、呼吸机等。
- **网络设备:**路由器、交换机等。
0
0