51单片机概述

51单片机是指Intel公司开发的MCS-51系列单片机及其兼容产品,是应用最广泛的8位单片机系列之一。其名称来源于该系列的第一款芯片8051。

主要特点:

  • 8位CPU:处理数据宽度为8位

  • 哈佛结构:程序存储器和数据存储器分开

  • 40引脚DIP封装:标准双列直插式封装

  • 4KB ROM:早期型号,现代兼容型号容量更大

  • 128B RAM:内部数据存储器

  • 32个I/O口:4个8位并行I/O端口

  • 2个16位定时器/计数器

  • 1个全双工串行通信口

  • 5个中断源:2个外部中断,2个定时器中断,1个串口中断

常见51单片机型号

型号主要特性
8051原始型号,4KB ROM,128B RAM
8031无片内ROM
89C51Atmel公司产品,Flash ROM
89S51支持ISP在线编程
STC89C52宏晶科技产品,8KB Flash,512B RAM
STC12C5A60S2增强型51,1T周期,60KB Flash,1280B RAM

51单片机内部结构

1. CPU结构

  • 算术逻辑单元(ALU):执行算术和逻辑运算

  • 累加器(ACC):主要寄存器,用于运算和数据传输

  • B寄存器:用于乘除法运算

  • 程序状态字(PSW):包含各种状态标志位

  • 程序计数器(PC):16位,指向下一条要执行的指令

2. 存储器结构

  • 程序存储器(ROM/Flash):存储程序代码

  • 内部数据存储器(RAM):128字节(52系列为256字节)

  • 特殊功能寄存器(SFR):控制各功能模块

  • 外部扩展存储器:可扩展至64KB

3. 输入输出端口

  • P0口:8位开漏双向I/O口,兼作地址/数据总线

  • P1口:8位准双向I/O口

  • P2口:8位准双向I/O口,兼作高8位地址总线

  • P3口:8位准双向I/O口,具有第二功能

51单片机最小系统

一个能工作的51单片机最小系统需要:

  1. 单片机芯片(如STC89C52)

  2. 时钟电路:通常11.0592MHz晶振+两个30pF电容

  3. 复位电路:10kΩ电阻+10μF电容构成上电复位

  4. 电源电路:5V稳定电源,加滤波电容

L298N介绍

L298N是一种双H桥电机驱动芯片,能够驱动两个直流电机或一个步进电机,广泛应用于机器人、智能小车等项目中。

主要特性

  • 工作电压:5V-35V

  • 最大电流:2A(单桥)

  • 逻辑电压:5V(兼容TTL电平)

  • 驱动方式:双H桥驱动

  • 可同时控制:2个直流电机或1个两相/四相步进电机

模块引脚说明

电源部分

  • +12V/VCC:电机驱动电源输入(5-35V)

  • GND:电源地

  • +5V:输出5V(当使能跳线帽接通时)或5V输入(当断开跳线帽时)

控制部分

  • ENA/ENB:PWM使能端(A/B通道)

  • IN1/IN2:A通道控制输入端

  • IN3/IN4:B通道控制输入端

与51单片机的连接方式

51单片机引脚连接L298N: 
- P1.0 → L298N ENA (PWM输入A) 
- P1.1 → L298N IN1 
- P1.2 → L298N IN2
- (如果需要控制第二个电机)  
- P1.3 → L298N ENB (PWM输入B)   
- P1.4 → L298N IN3   
- P1.5 → L298N IN4

电机控制逻辑

单个直流电机控制

IN1IN2ENA电机状态
00X停止
10PWM正转(PWM调速)
01PWM反转(PWM调速)
11X刹车

PWM调速原理

通过改变ENA/ENB引脚PWM信号的占空比来调节电机速度:

  • 占空比高 → 平均电压高 → 转速快

  • 占空比低 → 平均电压低 → 转速慢

典型应用电路

  1. 电源部分

    • 电机电源与单片机电源共地

    • 建议电机电源与逻辑电源分开供电

    • 大容量滤波电容靠近L298N电源引脚

  2. 保护电路

    • 电机两端并联续流二极管

    • 必要时添加散热片

