99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

程序員小哈
認證:優質創作者
作者動態
自動洗碗機綜合實例第二講 - 最小系統核心板PCB繪制
2024-07-18 09:21
自動洗碗機綜合實例第一講 - 最小系統核心板原理圖繪制
2024-07-16 09:40
線路板焊接的干貨都在這里呢
2024-07-14 12:08
基于單片機的智能風扇DIY總結
2024-07-13 14:42
基于HAL庫實現按鍵(外部中斷)翻轉一個LED
2024-06-30 14:02

讓數據顯示更直觀——OLED曲線顯示

問題由來

前兩天有網友留言,能否做一個顯示波形的實例,之前也有人提過類似問題,那么今天我們就來安排一下。

問題分析

我們在網上經常能看到一些大佬用0.96寸OLED制作的迷你示波器。

制作這個mini示波器,界面中的曲線繪制是一個難點。

小哈哥的主要工作是做上位機VC++開發的,由于要做譜圖顯示,所以也用到了曲線的繪制,下圖中就是使用VC++進行曲線繪制的部分代碼,我們可以看出,曲線是由一系列首尾相連的直線組成,所以要想繪制曲線,首先要實現移動到線條起點的函數MoveTo,以及實現畫線的函數LineTo

因為直線(其實說成線段更好)是由多個點組成,所以我們要實現畫線的函數,只要實現畫點的函數即可,然后在計算出來的位置依次畫點,即可實現直線的繪制。

實現目標

  • 實現畫點函數
  • 封裝畫點函數,進而實現畫線函數
  • 繪制一個三角形

顯示原理

OLED的核心驅動芯片是SSD1306,單片機與SSD1306通信,SSD1306再驅動OLED點亮對應的OLED像素點。

要想實現繪制三角形,我們就要先實現畫點繪制直線的函數,在這之前,我們先了解一下OLED的顯示原理。

OLED的構造

OLED由128*64個像素組成,64行和128列。

圖中每個晶格表示一位圖像數據,這些像素點對應SSD1306內部的一個GDDRAM數據內存,它有128*8字節,即128*64bit,每一個位對應一個像素點。

其中,每8行組成一個PAGE,該OLED一共分為8個PAGE(PAGE0~PAGE7)。

我們控制顯示的內容,只需要控制SSD1306的內部GDDRAM即可。下面是封裝的刷新GDDRAM的函數,其中 unsigned char OLED_GRAM[128][8]; 中緩存的就是待顯示的內容,我們先將要顯示的內容賦值給這個數組,然后將這個數組整體寫入GDDRAM即可,如果這個數組內的數據都為0,則相當于將顯示屏清屏(不顯示內容)。

void OLED_Refresh_Gram(void)
{
    unsigned char i,n;
    for(i=0;i<8;i++)
    {
        OLED_WR_Byte(0xb0+i,OLED_CMD);  //設置頁地址(0~7)
        OLED_WR_Byte(0x00,OLED_CMD);    //設置顯示位置—列低地址
        OLED_WR_Byte(0x10,OLED_CMD);    //設置顯示位置—列高地址  
         
        for(n=0;n<128;n++)  //寫一PAGE的GDDRAM數據
        {
            OLED_WR_Byte(OLED_GRAM[n][i],1);
        }
    }
}

畫點函數

由于 OLED_WR_Byte(OLED_GRAM[n][i],1); 函數一次操作一個字節,所以我們不能一次控制一個像素點,只能8個像素點一起控制;而且是垂直方向掃描控制;如下圖所示。因此垂直方向坐標可選為0~7;(8*8=64);水平方向可選坐標0~127。

我們封裝的畫點函數,即隨便給一個點的坐標(x,y),我們要計算出,這個像素點所屬的PAGE,然后看控制的是這列8個像素(對應一個字節數據)中的哪一個(對應1 bit數據)。

void OLED_DrawDot(unsigned char x,unsigned char y,unsigned char t)
{
 unsigned char pos,bx,temp=0;
    
 // 此OLED的分辨率為128*64,橫坐標大于127,縱坐標大于63,則參數非法 
    
 if(x>127||y>63) return;
    
 // 因為此OLED是按頁顯示,每頁8個像素,所以/8用于計算待顯示的點在哪頁中
 pos=(y)/8;
    
 // 一列中有8個像素,所以計算一下待顯示的點,在當前列中的第幾個點
 bx=y%8;
    
 // 移位,讓temp的第bx位為1
 temp=1<<(bx);
    
 if(t) 
  OLED_GRAM[x][pos]|=temp;  //第bx位,置1,其他位值不變
 else 
  OLED_GRAM[x][pos]&=~temp;  //第bx位,置0,其他位值不變
        
 // 刷新整個液晶屏
 OLED_Refresh_Gram(); 
}

參數說明:

  • x:顯示的橫坐標,即一行128個像素中的哪一個像素點
  • y:顯示的縱坐標,即一列64個像素中的哪一個像素點
  • t:0表示該像素不顯示,1表示該像素顯示

畫線函數

畫點的函數我們已經實現了,那么要想畫一條直線,我們就要計算出直線上都有哪些點,將直線上的點依次用畫點函數繪制出來,即完成了直線的繪制。

那怎么來求得直線上的任意點的坐標呢?如下圖所示,一般繪制一個直線都會給兩個已知點(x1,y1),(x2,y2),有了這兩個點的坐標,我們就可以求出這條直線的斜率,然后根據這個斜率和橫軸的范圍(x1,x2),依次代入直線方程,即可求出所有直線上的點的坐標。

我們舉個栗子,加深一下理解:

如果(x1=32,y1=48),(x2=96,y2=16),那么:

曲線斜率:K =(16-48)/(96-32)= -0.5==>該曲線上任意點坐標關系為:y = 48+K*(x – 32)

如果x=64, 因為 K=-0.5,所以 y=48-0.5*(64-32)=32 。

所以,(x=64,y=32)。

利用斜率法,我們封裝畫線函數如下:

void OLED_DrawLine(unsigned int x1, unsigned int y1, unsigned int x2,unsigned int y2)
{
 unsigned int t; 
 int offset_x,offset_y; 
 int incx,incy,uRow,uCol; 
 float K = 0.0f;
 offset_x=x2-x1;
 offset_y=y2-y1; 
 uRow=x1; 
 uCol=y1; 
 if(offset_x>0)
  incx=1;
 else if(offset_x==0)
  incx=0;    //垂直線
 else 
 {
  incx=-1;
  offset_x=-offset_x;
 }
 
 if(offset_y>0)
  incy=1;
 else if(offset_y==0)
  incy=0;    //水平線
 else
 {
  incy=-1;
  offset_y=-offset_y;
 }

 if(incx==0)
 {
  for(t=0;t<=offset_y+1;t++ )
  { 
   OLED_DrawDot(uRow,uCol+t*incy,1);
  }
 }
 else if(incy==0)
 {
  for(t=0;t<=offset_x+1;t++ )
  { 
   OLED_DrawDot(uRow+t*incx,uCol,1);
  }
 }
 else
 {
  K = (float)(((float)y2-(float)y1)*1.000/((float)x2-(float)x1));
  printf("K=%.3f\r\n",K);
  for(t=0;t<=offset_x+1;t++ )
  { 
   printf("X=%d,Y=%d\r\n",uRow+t,(u8)(uCol+t*K));
   OLED_DrawDot(uRow+t,(u8)(uCol+t*K),1);
  }
 }
}

注意:因為水平線和垂直線比較特殊,所以上面函數中對這兩種情況進行了單獨的繪制,沒有使用斜率法計算直線上的坐標。

結果展示

我們按如下坐標繪制一個三角形:

有了畫線函數,我們只要將上面三個點的坐標依次代入畫線函數即可,繪制三角形的代碼具體如下所示:

OLED_DrawLine(32, 48, 96,16);
OLED_DrawLine(96, 16, 96,48);
OLED_DrawLine(96, 48, 32,48);

編譯代碼生成結果如下:

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 1
收藏 3
關注 69
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 国产精妇在线观看第一区 | 欧美成人免费全部观看天天性色 | 在线看片免费人成视频影院看 | 国产精品r级最新在线观看 一区三区在线观看 | 天天躁日日躁狠狠躁aab吃奶 | 国产91精品一区二区三区四区 | 中国国语毛片免费观看视频 | 337P大尺度啪啪人体 | 成人黄网视频在线观看 | 男女免费av| 中文无码一区二区视频在线播放 | aⅴ小次郎改为av小四郎 | 少妇大胆瓣开下部自慰 | 欧美交换配乱吟粗大 | 国产精品久久久亚洲 | 中文字幕一区视频 | 久久精品国产欧美 | 日韩黄色一级片 | 国产下药迷晕一区二区三区在线看 | 欧美美女久久 | 亚洲区激情区无码区日韩区 | 久久国产亚洲精品 | 中文在线中文a | 影视先锋男人无码在线 | 中文字幕第36页 | 国产精品久久久亚洲一区 | 99精品观看 | 一区三区在线专区在线 | 91精品论坛| 美国av一区二区 | 国产中老年妇女精品 | 国产91精品久久久久 | 亚洲高清一区二 | 中文一区二区三区四区 | 91成人破解版| 免费乱码人妻系列无码专区 | 久久久精品久久 | 亚洲男同帅GAY片在线观看 | 四虎影院www | 欧美在线专区 | 国产精品久久久久久AV福利 |