为OLED屏增加GUI支持1:OLED驱动

来源:互联网 发布:盛杰网络课下载 编辑:程序博客网 时间:2024/05/01 22:06

为OLED屏增加GUI支持1:OLED驱动

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

说明:
一个可穿戴项目中使用到0.96寸OLED屏,这是一种小尺寸的单色屏,不需要复杂的界面。移植了emwin发现小屏幕单色屏很不合适,控件显示不尽如人意,占用的flash又太大。所以我自己编写一个轻量级的GUI。

GUI简介:
目前已有控件:
1.文本框
2.单色bmp图片显示控件
3.进度条

并支持:
1.中文字库
2.基本的2D绘图功能

显示效果图:
这里写图片描述

下载链接:
http://download.csdn.net/detail/jdh99/9376437

源代码:
驱动函数为GUI提供绘点函数以供调用
drv_lcd.h

/*** Copyright (c), 2015-2025* @file drv_lcd.h* @brief lcd驱动层头文件* @author jdh* @date 2015/7/28* @verbatim * 硬件连接说明* 电路标号          单片机引脚       LCD引脚* SDI               PB15            D0    * SCL               PB13            D1* CS                PB12            CS* NRST              NRST            RES* A0                PB1             DC* SDI               PB13            D0    * SCL               PB15            D1* CS                PB12            CS* NRST              PB10            RES* A0                PB11            DC* @endverbatim */#ifndef _DRV_LCD_H_#define _DRV_LCD_H_/**********************************************************************                           头文件**********************************************************************/#include "stm32f10x.h"/**********************************************************************                           函数**********************************************************************//*** @brief 初始lcd*/void drv_lcd_init(void);/*** @brief 画点* @param x:x坐标* @param y:y坐标* @param show:0:不显示,1:显示*/void drv_lcd_draw_pixel(uint8_t x,uint8_t y,uint8_t show);/*** @brief 打开显示* @param 0:关闭,1:打开*/void drv_lcd_display_set(uint8_t state);#en

drv_lcd.c

