您的位置:首页 > 汽车 > 时评 > 辉煌电商seo_展厅设计理念和设计构思_中国十大广告公司排行榜_企业培训的目的和意义

辉煌电商seo_展厅设计理念和设计构思_中国十大广告公司排行榜_企业培训的目的和意义

2024/12/23 10:53:51 来源:https://blog.csdn.net/weixin_43364551/article/details/143914436  浏览:    关键词:辉煌电商seo_展厅设计理念和设计构思_中国十大广告公司排行榜_企业培训的目的和意义
辉煌电商seo_展厅设计理念和设计构思_中国十大广告公司排行榜_企业培训的目的和意义

文章目录

  • 参考资料
  • 1. 准备工作
    • 1.1 win10配置51单片机开发环境
    • 1.1 Ubuntu配置51单片机开发环境
      • 问题1:`mcs51/8051.h`依赖于`mcs51/lint.h`
      • 问题2:提示找不到头文件`mcs51/8051.h`
  • 2. 认识51单片机
    • 2.1 STC89C52RC单片机
    • 2.2 管脚图
    • 2.3 原理图
    • 2.4 按键抖动
    • 2.5 头文件说明
    • 2.6 模块化函数
      • 2.6.1 延时函数
      • 2.6.2 矩阵键盘
  • 3. LED模块
    • 3.1 原理图
    • 实验1:点亮LED灯D1
    • 实验2:LED灯D8闪烁
    • 实验3:LED流水灯
  • 4. 独立按键模块
    • 4.1 原理图
    • 实验1:独立按键控制LED灯D1
  • 5. 动态数码管模块
    • 5.1 原理图
    • 实验1:数码管LED3显示2
    • 实验2:数码管LED8 ~ LED1分别显示0 ~ 8
  • 6. LCD1602接口
    • 6.1 原理图
  • 7. 矩阵按键模块
    • 7.1 原理图
    • 实验1:在LCD1602显示按下的键码(1 ~ 16)
    • 实验2:4位密码锁
  • 8. 定时器与中断
    • 8.1 原理图
    • 实验1:实现一个电子时钟
  • 9. 串口通信
    • 9.1 原理图
    • 实验1:每隔一秒发送一个数据,并且将接收字节保存到P2,控制LED灯

参考资料

51单片机入门教程-2020版 程序全程纯手打 从零开始入门
江协科技资料下载
51单片机(STC89C52RC)系统性学习笔记

1. 准备工作

1.1 win10配置51单片机开发环境

  1. 51单片机
