oled的一套stm32實驗2(自己的實驗)


stm32與OLED屏接口的引腳介紹:

      CS————GPIOD3;

      RST————GPIOD4;

      DC—————GPIOD5;

      D0——————GPIOD6;

      D1——————GPIOD7;

 

上是我參考別人的oled引腳的接線

但是 我買的oled模塊和別人的不是很一樣,雖然也是spi通信的

看一下我的接線:

模塊與stm32:

GND--GND

VCC--3.3v

SCL--PD6  :這個是時鍾

SDA--PD7 :這個是傳輸數據的,也就是數據線spi本應是兩條的,但是屏幕並沒有返回值,所以只有一條了

RES--PD4 :復位,

DC--PD5  :這個是命令或數據指示位,當為高電平的時候表示數據,低電平的時候表示命令

 

根據上面的取模方式,就要有相對應的代碼才行:

下面這行代碼就是對應的這種取模方式,這個是32*32的漢字.

void OLED_ShowChinese(int x, int y, const unsigned char *p)
{
    int i = 0;
    OLED_Coord(x, y);
    for(i = 0; i < 32; i+=2)   //因為漢字是占了屏幕里的兩行,所以要有上下兩個部分. 漢字的寬是32個像素.
    {
        SPI_Write(p[i], OLED_Data);
    }
    OLED_Coord(x, y+1);
    for(i = 1; i < 32; i+=2)
    {
        SPI_Write(p[i], OLED_Data);
    }
}

 

 

////////////////////////////////////////////////////////////////////////////////

下面我們要用stm32自帶的spi庫去配置oled屏幕

我們先看接線:

單片機                        -----oled屏幕

SPI1->CS      ------ PA4----CS      這個是片選,我的屏幕上沒有

SPI1->CLK    ------ PA5 ----D0     這個是spi
SPI1->MISO  ------ PA6-----D1     這個是spi
SPI1->MOSI  ------ PA7
                             PD4-----RST   (???這個我也有一點懷疑是不是spi的一部分),從源程序來看並不是.源程序中,只是在屏幕初始化的時候用了一下,其他時候沒有出現.
                              PD5-----DC     這個不是,就配置成普通的輸出就行
 
 
其實這樣看,感覺oled用的spi並不是很完整,也許是我的到的源程序沒有按照標准的spi編寫.
我的想法是這樣,先用stm32配置一個標准的spi程序,然后把屏接上去,看一看行不行.
 
 
本來想用stm32的spi實現,但是出了一點問題:
不知道為什么,總是多出一些小點.先存個檔,以后查看問題出在哪里吧.
 

 

對應的程序:
oled.c文件:
 
#include "oled.h"
#include "stm32f10x.h"



const unsigned char xing[]=
{    0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08,
    0x10,0x16,0xF0,0x21,0x40,0x40,0x3C,0x42,
    0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42,
    0x10,0x42,0x10,0x42,0x00,0x40,0x00,0x00};/*"姓",0*/
const unsigned char A[]=
{    0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02,
    0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20};/*"A",0*/
const unsigned char ming[]=
{    0x00,0x04,0x20,0x04,0x20,0x04,0x10,0x02,
    0x08,0xFE,0x14,0x43,0x67,0x43,0x84,0x42,
    0x44,0x42,0x24,0x42,0x14,0x42,0x0C,0x42,
    0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00};/*"名",0*/
const unsigned char ASCII_Colon[]=
{    0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,
    0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};/*":",0*/    
const unsigned char xue[]=
{    0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,
    0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
    0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,
    0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00};/*"學",0*/
const unsigned char hao[]=
{    0x80,0x00,0x80,0x00,0x80,0x00,0xBE,0x06,
    0xA2,0x05,0xA2,0x04,0xA2,0x04,0xA2,0x04,
    0xA2,0x44,0xA2,0x84,0xA2,0x44,0xBE,0x3C,
    0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00};/*"號",0*/

		
	
