写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做!
本文写于:2025.03.30
前言
本次笔记是用来记录我的学习过程,同时把我需要的困难和思考记下来,有助于我的学习,同时也作为一种习惯,可以督促我学习,是一个激励自己的过程,让我们开始51单片机的学习之路。
欢迎大家给我提意见,能给我的嵌入式之旅提供方向和路线,现在作为小白,我就先学习51单片机了,就跟着B站上的江协科技开始学习了.
在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容,因为我之前有一个开发板,我大概率会用我的板子模仿着来做.让我们一起加油!
另外为了增强我的学习效果:每次笔记把我不知道或者问题在后面提出来,再下一篇开头作为解答!
开发板说明
本人采用的是慧净的开发板,因为这个板子是我N年前就买的板子,索性就拿来用了。不再另外购买视频中的普中开发板了。
原理图如下
视频中的都用这个开发板来实现,如果有资源就利用起来。
仔细看了看:开发板的晶振为:11.0592Mhz;12Mhz晶振是用来给CH340G芯片外置晶振;
下图是实物图
引用
51单片机入门教程-2020版 程序全程纯手打 从零开始入门
还参考了下图中的书籍:
手把手教你学51单片机(C语言版)
STC89C52手册
解答和科普
一、LCD1602代码编写
引脚定义:
sbit LCD_RS=P1^0;
sbit LCD_RW=P1^1;
sbit LCD_EN=P2^5;
#define LCD_DataPort P0
私有化延迟函数
void LCD_Delay() //@11.0592MHz 1ms移植后修改
{
unsigned char i, j;
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
写命令
void LCD_WriterCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1; //注意时序,
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
写数据
void LCD_WriterData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1; //注意时序,
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
初始化
void LCD_Init(void)
{
LCD_WriterCommand(0x38);
LCD_WriterCommand(0x0C);
LCD_WriterCommand(0x06);
LCD_WriterCommand(0x01);
}
对行和列进行运算转换为实际的地址:
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
if(Line==1)
{
LCD_WriterCommand(0x80|(Column-1));
}
if(Line==2)
{
LCD_WriterCommand(0x80|(Column-1)+0x40);
}
LCD_WriterData(Char);
}
现象
字符串
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
unsigned char i;
if(Line==1)
{
LCD_WriterCommand(0x80|(Column-1));
}
if(Line==2)
{
LCD_WriterCommand(0x80|(Column-1)+0x40);
}
for(i=0;String[i]!='\0';i++)
{
LCD_WriterData(String[i]);
}
}
测试字符串
显示无符号的数字
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column); //789 抽取转化为字符 789/100%10=7 789/10%10=8 789/1%10=9
for(i=Length;i>0;i--)
{
LCD_WriterData('0'+Number/LCD_Pow(10,i-1)%10); // 转换asc码
}
}
显示有符号的数字
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_WriterData('+');
Number1=Number;
}
else
{
LCD_WriterData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriterData('0'+Number1/LCD_Pow(10,i-1)%10); // 转换asc码
}
}
十六进制显示数字
void LCD_ShowHexNum(unsigned char Line, unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
unsigned char SingNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingNumber=Number/LCD_Pow(16,i-1)%16;
if(SingNumber<10)
{
LCD_WriterData('0'+SingNumber);
}
else
{
LCD_WriterData('A'+SingNumber-10);
}
}
}
显示二进制数
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_WriterData('0'+Number/LCD_Pow(2,i-1)%2); // 转换asc码
}
}
显示特殊字符
LCD_ShowChar(2,13,0xDF);
流动字幕
要产生流动字幕的效果:写一个超出屏幕范围,但是没有超出DDRM范围的一个东西,162,DDRM是402,
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "Init.h"
void main()
{
LCD_Init();
Nixie_OFF();
DianZhengGuan();
LCD_ShowChar(1,1,'A'); //不是标准的码表
LCD_ShowString(1,3,"HELLO");
LCD_ShowNum(1,9,66,2);
LCD_ShowSignedNum(1,12,-66,2);
LCD_ShowHexNum(2,1,0xAB,2);
LCD_ShowBinNum(2,4,0xA5,8);
LCD_ShowChar(2,13,0xDF);
LCD_ShowChar(2,14,'C');
LCD_ShowString(1,16,"Welcome to AI");
while(1)
{
LCD_WriterCommand(0x18);
Delay(500);
}
}
2、LCD1602.C
#include <REGX52.H>
sbit LCD_RS=P1^0;
sbit LCD_RW=P1^1;
sbit LCD_EN=P2^5;
#define LCD_DataPort P0
void LCD_Delay() //@11.0592MHz 1ms移植后修改
{
unsigned char i, j;
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
void LCD_WriterCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1; //注意时序,
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
void LCD_WriterData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1; //注意时序,
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
void LCD_Init(void)
{
LCD_WriterCommand(0x38);
LCD_WriterCommand(0x0C);
LCD_WriterCommand(0x06);
LCD_WriterCommand(0x01);
}
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriterCommand(0x80|(Column-1));
}
if(Line==2)
{
LCD_WriterCommand(0x80|(Column-1)+0x40);
}
}
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
LCD_SetCursor(Line,Column);
LCD_WriterData(Char);
}
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++)
{
LCD_WriterData(String[i]);
}
}
int LCD_Pow(int X,int Y)
{
unsigned char i;
int Result=1;
for(i=0;i<Y;i++)
{
Result*=X;
}
return Result;
}
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
LCD_SetCursor(Line,Column); //789 抽取转化为字符 789/100%10=7 789/10%10=8 789/1%10=9
for(i=Length;i>0;i--)
{
LCD_WriterData('0'+Number/LCD_Pow(10,i-1)%10); // 转换asc码
}
}
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_WriterData('+');
Number1=Number;
}
else
{
LCD_WriterData('-');
Number1=-Number;
}
for(i=Length;i>0;i--)
{
LCD_WriterData('0'+Number1/LCD_Pow(10,i-1)%10); // 转换asc码
}
}
void LCD_ShowHexNum(unsigned char Line, unsigned char Column,unsigned int Number,unsigned char Length)
{
unsigned char i;
unsigned char SingNumber;
LCD_SetCursor(Line,Column);
for(i=Length;i>0;i--)
{
SingNumber=Number/LCD_Pow(16,i-1)%16;
if(SingNumber<10)
{
LCD_WriterData('0'+SingNumber);
}
else
{
LCD_WriterData('A'+SingNumber-10);
}
}
}
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_WriterData('0'+Number/LCD_Pow(2,i-1)%2); // 转换asc码
}
}
#ifndef __LCD1602_H
#define __LCD1602_H
void LCD_Init(void);
void LCD_WriterCommand(unsigned char Command);
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned 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
实验现象:
LCD1602显示及滚动字幕
问题
总结
本节课主要学了LCD的功能代码编写,定义好引脚。然后根据时序先完成对写指令和写数据的编写,然后就是运用这些底层函数完成初始化,然后完成写指令,然后是位置的定义控制光标位,最后封装了各个功能函数。