第四章——整合代码
下面是完整的 LCD1602 8 总线的代码:
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_ENTRY_MODE 0x06
#define LCD_SURSOR_SHIFT 0x18
#define LCD_FUNCTION_SET 0x38
#define LCD_SET_CGRAM_ADDR 0x40
#define LCD_SET_DDRAM_ADDR 0x80
uint8_t LCD_DISPLAY_CONTROL = 0x0C;
//定义LCD1602引脚
const uint8_t EN = 10, RW = 11, RS = 12;
const uint8_t data_pins[] = {9, 8, 7, 6, 5, 4, 3, 2};
const char* message = "Hello world!";
uint8_t duck[] = {0x4, 0xe, 0xe, 0xe, 0x1f, 0x0, 0x4};
void send_pins(uint8_t);
uint8_t read_pins();
void wait_ready();
void write_cmd();
void write_data();
void lcd_init();
void lcd_clear();
void lcd_home();
void display_off();
void display_on();
void cursor_off();
void cursor_on();
void blink_off();
void blink_on();
void scroll_left();
void scroll_right();
void set_cursor();
void print(const char);
void print(const char*);
void creat_char(uint8_t, uint8_t*);
void setup() {
lcd_init();
creat_char(0, duck);
set_cursor(0, 0);
print(message);
print('*');
set_cursor(7, 1);
print("Have a nice day! By Mr.Addict!");
set_cursor(37, 1);
write_data(0);
}
void loop() {
scroll_left();
delay(1000);
}
// 发送数据到引脚
void send_pins(uint8_t dat) {
for (int i = 0; i < 8; i++) {
digitalWrite(data_pins[i], (dat >> i) & 0x01);
}
}
// 读取引脚数据
uint8_t read_pins() {
uint8_t sta = 0;
for (uint8_t i = 0; i < 8; i++) {
sta |= (uint8_t)digitalRead(data_pins[i]) << i;
}
return sta;
}
// 等待LCD1602准备好
void wait_ready() {
uint8_t sta;
// 读取LCD状态RS=0,RW=1
digitalWrite(RS, LOW);
digitalWrite(RW, HIGH);
// 将引脚设置为输入模式
for (uint8_t i = 0; i < 8; i++) {
pinMode(data_pins[i], INPUT);
}
// 读取引脚状态
do {
digitalWrite(EN, HIGH);
sta = read_pins();
digitalWrite(EN, LOW);
} while (sta & 0x80); // 读取Bit7的Busy Flag
// 将引脚重新设置为输出
for (uint8_t i = 0; i < 8; i++) {
pinMode(data_pins[i], OUTPUT);
}
}
// 写命令
void write_cmd(uint8_t cmd) {
wait_ready();
// 写命令RS=0,RW=0
digitalWrite(RS, LOW);
digitalWrite(RW, LOW);
send_pins(cmd);
// 发送命令需要EN高脉冲
digitalWrite(EN, HIGH);
digitalWrite(EN, LOW);
}
// 写数据到DDRAM
void write_data(uint8_t dat) {
wait_ready();
// 写数据RS=1,RW=0
digitalWrite(RS, HIGH);
digitalWrite(RW, LOW);
send_pins(dat);
// 发送数据需要EN高脉冲
digitalWrite(EN, HIGH);
digitalWrite(EN, LOW);
}
// LCD初始化
void lcd_init() {
pinMode(EN, OUTPUT);
pinMode(RS, OUTPUT);
pinMode(RW, OUTPUT);
write_cmd(LCD_FUNCTION_SET); // 8总线,2行显示区域,5x8字体
write_cmd(LCD_DISPLAY_CONTROL); // 显示开,光标关,闪烁关
write_cmd(LCD_CLEAR); // 清屏
write_cmd(LCD_ENTRY_MODE); // 地址自动+1,文字不动
}
// 清空屏幕
void lcd_clear() {
write_cmd(LCD_CLEAR);
}
// 光标以及光标指针回到初始状态
void lcd_home() {
write_cmd(LCD_HOME);
}
// 关闭LCD
void display_off() {
LCD_DISPLAY_CONTROL &= ~0x04;
write_cmd(LCD_DISPLAY_CONTROL);
}
// 打开LCD
void display_on() {
LCD_DISPLAY_CONTROL |= 0x04;
write_cmd(LCD_DISPLAY_CONTROL);
}
// 关闭光标
void cursor_off() {
LCD_DISPLAY_CONTROL &= ~0x02;
write_cmd(LCD_DISPLAY_CONTROL);
}
// 打开光标
void cursor_on() {
LCD_DISPLAY_CONTROL |= 0x02;
write_cmd(LCD_DISPLAY_CONTROL);
}
// 关闭光标闪烁
void blink_off() {
LCD_DISPLAY_CONTROL &= ~0x01;
write_cmd(LCD_DISPLAY_CONTROL);
}
// 打开光标闪烁
void blink_on() {
LCD_DISPLAY_CONTROL |= 0x01;
write_cmd(LCD_DISPLAY_CONTROL);
}
// 向左滚动一列
void scroll_left() {
write_cmd(LCD_SURSOR_SHIFT);
}
// 向右滚动一列
void scroll_right() {
write_cmd(LCD_SURSOR_SHIFT | 0x04);
}
// 设置光标位置
void set_cursor(uint8_t x, uint8_t y) {
uint8_t addr;
if (y == 0)
addr = 0x00 + x; // 第一行字符地址从 0x00开始
else
addr = 0x40 + x; // 第二行字符地址从 0x40开始
write_cmd(LCD_SET_DDRAM_ADDR | addr); // 设置DDRAM地址
}
// 打印字符
void print(const char cha) {
write_data(cha);
}
// 打印字符串
void print(const char* str) {
while (*str) {
write_data(*str++); // 先取指针的值,再将指针地址自增
}
}
// 自定义一个新的CGRAM字符
void creat_char(uint8_t num, uint8_t* bit_map) {
// 设置CGRAM地址
write_cmd(LCD_SET_CGRAM_ADDR + 8 * num);
for (uint8_t i = 0; i < 8; i++) {
write_data(bit_map[i]);
}
}