const unsigned char liao[] =          // 瞭望,不知道為什么不行,這個好像是定義了一個結構體,實際上,我可以讓文字的顯示更加靈活.
{
      0x10,0x04,0x10,0x03,0xD0,0x00,0xFF,0xFF,
      0x90,0x80,0x10,0x41,0x00,0x20,0xFC,0x1F,
      0x04,0x00,0x04,0x00,0x04,0x00,0xFE,0x3F,
      0x04,0x40,0x00,0x40,0x00,0x70,0x00,0x00,
};
const unsigned char wang[] =  
{
      0x10,0x04,0x10,0x03,0xD0,0x00,0xFF,0xFF,
      0x90,0x20,0x18,0x11,0xE8,0x8F,0x08,0x81,
      0xE8,0x5F,0x08,0x21,0xFF,0x17,0x08,0x38,
      0x0A,0x46,0x8C,0x81,0x08,0xE0,0x00,0x00
};


/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/

void OLED_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    
    //開啟GPIOD的時鍾

	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);

	    //設置GPIO的基本參數
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4;  
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽輸出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;     //輸出速度50MHz
    GPIO_Init(GPIOD, &GPIO_InitStruct);
		
	
    
    GPIO_SetBits(GPIOD, GPIO_Pin_4 | GPIO_Pin_5 );
}


/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
//下面是spi的協議實現部分
void SPI_Write(char data, int Mode)
{    
    if(Mode)
    {
        OLED_DC(1);        //DC引腳輸入高,表示寫數據
    }
    else
    {
        OLED_DC(0);        //DC引腳輸入低,表示寫命令
    }
    //OLED_CS(0);            //CS引腳輸入低,片選使能
		
    
    SPI_I2S_SendData(SPI1, data);
	  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//判斷有沒有傳輸完,對於傳輸是很重要的.
		
   
    OLED_DC(0);            //DC引腳輸入低, 命令行恢復默認.
    //OLED_CS(1);            //CS引腳輸入高,片選失能
}

void spi1(void)   //spi1的配置.
{
	GPIO_InitTypeDef GPIO_InitStructure;
	SPI_InitTypeDef  SPI_InitStructure;  //經常把這個開關忘掉

    /* SPI的IO口和SPI外設打開時鍾 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//也經常把這個忘掉

    /* SPI的IO口設置 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7); //PA5.6.7上拉
/***************************************************************************/
/************************* 設置SPI的參數 ***********************************/
/***************************************************************************/
	
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//選擇全雙工SPI模式
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;     //主機模式
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位SPI
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;       //時鍾懸空高電平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;      //在第二個時鍾采集數據
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		  //Nss使用軟件控制
	/* 選擇波特率預分頻為256 */
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//從最高位開始傳輸
	SPI_InitStructure.SPI_CRCPolynomial = 7;
	
	SPI_Cmd(SPI1, ENABLE);
	SPI_Init(SPI1, &SPI_InitStructure);
}




/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
//坐標的實現
void OLED_Coord(unsigned char x, unsigned char y)
{
    SPI_Write((0xb0+(y & 0x0f)), OLED_Order);        //設置OLED顯示的頁                 
    SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//設置OLED水平坐標的高4位    根據上面那張圖分析,這是取x的高四位,
    SPI_Write((x & 0x0f)|0x01, OLED_Order);                //設置OLED水平坐標的低4位  至於為什么要|0x01,可能是為了防止太靠邊。
}

/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
void OLED_Clear(void)
{
    int i = 0, j = 0;
    for(i = 0; i < 8; i++)
    {
        OLED_Coord(0, i);               
        for(j = 0; j < 128; j++)
        {
            SPI_Write(0x00, OLED_Data);
        }
    }
}



/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
void OLED_Display_Off(void)
{
    //電荷泵設置(初始化時必須打開,否則看不到顯示)
    SPI_Write(0x8D, OLED_Order);
    SPI_Write(0x10, OLED_Order);//bit2   0:關閉        1:打開
    SPI_Write(0xAE, OLED_Order);//0xAE:關閉顯示
}


/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
void OLED_Display_On(void)
{
    //電荷泵設置(初始化時必須打開,否則看不到顯示)
    SPI_Write(0x8D, OLED_Order);
    SPI_Write(0x14, OLED_Order);//bit2   0:關閉        1:打開
    SPI_Write(0xAF, OLED_Order);//0xAF:開顯示    
}


/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/