/*** Copyright (c), 2015-2025* @file drv_lcd.c* @brief lcd驱动层主文件* @author jdh* @date 2015/7/28*//**********************************************************************                           头文件**********************************************************************/#include "drv_lcd.h"/**********************************************************************                           宏定义**********************************************************************//*** @brief 写入模式*///写命令#define OLED_CMD            0   //写数据#define OLED_DATA           1   /**********************************************************************                           静态变量**********************************************************************//*** @brief OLED的显存* @verbatim * 存放格式如下:* [0]0 1 2 3 ... 127    * [1]0 1 2 3 ... 127    * [2]0 1 2 3 ... 127    * [3]0 1 2 3 ... 127    * [4]0 1 2 3 ... 127    * [5]0 1 2 3 ... 127    * [6]0 1 2 3 ... 127    * [7]0 1 2 3 ... 127* @endverbatim */static uint8_t OLED_Gram[128][8];   /**********************************************************************                           静态函数**********************************************************************//*** @brief 初始io*/static void init_io(void);/*** @brief 初始化spi*/static void init_spi(void);/*** @brief 初始化SSD1306 */static void init_oled(void);/*** @brief 向SSD1306写入一个字节* @param dat:要写入的数据/命令* @param cmd:数据/命令标志 0,表示命令;1,表示数据*/static void oled_write_byte(uint8_t dat,uint8_t cmd);/*** @brief 切换数据或者命令模式* @param state:0:命令,1:数据*/static void oled_dc_set(uint8_t state);/*** @brief 片选* @param mode:0:片选,1:未选*/static void oled_cs_set(uint8_t state);/*** @brief 更新显存到LCD   */static void oled_refresh_gram(void);/*** @brief 清屏*/static void oled_clear(void);/*** @brief 设置坐标点* @param x:x坐标* @param y:y坐标*/static void oled_set_pos(uint8_t x,uint8_t y);/*** @brief spi发送一个字节* @param byte:发送的字节* @retval 读取的字节*/static uint8_t spi_send_byte(uint8_t byte);/**********************************************************************                           函数**********************************************************************//*** @brief 初始lcd*/void drv_lcd_init(void){    init_io();    init_spi();    init_oled();}/*** @brief 画点* @param x:x坐标* @param y:y坐标* @param show:0:不显示,1:显示*/void drv_lcd_draw_pixel(uint8_t x,uint8_t y,uint8_t show){    uint8_t pos = 0;    uint8_t bx = 0;    uint8_t temp = 0;    //设置坐标点    oled_set_pos(x,y);    //p岸段是否超出范围    if (x > 127 || y > 64)    {        return;    }    pos = 7 - y / 8;    bx = y % 8;    temp = 1 << (7 - bx);    if (show)    {        OLED_Gram[x][pos] |= temp;    }    else    {        OLED_Gram[x][pos] &= ~temp;    }           //设置显示位置—列高地址       oled_write_byte(OLED_Gram[x][pos],OLED_DATA); }/*** @brief 打开显示* @param 0:关闭,1:打开*/void drv_lcd_display_set(uint8_t state){    if (state)    {        oled_write_byte(0xAF,OLED_CMD);    }    else    {        oled_write_byte(0xAE,OLED_CMD);    }}/*** @brief 初始io*/static void init_io(void){    //定义IO初始化结构体    GPIO_InitTypeDef GPIO_InitStructure;    //初始化时钟    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);    //管脚初始化      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;    //选择GPIO响应速度    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //设置为输出               GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //初始化                   GPIO_Init(GPIOB, &GPIO_InitStructure);     //复位脚    //初始化时钟    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);    //管脚初始化      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;    //选择GPIO响应速度    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //设置为输出               GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //初始化                   GPIO_Init(GPIOB, &GPIO_InitStructure);      GPIO_SetBits(GPIOB,GPIO_Pin_10);}/**********************************************************************                           初始化spi**********************************************************************/static void init_spi(void){    //定义IO初始化结构体    GPIO_InitTypeDef GPIO_InitStructure ;    //定义SPI初始化结构体    SPI_InitTypeDef  SPI_InitStructure ;    //配置其他引脚    //配置CSN    //开启时钟    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE ) ;    //配置SPI引脚CSN    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;    GPIO_Init( GPIOB, &GPIO_InitStructure );    //初始化SPI    //关闭SPI    SPI_Cmd(SPI2,DISABLE);    //初始化SPI时钟      RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);    //设置IO口时钟          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);     //配置SPI1引脚:SCK, MISO and MOSI    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;    GPIO_Init( GPIOB, &GPIO_InitStructure );    // SPI配置    //SPI_I2S_DeInit(SPI2);    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ;    SPI_InitStructure.SPI_Mode = SPI_Mode_Master ;    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b ;    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High ;    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge ;    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ;    //SPI波特率分频设置    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ;    //SPI设置成LSB模式    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB ;    SPI_InitStructure.SPI_CRCPolynomial = 7 ;    SPI_Init( SPI2, &SPI_InitStructure ) ;    //启动SPI    SPI_Cmd(SPI2,ENABLE);}/*** @brief 初始化SSD1306 */static void init_oled(void){                                                 oled_write_byte(0xAE,OLED_CMD); //关闭显示    oled_write_byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率    oled_write_byte(80,OLED_CMD);   //[3:0],分频因子;[7:4],震荡频率    oled_write_byte(0xA8,OLED_CMD); //设置驱动路数    oled_write_byte(0X3F,OLED_CMD); //默认0X3F(1/64)     oled_write_byte(0xD3,OLED_CMD); //设置显示偏移    oled_write_byte(0X00,OLED_CMD); //默认为0    oled_write_byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.    oled_write_byte(0x8D,OLED_CMD); //电荷泵设置    oled_write_byte(0x14,OLED_CMD); //bit2,开启/关闭    oled_write_byte(0x20,OLED_CMD); //设置内存地址模式    oled_write_byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;    oled_write_byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;    oled_write_byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数    oled_write_byte(0xDA,OLED_CMD); //设置COM硬件引脚配置    oled_write_byte(0x12,OLED_CMD); //[5:4]配置    oled_write_byte(0x81,OLED_CMD); //对比度设置    oled_write_byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)    oled_write_byte(0xD9,OLED_CMD); //设置预充电周期    oled_write_byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;    oled_write_byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率    oled_write_byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;    oled_write_byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)    oled_write_byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示                                    oled_write_byte(0xAF,OLED_CMD); //开启显示       oled_clear();}  /*** @brief 向SSD1306写入一个字节* @param dat:要写入的数据/命令* @param cmd:数据/命令标志 0,表示命令;1,表示数据*/static void oled_write_byte(uint8_t dat,uint8_t cmd){           //设置传输模式    oled_dc_set(cmd);    //片选    oled_cs_set(0);    //发送数据    spi_send_byte(dat);    //关闭片选    oled_cs_set(1);     //设置传输模式    oled_dc_set(cmd);       //设置传输模式:数据    oled_dc_set(OLED_DATA); } /*** @brief 切换数据或者命令模式* @param state:0:命令,1:数据*/static void oled_dc_set(uint8_t state){    if (state)    {        GPIO_SetBits(GPIOB,GPIO_Pin_11);    }    else    {        GPIO_ResetBits(GPIOB,GPIO_Pin_11);    }}/*** @brief 片选* @param mode:0:片选,1:未选*/static void oled_cs_set(uint8_t state){    if (state)    {        GPIO_SetBits(GPIOB,GPIO_Pin_12);    }    else    {        GPIO_ResetBits(GPIOB,GPIO_Pin_12);    }}/*** @brief 更新显存到LCD   */static void oled_refresh_gram(void){    uint8_t i = 0;    uint8_t n = 0;    for (i = 0;i < 8;i++)      {          //设置页地址(0~7)        oled_write_byte(0xb0 + i,OLED_CMD);        //设置显示位置—列低地址        oled_write_byte(0x02,OLED_CMD);        //设置显示位置—列高地址           oled_write_byte(0x10,OLED_CMD);        //更新数据        for (n = 0;n < 128;n++)        {            oled_write_byte(OLED_Gram[n][i],OLED_DATA);         }    }   }/*** @brief 清屏*/static void oled_clear(void){      uint8_t i = 0;    uint8_t n = 0;    for (i = 0;i < 8;i++)    {        for(n=0;n<128;n++)        {            OLED_Gram[n][i] = 0;         }               }    //更新显示    oled_refresh_gram();}/*** @brief 设置坐标点* @param x:x坐标* @param y:y坐标*/static void oled_set_pos(uint8_t x,uint8_t y) {     oled_write_byte(0xb0 + (7 - y / 8),OLED_CMD);    oled_write_byte(((x & 0xf0) >> 4) | 0x10,OLED_CMD);    oled_write_byte((x & 0x0f),OLED_CMD); } /*** @brief spi发送一个字节* @param byte:发送的字节* @retval 读取的字节*/static uint8_t spi_send_byte(uint8_t byte){           while (SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE) == RESET);    SPI_I2S_SendData(SPI2,byte);    while (SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET);    return SPI_I2S_ReceiveData(SPI2);}

