OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6455|回复: 0

OLED实验画点函数的理解与修改心得分享

[复制链接]

7

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2018-6-20
在线时间
45 小时
发表于 2023-1-12 19:35:14 | 显示全部楼层 |阅读模式
本帖最后由 ningzhen 于 2023-1-12 19:38 编辑

一、理解原子哥的画点函数
我想很多同学都和我一样,最懵圈的就是一件事:x,y的坐标是以哪里为原点的坐标系?
http://47.111.11.73/forum.php?mo ... hlight=%BB%AD%B5%E3
从这个帖子原子的回复,我知道了是以插在开发板之后的左上角为原点,向右向下的坐标系。

结合各位先进的帖子、SSD1306手册和实际仿真理解此画点函数:
void OLED_DrawPoint(u8 x,u8 y,u8 t);

1.OLED模块放在手里,插座在右下时,OLED才是正放;当OLED模块插在开发板上时,其实是倒着的(相当于逆时针旋转了180度);

2.OLED正放时,按数据手册,无重映射的情况下,是从左到右0->127,从上到下PAGE0->PAGE7,COM0->COM63(COM我的理解是硬件的顺序),每个字节低位在上,高位在下,如图1,图2
1 GDDRAM的PAGE和COM排列.png

2 正放时字节的高低位次序.png
3.OLED旋转180度安装到开发板上,所以编写程序时,在初始化函数中,通过
  1. OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
复制代码
这样一条命令,将列地址(即x轴)重映射re-mapping了,所以x轴还是从左到右0->127。而y轴却没有重映射,所以y轴现在PAGE0->PAGE7,row0->row63都是从下到上递增的,
每写一个字节,也是高位在上低位在下了,如图3
3 原子哥程序的坐标.jpg
而画点函数的坐标系是如何建立的呢?答案是以左上角为原点,向右向下建系(在主函数里清屏然后OLED_DrawPoint(100,7,1))再停住,验证一下就知道了)。
所以(100,29)的页数是7-y/8=4,该坐标的字节的bit7(最上面,y坐标24)写1然后右移(y%8)位,即bit2写1,就相当于最低位(最下面,y坐标31)写1然后左移(7-y%8)=2位。

4.在将GRAM写入OLED的OLED_Refresh_Gram()中,我们注意到是给出了页地址和列起始地址,然后自动一列一列的写完了一页,再自动加页。
  1. void OLED_Refresh_Gram(void)
  2. {
  3.   u8 i,n;                    
  4.   for(i=0;i<8;i++)  
  5.   {  
  6.     OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
  7.     OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
  8.     OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
  9.     for(n=0;n<128;n++)
  10.     OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
  11.   }   
  12. }
复制代码
先写PAGE0,最后写PAGE7。PAGE0对应的是OLED_GRAM[n][0],PAGE7对应OLED_GRAM[n][7],也就是说我们定义的OLED_GRAM和此时倒过来的OLED显示区域就是一一对应的了。

千万不要将画点函数的y坐标与OLED_GRAM[n]的纵坐标i弄混,二者是经过转换的。还是以(100,7)(当然是右下坐标系)的画点为例,该点的位置预计在OLED的右上部分,
转换成OLED_GRAM[100][7]的确是在右上角的一个字节。

其实可以仿真一下程序,在主函数只保留显示"ALIENTEK",然后在OLED_Refresh_Gram(void)单步运行,就很清楚的看出来扫描显示的过程了。


二、一种修改原子哥画点函数y坐标的思路与实验
http://47.111.11.73/forum.php?mo ... hlight=%BB%AD%B5%E3
就是按照这位先进的思路走吧,但是我认为二维数组部分可以不动,只需要在OLED初始化中把y轴的扫描方向也重定义下,即从COM63->COM0进行扫描,相当于把y轴也re-mapping了,
  1. OLED_WR_Byte(0xC8,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
复制代码
还是看图1的绿色字体的部分,现在倒过来的OLED模块从上到下是COM63->COM0,就是从上到下PAGE0->PAGE7,row0->row63,每个字节也是低位在上,高位在下,所有的坐标都统一为右下坐标系,如图4:
4 re-mapping Y轴后的坐标.jpg
这样画点函数中,(x,y)画点就是
OLED_GRAM[x][y/8] |= 1<<(y%8);
也就是说,我们定义的OLED_GRAM[n]数组,现在也是纵坐标越小越在上面了。

那么是否需要修改取字模的时候的顺向(高前低后)为逆向(低前高后)呢?
答案是不需要。因为这个和OLED的扫描方向无关,只和OLED_ShowChar();函数有关:
  1. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
  2. {                                 
  3.     ......
  4.     for(t1=0;t1<8;t1++)
  5.     {
  6.         if(temp&0x80)    //y坐标越小,位置越靠上,对应的字模的字节的位越高
  7.              OLED_DrawPoint(x,y,mode);
  8.         else
  9.              OLED_DrawPoint(x,y,!mode);
  10.         temp<<=1;    //左移temp一位,即从最高位开始取,取到最低位
  11.         y++;
  12.         if((y-y0)==size)   
  13.         {
  14.             y=y0;    //取完本列了,开始下一列
  15.             x++;
  16.             break;
  17.         }
  18.     }
  19. }
复制代码
以写入字符的位置坐标为起点,从字符模的最高位逐位取到最低位,同时纵坐标从y逐次加到(y+size),也就是从上到下写完这个字符的第一列,然后换行。本函数只是调用画点函数,不管画点或者后面是怎么实现的。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 23:10

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表