功能结构分析
源码地址
实物连线图
找到I2C上的串口,以及和板子上的端口相对应
-
GND->GND
-
VCC->5V
-
SOA->A4
-
SCL->A5
项目演示(视频)
查看I2C地址
板子后面的有I2C的接口,简化了电路以及节约了io口。默认是ox27.但是有些的不是。所以这里需要查看一下
#include <Wire.h>
void setup() {
Serial.begin(9600);
while (!Serial) { }
Serial.println("这里是寻找lcd液晶屏幕I2c地址");
byte count = 0;
Wire.begin();
for (byte i = 8 ; i < 120; i++) {
Wire.beginTransmission(i);
if (Wire.endTransmission () == 0) {
Serial.print("地址是:");
Serial.print(i, DEC);
Serial.print("(OX");
Serial.print(i, HEX);
Serial.println(")");
count++;
delay(i);
}
}
Serial.print("发现了");
Serial.print(count, DEC);
Serial.print("个设备");
}
void loop() {
}
就是这个
运行结果
在lcd上显示helloworld
导入库函数
找到软件的菜单栏的项目,点击加载库搜索LiquidCrystal_I2C
如果LiquidCrystal_I2C没有变颜色,可能是下载错了。
烧录程序后如果没有显示东西,但是背景光亮了,那么则调节后面的电位器
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
void setup(){
lcd.init(); // 初始化LCD
lcd.backlight(); //设置LCD背景等亮
}
void loop(){
//列 行
lcd.setCursor(0,0); //设置显示指针
lcd.print("hello world"); //输出字符到LCD1602上
lcd.setCursor(1,1);
lcd.print("YQ");
delay(500);
}
显示汉字并移动
由于lcd1602是需要进行写入以及读写才能进行显示操作。以及这里的Lcd1602是有I2c串口的。所以我们需要先导入LiquidCrystal_I2C这个库文件
引入LiquidCrystal_I2C
如果没有引入函数库,请看上文显示helloworld的引入LiquidCrystal_I2C
#include <Wire.h> //加载Wire通讯库
#include <LiquidCrystal_I2C.h> //加载液晶屏库
LiquidCrystal_I2C lcd(0x27, 16, 2); // 设 LCD的地址为0x27,16列2行
-
这里引入了wire库来进行写入
-
引入LiquidCrystal_I2C.h来加载lcd
-
定义了lcd的I2c串口,以及行列,最多也只能16列2行,1602的名字也由此而来
显示字符
在lcd里是需要将字符进行写入和输出才能显示的。所以需要write和print函数
#if defined(ARDUINO) && ARDUINO >= 100//判断版本
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif
-
用if判断arduino版本。这里是由于现在的版本和之前的版本写入和读取方式不同。需要判断一下
-
使用define关键字来声明一个一个函数,这里主要是使用define的预编译功能。也就是提前声明,比如我要打你了。我要先给你说我要打你了,给你要给跑路的机会这里的意思也就说,自己声明一个函数来替代了老版本的写入和输入的写法。因为现在的版本舍去了BYTE这个关键字了
所以采用预编译的方式来进行字符显示(输入和输出)
引入字符
-
我这里是定义的一个无符号类型的int8_t的二维数组。主要是为了方便,减少代码量。
-
uint8_t自行百度。这个是和int相关的一个数据类型,我记得是以8位的2进制方式存储
-
二位数组,第一个【】是行,第二个是列。这里 为了方便,并没有定死行是具体的。只是规定了列的长度是8,因为lcd是5*8的点阵构成。这里需要使用十六进制来对点阵进行转换
-
很明显,锦字是用的4个单元格来组成的。城是两个。
-
汉字字符用点阵工具来生成。
//要显示的汉字编码,定义为一个数组
uint8_t code [][8] = {
// 锦
{0x00, 0x00, 0x02, 0x04, 0x0F, 0x14, 0x0F, 0x04},
{0x04, 0x04, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00},
{0x00, 0x02, 0x04, 0x1F, 0x11, 0x1F, 0x11, 0x1F},//白
{0x04, 0x04, 0x1F, 0x15, 0x15, 0x15, 0x04, 0x00},//巾
// 城
{0x00, 0x0B, 0x1E, 0x0B, 0x0A, 0x0E, 0x1A, 0x06},
{0x12, 0x1F, 0x08, 0x1A, 0x14, 0x16, 0x19, 0x10},
{0x04, 0x04, 0x1F, 0x04, 0x04, 0x0A, 0x11, 0x11},//大
{0x15, 0x1F, 0x11, 0x0F, 0x02, 0x1F, 0x04, 0x0C},//学
};
初始化灯光
void setup() {
lcd.init(); //初始化LCD
lcd.backlight(); //打开背光
}
-
在setup函数里初始化
-
第一是初始化lcd,这里是调用的init函数。init里面是啥就不深究了
-
backlight则是打开背景光。
显示多个汉字(字符串)
-
这里用的一个for循环来定位二维数组里的行
-
使用createChar函数来创建每个字符。
-
使用setCursor来设置字符(单个汉字)所在的坑位(列 ,行)
-
使用printByte函数来进行写入和读取操作(预编译设置好了的)
-
逻辑是通过for循环来写入和读取每个字符。进行显示。
-
通过switch来判断,在数组里索引的第2个位置的字符需要在第二排的第一个坑位,以及在第3个需要设置在第一排的坑位,但是位置需要是第2的位置,以及第4个位置的字符需要在第二排的第一个坑位。然后后面的需要向前移动
-
后面在lcd的第二排的第9个格子的位置显示
使用for来控制数组行,则是创建字符
这里有个bug:
-
在创建字符的时候,二维数组只是用了行。
-
最多只能放8个字符。由于这里只是用了i的行。列并未操作。如果i在等于8的时候,会对行和列有所错误判断,显示跳动的错误字符
-
如果要多放字符,需要自己在重新定义个for循环自己从想要的位置开始定义。则i不是等于0是你想要显示的字符的索引
-
例如是要从第8个字符开始,那么for(int = 8;i<20;i++){};i<数组行长度这里加入你有20个字符(20行)
-
-
手动映射字符位置,以及控制所在位置,没有字符数量
-
for控制位置是i-1和i-2原理也是由此而来
移动
-
scrollDisplayLeft:左移动
-
scrollDisplayRight:右移动
-
这里使用for循环来控制移动的列
-
使用delay()延时函数来控制移动的速度,如果有余晖(重影)则增大延迟时间即可
-
外面的 delay(500);则是在每次移动次数结束后进行下一次的移动的延迟;则在这里,就是左边移动、右边移动、左边移动,然后下一波开始,的延迟就是500毫秒之后。由于loop是死循环就不用自己在加死循环了,所以会一直跑来跑去,其实这里只要左边移动和右边移动就可以。这个无所谓
// 移动
for (int positionCounter = 0; positionCounter < 13; positionCounter++)
{
lcd.scrollDisplayLeft();
delay(900);
}
for (int positionCounter = 0; positionCounter < 29; positionCounter++)
{
lcd.scrollDisplayRight();
delay(900);
}
for (int positionCounter = 0; positionCounter < 16; positionCounter++)
{
lcd.scrollDisplayLeft();
delay(900);
}
// 下次移动的延迟
delay(500);
暂无评论内容