zoukankan      html  css  js  c++  java
  • 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)
        {
                        
        }    
        
        
        
    }
     
     
  • 相关阅读:
    介绍一些好用的ArcToolbox工具(默认ArcGIS没有)
    我的技术博客开始啦
    Qualcomm和MTK两个android平台比较
    kali安装nessus
    ImportError: cannot import name pxssh
    python 批量下载文件
    GitHub如何修改用户名
    Sass中使用@each循环
    PhpStorm 实用快捷键
    GitHub如何删除一个repository(仓库)
  • 原文地址:https://www.cnblogs.com/chulin/p/9376134.html
Copyright © 2011-2022 走看看