oled.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. #include "oled.h"
  2. #include "oledfont.h"
  3. #include "main.h"
  4. uint8_t OLED_GRAM[144][8];
  5. extern bool interface_work ;
  6. //画点
  7. //x:0~127
  8. //y:0~63
  9. //t:1 填充 0,清空
  10. void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t)
  11. {
  12. uint8_t i,m,n;
  13. i=y/8;
  14. m=y%8;
  15. n=1<<m;
  16. if(t){OLED_GRAM[x][i]|=n;}
  17. else
  18. {
  19. OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  20. OLED_GRAM[x][i]|=n;
  21. OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  22. }
  23. }
  24. //画线
  25. //x1,y1:起点坐标
  26. //x2,y2:结束坐标
  27. void OLED_DrawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t mode)
  28. {
  29. uint16_t t;
  30. int xerr=0,yerr=0,delta_x,delta_y,distance;
  31. int incx,incy,uRow,uCol;
  32. delta_x=x2-x1; //计算坐标增量
  33. delta_y=y2-y1;
  34. uRow=x1;//画线起点坐标
  35. uCol=y1;
  36. if(delta_x>0)incx=1; //设置单步方向
  37. else if (delta_x==0)incx=0;//垂直线
  38. else {incx=-1;delta_x=-delta_x;}
  39. if(delta_y>0)incy=1;
  40. else if (delta_y==0)incy=0;//水平线
  41. else {incy=-1;delta_y=-delta_x;}
  42. if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
  43. else distance=delta_y;
  44. for(t=0;t<distance+1;t++)
  45. {
  46. OLED_DrawPoint(uRow,uCol,mode);//画点
  47. xerr+=delta_x;
  48. yerr+=delta_y;
  49. if(xerr>distance)
  50. {
  51. xerr-=distance;
  52. uRow+=incx;
  53. }
  54. if(yerr>distance)
  55. {
  56. yerr-=distance;
  57. uCol+=incy;
  58. }
  59. }
  60. }
  61. //x,y:圆心坐标
  62. //r:圆的半径
  63. void OLED_DrawCircle(uint8_t x,uint8_t y,uint8_t r)
  64. {
  65. int a, b,num;
  66. a = 0;
  67. b = r;
  68. while(2 * b * b >= r * r)
  69. {
  70. OLED_DrawPoint(x + a, y - b,1);
  71. OLED_DrawPoint(x - a, y - b,1);
  72. OLED_DrawPoint(x - a, y + b,1);
  73. OLED_DrawPoint(x + a, y + b,1);
  74. OLED_DrawPoint(x + b, y + a,1);
  75. OLED_DrawPoint(x + b, y - a,1);
  76. OLED_DrawPoint(x - b, y - a,1);
  77. OLED_DrawPoint(x - b, y + a,1);
  78. a++;
  79. num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
  80. if(num > 0)
  81. {
  82. b--;
  83. a--;
  84. }
  85. }
  86. }
  87. void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
  88. {
  89. uint8_t i;
  90. if(cmd)
  91. {
  92. OLED_DC_Set();
  93. }
  94. else
  95. OLED_DC_Clr();
  96. OLED_CS_Clr();
  97. for(i=0;i<8;i++)
  98. {
  99. OLED_SCL_Clr();
  100. if(dat&0x80)
  101. {
  102. OLED_SDA_Set();
  103. }
  104. else
  105. OLED_SDA_Clr();
  106. OLED_SCL_Set();
  107. dat<<=1;
  108. }
  109. OLED_CS_Set();
  110. OLED_DC_Set();
  111. }
  112. //反显函数
  113. void OLED_ColorTurn(uint8_t i)
  114. {
  115. if(i==0)
  116. {
  117. OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
  118. }
  119. if(i==1)
  120. {
  121. OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
  122. }
  123. }
  124. //屏幕旋转180度
  125. void OLED_DisplayTurn(uint8_t i)
  126. {
  127. if(i==0)
  128. {
  129. OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
  130. OLED_WR_Byte(0xA1,OLED_CMD);
  131. }
  132. if(i==1)
  133. {
  134. OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
  135. OLED_WR_Byte(0xA0,OLED_CMD);
  136. }
  137. }
  138. //开启OLED显示
  139. void OLED_DisPlay_On(void)
  140. {
  141. OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
  142. OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
  143. OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
  144. }
  145. //关闭OLED显示
  146. void OLED_DisPlay_Off(void)
  147. {
  148. OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
  149. OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
  150. OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
  151. }
  152. //更新显存到OLED
  153. void OLED_Refresh(void)
  154. {
  155. uint8_t i,n;
  156. for(i=0;i<8;i++)
  157. {
  158. OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
  159. OLED_WR_Byte(0x02,OLED_CMD); //设置低列起始地址
  160. OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址
  161. for(n=0;n<128;n++)
  162. OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
  163. }
  164. }
  165. //清屏函数
  166. void OLED_Clear(void)
  167. {
  168. uint8_t i,n;
  169. for(i=0;i<8;i++)
  170. {
  171. for(n=0;n<128;n++)
  172. {
  173. OLED_GRAM[n][i]=0;//清除所有数据
  174. }
  175. }
  176. OLED_Refresh();//更新显示
  177. #ifdef ClearOled
  178. #if ClearOled == 1
  179. printf("Clear_OLED\r\n");
  180. #endif
  181. #endif
  182. }
  183. //在指定位置显示一个字符,包括部分字符
  184. //x:0~127
  185. //y:0~63
  186. //size1:选择字体 6x8/6x12/8x16/12x24
  187. //mode:0,反色显示;1,正常显示
  188. void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size1,uint8_t mode)
  189. {
  190. uint8_t i,m,temp,size2,chr1;
  191. uint8_t x0=x,y0=y;
  192. if(size1==8)size2=6;
  193. else size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数
  194. chr1=chr-' '; //计算偏移后的值
  195. for(i=0;i<size2;i++)
  196. {
  197. if(size1==8)
  198. {temp=asc2_0806[chr1][i];} //调用0806字体
  199. else if(size1==12)
  200. {temp=asc2_1206[chr1][i];} //调用1206字体
  201. else if(size1==16)
  202. {temp=asc2_1608[chr1][i];} //调用1608字体
  203. else if(size1==24)
  204. {temp=asc2_2412[chr1][i];} //调用2412字体
  205. else return;
  206. for(m=0;m<8;m++)
  207. {
  208. if(temp&0x01)
  209. {
  210. OLED_DrawPoint(x,y,mode);
  211. }
  212. else
  213. {
  214. OLED_DrawPoint(x,y,!mode);
  215. }
  216. temp>>=1;
  217. y++;
  218. }
  219. x++;
  220. if((size1!=8)&&((x-x0)==size1/2))
  221. {x=x0;y0=y0+8;}
  222. y=y0;
  223. }
  224. }
  225. //显示字符串
  226. //x,y:起点坐标
  227. //size1:字体大小
  228. //*chr:字符串起始地址
  229. //mode:0,反色显示;1,正常显示
  230. void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t size1,uint8_t mode)
  231. {
  232. while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
  233. {
  234. OLED_ShowChar(x,y,*chr,size1,mode);
  235. if(size1==8)x+=6;
  236. else x+=size1/2;
  237. chr++;
  238. }
  239. }
  240. //m^n
  241. uint32_t OLED_Pow(uint8_t m,uint8_t n)
  242. {
  243. uint32_t result=1;
  244. while(n--)
  245. {
  246. result*=m;
  247. }
  248. return result;
  249. }
  250. //显示数字
  251. //x,y :起点坐标
  252. //num :要显示的数字
  253. //len :数字的位数
  254. //size:字体大小
  255. //mode:0,反色显示;1,正常显示
  256. void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size1,uint8_t mode)
  257. {
  258. uint8_t t,temp,m=0;
  259. if(size1==8)m=2;
  260. for(t=0;t<len;t++)
  261. {
  262. temp=(num/OLED_Pow(10,len-t-1))%10;
  263. if(temp==0)
  264. {
  265. OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
  266. }
  267. else
  268. {
  269. OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
  270. }
  271. }
  272. }
  273. //显示汉字
  274. //x,y:起点坐标
  275. //num:汉字对应的序号
  276. //mode:0,反色显示;1,正常显示
  277. void OLED_ShowChinese(uint8_t x,uint8_t y,uint8_t num,uint8_t size1,uint8_t mode)
  278. {
  279. uint8_t m,temp;
  280. uint8_t x0=x,y0=y;
  281. uint16_t i,size3=(size1/8+((size1%8)?1:0))*size1; //得到字体一个字符对应点阵集所占的字节数
  282. for(i=0;i<size3;i++)
  283. {
  284. if(size1==16)
  285. {temp=Hzk1[num][i];}//调用16*16字体
  286. else if(size1==24)
  287. {temp=Hzk2[num][i];}//调用24*24字体
  288. else if(size1==32)
  289. {temp=Hzk3[num][i];}//调用32*32字体
  290. else if(size1==64)
  291. {temp=Hzk4[num][i];}//调用64*64字体
  292. else if(size1==12)
  293. {temp=Hzk5[num][i];}//调用12*12字体
  294. else if(size1==14)
  295. {temp=Hzk6[num][i];}//调用14*14字体
  296. else if(size1==18)
  297. {temp=Hzk7[num][i];}//调用18*18字体
  298. else if(size1==15)
  299. {temp=Hzk8[num][i];}//调用15*15字体
  300. else return;
  301. for(m=0;m<8;m++)
  302. {
  303. if(temp&0x01)OLED_DrawPoint(x,y,mode);
  304. else OLED_DrawPoint(x,y,!mode);
  305. temp>>=1;
  306. y++;
  307. }
  308. x++;
  309. if((x-x0)==size1)
  310. {x=x0;y0=y0+8;}
  311. y=y0;
  312. }
  313. }
  314. //num 显示汉字的个数
  315. //space 每一遍显示的间隔
  316. //mode:0,反色显示;1,正常显示
  317. void OLED_ScrollDisplay(uint8_t num,uint8_t space,uint8_t mode)
  318. {
  319. uint8_t i,n,t=0,m=0,r;
  320. while(1)
  321. {
  322. if(m==0)
  323. {
  324. OLED_ShowChinese(128,24,t,16,mode); //写入一个汉字保存在OLED_GRAM[][]数组中
  325. t++;
  326. }
  327. if(t==num)
  328. {
  329. for(r=0;r<16*space;r++) //显示间隔
  330. {
  331. for(i=1;i<144;i++)
  332. {
  333. for(n=0;n<8;n++)
  334. {
  335. OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
  336. }
  337. }
  338. OLED_Refresh();
  339. }
  340. t=0;
  341. }
  342. m++;
  343. if(m==16){m=0;}
  344. for(i=1;i<144;i++) //实现左移
  345. {
  346. for(n=0;n<8;n++)
  347. {
  348. OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
  349. }
  350. }
  351. OLED_Refresh();
  352. }
  353. }
  354. //x,y:起点坐标
  355. //sizex,sizey,图片长宽
  356. //BMP[]:要写入的图片数组
  357. //mode:0,反色显示;1,正常显示
  358. void OLED_ShowPicture(uint8_t x,uint8_t y,uint8_t sizex,uint8_t sizey,uint8_t BMP[],uint8_t mode)
  359. {
  360. uint16_t j=0;
  361. uint8_t i,n,temp,m;
  362. uint8_t x0=x,y0=y;
  363. sizey=sizey/8+((sizey%8)?1:0);
  364. for(n=0;n<sizey;n++)
  365. {
  366. for(i=0;i<sizex;i++)
  367. {
  368. temp=BMP[j];
  369. j++;
  370. for(m=0;m<8;m++)
  371. {
  372. if(temp&0x01)
  373. {
  374. OLED_DrawPoint(x,y,mode);
  375. }
  376. else
  377. {
  378. OLED_DrawPoint(x,y,!mode);
  379. }
  380. temp>>=1;
  381. y++;
  382. }
  383. x++;
  384. if((x-x0)==sizex)
  385. {
  386. x=x0;
  387. y0=y0+8;
  388. }
  389. y=y0;
  390. }
  391. }
  392. }
  393. //OLED的初始化
  394. void OLED_Init(void)
  395. {
  396. GPIO_InitTypeDef GPIO_InitStructure;
  397. GPIO_InitStructure.Pin = GPIO_PIN_5|GPIO_PIN_7;
  398. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  399. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_MEDIUM;//速度50MHz
  400. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  401. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5|GPIO_PIN_7,GPIO_PIN_SET);
  402. OLED_RES_Clr();
  403. HAL_Delay(200);
  404. OLED_RES_Set();
  405. OLED_WR_Byte(0xAE,OLED_CMD); /*display off*/
  406. OLED_WR_Byte(0x02,OLED_CMD); /*set lower column address*/
  407. OLED_WR_Byte(0x10,OLED_CMD); /*set higher column address*/
  408. OLED_WR_Byte(0x40,OLED_CMD); /*set display start line*/
  409. OLED_WR_Byte(0xB0,OLED_CMD); /*set page address*/
  410. OLED_WR_Byte(0x81,OLED_CMD); /*contract control*/
  411. OLED_WR_Byte(0xcf,OLED_CMD); /*128*/
  412. OLED_WR_Byte(0xA1,OLED_CMD); /*set segment remap*/
  413. OLED_WR_Byte(0xA6,OLED_CMD); /*normal / reverse*/
  414. OLED_WR_Byte(0xA8,OLED_CMD); /*multiplex ratio*/
  415. OLED_WR_Byte(0x3F,OLED_CMD); /*duty = 1/64*/
  416. OLED_WR_Byte(0xad,OLED_CMD); /*set charge pump enable*/
  417. OLED_WR_Byte(0x8b,OLED_CMD); /* 0x8B 内供 VCC */
  418. OLED_WR_Byte(0x33,OLED_CMD); /*0X30---0X33 set VPP 9V */
  419. OLED_WR_Byte(0xC8,OLED_CMD); /*Com scan direction*/
  420. OLED_WR_Byte(0xD3,OLED_CMD); /*set display offset*/
  421. OLED_WR_Byte(0x00,OLED_CMD); /* 0x20 */
  422. OLED_WR_Byte(0xD5,OLED_CMD); /*set osc division*/
  423. OLED_WR_Byte(0x80,OLED_CMD);
  424. OLED_WR_Byte(0xD9,OLED_CMD); /*set pre-charge period*/
  425. OLED_WR_Byte(0x1f,OLED_CMD); /*0x22*/
  426. OLED_WR_Byte(0xDA,OLED_CMD); /*set COM pins*/
  427. OLED_WR_Byte(0x12,OLED_CMD);
  428. OLED_WR_Byte(0xdb,OLED_CMD); /*set vcomh*/
  429. OLED_WR_Byte(0x40,OLED_CMD);
  430. OLED_Clear();
  431. OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/
  432. //printf("ok");
  433. }