lcd.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. #include "gd32f30x.h"
  2. #include "gd32f30x_it.h"
  3. #include "gd32f30x_spi.h"
  4. #include "gd32f30x_rcu.h"
  5. #include "gd32f30x_gpio.h"
  6. #include "oledfont.h"
  7. #include "lcd.h"
  8. #include "lcd.h"
  9. #include "delay.h"
  10. u16 BACK_COLOR; //背景色
  11. /******************************************************************************
  12. 函数说明:LCD串行数据写入函数
  13. 入口数据:dat 要写入的串行数据
  14. 返回值: 无
  15. ******************************************************************************/
  16. void LCD_Writ_Bus(u8 dat)
  17. {
  18. u8 i;
  19. OLED_CS_Clr();
  20. for(i=0;i<8;i++)
  21. {
  22. OLED_SCLK_Clr();
  23. if(dat&0x80)
  24. OLED_SDIN_Set();
  25. else
  26. OLED_SDIN_Clr();
  27. OLED_SCLK_Set();
  28. dat<<=1;
  29. }
  30. OLED_CS_Set();
  31. }
  32. /******************************************************************************
  33. 函数说明:LCD写入数据
  34. 入口数据:dat 写入的数据
  35. 返回值: 无
  36. ******************************************************************************/
  37. void LCD_WR_DATA8(u8 dat)
  38. {
  39. OLED_DC_Set();//写数据
  40. LCD_Writ_Bus(dat);
  41. }
  42. /******************************************************************************
  43. 函数说明:LCD写入数据
  44. 入口数据:dat 写入的数据
  45. 返回值: 无
  46. ******************************************************************************/
  47. void LCD_WR_DATA(u16 dat)
  48. {
  49. OLED_DC_Set();//写数据
  50. LCD_Writ_Bus(dat>>8);
  51. LCD_Writ_Bus(dat);
  52. }
  53. /******************************************************************************
  54. 函数说明:LCD写入命令
  55. 入口数据:dat 写入的命令
  56. 返回值: 无
  57. ******************************************************************************/
  58. void LCD_WR_REG(u8 dat)
  59. {
  60. OLED_DC_Clr();//写命令
  61. LCD_Writ_Bus(dat);
  62. }
  63. /******************************************************************************
  64. 函数说明:设置起始和结束地址
  65. 入口数据:x1,x2 设置列的起始和结束地址
  66. y1,y2 设置行的起始和结束地址
  67. 返回值: 无
  68. ******************************************************************************/
  69. void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
  70. {
  71. if(USE_HORIZONTAL==0)
  72. {
  73. LCD_WR_REG(0x2a);//列地址设置
  74. LCD_WR_DATA(x1);
  75. LCD_WR_DATA(x2);
  76. LCD_WR_REG(0x2b);//行地址设置
  77. LCD_WR_DATA(y1);
  78. LCD_WR_DATA(y2);
  79. LCD_WR_REG(0x2c);//储存器写
  80. }
  81. else if(USE_HORIZONTAL==1)
  82. {
  83. LCD_WR_REG(0x2a);//列地址设置
  84. LCD_WR_DATA(x1);
  85. LCD_WR_DATA(x2);
  86. LCD_WR_REG(0x2b);//行地址设置
  87. LCD_WR_DATA(y1+80);
  88. LCD_WR_DATA(y2+80);
  89. LCD_WR_REG(0x2c);//储存器写
  90. }
  91. else if(USE_HORIZONTAL==2)
  92. {
  93. LCD_WR_REG(0x2a);//列地址设置
  94. LCD_WR_DATA(x1);
  95. LCD_WR_DATA(x2);
  96. LCD_WR_REG(0x2b);//行地址设置
  97. LCD_WR_DATA(y1);
  98. LCD_WR_DATA(y2);
  99. LCD_WR_REG(0x2c);//储存器写
  100. }
  101. else
  102. {
  103. LCD_WR_REG(0x2a);//列地址设置
  104. LCD_WR_DATA(x1+80);
  105. LCD_WR_DATA(x2+80);
  106. LCD_WR_REG(0x2b);//行地址设置
  107. LCD_WR_DATA(y1);
  108. LCD_WR_DATA(y2);
  109. LCD_WR_REG(0x2c);//储存器写
  110. }
  111. }
  112. /******************************************************************************
  113. 函数说明:LCD初始化函数
  114. 入口数据:无
  115. 返回值: 无
  116. ******************************************************************************/
  117. void Lcd_Init(void)
  118. {
  119. // GPIO_InitTypeDef GPIO_InitStructure;
  120. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE, ENABLE); //使能A端口时钟
  121. // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  122. // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
  123. // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
  124. // GPIO_Init(GPIOG, &GPIO_InitStructure); //初始化GPIOG12
  125. // GPIO_SetBits(GPIOG,GPIO_Pin_12);
  126. //
  127. // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_15;
  128. // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
  129. // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
  130. // GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD1,5,15
  131. // GPIO_SetBits(GPIOD,GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_15);
  132. //
  133. // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_10;
  134. // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
  135. // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
  136. // GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化GPIOE8,10
  137. // GPIO_SetBits(GPIOE,GPIO_Pin_8|GPIO_Pin_10);
  138. /*
  139. SCL <--------> PA5 (clock)
  140. SDA <--------> PA7 (data)
  141. RES <--------> PA11 (reset)
  142. DC <--------> PA8 (data / cmd)
  143. CS <--------> PA12 (chip select)
  144. BLK <--------> PD2 (background)
  145. */
  146. rcu_periph_clock_enable(RCU_GPIOA);
  147. rcu_periph_clock_enable(RCU_GPIOD);
  148. gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_5);
  149. gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_7);
  150. gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_8);
  151. gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_11);
  152. gpio_init(GPIOA,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_12);
  153. gpio_init(GPIOD,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_2);
  154. gpio_bit_set(GPIOD,GPIO_PIN_2);
  155. gpio_bit_set(GPIOA,GPIO_PIN_7);
  156. gpio_bit_set(GPIOA,GPIO_PIN_8);
  157. gpio_bit_set(GPIOA,GPIO_PIN_11);
  158. gpio_bit_set(GPIOA,GPIO_PIN_12);
  159. gpio_bit_set(GPIOA,GPIO_PIN_5);
  160. OLED_RES_Clr();
  161. delay_ms(200);
  162. OLED_RES_Set();
  163. delay_ms(200);
  164. OLED_BLK_Set();
  165. delay_ms(200);
  166. //************* Start Initial Sequence **********//
  167. LCD_WR_REG(0x36);
  168. if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
  169. else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
  170. else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
  171. else LCD_WR_DATA8(0xA0);
  172. LCD_WR_REG(0x3A);
  173. LCD_WR_DATA8(0x05);
  174. LCD_WR_REG(0xB2);
  175. LCD_WR_DATA8(0x0C);
  176. LCD_WR_DATA8(0x0C);
  177. LCD_WR_DATA8(0x00);
  178. LCD_WR_DATA8(0x33);
  179. LCD_WR_DATA8(0x33);
  180. LCD_WR_REG(0xB7);
  181. LCD_WR_DATA8(0x35);
  182. LCD_WR_REG(0xBB);
  183. LCD_WR_DATA8(0x19);
  184. LCD_WR_REG(0xC0);
  185. LCD_WR_DATA8(0x2C);
  186. LCD_WR_REG(0xC2);
  187. LCD_WR_DATA8(0x01);
  188. LCD_WR_REG(0xC3);
  189. LCD_WR_DATA8(0x12);
  190. LCD_WR_REG(0xC4);
  191. LCD_WR_DATA8(0x20);
  192. LCD_WR_REG(0xC6);
  193. LCD_WR_DATA8(0x0F);
  194. LCD_WR_REG(0xD0);
  195. LCD_WR_DATA8(0xA4);
  196. LCD_WR_DATA8(0xA1);
  197. LCD_WR_REG(0xE0);
  198. LCD_WR_DATA8(0xD0);
  199. LCD_WR_DATA8(0x04);
  200. LCD_WR_DATA8(0x0D);
  201. LCD_WR_DATA8(0x11);
  202. LCD_WR_DATA8(0x13);
  203. LCD_WR_DATA8(0x2B);
  204. LCD_WR_DATA8(0x3F);
  205. LCD_WR_DATA8(0x54);
  206. LCD_WR_DATA8(0x4C);
  207. LCD_WR_DATA8(0x18);
  208. LCD_WR_DATA8(0x0D);
  209. LCD_WR_DATA8(0x0B);
  210. LCD_WR_DATA8(0x1F);
  211. LCD_WR_DATA8(0x23);
  212. LCD_WR_REG(0xE1);
  213. LCD_WR_DATA8(0xD0);
  214. LCD_WR_DATA8(0x04);
  215. LCD_WR_DATA8(0x0C);
  216. LCD_WR_DATA8(0x11);
  217. LCD_WR_DATA8(0x13);
  218. LCD_WR_DATA8(0x2C);
  219. LCD_WR_DATA8(0x3F);
  220. LCD_WR_DATA8(0x44);
  221. LCD_WR_DATA8(0x51);
  222. LCD_WR_DATA8(0x2F);
  223. LCD_WR_DATA8(0x1F);
  224. LCD_WR_DATA8(0x1F);
  225. LCD_WR_DATA8(0x20);
  226. LCD_WR_DATA8(0x23);
  227. LCD_WR_REG(0x21);
  228. LCD_WR_REG(0x11);
  229. //Delay (120);
  230. LCD_WR_REG(0x29);
  231. }
  232. /******************************************************************************
  233. 函数说明:LCD清屏函数
  234. 入口数据:无
  235. 返回值: 无
  236. ******************************************************************************/
  237. void LCD_Clear(u16 Color)
  238. {
  239. u16 i,j;
  240. LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
  241. for(i=0;i<LCD_W;i++)
  242. {
  243. for (j=0;j<LCD_H;j++)
  244. {
  245. LCD_WR_DATA(Color);
  246. }
  247. }
  248. }
  249. /******************************************************************************
  250. 函数说明:LCD显示汉字
  251. 入口数据:x,y 起始坐标
  252. index 汉字的序号
  253. size 字号
  254. 返回值: 无
  255. ******************************************************************************/
  256. //void LCD_ShowChinese(u16 x,u16 y,u8 index,u8 size,u16 color)
  257. //{
  258. // u8 i,j;
  259. // u8 *temp,size1;
  260. // if(size==16){temp=Hzk16;}//选择字号
  261. // if(size==32){temp=Hzk32;}
  262. // LCD_Address_Set(x,y,x+size-1,y+size-1); //设置一个汉字的区域
  263. // size1=size*size/8;//一个汉字所占的字节
  264. // temp+=index*size1;//写入的起始位置
  265. // for(j=0;j<size1;j++)
  266. // {
  267. // for(i=0;i<8;i++)
  268. // {
  269. // if((*temp&(1<<i))!=0)//从数据的低位开始读
  270. // {
  271. // LCD_WR_DATA(color);//点亮
  272. // }
  273. // else
  274. // {
  275. // LCD_WR_DATA(BACK_COLOR);//不点亮
  276. // }
  277. // }
  278. // temp++;
  279. // }
  280. //}
  281. /******************************************************************************
  282. 函数说明:LCD显示汉字
  283. 入口数据:x,y 起始坐标
  284. 返回值: 无
  285. ******************************************************************************/
  286. void LCD_DrawPoint(u16 x,u16 y,u16 color)
  287. {
  288. LCD_Address_Set(x,y,x,y);//设置光标位置
  289. LCD_WR_DATA(color);
  290. }
  291. /******************************************************************************
  292. 函数说明:LCD画一个大的点
  293. 入口数据:x,y 起始坐标
  294. 返回值: 无
  295. ******************************************************************************/
  296. void LCD_DrawPoint_big(u16 x,u16 y,u16 color)
  297. {
  298. LCD_Fill(x-1,y-1,x+1,y+1,color);
  299. }
  300. /******************************************************************************
  301. 函数说明:在指定区域填充颜色
  302. 入口数据:xsta,ysta 起始坐标
  303. xend,yend 终止坐标
  304. 返回值: 无
  305. ******************************************************************************/
  306. void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
  307. {
  308. u16 i,j;
  309. LCD_Address_Set(xsta,ysta,xend,yend); //设置光标位置
  310. for(i=ysta;i<=yend;i++)
  311. {
  312. for(j=xsta;j<=xend;j++)LCD_WR_DATA(color);//设置光标位置
  313. }
  314. }
  315. /******************************************************************************
  316. 函数说明:画线
  317. 入口数据:x1,y1 起始坐标
  318. x2,y2 终止坐标
  319. 返回值: 无
  320. ******************************************************************************/
  321. void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
  322. {
  323. u16 t;
  324. int xerr=0,yerr=0,delta_x,delta_y,distance;
  325. int incx,incy,uRow,uCol;
  326. delta_x=x2-x1; //计算坐标增量
  327. delta_y=y2-y1;
  328. uRow=x1;//画线起点坐标
  329. uCol=y1;
  330. if(delta_x>0)incx=1; //设置单步方向
  331. else if (delta_x==0)incx=0;//垂直线
  332. else {incx=-1;delta_x=-delta_x;}
  333. if(delta_y>0)incy=1;
  334. else if (delta_y==0)incy=0;//水平线
  335. else {incy=-1;delta_y=-delta_x;}
  336. if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
  337. else distance=delta_y;
  338. for(t=0;t<distance+1;t++)
  339. {
  340. LCD_DrawPoint(uRow,uCol,color);//画点
  341. xerr+=delta_x;
  342. yerr+=delta_y;
  343. if(xerr>distance)
  344. {
  345. xerr-=distance;
  346. uRow+=incx;
  347. }
  348. if(yerr>distance)
  349. {
  350. yerr-=distance;
  351. uCol+=incy;
  352. }
  353. }
  354. }
  355. /******************************************************************************
  356. 函数说明:画矩形
  357. 入口数据:x1,y1 起始坐标
  358. x2,y2 终止坐标
  359. 返回值: 无
  360. ******************************************************************************/
  361. void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
  362. {
  363. LCD_DrawLine(x1,y1,x2,y1,color);
  364. LCD_DrawLine(x1,y1,x1,y2,color);
  365. LCD_DrawLine(x1,y2,x2,y2,color);
  366. LCD_DrawLine(x2,y1,x2,y2,color);
  367. }
  368. /******************************************************************************
  369. 函数说明:画圆
  370. 入口数据:x0,y0 圆心坐标
  371. r 半径
  372. 返回值: 无
  373. ******************************************************************************/
  374. void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
  375. {
  376. int a,b;
  377. a=0;b=r;
  378. while(a<=b)
  379. {
  380. LCD_DrawPoint(x0-b,y0-a,color); //3
  381. LCD_DrawPoint(x0+b,y0-a,color); //0
  382. LCD_DrawPoint(x0-a,y0+b,color); //1
  383. LCD_DrawPoint(x0-a,y0-b,color); //2
  384. LCD_DrawPoint(x0+b,y0+a,color); //4
  385. LCD_DrawPoint(x0+a,y0-b,color); //5
  386. LCD_DrawPoint(x0+a,y0+b,color); //6
  387. LCD_DrawPoint(x0-b,y0+a,color); //7
  388. a++;
  389. if((a*a+b*b)>(r*r))//判断要画的点是否过远
  390. {
  391. b--;
  392. }
  393. }
  394. }
  395. /******************************************************************************
  396. 函数说明:显示字符
  397. 入口数据:x,y 起点坐标
  398. num 要显示的字符
  399. mode 1叠加方式 0非叠加方式
  400. 返回值: 无
  401. ******************************************************************************/
  402. void LCD_ShowChar(u16 x,u16 y,u8 num,u8 mode,u16 color)
  403. {
  404. u8 temp;
  405. u8 pos,t;
  406. u16 x0=x;
  407. if(x>LCD_W-16||y>LCD_H-16)return; //设置窗口
  408. num=num-' ';//得到偏移后的值
  409. LCD_Address_Set(x,y,x+8-1,y+16-1); //设置光标位置
  410. if(!mode) //非叠加方式
  411. {
  412. for(pos=0;pos<16;pos++)
  413. {
  414. temp=asc2_1608[(u16)num*16+pos]; //调用1608字体
  415. for(t=0;t<8;t++)
  416. {
  417. if(temp&0x01)LCD_WR_DATA(color);
  418. else LCD_WR_DATA(BACK_COLOR);
  419. temp>>=1;
  420. x++;
  421. }
  422. x=x0;
  423. y++;
  424. }
  425. }else//叠加方式
  426. {
  427. for(pos=0;pos<16;pos++)
  428. {
  429. temp=asc2_1608[(u16)num*16+pos]; //调用1608字体
  430. for(t=0;t<8;t++)
  431. {
  432. if(temp&0x01)LCD_DrawPoint(x+t,y+pos,color);//画一个点
  433. temp>>=1;
  434. }
  435. }
  436. }
  437. }
  438. /******************************************************************************
  439. 函数说明:显示字符串
  440. 入口数据:x,y 起点坐标
  441. *p 字符串起始地址
  442. 返回值: 无
  443. ******************************************************************************/
  444. void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 color)
  445. {
  446. while(*p!='\0')
  447. {
  448. if(x>LCD_W-16){x=0;y+=16;}
  449. if(y>LCD_H-16){y=x=0;LCD_Clear(RED);}
  450. LCD_ShowChar(x,y,*p,0,color);
  451. x+=8;
  452. p++;
  453. }
  454. }
  455. /******************************************************************************
  456. 函数说明:显示数字
  457. 入口数据:m底数,n指数
  458. 返回值: 无
  459. ******************************************************************************/
  460. u32 mypow(u8 m,u8 n)
  461. {
  462. u32 result=1;
  463. while(n--)result*=m;
  464. return result;
  465. }
  466. /******************************************************************************
  467. 函数说明:显示数字
  468. 入口数据:x,y 起点坐标
  469. num 要显示的数字
  470. len 要显示的数字个数
  471. 返回值: 无
  472. ******************************************************************************/
  473. void LCD_ShowNum(u16 x,u16 y,u16 num,u8 len,u16 color)
  474. {
  475. u8 t,temp;
  476. u8 enshow=0;
  477. for(t=0;t<len;t++)
  478. {
  479. temp=(num/mypow(10,len-t-1))%10;
  480. if(enshow==0&&t<(len-1))
  481. {
  482. if(temp==0)
  483. {
  484. LCD_ShowChar(x+8*t,y,' ',0,color);
  485. continue;
  486. }else enshow=1;
  487. }
  488. LCD_ShowChar(x+8*t,y,temp+48,0,color);
  489. }
  490. }
  491. /******************************************************************************
  492. 函数说明:显示小数
  493. 入口数据:x,y 起点坐标
  494. num 要显示的小数
  495. len 要显示的数字个数
  496. 返回值: 无
  497. ******************************************************************************/
  498. void LCD_ShowNum1(u16 x,u16 y,float num,u8 len,u16 color)
  499. {
  500. u8 t,temp;
  501. u16 num1;
  502. num1=num*100;
  503. for(t=0;t<len;t++)
  504. {
  505. temp=(num1/mypow(10,len-t-1))%10;
  506. if(t==(len-2))
  507. {
  508. LCD_ShowChar(x+8*(len-2),y,'.',0,color);
  509. t++;
  510. len+=1;
  511. }
  512. LCD_ShowChar(x+8*t,y,temp+48,0,color);
  513. }
  514. }
  515. /******************************************************************************
  516. 函数说明:显示40x40图片
  517. 入口数据:x,y 起点坐标
  518. 返回值: 无
  519. ******************************************************************************/
  520. //void LCD_ShowPicture(u16 x1,u16 y1,u16 x2,u16 y2)
  521. //{
  522. // int i;
  523. // LCD_Address_Set(x1,y1,x2,y2);
  524. // for(i=0;i<1600;i++)
  525. // {
  526. // LCD_WR_DATA8(image[i*2+1]);
  527. // LCD_WR_DATA8(image[i*2]);
  528. // }
  529. //}