void OLED_Init(void)
{
    OLED_GPIO_Init();
    
    OLED_RST(1);
    delay(6000);  //這里有一個延遲,即便是使用滴答定時器也終究是delay,所以怎樣去除這個delay呢?
    OLED_RST(0);
    delay(6000);  //怎樣去除這個delay呢???
    OLED_RST(1);
    
    SPI_Write(0xAE, OLED_Order);//0xAE:關顯示   
    
    SPI_Write(0x00, OLED_Order);//設置低列地址
    SPI_Write(0x10, OLED_Order);//設置高列地址
    
    //設置行顯示的開始地址(0-63)
    //40-47: (01xxxxx)
    SPI_Write(0x40, OLED_Order);
    
    //設置對比度
    SPI_Write(0x81, OLED_Order);
    SPI_Write(0xff, OLED_Order);//這個值越大,屏幕越亮(和上條指令一起使用)(0x00-0xff)
    
    SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置,  0xA0: 正常顯示(默認0xA0)
    SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置,  0xC0: 正常顯示(默認0xC0)
    
    //0xA6: 表示正常顯示(在面板上1表示點亮,0表示不亮)
    //0xA7: 表示逆顯示(在面板上0表示點亮,1表示不亮)
    SPI_Write(0xA6, OLED_Order);
    
    SPI_Write(0xA8, OLED_Order);//設置多路復用率(1-64)
    SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默認為3f)
    
    
    //設置顯示抵消移位映射內存計數器
    SPI_Write(0xD3, OLED_Order);
    SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默認為0x00)
    
    //設置顯示時鍾分頻因子/振盪器頻率
    SPI_Write(0xD5, OLED_Order);
    //低4位定義顯示時鍾(屏幕的刷新時間)(默認:0000)分頻因子= [3:0]+1
    //高4位定義振盪器頻率(默認:1000)
    SPI_Write(0x80, OLED_Order);//
    
    //時鍾預充電周期
    SPI_Write(0xD9, OLED_Order);
    SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1;   [7:4] PHASE 2
    
    //設置COM硬件應腳配置
    SPI_Write(0xDA, OLED_Order);
    SPI_Write(0x12, OLED_Order);//[5:4]  默認:01
    
    SPI_Write(0xDB, OLED_Order);//
    SPI_Write(0x40, OLED_Order);//
    
    //設置內存尋址方式
    SPI_Write(0x20, OLED_Order);
    //00: 表示水平尋址方式
    //01: 表示垂直尋址方式
    //10: 表示頁尋址方式(默認方式)
    SPI_Write(0x02, OLED_Order);//    
    
    //電荷泵設置(初始化時必須打開,否則看不到顯示)
    SPI_Write(0x8D, OLED_Order);
    SPI_Write(0x14, OLED_Order);//bit2   0:關閉        1:打開
    
    //設置是否全部顯示 0xA4: 禁止全部顯示
    SPI_Write(0xA4, OLED_Order);

    //0xA6: 表示正常顯示(在面板上1表示點亮,0表示不亮)
    //0xA7: 表示逆顯示(在面板上0表示點亮,1表示不亮)
    SPI_Write(0xA6, OLED_Order);//
    
    SPI_Write(0xAF, OLED_Order);//0xAF:開顯示
    
    SPI_Write(0xAF, OLED_Order);//0xAF:開顯示
    
    OLED_Clear();
}


/*******************************************************************************
* 函 數 名         : 
* 函數功能		       : 
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
void OLED_ShowChinese(int x, int y, const unsigned char *p)
{
    int i = 0;
    OLED_Coord(x, y);
    for(i = 0; i < 32; i+=2)   //因為漢字是占了屏幕里的兩行,所以要有上下兩個部分. 漢字的寬是32個像素.
    {
        SPI_Write(p[i], OLED_Data);
    }
    OLED_Coord(x, y+1);
    for(i = 1; i < 32; i+=2)
    {
        SPI_Write(p[i], OLED_Data);
    }
}


/*******************************************************************************
* 函 數 名         : OLED_ShowChar
* 函數功能		       : 輸出一個ascii
* 輸    入         : 
* 輸    出         : 無
*******************************************************************************/
void OLED_ShowChar(int x, int y, const unsigned char *p)
{
    int i = 0;
    OLED_Coord(x, y);
    for(i = 0; i < 16; i+=2)
    {
        SPI_Write(p[i], OLED_Data);
    }
    OLED_Coord(x, y+1);
    for(i = 1; i < 16; i+=2)
    {
        SPI_Write(p[i], OLED_Data);
    }
}

 

