1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
| // 对应 LCD1602 上面的 7 个引脚,由于全是 GPIOA 就不定义 PORT 了,只定义 PIN
#define LCD_RS_PIN GPIO_PIN_4 // PA4
#define LCD_RW_PIN GPIO_PIN_5 // PA5 这个可以省掉,直接接 GND
#define LCD_E_PIN GPIO_PIN_6 // PA6
#define LCD_D4_PIN GPIO_PIN_0 // PA0
#define LCD_D5_PIN GPIO_PIN_1 // PA1
#define LCD_D6_PIN GPIO_PIN_2 // PA2
#define LCD_D7_PIN GPIO_PIN_3 // PA3
#include "gd32vw55x.h"
#include "systick.h"
#define LCD1602_RS_L() GPIO_BC(GPIOA) = LCD_RS_PIN
#define LCD1602_RS_H() GPIO_BOP(GPIOA) = LCD_RS_PIN
#define LCD1602_RW_L() GPIO_BC(GPIOA) = LCD_RW_PIN
#define LCD1602_RW_H() GPIO_BOP(GPIOA) = LCD_RW_PIN
#define LCD1602_E_L() GPIO_BC(GPIOA) = LCD_E_PIN
#define LCD1602_E_H() GPIO_BOP(GPIOA) = LCD_E_PIN
// 等待 1us
static void delay_us(uint32_t us)
{
uint32_t i = us * 160;
while (i--) {}
}
// 初始化所有用到的 GPIO 为输出模式,且无上下拉电阻模式,并且全部设置为低位
void LCD1602_4L_Init(void) {
rcu_periph_clock_enable(RCU_GPIOA);
// 配置RS引脚
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_RS_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_RS_PIN);
GPIO_BC(GPIOA) = LCD_RS_PIN; // 初始置低
// 配置RW引脚(建议接地,此处保留可配置性)
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_RW_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_RW_PIN);
GPIO_BC(GPIOA) = LCD_RW_PIN; // 初始置低
// 配置E引脚
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_E_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_E_PIN);
GPIO_BC(GPIOA) = LCD_E_PIN; // 初始置低
// 配置数据线D4-D7
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_D4_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_D4_PIN);
GPIO_BC(GPIOA) = LCD_D4_PIN; // 初始置低
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_D5_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_D5_PIN);
GPIO_BC(GPIOA) = LCD_D5_PIN; // 初始置低
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_D6_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_D6_PIN);
GPIO_BC(GPIOA) = LCD_D6_PIN; // 初始置低
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_D7_PIN);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, LCD_D7_PIN);
GPIO_BC(GPIOA) = LCD_D7_PIN; // 初始置低
// 初始化 lcd
LCD1602_4L_WriteCMD(0x28);//四线模式
LCD1602_4L_WriteCMD(0x0c);
LCD1602_4L_WriteCMD(0x06);
LCD1602_4L_WriteCMD(0x01);//清屏
delay_us(50);
}
static void LCD1602_4L_Write(unsigned char cmd, unsigned char data) {
// 写命令和写数据只有一个 RS 寄存器不同
if (cmd) LCD1602_RS_L(); else LCD1602_RS_H();
// RW 是可以不整的,如果不需要读的话
LCD1602_RW_L();
// 开启写入数据
LCD1602_E_H();
// 按倒序写 0b11110000 的数据到 D4-D7
// gpio_bit_write 是 GPIO_BC GPIO_BOP 的包装
gpio_bit_write(GPIOA, LCD_D4_PIN, data&0x10);
gpio_bit_write(GPIOA, LCD_D5_PIN, data&0x20);
gpio_bit_write(GPIOA, LCD_D6_PIN, data&0x40);
gpio_bit_write(GPIOA, LCD_D7_PIN, data&0x80);
// 等待并开启下一次写入
delay_us(1);
LCD1602_E_L();
delay_us(1);
LCD1602_E_H();
// 按倒序写 0b00001111 的数据到 D4-D7
gpio_bit_write(GPIOA, LCD_D4_PIN, data&0x01);
gpio_bit_write(GPIOA, LCD_D5_PIN, data&0x02);
gpio_bit_write(GPIOA, LCD_D6_PIN, data&0x04);
gpio_bit_write(GPIOA, LCD_D7_PIN, data&0x08);
// 最后再关闭写入
delay_us(1);
LCD1602_E_L();
delay_us(100);
}
void LCD1602_4L_WriteCMD(unsigned char CMD) {
LCD1602_4L_Write(1, CMD);
}
void LCD1602_4L_WriteData(unsigned char CMD) {
LCD1602_4L_Write(0, CMD);
}
// 设置位置
void LCD1602_4L_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD1602_4L_WriteCMD(0x80|(Column-1));
}
if(Line==2)
{
LCD1602_4L_WriteCMD(0x80|(Column-1)+0x40);
}
if(Line==3)
{
LCD1602_4L_WriteCMD(0x80|(Column-1)+20);
}
if(Line==4)
{
LCD1602_4L_WriteCMD(0x80|(Column-1)+0x54);
}
}
// 补一个这个用来直接写文字,比较方便
void LCD1602_4L_PrintString(unsigned char Line,unsigned char Column,unsigned char *String)
{
unsigned char i;
LCD1602_4L_SetCursor(Line, Column);
for(i=0;String[i]!=0;i++)
{
LCD1602_4L_WriteData(String[i]);
}
}
// 补一个这个用来直接清理文字
void LCD1602_4L_Clear(unsigned char Line,unsigned char Column, unsigned char Length) {
unsigned char i;
LCD1602_4L_SetCursor(Line, Column);
for(i=0;i<Length;i++)
{
LCD1602_4L_WriteData(' ');
}
}
|