proteus仿真图 

代码实现 

主函数 

#include <REGX52.H>
#include <intrins.h>
#include "LCD1602.h"
#include "public.h"
#include "stdio.h"
char war[32];sbit IN1 = P1^1;
sbit IN2 = P1^2;
sbit ENA = P1^0;  // PWM输出引脚unsigned char PWM = 0;  // PWM占空比 0-100
bit DIR = 0;            // 方向 0或1void Timer0Init()  // 100us@11.0592MHz
{TMOD &= 0xF0;  // 设置定时器模式TMOD |= 0x02;  // 8位自动重装模式TH0 = 0xA4;    // 重装值TL0 = 0xA4;    // 初始值TR0 = 1;       // 启动定时器ET0 = 1;       // 使能定时器中断EA = 1;        // 开启总中断
}void main()
{Timer0Init();LCD_Init();LCD_Clear();IN1 = 1;IN2 = 0;  // 初始方向PWM =20;	while(1){// 这里可以添加按键扫描或其他控制逻辑来改变PWM值// 例如:// if(按键加按下) PWM++;// if(按键减按下) PWM--;// if(按键方向按下) DIR = !DIR;if(P1_4 ==0){Delay_ms(100);if(P1_4 ==0) { PWM++; }}if(P1_5 ==0){Delay_ms(100);if(P1_5 ==0) { PWM--; }}if(P1_6 ==0){Delay_ms(100);if(P1_6 ==0) { DIR = !DIR; }}// 限制PWM范围if(PWM > 100) PWM = 100;if(PWM < 0) PWM = 0;// 设置方向if(DIR){IN1 = 1;IN2 = 0;}else{IN1 = 0;IN2 = 1;}sprintf(war,"PWM:%03d DIR:%d",(int)PWM,(int)DIR);LCD_ShowString(2,1,war);	}
}void Timer0_ISR() interrupt 1
{static unsigned char count = 0;count++;if(count >= 100){count = 0;}if(count < PWM){ENA = 1;  // 高电平期间电机通电}else{ENA = 0;  // 低电平期间电机断电}
}

LCD1602.c

#include <REGX52.H>//引脚配置:
//sbit LCD_RS=P1^2;
//sbit LCD_RW=P1^3;
//sbit LCD_EN=P1^4;sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0//函数定义:
/*** @brief  LCD1602延时函数,12MHz调用可延时1ms* @param  无* @retval 无*/
void LCD_Delay()
{unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);
}/*** @brief  LCD1602写命令* @param  Command 要写入的命令* @retval 无*/
void LCD_WriteCommand(unsigned char Command)
{LCD_RS=0;LCD_RW=0;LCD_DataPort=Command;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602写数据* @param  Data 要写入的数据* @retval 无*/
void LCD_WriteData(unsigned char Data)
{LCD_RS=1;LCD_RW=0;LCD_DataPort=Data;LCD_EN=1;LCD_Delay();LCD_EN=0;LCD_Delay();
}/*** @brief  LCD1602设置光标位置* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @retval 无*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{if(Line==1){LCD_WriteCommand(0x80|(Column-1));}else if(Line==2){LCD_WriteCommand(0x80|(Column-1+0x40));}
}/*** @brief  LCD1602初始化函数* @param  无* @retval 无*/
void LCD_Init()
{LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动LCD_WriteCommand(0x01);//光标复位,清屏
}void LCD_Clear()
{LCD_WriteCommand(0x01);//光标复位,清屏
}
/*** @brief  在LCD1602指定位置上显示一个字符* @param  Line 行位置,范围:1~2* @param  Column 列位置,范围:1~16* @param  Char 要显示的字符* @retval 无*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{LCD_SetCursor(Line,Column);LCD_WriteData(Char);
}/*** @brief  在LCD1602指定位置开始显示所给字符串* @param  Line 起始行位置,范围:1~2* @param  Column 起始列位置,范围:1~16* @param  String 要显示的字符串* @retval 无*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{unsigned char i;LCD_SetCursor(Line,Column);for(i=0;String[i]!='\0';i++){LCD_WriteData(String[i]);}
}///**
//  * @brief  返回值=X的Y次方
//  */
//int LCD_Pow(int X,int Y)
//{
//	unsigned char i;
//	int Result=1;
//	for(i=0;i<Y;i++)
//	{
//		Result*=X;
//	}
//	return Result;
//}///**
//  * @brief  在LCD1602指定位置开始显示所给数字
//  * @param  Line 起始行位置,范围:1~2
//  * @param  Column 起始列位置,范围:1~16
//  * @param  Number 要显示的数字,范围:0~65535
//  * @param  Length 要显示数字的长度,范围:1~5
//  * @retval 无
//  */
//void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
//{
//	unsigned char i;
//	LCD_SetCursor(Line,Column);
//	for(i=Length;i>0;i--)
//	{
//		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
//	}
//}///**
//  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
//  * @param  Line 起始行位置,范围:1~2
//  * @param  Column 起始列位置,范围:1~16
//  * @param  Number 要显示的数字,范围:-32768~32767
//  * @param  Length 要显示数字的长度,范围:1~5
//  * @retval 无
//  */
//void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
//{
//	unsigned char i;
//	unsigned int Number1;
//	LCD_SetCursor(Line,Column);
//	if(Number>=0)
//	{
//		LCD_WriteData('+');
//		Number1=Number;
//	}
//	else
//	{
//		LCD_WriteData('-');
//		Number1=-Number;
//	}
//	for(i=Length;i>0;i--)
//	{
//		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
//	}
//}///**
//  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
//  * @param  Line 起始行位置,范围:1~2
//  * @param  Column 起始列位置,范围:1~16
//  * @param  Number 要显示的数字,范围:0~0xFFFF
//  * @param  Length 要显示数字的长度,范围:1~4
//  * @retval 无
//  */
//void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
//{
//	unsigned char i,SingleNumber;
//	LCD_SetCursor(Line,Column);
//	for(i=Length;i>0;i--)
//	{
//		SingleNumber=Number/LCD_Pow(16,i-1)%16;
//		if(SingleNumber<10)
//		{
//			LCD_WriteData(SingleNumber+'0');
//		}
//		else
//		{
//			LCD_WriteData(SingleNumber-10+'A');
//		}
//	}
//}///**
//  * @brief  在LCD1602指定位置开始以二进制显示所给数字
//  * @param  Line 起始行位置,范围:1~2
//  * @param  Column 起始列位置,范围:1~16
//  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
//  * @param  Length 要显示数字的长度,范围:1~16
//  * @retval 无
//  */
//void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
//{
//	unsigned char i;
//	LCD_SetCursor(Line,Column);
//	for(i=Length;i>0;i--)
//	{
//		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
//	}
//}

lcd1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__//用户调用函数:
void LCD_Init();
void LCD_Clear();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
//void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
//void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
//void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
//void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);#endif

#ifndef _public_H
#define _public_H#include "REGX52.h"		 #define  u16 unsigned int 	//对系统默认数据类型进行重定义
#define u8 unsigned char void Delay_us(u16 ten_us);
void Delay_ms(u16 ms);#endif
#include "public.h"/*******************************************************************************
* 函 数 名       : delay_10us
* 函数功能		 : 延时函数,ten_us=1时,大约延时10us
* 输    入       : ten_us
* 输    出    	 : 无
*******************************************************************************/
void Delay_us(u16 ten_us)
{while(ten_us--);	
}/*******************************************************************************
* 函 数 名       : delay_ms
* 函数功能		 : ms延时函数,ms=1时,大约延时1ms
* 输    入       : ms:ms延时时间
* 输    出    	 : 无
*******************************************************************************/
void Delay_ms(u16 ms)
{u16 i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}

效果演示 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86212.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86212.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/86212.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

批量将exb文件转为pdf的实用工具

最近在工作中遇到了一个棘手的问题&#xff1a;需要将大量CAXA电子图板(.exb)格式的图纸文件转换为PDF格式以便于共享和查阅。手动一个个打开转换不仅效率低下&#xff0c;而且容易出错。于是&#xff0c;我决定开发一个批量转换工具来解决这个问题。 使用效果 在实际使用中&…

从C++编程入手设计模式——命令模式

从C编程入手设计模式——命令模式 ​ 命令模式是一个用指令封装请求的优雅方法。换而言之&#xff0c;对于一个复杂的系统&#xff0c;当我们发现&#xff0c;使用一系列的指令&#xff08;Command&#xff09;来操作对象的时候&#xff0c;这个设计模式就会显得非常的实用。我…

【基础篇-消息队列】——如何通过网络传输结构化的数据( 序列化与反序列化)

目录 一、引入前提二、选择哪种序列化实现2.1、选择哪种序列化实现需要权衡的几个因素2.2、如何选择哪种序列化实现三、实现高性能的序列化和反序列化四、小结本文来源:极客时间vip课程笔记 一、引入前提 在 TCP 的连接上,它传输数据的基本形式就是二进制流,也就是一段一段的…

LINUX 622 SAMBA

SAMBA案例 user01通过wondows或linux在/samba/share 中创建、删除文件 环境配置 samba安装 [rootsamba caozx26]# yum install samba -y 已加载插件&#xff1a;fastestmirror, langpacks Loading mirror speeds from cached hostfile 正在解决依赖关系 --> 正在检查事务…

Linux Sonic Agent 端部署(详细版)(腾讯云)

&#xff08;因为服务器是Linux的&#xff0c;只是安装了&#xff0c;并没有验证&#xff09; 1、编辑docker-compose.yml文件 在Services下添加Agent sonic-agent:image: "sonicorg/sonic-agent-linux:v2.7.2"environment:- SONIC_SERVER_HOST${SONIC_SERVER_HOST…

SpringCloud学习笔记 - 2、关于Cloud各种组件的停更/升级/替换

文章目录 前言SpringCloud是什么&#xff1f;SpringCloud 在 2018 年&#xff0c;技术体系SpringCloud 在 2020 年&#xff0c;“移除”了技术体系SpringCloud 在 2024 年&#xff0c;移除了技术体系SpringCloud 2024年&#xff0c;技术体系服务注册与发现 模块1、Eureka2、Con…

全面掌握 Nginx的功能和使用方法

从 C10K 到现代云原生 第一章 稀缺性哲学与 C10K 挑战 Nginx 的诞生并非偶然&#xff0c;它是在特定历史背景下&#xff0c;对一个严峻工程危机的直接而革命性的回应。要真正理解 Nginx 的设计精髓&#xff0c;我们必须回到 20 世纪末&#xff0c;探究那个催生了它的时代性难题…

[Linux] Vim编辑器 Linux输入输出重定向

Vim编辑器 Vim模式 command模式&#xff1a;该模式下键盘中的字母有特殊含义。如&#xff1a;G是跳转到最后一行&#xff1b;gg是跳转到第一行。 edit模式&#xff1a;在command模式下按i进入该模式。在该模式可以输入内容。在该模式下按esc返回command模式。 extended com…

用Rust写平衡三进制乘法器

1、平衡三进制乘法表 前面写了平衡三进制的加法器&#xff0c;这个乘法器是在这基础上的&#xff0c;没看过的可以回去看看&#xff0c;说到乘法器还是要参考前苏联的资料的&#xff0c;平衡三进制的乘法也是很方便的&#xff0c;在平衡三进制基础中有详细讲过&#xff0c;下图…

解决Vue2官网Webpack源码泄露漏洞

一&#xff1a;漏洞产生 Webpack是一个JavaScript应用程序的静态资源打包器。大部分Vue等应用项目会使用Webpack进行打包&#xff0c;如果没有正确配置&#xff0c;就会导致项目源码泄露&#xff0c;可能泄露的各种信息如API、加密算法、管理员邮箱、内部功能等等。 F12查看源…

新中国风通用读书颂词分享PPT模版

新国风PPT模版&#xff0c;古风影视剧PPT模版&#xff0c;天青色中国风读书颂词分享会PPT模版&#xff0c;国风通用PPT模版&#xff0c;茶味PPT模版&#xff0c;风雪夜归人PPT模版&#xff0c;小别离PPT模版&#xff0c;西江月茶词PPT模版 新中国风通用读书颂词分享PPT模版&…

Rust自动化测试的框架

Rust实现Web自动化测试的框架 以下是10个使用Rust实现Web自动化测试的框架示例,涵盖不同场景和工具链: 使用thirtyfour(基于Selenium) use thirtyfour::prelude::*;async fn example_selenium() -> WebDriverResult<()> {let caps = DesiredCapabilities::chro…

MySQL性能测试模板

引言&#xff1a;为什么MySQL性能测试如此重要&#xff1f; 你是否遇到过这些问题&#xff1a; 线上数据库突然卡顿&#xff0c;QPS暴跌&#xff1f;业务高峰期MySQL服务器CPU 100%&#xff0c;却找不到瓶颈&#xff1f;新功能上线后&#xff0c;数据库性能不升反降&#xff…

第八课:大白话教你逻辑回归

这节课咱们来聊聊 逻辑回归(Logistic Regression),别看名字里有“回归”,它其实是用来干 分类 的活儿的!我会用最接地气的方式,从定义讲到实战,保证你笑着学会,还能拿去忽悠朋友! 一:逻辑回归是啥?——当回归想不开,转行搞分类 1.1 定义:逻辑回归是个“概率算命…

项目中后端如何处理异常?

为了统一管理异常&#xff0c;在项目中封装了自定义异常类(BusinessException),全局异常处理器(GlobalExceptionHandler), 以及一些状态码(ErrorCode), 便于前端统一处理异常. 主要流程如下: 当项目业务发生逻辑错误时,会抛出BusinessException, 其中包含自定义错误码和信息.…

群晖 NAS Docker 镜像加速配置详细教程

通过为群晖NAS的Docker配置镜像仓库加速服务&#xff0c;可显著提升镜像拉取速度与稳定性。本指南详细介绍使用毫秒镜像 (1ms.run) 服务的配置步骤及日常使用方法。 一、配置前准备 开始配置前&#xff0c;推荐使用毫秒镜像的免登录方式获取镜像仓库地址。相比传统的账号密码…

Deepoc行业垂直大模型作为行业知识与AI深度融合的专用工具

一、​​行业专用智能诊断与预测性维护​​ ​​设备健康管理​​ ​​多源异构数据融合​​&#xff1a;垂直大模型通过时序对齐算法&#xff08;如动态时间规整DTW&#xff09;整合振动&#xff08;5kHz&#xff09;、温度&#xff08;1Hz&#xff09;、电流等多维度传感器数…

内存泄漏系列专题分析之二十五:内存泄漏测试report Camera相机进程各种内存指标dump方式

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:内存泄漏系列专题分析之二十四:内存泄漏测试Camera相机进程内存指标分布report概述 这一篇我们开始讲: 内存泄漏系列专题分析之二十五:内存泄漏测试report Camera相机进程各种内存指标dump方式 目录 一、问…

mysql 加锁算法 详解

锁 锁分类 从锁的操作划分 共享锁和排他锁 共享锁&#xff08;读锁&#xff09;和排他锁&#xff08;写锁&#xff09;。对于更新语句&#xff0c;InnoDB会自动加上排他锁&#xff1b;对于查询语句&#xff0c;如果是快照读&#xff0c;由于MVCC的存在&#xff0c;InnoDB不会…

使用EasyExcel导出带下拉框选项excel模板

使用EasyExcel导出excel模版&#xff0c;表头字段动态生成下拉框选择&#xff0c;并且阻止输入不符合下拉框选项的值&#xff0c;会在表格进行提示。 为了避免excel下拉框选项过多&#xff0c;导致下拉框内容不显示&#xff0c;新建一个sheet页&#xff0c;将下拉框内容存储在…