正在重新握手 ... 成功			[0.578"]
当前的波特率: 115200
正在擦除目标区域 ... 完成 !		[0.328"]
正在下载用户代码 ... 完成 !		[0.141"]
正在设置硬件选项 ... 完成 !		[0.031"]更新后的硬件选项为:. 当前的时钟频率: 11.088MHz. 系统频率为12T(单倍速)模式. 振荡器的放大增益不降低. 当看门狗启动后,任何复位都可停止看门狗. MCU内部的扩展RAM可用. ALE脚的功能选择仍然为ALE功能脚. P1.0和P1.1与下次下载无关. 下次下载用户程序时,不擦除用户EEPROM区单片机型号: STC89C52RC/LE52RC固件版本号: 6.6.4C
  1. 编程工具 Keil5 C51 新建项目时选择AT89C51RC2

  2. 将程序载入到51单片机的工具 STC-ISP
    在这里插入图片描述

  3. 51单片机接入电脑,并配置驱动CH340_CH341
    在这里插入图片描述

1.1 Ubuntu配置51单片机开发环境

  1. 编辑器 VS Code 安装教程
  2. 安装VS Code插件 C/C++ Extension Pack
  3. 安装编译工具 sudo apt-get install sdcc
  4. 程序编译
    sdcc 1_LED_1.c
    将编译生成的文件输出到out目录,需要先通过sudo mkdir out创建out目录
    sdcc 1_LED_1.c -o out/

问题1:mcs51/8051.h依赖于mcs51/lint.h

#include <mcs51/lint.h>
#include <mcs51/8051.h>

问题2:提示找不到头文件mcs51/8051.h

在这里插入图片描述
8051.h是安装sdcc后产生的,请先确保sdcc已经安装,sudo find / -name 8051.h搜索一下头文件8051.h所在的目录
在这里插入图片描述
这里目录是/usr/share/sdcc/include,将该路径配置到includepath,先点击Quick Fix
在这里插入图片描述
再点击Edit “includePath” setting
在这里插入图片描述

添加/usr/share/sdcc/includeInclude path
在这里插入图片描述

2. 认识51单片机

2.1 STC89C52RC单片机

  • 所属系列:51单片机系列
  • 公司:STC公司
  • 位数:8位
  • RAM:512字节
  • ROM:4K(Flash)
  • 工作频率:11.088MHz(本开发板使用)

2.2 管脚图

在这里插入图片描述

2.3 原理图

在这里插入图片描述
高清PDF可从这里下载江协科技资料下载

2.4 按键抖动

对于机械开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。
在这里插入图片描述
因此,需要进行防抖处理,如下:

// 这是一个检测独立按键K1是否按下,并控制LED模块的简化代码
if(P3_1==0)			// 如果K1按键按下,P3_1的值会变为0
{Delay(20);		// 延时20毫秒消抖while(P3_1==0);	// 死循环空转,直到K1按键松开,P3_1变为1,跳出循环Delay(20);		// 延时20毫秒消抖P2_0=~P2_0;		// LED1的亮灭情况
}

2.5 头文件说明

#include <mcs51/lint.h>
#include <mcs51/8051.h>
#include <REGX52.H>

2.6 模块化函数

2.6.1 延时函数

#ifndef __DELAY_H__
#define __DELAY_H__void Delayms(unsigned int k);#endif
#include <INTRINS.H>// 延时k ms
void Delayms(unsigned int k)		//@11.0592MHz
{unsigned char i, j;while (k --) {_nop_();i = 2;j = 199;do{while (--j);} while (--i);}
}

2.6.2 矩阵键盘

#ifndef __MATRIXKEYBOARD_H__
#define __MATRIXKEYBOARD_H__unsigned int matrixKeyboard();#endif
#include <at89c51RC2.h>
#include "Delay.h"
// 反回键码(1 ~ 16),行优先遍历
// 按列扫描矩阵键盘
// 如果按行的话,P1_5和蜂鸣器冲突,会导致其发声
unsigned int matrixKeyboard() {unsigned int keyNum = 0;P1 = 0xFF;P1_3 = 0; // 第一列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 1;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 5;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 9;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 13;}P1 = 0xFF;P1_2 = 0; // 第二列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 2;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 6;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 10;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 14;}P1 = 0xFF;P1_1 = 0; // 第三列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 3;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 7;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 11;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 15;}P1 = 0xFF;P1_0 = 0; // 第四列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 4;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 8;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 12;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 16;}return keyNum;
}

3. LED模块

3.1 原理图

在这里插入图片描述
LED等的左侧接入VCC正极,若要使灯亮,则右侧需要接入负极,也就是对应的寄存器位需要赋值为0。

实验1:点亮LED灯D1

#include <AT89C51RC2.h>
/*** 点亮LED灯D1
*/
void main() {P2 = 0xFF; // 将所有灯熄灭P2_0 = 0; // D1灯亮起while (1); // 程序始终保持运行
}

实验2:LED灯D8闪烁

#include <AT89C51RC2.h>
#include <INTRINS.H>/*** LED灯D8闪烁
*/
void main() {P2 = 0xFF; while (1){P2_7 = 0; // D8灯亮Delayms(1000); // 延迟1000ms = 1sP2_7 = 1; // D8灯灭Delayms(1000); // 延迟1000ms = 1s} 
}

实验3:LED流水灯

#include <AT89C51RC2.h>
#include "Delay.h"/*** LED灯D1 ~ D8按顺序点亮,每次只有一个灯亮
*/
void main() {// 1111 1110// 1111 1101// 1111 1011// ...// 1111 1110// =》 其实就是实现循环左移P2 = 0xFE;while (1){P2 <<= 1;if (P2 != 0xFE) P2 |= 0x01;Delayms(1000); // 延迟1000ms = 1s} 
}

4. 独立按键模块

4.1 原理图

在这里插入图片描述

实验1:独立按键控制LED灯D1

#include <AT89C51RC2.h>
#include "Delay.h"/*** 独立按键K1控制LED灯D1* 按下按键并松开后,变换灯D1的状态
*/
void main() {while (1){// 注意控制K1的是P3_1,控制K2的是P3_0// 当值为0是代表按键按下if (P3_1 == 0) {Delay(20); // 消除按键抖动while (P3_1 == 0); // 一直保持按下的状态则卡在这Delay(20); // 消除按键抖动P2_0 = ~P2_0; // 状态取反}} 
}

5. 动态数码管模块

5.1 原理图

在这里插入图片描述在这里插入图片描述
LED1 ~ LED8的亮灭(位选)由P24, P23, P22三位决定,P24位高位,当这三个位表示数据n时,Yn对应的灯亮,Y0对应LED1
P0_0 ~ P0_6分别控制a ~ g晶体管,P0_7控制dp晶体管,为1代表选中。(P0_7是最高位,P0_0是最低位)

实验1:数码管LED3显示2

#include <AT89C51RC2.h>/*** 数码管LED3显示2
*/
void main() {// 选中数码管LED3,对应Y2  P2_4 P2_3 P2_2 = 0 1 0P2_4 = 0;P2_3 = 1;P2_2 = 0;// a b c d e f g dp// 0 1 2 3 4 5 6 7// a b c d e f g dp// 1 1 0 1 1 0 1 0 => 0101 1011 = 0x5B// 数字2,需要点亮 a b g e dP0 = 0x5B;while (1);
}

实验2:数码管LED8 ~ LED1分别显示0 ~ 8

// 对应数字 0 ~ 9 的段码
unsigned char NixieTable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
// 在LED-loc 显示num
void Nixie(unsigned char loc, unsigned char num) { P2_4 = 0; P2_3 = 0; P2_2 = 0; // 1110 0011 = 0xE3 P2 &= 0xE3if ((loc & 0x01) == 1) P2_2 = 1;if ((loc & 0x02) == 2) P2_3 = 1;if ((loc & 0x04) == 4) P2_4 = 1;P0 = NixieTable[num];// 消影,数字清零,防止上一个位置的数字显示到下一个位置Delayms(1);P0 = 0x00;
}/*** 数码管LED8 ~ LED1分别显示0 ~ 8
**/
void main() {unsigned char i;while (1) {for (i = 0; i <= 7; i ++) {Nixie(7 - i, i);}}
}

6. LCD1602接口

6.1 原理图

在这里插入图片描述

7. 矩阵按键模块

7.1 原理图

在这里插入图片描述

实验1:在LCD1602显示按下的键码(1 ~ 16)

#include <at89c51RC2.h>
#include "Delay.h"
// 反回键码(1 ~ 16),行优先遍历
// 没有按下任何键则返回0
// 按列扫描矩阵键盘
// 如果按行的话,P1_5和蜂鸣器冲突,会导致其发声
unsigned int matrixKeyboard() {unsigned int keyNum = 0;P1 = 0xFF;P1_3 = 0; // 第一列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 1;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 5;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 9;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 13;}P1 = 0xFF;P1_2 = 0; // 第二列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 2;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 6;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 10;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 14;}P1 = 0xFF;P1_1 = 0; // 第三列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 3;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 7;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 11;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 15;}P1 = 0xFF;P1_0 = 0; // 第四列if (P1_7 == 0) {Delayms(20); while (P1_7 == 0); Delayms(20); keyNum = 4;}if (P1_6 == 0) {Delayms(20); while (P1_6 == 0); Delayms(20); keyNum = 8;}if (P1_5 == 0) {Delayms(20); while (P1_5 == 0); Delayms(20); keyNum = 12;}if (P1_4 == 0) {Delayms(20); while (P1_4 == 0); Delayms(20); keyNum = 16;}return keyNum;
}// 在LCD1602显示按下的键码(1 ~ 16)
void main() {unsigned int num = 0, newNum = 0;LCD_Init();while (1) {newNum = matrixKeyboard();if (newNum != 0) {num = newNum;}LCD_ShowNum(1, 1, num, 2); // 第一行第一列显示,占两个位置}
}

实验2:4位密码锁

// 10为0,11为确认,12为清空
void main() {// num,保存当前输入的密码// keyNum,记录矩阵键盘按下的键码// count,记录当前已经输入多少个数字unsigned int num = 0, keyNum = 0, count = 0;// LCD1602初始化LCD_Init();// 在第一行的前9个输入固定显示输入提示符LCD_ShowString(1, 1, "PASSWORD:");while (1) {// 第10个字符显示当前输入的密码LCD_ShowNum(1, 10, num, 4);// 获取当前矩阵键盘的键码(没有按下任何键则返回0)keyNum = matrixKeyboard();if (keyNum >= 1 && keyNum <= 9 && count < 4) {num = num * 10 + keyNum;count ++;} else if (keyNum == 11 && count == 4) {if (num == 1234) {LCD_ShowString(2, 1, "OK");} else {LCD_ShowString(2, 1, "ERR");}} else if (keyNum == 12) {num = 0;count = 0;LCD_ShowString(2, 1, "   ");}}
}

8. 定时器与中断

定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成
定时器作用︰
(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作
(2)替代长时间的Delay,提高CPU的运行效率和处理速度(…)

8.1 原理图

在这里插入图片描述

TL0和TH0发生溢出时(达到65535),TF0标志位被置位1,从而引发中断。

  1. 生成定时器初始化代码
    在这里插入图片描述
void Timer0Init(void)		//1毫秒@11.0592MHz
{AUXR &= 0x7F;		//定时器时钟12T模式TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0x66;		//设置定时初值TH0 = 0xFC;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时// 这两个开关配置需要自己加一下ET0 = 1; // 打开定时器0EA = 1; // 打开总开关
}

实验1:实现一个电子时钟

void Timer0Init()		//1毫秒@11.0592MHz
{AUXR &= 0x7F;		//定时器时钟12T模式TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0x66;		//设置定时初值 TH0 = 0xFC;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时ET0 = 1; // 打开定时器0EA = 1; // 打开总开关
}unsigned int count = 0;
// 设置时钟为 23:59:45 方便调试
unsigned int second = 45;
unsigned int minute = 59;
unsigned int hour = 23;void main() {
//	// TMOD不可位寻址, M0给1 => 0x01
//	// TMOD = 0x01; // 配置定时器0
//	// 防止对定时器1的配置产生影响,使用与或赋值法
//	TMOD &= 0xF0; // 清空定时器0的配置
//	TMOD |= 0x01; // 配置定时器0
//	
//	// TCON可位寻址,TF0 = 0, TR0 = 1
//	TF0 = 0;
//	TR0 = 1;
//	
//	// 64635 到 65535 相差1000,也就是1ms会发生中断
//	TH0 = 64535 / 256; // 取高8位
//	TL0 = 54535 % 256; // 取低8位
//	
//	// 定时器开关
//	ET0 = 1; // 打开定时器0
//	EA = 1; // 打开总开关
	PT0 = 0;Timer0Init();LCD_Init();LCD_ShowChar(1, 3, ':');LCD_ShowChar(1, 6, ':');while (1) {if (second == 60) {second = 0;minute ++;}if (minute == 60) {minute = 0;hour ++;}if (hour == 24) {hour = 0;}LCD_ShowNum(1, 1, hour, 2);LCD_ShowNum(1, 4, minute, 2);LCD_ShowNum(1, 7, second, 2);}
}// 发生时钟中断时,会触发该函数,中断号为1
void Timer0_Routube() interrupt 1 {TL0 = 0x66;		//设置定时初值TH0 = 0xFC;		//设置定时初值count ++;if (count == 1000) {second ++;count = 0;// 中断程序应该尽量简短
//		if (second == 60) {
//			second = 0;
//			minute ++;
//			if (minute == 60) {
//				minute = 0;
//				hour ++;
//				if (hour == 24) {
//					hour = 0;
//				}
//			}
//		}}
}

9. 串口通信

9.1 原理图

在这里插入图片描述

  1. 使用波特率计算器生成定时器1的配置,用于设置接收和发送速度
    在这里插入图片描述

    // 配置定时器1用于串口的同步通讯,控制波特率
    void UartInit(void)		//4800bps@11.0592MHz
    {PCON &= 0x7F;		//波特率不倍速 // 方式1(SM0 = 0; SM1 = 1) 允许接收(REN = 1)SCON = 0x50;		//8位数据,可变波特率AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12TAUXR &= 0xFE;		//串口1选择定时器1为波特率发生器TMOD &= 0x0F;		//清除定时器1模式位TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xFA;		//设定定时初值TH1 = 0xFA;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1// 当发送缓存区满和接收缓冲区满都会触发串口中断,中断号为4EA = 1; // 中断允许控制位ES = 1; // 允许串口中断
    }
    
  2. 使用串口助手测试串口通信功能
    在这里插入图片描述
    注意串口需要与左半部分的串口号保持一致,波特率需要与定时器1的配置保持一致。

实验1:每隔一秒发送一个数据,并且将接收字节保存到P2,控制LED灯

#include <AT89C51RC2.h>
#include <INTRINS.H>
#include "Delay.h"// 配置定时器1用于串口的同步通讯,控制波特率
void UartInit(void)		//4800bps@11.0592MHz
{PCON &= 0x7F;		//波特率不倍速 // 方式1(SM0 = 0; SM1 = 1) 允许接收(REN = 1)SCON = 0x50;		//8位数据,可变波特率AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12TAUXR &= 0xFE;		//串口1选择定时器1为波特率发生器TMOD &= 0x0F;		//清除定时器1模式位TMOD |= 0x20;		//设定定时器1为8位自动重装方式TL1 = 0xFA;		//设定定时初值TH1 = 0xFA;		//设定定时器重装值ET1 = 0;		//禁止定时器1中断TR1 = 1;		//启动定时器1// 当发送缓存区满和接收缓冲区满都会触发串口中断,中断号为4EA = 1; // 中断允许控制位ES = 1; // 允许串口中断
}
// 串口发送一个字节的数据
void sendByte(unsigned char buffer) {SBUF = buffer; // 发送数据while (TI == 0); // 等待数据发送完成TI = 0; // 复位
}
void main() {unsigned char buffer = 0x00;// 初始化串口UartInit();while (1) {sendByte(buffer);buffer ++;Delayms(1000);}
}// 串口中断程序,中断号为4
// 发送缓存区满和接收缓冲区满都会触发该中断
// 接收中断触发时,RI = 1;发送中断触发时,TI = 1
// 处理完中断后,需要将手动将RI或者TI复位为0,否则会重复触发串口中断
// 用接收的数据控制P2寄存器,也就是LED灯
void UARTRoutine() interrupt 4 {unsigned char buffer = SBUF;if (RI == 1) { // 串口接收中断P2 = SBUF;RI = 0;}
//	if (TI == 1) // 串口发送中断
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com