inf_lcd.h

/*** Copyright (c), 2015-2025* @file inf_lcd.c* @brief lcd接口层头文件* @author jdh* @date 2015/7/28*/#ifndef _INF_LCD_H_#define _INF_LCD_H_/**********************************************************************                           头文件**********************************************************************/#include "drv_lcd.h"/**********************************************************************                           函数**********************************************************************//*** @brief 初始lcd*/void inf_lcd_init(void);/*** @brief 画点* @param x:x坐标* @param y:y坐标* @param show:0:不显示,1:显示*/void inf_lcd_draw_pixel(uint8_t x,uint8_t y,uint8_t show);/*** @brief 打开显示* @param 0:关闭,1:打开*/void inf_lcd_display_set(uint8_t state);#endif

inf_lcd.c

/*** Copyright (c), 2015-2025* @file inf_lcd.c* @brief lcd接口层主文件* @author jdh* @date 2015/7/28* @update 2015/9/2* @update 2015/9/3*//**********************************************************************                           头文件**********************************************************************/#include "inf_lcd.h"#include "string.h"/**********************************************************************                           函数**********************************************************************//*** @brief 初始lcd*/void inf_lcd_init(void){    drv_lcd_init();  }/*** @brief 画点* @param x:x坐标* @param y:y坐标* @param show:0:不显示,1:显示*/void inf_lcd_draw_pixel(uint8_t x,uint8_t y,uint8_t show){    drv_lcd_draw_pixel(x,y,show);}/*** @brief 打开显示* @param 0:关闭,1:打开*/void inf_lcd_display_set(uint8_t state){    drv_lcd_display_set(state);}
1 1
原创粉丝点击