oled.h文件:

#ifndef _oled_H
#define _oled_H
#include "stm32f10x.h"
extern const unsigned char xing[];
extern const unsigned char A[];
extern const unsigned char ming[];
extern const unsigned char ASCII_Colon[];
extern const unsigned char xue[];
extern const unsigned char hao[];
extern const unsigned char liao[];
extern const unsigned char wang[];

//也不知上面這些define是否應該定義在.h文件,是不是定義在.c文件中更合理,感覺不是,因為定義在.h中主函數可以調用頭文件來應用.[]???
#define OLED_CS(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_3):GPIO_ResetBits(GPIOD, GPIO_Pin_3)    //X為1時對應GPIO端口輸出高電平,X為0時對應GPIO端口輸出低電平

#define OLED_RST(X)       X?GPIO_SetBits(GPIOD, GPIO_Pin_4):GPIO_ResetBits(GPIOD, GPIO_Pin_4)    

#define OLED_DC(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_5):GPIO_ResetBits(GPIOD, GPIO_Pin_5)

#define OLED_D0(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_6):GPIO_ResetBits(GPIOD, GPIO_Pin_6)    

#define OLED_D1(X)        X?GPIO_SetBits(GPIOD, GPIO_Pin_7):GPIO_ResetBits(GPIOD, GPIO_Pin_7)    


#define OLED_Order 0//定義寫命令  我以前粘貼的時候,這里雖然沒有出錯,但是在相應的.c文件中出現了錯誤.就是因為這里粘貼了不該粘貼的東西.
#define OLED_Data  1//定義寫數據

void OLED_GPIO_Init(void);
void delay(u32 i);
void SPI_Write(char data, int Mode);
void OLED_Coord(unsigned char x, unsigned char y);
void OLED_Clear(void);
void OLED_Display_Off(void);
void OLED_Display_On(void);
void OLED_Init(void);
void OLED_ShowChinese(int x, int y, const unsigned char *p);
void OLED_ShowChar(int x, int y, const unsigned char *p);
void spi1(void);






#endif 

 

下面是主函數:

/*******************************************************************************
*                 
*                                普中科技
--------------------------------------------------------------------------------
* 實 驗 名         : 蜂鳴器實驗
* 實驗說明       : 通過IO產生一定頻率的脈沖實現蜂鳴器發聲
* 連接方式       : 
* 注    意         :     所用函數在beep.c文件內
*******************************************************************************/


//#include "stm32f10x.h"
#include "public.h"  //公共函數頭文件
#include "oled.h"

//#include "beep.h"    //蜂鳴器函數頭文件

/****************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Output         : None
* Return         : None
****************************************************************************/
int main()
{    
    //SysClockInit();
      SystemInit();  //這里還是有點問題的,我該怎樣甚至時鍾的函數.
      //OLED_GPIO_Init();
      spi1();
    OLED_Init();   //程序就是一層一層的,協議也是一層一層的.應該學會去撥開.
    OLED_ShowChinese(0, 0, xing);//‘姓’      //這個xing[]的數組是定義在.c文件中的,用extern在.h文件中拓展,之后主函數里include相應的.h就可以在main函數里進行調用這個變量了.
    OLED_ShowChinese(18, 0, ming);//‘名’
    //OLED_ShowChar(36, 0, ASCII_Colon);//‘:’
    OLED_ShowChinese(0, 2, xue);//‘學’    
    OLED_ShowChinese(18, 2, hao);//‘號’
    //OLED_ShowChar(36, 2, ASCII_Colon);//‘:’ 
    
    OLED_ShowChinese(0, 4, liao);//‘瞭’
      OLED_ShowChinese(18, 4, wang);//‘望’
      //OLED_ShowChar(36, 4, ASCII_Colon);//‘:’
    while(1)
    {
                    
    }    
    
    
    
}

 

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM