国产免费AV|泡泡玛特欧洲总部将设在伦敦|中文天堂网www新版资源在线|一本久道综合在线中文|国精产品一二三产区的使用方法|香蕉鱼在线观看|www.27eee

ELEOK

標(biāo)題: STM32根據(jù)字符串生成二維碼并在OLED顯示 附源程序 [打印本頁]

作者: 路漫漫    時間: 2020-6-7 16:04
標(biāo)題: STM32根據(jù)字符串生成二維碼并在OLED顯示 附源程序
有完整工程可下載,用的HAL庫,STM32Cubemx配置的工程
STM32_IIC_OLED_QR_Code.zip (15.77 MB, 售價: 1 E幣)


以前因為某些需要,需要單片機(jī)根據(jù)字符串自動生成二維碼,(而不是把二維碼圖片取模再用LCD顯示圖片)在LCD12864中顯示了出來,效果圖如下:


可以看到圖片清晰地顯示了出來,且用任意掃碼工具都能快速掃描出結(jié)果。感謝前輩的無私分享。
        好了,回歸正題,最近手頭有一塊0.96寸OLED 屏幕,閑來無事就顯示個二維碼玩玩。首先移植前輩的二維碼庫,只需要QR_Encode.c和QR_Encode.h這兩個就足夠了。移植到任何一個能正常使用的oled驅(qū)動例程中,編寫打點和畫矩形函數(shù),再調(diào)用QR_Encode.c中的bool EncodeData(char *lpsSource)函數(shù)就會根據(jù)你輸入的字符串生成二維碼數(shù)據(jù)并保存在全局?jǐn)?shù)組m_byModuleData[MAX_MODULESIZE][MAX_MODULESIZE];中了,二維碼的數(shù)據(jù)都是0或1,顯示到屏幕時只需要一個個判斷,遇1打點,遇0擦點(二維碼正顯)或遇1擦點,遇0打點(二維碼反顯),最后再刷新到oled上就好了。但這樣的話得出來的二維碼是比較小的,我們需要寫算法進(jìn)行放大。放大的原理是一個點用幾個點表示,我用的方法是遇到0就畫一個實心的矩形,遇到1就擦除一個實心矩形里面的所有點(反顯),效果圖如下:



我們看到,這個反顯的二維碼是能生成并顯示出來了,但是沒有打底或沒有邊框就顯得很難看。所以為了好看,需要給它加個邊框或打個白底,效果圖如下(右)


此時可以看到右邊這個打了白底的邊框就顯得很好看了。圖中左邊是沒有打底的正顯二維碼,為何要用反顯而不用正顯呢?因為正顯的除非掃碼算法優(yōu)化得特別好(如QQ、微信等),不然一般的掃碼比較難掃描出結(jié)果,而反顯的一掃就出來了,不信你們可以用瀏覽器的掃碼或多試幾個掃碼軟件看看。下圖是正顯的二維碼

顯示二維碼到LCD最重要的是打點函數(shù),可以開辟一個緩存用來存儲打點的數(shù)據(jù),最后把二維碼數(shù)據(jù)和其他數(shù)據(jù)如邊框或打底的數(shù)據(jù)都存完進(jìn)這個緩存后再調(diào)用刷新屏幕函數(shù)刷新到oled即可。
打點函數(shù)如下:
  1. void OLED_DrawPoint(u8 x, u8 y, u8 t)
  2. {
  3.     u8 pos, bx, temp = 0;
  4.     if(x > 127 || y > 63)
  5.     {
  6.         return;//超出范圍了.
  7.     }
  8.         pos = 7 - y/8;
  9.         bx = y % 8;
  10.         temp = 1 << (7 - bx);
  11.         t ? (OLED_GRAM[x][pos] |= temp) : (OLED_GRAM[x][pos] &= ~temp);   
  12. }
復(fù)制代碼
刷新顯存函數(shù)如下:
  1. void OLED_Refresh_Gram(void)//更新顯存到OLED
  2. {
  3.         u8 i, n;                    
  4.         for(i = 0; i < 8; i++)  
  5.         {  
  6.                 WriteCmd(0xb0 + i);    //設(shè)置頁地址(0~7)
  7.                 WriteCmd(0x00);      //設(shè)置顯示位置—列低地址
  8.                 WriteCmd(0x10);      //設(shè)置顯示位置—列高地址   
  9.                 for(n = 0; n < 128; n++)
  10.                 {
  11.                         WriteDat(OLED_GRAM[n]);
  12.                 }
  13.         }   
  14. }
復(fù)制代碼
下面就是最重要的我封裝好了的二維碼顯示函數(shù):
  1. /**************************************************************************************************************
  2. 功能:在oled上顯示二維碼
  3. 參數(shù):str->二維碼內(nèi)容;   offset->二維碼在X軸上的位置,范圍為0-127;  colour=1->二維碼正顯  colour=0->二維碼反顯
  4. **************************************************************************************************************/
  5. void OLED_QRcode_Display(char *str,uint8_t offset,uint8_t colour)//二維碼的內(nèi)容和第一個點再X軸的位置
  6. {
  7.         uint32_t i,j,point;
  8.         uint8_t exp = 1;//放大倍數(shù)
  9.         uint8_t pos_X,pos_Y;   
  10.     if(colour)
  11.         point = 1;
  12.     else
  13.         point = 0;   

  14.     EncodeData(str);        
  15.         exp = 64 / m_nSymbleSize;           //根據(jù)屏幕尺寸自動計算最佳放大倍數(shù)
  16.         pos_Y = (64 - exp*m_nSymbleSize)/2;        //這是二維碼左下角第一個點的縱坐標(biāo)
  17.         pos_X = pos_Y + offset;             //這是二維碼左下角第一個點的橫坐標(biāo)

  18.     if(point==0)
  19.         OLED_Fill2(pos_X-2,pos_Y-2,pos_X + exp*m_nSymbleSize+2,pos_Y + exp*m_nSymbleSize+2,1);//給反顯的二維碼填充底色
  20.     //exp*m_nSymbleSize為放大后二維碼的邊長(二維碼是正方形)
  21.         for(i=0;i<m_nSymbleSize;i++)
  22.         {
  23.                 for(j=0;j<m_nSymbleSize;j++)
  24.                 {
  25.                                 if(m_byModuleData[j] == 1)
  26.                                 {
  27.                                         OLED_Fill2(pos_X,pos_Y,pos_X+exp,pos_Y+exp,point);//畫矩形并填充
  28.                                 }
  29.                                 if(m_byModuleData[j] == 0)
  30.                                 {
  31.                                         OLED_Fill2(pos_X,pos_Y,pos_X+exp,pos_Y+exp,1-point);//清空矩形區(qū)域
  32.                                 }
  33.                                 pos_Y += exp;
  34.                 }
  35.                 pos_X += exp;
  36.                 pos_Y -= m_nSymbleSize*exp;
  37.         }
  38.     OLED_Refresh_Gram();
  39. }
復(fù)制代碼
調(diào)用方法如下:




其中,str是二維碼的內(nèi)容,可中英文和數(shù)字,若要掃碼時自動打開網(wǎng)頁,則需要在前面加https:// ;offset是二維碼在X軸上的初始橫坐標(biāo),范圍為0-127,可用此調(diào)整二維碼的橫坐標(biāo)讓它居左居中等,縱坐標(biāo)我現(xiàn)在設(shè)定的是自動調(diào)整到最大,可以自己修改。colour是正反顯選擇,0是反顯,1是正顯。如我要生成一個掃碼就自動進(jìn)入百度網(wǎng)頁的居中反顯二維碼時參數(shù)如下:OLED_QRcode_Display("https://baidu.com",63,0);這樣就能達(dá)到我們想要的效果了。下面是一正一反顯二維碼圖:


下面是我的硬件平臺:STM32F103C8T6核心板和0.96寸oled。移植到其他平臺時內(nèi)存8K以下的慎用,可能內(nèi)存會爆。。


作者: cong2025    時間: 2026-2-4 16:48
先碼后看,給你點贊





歡迎光臨 ELEOK (http://m.afoofa.cn/) Powered by Discuz! X5.0