标题: 提问个OLED的显示程序问题 [打印本页]

作者: 高手本人    时间: 2018-11-16 14:40
标题: 提问个OLED的显示程序问题
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;  
while(n--)result*=m;   
return result;
}       //这一段我理解的。

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{         
u8 t,temp;
u8 enshow=0;         
for(t=0;t<len;t++)
{
  temp=(num/oled_pow(10,len-t-1))%10;//这里算出来到底是什么数
  if(enshow==0&&t<(len-1))
  {
   if(temp==0)
   {
    OLED_ShowChar(x+(size2/2)*t,y,' ');//这里的' '怎么和阿斯克码表对上的
    continue;
   }else enshow=1;
     
  }
   OLED_ShowChar(x+(size2/2)*t,y,temp+'0'); //这里又为什么+0
}
}   



作者: 凌净清河    时间: 2018-11-17 17:44
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;  
while(n--)result*=m;   
return result;
}

这个函数我觉得你并不理解,不然也就不会不明白temp指的是什么了。现在我给你分析一下,就按照我最开始的思路来读程序,跟着我一步一步走好了:

根据函数名,我们可以大概了解这个函数的功能是显示一个数字,传入的参数是X坐标(字符在一行的哪一个位置)、y坐标(字符显示在哪一个行)、一个待显示的数据、数据的长度和显示字符的跨度

enshow是一个使能标志,那么这个使能位是在什么时候起作用,什么时候关闭呢?

if(enshow==0&&t<(len-1))

这一句的意思你明白,是当这个enshow为0并且再数据长度范围内的时候,进行temp==0的判断,而不满足这个条件,enshow就会置1,显然,是在判断数据传输是否完成,并且在达到给定的数据长度后终止传输。

纵观函数的结构可以看出,在许可长度范围内,函数循环计算一个temp量,从最后一句
OLED_ShowChar(x+(size2/2)*t,y,temp+'0');
可以看到,这个temp实际上是待显示位数字,比如1,2,3...而不是数字的ASCII码,所以这里需要以‘0’做基准把数字转换为其ASCII码,可以猜测,OLED_ShowChar()函数是传入一个ASCII码,在ASCII码字模表中取模显示对应的字符。






知道了temp是什么意思,我们反过来看temp是如何求得的:

temp=(num/oled_pow(10,len-t-1))%10

这句中,num是待显示的数据,我们知道了该显示函数是按位取出num,那么这一句的作用必然是按位取数,结尾的%10(取余运算)表明所取的数是前面所求整数数据的最后一位。

现在到了最关键的部分了
oled_pow(10,len-t-1)返回的是一个什么数据?

将实参代入形参即m为累乘数据,n为数据长度-已处理位数-1
(此处的减一是为了适应C语言计数到“0”为止)

u32 oled_pow(u8 m,u8 n)
{
u32 result=1;  
while(n--)result*=m;   
return result;
}
翻译一下:
结果值result初始值为1;
当 在长度范围内 时,结果值=结果值*累乘数据
返回 结果值

也就是说,返回的是(10)^(显示的长度)

这样,num/oled_pow(10,len-t-1)指的是对指定长度取模(取num定长)

例如:num=1325416;显示长度为5,那么num/oled_pow(10,len-t-1)运算之后就是13。在这个结果上再对10取余就是最后一位。
由于t的变化,可以遍历每一位。

但是如果数据在变化,那当数据位数过少的时候,前面位会显示什么呢?是0。例如规定显示5位,但是实际上数据只有2位,那显示就会变成000XX,为了美观,也要把这个0干掉。

事实上,
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ');
continue;
}
就是干这个工作的,当取出的位为0的时候,就用空格代替改数值达到消隐无效0的作用。从上面的分析我们可以知道,这个传入的ASCII码应该是由一个char类型的值在接收,所以这里的空格会以ASCII码的形式存入形参。



我想我应该讲完了,你的三个问题答案整理如下:

1.temp=(num/oled_pow(10,len-t-1))%10;//这里算出来到底是什么数
答:该出算出的是本次要显示的位对应的数值

2.OLED_ShowChar(x+(size2/2)*t,y,'');//这里的''怎么和阿斯克码表对上的
答:猜测接收的形参是char类型,所以空格直接以字符型存入了(即存入的是空格的ASCII码)

3.OLED_ShowChar(x+(size2/2)*t,y,temp+'0'); //这里又为什么+0
答:因为需要以0为基准将数字类型转为对应的ASCII码。


打字不易,希望认真读懂为好。
作者: 奇异的想法    时间: 2019-7-20 20:00
凌净清河 发表于 2018-11-17 17:44
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;  

感谢一楼大佬的仔细讲解。多谢大佬

作者: ahweixiao    时间: 2019-8-24 01:40
太厉害,佩服学习了
作者: lkjdf    时间: 2019-11-18 15:07
感謝大佬的講解,一目了然
作者: 我洒脱也木槿    时间: 2020-1-20 19:38
谢谢一楼大佬的细心讲解
作者: 丽莎兰曦    时间: 2020-1-22 15:46
谢谢一楼大佬
作者: 高手本人    时间: 2020-4-30 12:42
感谢一楼大佬耐心讲解
作者: Lizhaojun97    时间: 2021-1-8 00:29
凌净清河 发表于 2018-11-17 17:44
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;  

1325416不是应该显示为7位吗?为什么是说显示为5位呢?
作者: Lizhaojun97    时间: 2021-1-8 00:47
凌净清河 发表于 2018-11-17 17:44
u32 oled_pow(u8 m,u8 n)
{
u32 result=1;  

非常感谢您的讲解,我已经理解这个函数的功能和作用过程了。再次表示深切的感谢。
作者: whisper01    时间: 2021-2-14 19:10
谢大佬,自己看了半天也没明白,看了讲解瞬间理解,太强了
作者: 清风竹影69    时间: 2021-11-26 09:37
例如:num=1325416;显示长度为5,那么num/oled_pow(10,len-t-1)运算之后就是13。在这个结果上再对10取余就是最后一位。
改为下面这种说法容易懂一些(“显示长度为5”的说法太突然,的确令人困惑):
例如:num=1325416;如果己经显示了25416这五位数,紧接着需要显示“3”,那么可以用语句num/oled_pow(10,len-t-1)进行运算得到结果“13”。在这个结果上“13”再对10取余就得到“3”。




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1