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. }
|