标题: stm32驱动LCD12864液晶屏驱动程序 [打印本页]
作者: dz1024 时间: 2019-11-7 12:03
标题: stm32驱动LCD12864液晶屏驱动程序
stm32驱动LCD12864液晶屏驱动程序,亲测可行,复制直接能用!
废话不多说,直接贴程序
就两个文件,LCD12864.h和LCD12864.c,自己复制过去后,改一下引脚即可
单片机主频:72MHZ
LCD12864.h如下所示
1. #ifndef __LCD12864_H
2. #define __LCD12864_H
3. #include "sys.h"
4.
5.
6. #define LCD1602_RS PEout(0) // PE0 godefine之后我们会发现,这个宏最后就是在这个io的地址这里赋值
7. // #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
8. #define LCD1602_RW PEout(1) // PE1
9. #define LCD1602_E PAout(3) // PA3
10.
11.
12.void LCD12864IO_Init(void);
13.
14.void LCD1602_DB_IO_outputMode(void);
15.void LCD1602_DB_IO_inputMode(void);
16.
17.void write_LCD1602_DB(uint8_t data);
18.uint8_t read_LCD1602_DB(void);
19.
20.
21.void InitLcd1602(void);
22.void LcdShowStr(unsigned char row, unsigned char column, unsigned char *str);
23.void LcdWriteCmd(unsigned char cmd);
24.
25.void LcdShowImage(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *img);
26.void LcdClearArea(uint8_t x, uint8_t y, uint8_t w, uint8_t h);
27.
28.//#ifndef _HE_
29.extern uint8_t HE[];
30.extern uint8_t QQ[];
31.extern uint8_t myVX[];
32.
33.//#endif
34.
35.#endif
LCD12864.c如下所示:
1. #include "lcd12864.h"
2. #include "delay.h"
3. //#define _HE_
4.
5. uint8_t HE[]=
6. {
7.
8.
9. 0x20,0x00,0x70,0x00,0x1E,0x00,0x10,0x3E,0x10,0x22,0xFF,0x22,0x10,0x22,0x18,0x22,0x38,0x22,0x54,0x22,0x54,0x22,0x12,0x22,0x11,0x3E,0x10,0x22,0x10,0x00,0x10,0x00/*"和",0*/
10./* (16 X 16 , 宋体 )*/
11.
12.};
13.
14.uint8_t QQ[]=
15.{
16.
17.
18.0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xE0,0x3F,0xE0,0x7F,0xF0,0x7F,0xF8,0x7D,0xF0,0x3C,0xD0,0x2C,0x30,0x30,0x70,0x38,0xE0,0x1F,0x00,0x00,0x00,0x00/*"C:\Users\Administrator\Desktop\qqXiaoBing.bmp",0*/
19./* (16 X 16 )*/
20.
21.
22.
23.
24.};
25.
26.u8 myVX[]=
27.{
28.0x00,0x0D,0xFC,0xC8,0x0F,0x3F,0xB0,0x00,0x00,0x0D,0xFC,0xC8,0x0F,0x3F,0xB0,0x00,
29.0x3F,0xCC,0x7C,0x0F,0x93,0x26,0x33,0xFC,0x20,0xCD,0x80,0x31,0xF0,0x9F,0xB3,0x04,
30.0x20,0xCD,0x80,0x31,0xF0,0xDF,0xB3,0x04,0x20,0xCF,0xFF,0xC6,0x0C,0xD9,0xB3,0x04,
31.0x20,0xCF,0xFF,0xC6,0x0C,0x99,0xB3,0x04,0x20,0xCF,0x80,0xCE,0x1C,0xE1,0xB3,0x04,
32.0x20,0xCF,0xC0,0xCE,0x1C,0xE1,0x33,0x04,0x3F,0xCD,0xE0,0x30,0x00,0xC6,0x33,0xFC,
33.0x00,0x0D,0x9B,0x36,0x6C,0xD9,0xB0,0x00,0x00,0x0D,0x9B,0x36,0x6C,0xD9,0xB0,0x00,
34.0xFF,0xFD,0x9F,0xC9,0x83,0x9F,0xBF,0xFF,0xFF,0xFD,0x9F,0xC9,0x83,0x9F,0xBF,0xFF,
35.0xE0,0xCD,0xFC,0x07,0xF0,0x27,0xC0,0xE0,0x06,0x32,0x79,0xC6,0x33,0x39,0xBC,0x99,
36.0x06,0x32,0x7B,0xC6,0x13,0x39,0xBC,0x9B,0xF9,0x01,0x9E,0x0F,0x9C,0x18,0x33,0x64,
37.0xF9,0x01,0x9C,0x0F,0x9C,0x18,0x33,0x64,0x06,0xFC,0x63,0x08,0x73,0x18,0x33,0x1C,
38.0x06,0xFC,0x61,0x08,0x73,0x18,0x33,0x1C,0xD8,0x03,0x9F,0x01,0x8F,0xE7,0xF3,0xE3,
39.0xD8,0x03,0x9F,0x01,0x8F,0xE7,0xF3,0xE3,0xFE,0x31,0x98,0xC9,0xFC,0x87,0x8C,0x87,
40.0x1F,0x03,0x9F,0x35,0xEC,0x18,0x43,0x98,0x1F,0x03,0x9F,0x36,0xEC,0x18,0x43,0x98,
41.0xFE,0xF3,0xE0,0x7F,0xAC,0x39,0xB0,0xF8,0xFE,0xF3,0xE0,0xFF,0xDC,0x39,0xB0,0xF8,
42.0x3E,0xC3,0xFF,0xE6,0x5C,0xE6,0x70,0x60,0xF7,0xF3,0x6F,0xFD,0xCC,0x1F,0xBC,0x9F,
43.0xE7,0xF2,0x67,0xFE,0xFF,0x1F,0xBC,0x9F,0xC7,0xCE,0x7D,0xA1,0xFF,0x00,0x3C,0xE0,
44.0xC7,0xCE,0x7D,0x83,0xBB,0x80,0x3C,0xE0,0x3F,0x3E,0x1C,0x83,0xFF,0x99,0xFF,0xFB,
45.0x3F,0x3E,0x1C,0x43,0xFF,0x99,0xFF,0xFB,0x19,0x02,0x18,0x7F,0xFF,0xB8,0x40,0x07,
46.0x00,0xFC,0x79,0xF3,0xFF,0x39,0xFC,0x83,0x00,0xFC,0x7B,0xF1,0xFF,0x79,0xFC,0x83,
47.0xD9,0x00,0x04,0xF1,0xFF,0x18,0x0F,0xF8,0xD9,0x00,0x04,0xF1,0x83,0x18,0x0F,0xF8,
48.0x18,0xFC,0x19,0xF8,0x1F,0x39,0x80,0xFB,0x18,0xFC,0x19,0xF8,0x1F,0x39,0x80,0xFB,
49.0x27,0xCE,0x66,0x31,0xEC,0x07,0xC0,0x1C,0x38,0x30,0x07,0x0E,0x73,0xE0,0x3C,0x84,
50.0x38,0x30,0x07,0x0E,0x73,0xE0,0x3C,0x84,0x3E,0xC1,0x81,0xC1,0x83,0x00,0x7C,0xF8,
51.0x3E,0xC1,0x83,0xC1,0x83,0x00,0x7C,0xF8,0x21,0x31,0x99,0xF6,0x1C,0x3F,0xFC,0xF8,
52.0x21,0x31,0x9B,0xF6,0x1C,0x3F,0xFC,0xF8,0x39,0x0C,0x1B,0xC9,0x93,0x20,0x00,0x03,
53.0xFF,0xFC,0x03,0x0E,0x6F,0x61,0x1E,0x7F,0xFF,0xFC,0x03,0x0E,0x6F,0x21,0xBF,0x7F,
54.0x00,0x0F,0xE3,0xFF,0xFF,0x81,0xB3,0x18,0x00,0x0F,0xE3,0xFF,0xFF,0xC1,0xB3,0x18,
55.0x3F,0xCE,0x67,0x37,0x83,0xF8,0x3F,0x7B,0x3F,0xCE,0x67,0x37,0x83,0xF8,0x3E,0x79,
56.0x20,0xCC,0x1B,0x36,0x13,0x18,0x00,0x60,0x20,0xCD,0xE7,0x07,0xEF,0x86,0x30,0x07,
57.0x20,0xCD,0xE7,0x07,0xEF,0xC6,0x30,0x07,0x20,0xCC,0x7C,0xCE,0x63,0xC6,0x3C,0x9C,
58.0x20,0xCC,0x7C,0xCE,0x63,0xC6,0x3C,0x9C,0x3F,0xCE,0x67,0x39,0xEC,0xDE,0x0C,0xFC,
59.0x3F,0xCF,0x67,0x3D,0xE4,0x9E,0x0D,0xFC,0x00,0x0F,0xE4,0x3E,0x63,0x19,0xFF,0x80,/*"C:\Users\Administrator\Desktop\我的微信二维码.bmp",0*/
60./* (64 X 64 )*/
61.
62.}
63.;
64.
65.
66.void LCD12864IO_Init(void)
67.{
68.
69.GPIO_InitTypeDef GPIO_InitStructure;
70.
71.RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOA,ENABLE);
72. //使能PG,PE,PA端口时钟
73.GPIO_InitStructure.GPIO_Pin = 0XFF; //PG端口配置
74.GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
75.GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
76. GPIO_Init(GPIOG,&GPIO_InitStructure); //根据设定参数初始化GPIOG.0
77.GPIO_SetBits(GPIOG,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PG.0 输出高
78.
79.GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //PE.0,PE.1,端口配置
80. GPIO_Init(GPIOE,&GPIO_InitStructure); //根据设定参数初始化GPIOE.0.1
81.GPIO_SetBits(GPIOE,GPIO_Pin_0|GPIO_Pin_1); //PE.0.1 输出高
82.
83.GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //PA3端口配置
84. GPIO_Init(GPIOA,&GPIO_InitStructure); //根据设定参数初始化GPIOPA3
85.GPIO_SetBits(GPIOA,GPIO_Pin_3); //PA3 输出高
86.
87.}
88.void LCD1602_DB_IO_outputMode(void)
89.{
90.GPIO_InitTypeDef GPIO_InitStructure;
91.GPIO_InitStructure.GPIO_Pin = 0XFF; //PG端口配置
92.GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
93.GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
94. GPIO_Init(GPIOG,&GPIO_InitStructure); //根据设定参数初始化GPIOG.0
95.GPIO_SetBits(GPIOG,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PG.0 输出高
96.
97.}
98.
99.void LCD1602_DB_IO_inputMode(void)
100. {
101. GPIO_InitTypeDef GPIO_InitStructure;
102. GPIO_InitStructure.GPIO_Pin = 0XFF; //PG端口配置
103. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
104. GPIO_Init(GPIOG, &GPIO_InitStructure); //根据设定参数初始化GPIOG.0
105. GPIO_SetBits(GPIOG,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //PG.0 输出高
106.
107. }
108.
109. void write_LCD1602_DB(uint8_t data)
110. {
111. GPIO_Write(GPIOG,(uint16_t)data);
112. }
113.
114. uint8_t read_LCD1602_DB(void)
115. {
116. uint8_t value;
117. value=(uint8_t)GPIO_ReadInputData(GPIOG);
118. return value;
119. }
120.
121. /* 等待液晶准备好 */
122. void LcdWaitReady()
123. {
124. unsigned char sta;
125. delay_us(1);
126.
127. LCD1602_RS = 0;
128. delay_us(1);
129.
130. LCD1602_RW = 1;
131. delay_us(1);
132.
133. do {
134. LCD1602_E = 1;
135. delay_us(1);
136.
137. LCD1602_DB_IO_inputMode();
138. sta= read_LCD1602_DB();
139. LCD1602_DB_IO_outputMode();
140. delay_us(1);
141.
142. LCD1602_E = 0;
143. delay_us(1);
144.
145. } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
146. }
147. /* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
148. void LcdWriteCmd(unsigned char cmd)
149. {
150. delay_us(1);
151.
152. LcdWaitReady();
153. delay_us(1);
154.
155. LCD1602_RS = 0;
156. delay_us(1);
157.
158. LCD1602_RW = 0;
159. delay_us(1);
160.
161. write_LCD1602_DB(cmd);
162. delay_us(1);
163.
164. LCD1602_E = 1;
165. delay_us(1);
166.
167. LCD1602_E = 0;
168. delay_us(1);
169.
170. }
171.
172. /* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
173. void LcdWriteDat(unsigned char dat)
174. {
175. delay_us(1);
176.
177. LcdWaitReady();
178. delay_us(1);
179.
180. LCD1602_RS = 1;
181. delay_us(1);
182.
183. LCD1602_RW = 0;
184. delay_us(1);
185.
186. write_LCD1602_DB(dat);
187. delay_us(1);
188.
189. LCD1602_E = 1;
190. delay_us(1);
191.
192. LCD1602_E = 0;
193. delay_us(1);
194.
195. }
196. /* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
197. void LcdSetCursor(unsigned char x, unsigned char y)
198. {
199. unsigned char addr;
200.
201. if (y >= 2) //说明我们想显示在右半屏
202. {
203. y-= 2;
204. x+= 8; //那么x就得往右挪动8个汉字了
205. }
206. addr =y*16 + x; //现在这个是以一个汉字为单位,这里所有所说的汉字为单位的意思是16*16
207. //由起始DDRAM地址连续写入字符串
208. //addr的值是所有的汉字后面的地址,也是汉字为单位,即ddram也是以汉字为单位的
209. LcdWriteCmd(0x30); //启动DDRAM操作
210. LcdWriteCmd(0x80|addr); //设置ram地址
211. }
212. /* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
213. void LcdShowStr(unsigned char row, unsigned char column, unsigned char *str)
214. {
215. unsigned char n=0,a;
216. unsigned char *fore_str;
217. LcdSetCursor(column, row); //设置起始地址
218. while (*str != '\0') //连续写入字符串数据,直到检测到结束符
219. {
220.
221. if((n+1)%2==0) //奇数地址
222. {
223. fore_str=str-1;
224. if(*fore_str>0x80)
225. {
226. LcdWriteDat(*str++);
227. }
228. else if(*str>0x80)
229. LcdWriteDat(' ');
230. else if(*str<=0x80)
231. LcdWriteDat(*str++);
232. }
233. else
234. LcdWriteDat(*str++); //先取str指向的数据,然后str自加1
235. n++;
236.
237. if((n+2*column)%16==0)
238. {
239. a=(n+2*column)/16;
240. if(row==0)
241. {
242. if(a==1)
243. LcdWriteCmd(0x90);
244. if(a==2)
245. LcdWriteCmd(0x88);
246. if(a==3)
247. LcdWriteCmd(0x98);
248. if(a==4)
249. LcdWriteCmd(0x80);
250. }
251.
252. if(row==1)
253. {
254. if(a==1)
255. LcdWriteCmd(0x88);
256. if(a==2)
257. LcdWriteCmd(0x98);
258. if(a==3)
259. LcdWriteCmd(0x80);
260. if(a==4)
261. LcdWriteCmd(0x90);
262. }
263.
264. if(row==2)
265. {
266. if(a==1)
267. LcdWriteCmd(0x98);
268. if(a==2)
269. LcdWriteCmd(0x80);
270. if(a==3)
271. LcdWriteCmd(0x90);
272. if(a==4)
273. LcdWriteCmd(0x88);
274. }
275.
276. if(row==3)
277. {
278. if(a==1)
279. LcdWriteCmd(0x80);
280. if(a==2)
281. LcdWriteCmd(0x90);
282. if(a==3)
283. LcdWriteCmd(0x88);
284. if(a==4)
285. LcdWriteCmd(0x98);
286. }
287.
288.
289.
290. }
291. }
292. }/* 初始化1602液晶 */
293. void InitLcd1602()
294. {
295. LcdWriteCmd(0x38); //16*2显示,5*7点阵,8位数据接口
296. LcdWriteCmd(0x0C); //显示器开,光标关闭
297. LcdWriteCmd(0x06); //文字不动,地址自动+1
298. LcdWriteCmd(0x01); //清屏
299. }
300.
301.
302.
303.
304. /*
305. * 函数名:LcdShowImage
306. * 描 述:在显示屏上显示一幅图像
307. * 输 入:img - 待显示图像指针
308. * x - 屏幕显示横坐标(以像素为单位)
309. * y - 屏幕显示纵坐标(以像素为单位)
310. * w - 图像宽度(以像素为单位)
311. * h - 图像高度(以像素为单位)
312. * 输 出:无
313. * 备 注:x与w必须是16的整数倍,因CGRAM最小寻址单位为2字节;y与h可为0-63的任意值。
314. */
315.
316. //经过我的不断测试,y和h的值也是可以取到64,而且显示汉字,也得取到16而不是15,那么来说,是多少像素高度,这里就填多少
317. void LcdShowImage(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t *img)
318. {
319. uint16_t i;
320. uint8_t xi,yi;
321. uint8_t xt,yt;
322.
323. x>>= 4;
324. w>>= 3;
325. i = 0;
326. LcdWriteCmd(0x36); //启动CGRAM操作
327.
328. for (yi=0; yi<h; yi++)
329. {
330. yt= y+yi;
331. xt= x;
332. if (yt >= 32)
333. {
334. yt -= 32;
335. xt += 8;
336. }
337. LcdWriteCmd(0x80|yt);
338. LcdWriteCmd(0x80|xt);
339. for (xi=0; xi<w; xi++)
340. {
341. LcdWriteDat(img[i++]);
342. }
343. }
344. }
345.
346. /*
347. * 函数名:LcdClearArea
348. * 描 述:清除屏幕上的一块图形显示区域
349. * 输 入:x - 区域起始横坐标(以像素为单位)
350. * y - 区域起始纵坐标(以像素为单位)
351. * w - 区域宽度(以像素为单位)
352. * h - 区域高度(以像素为单位)
353. * 输 出:无
354. * 备 注:x与w必须是16的整数倍,因CGRAM最小寻址单位为2字节;y与h可为0-63的任意值。
355. */
356.
357.
358. //记住,绘图模式时候屏幕默认有乱点显示的数据的,需要我们先调用这个函数后面才能正常显示
359.
360. void LcdClearArea(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
361. {
362. uint8_t xi,yi;
363. uint8_t xt,yt;
364.
365. x>>= 4;
366. w>>= 3;
367. LcdWriteCmd(0x36); //启动CGRAM操作
368. for (yi=0; yi<h; yi++)
369. {
370. yt= y+yi;
371. xt= x;
372. if (yt >= 32)
373. {
374. yt -= 32;
375. xt += 8;
376. }
377. LcdWriteCmd(0x80|yt);
378. LcdWriteCmd(0x80|xt);
379. for (xi=0; xi<w; xi++)
380. {
381. LcdWriteDat(0x00); //写入0x00以清除显示
382. }
383. }
384. }
385.
主函数main()中这样调用即可:
1. void main()
2. {
3. LCD12864IO_Init(void);
4. // 为什么驱动函数会出现1602的字样,因为这个LCD12864的驱动程序我是从1602液晶屏移植过来的,
5. // 只是忘记改了名字而已,就这样吧
6. InitLcd1602(void);
7. LcdShowStr(1,1,"hello 你好");
8. while(1);
9. }
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |