为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
- 为OLED屏增加GUI支持1:OLED驱动
- 为OLED屏增加GUI支持3:字库
- 为OLED屏增加GUI支持4:文本框控件
- 为OLED屏增加GUI支持5:图片控件
- 为OLED屏增加GUI支持6:进度条控件
- 为OLED屏增加GUI支持7:综合实例
- 为OLED屏增加GUI支持6:进度条控件
- 为OLED屏增加GUI支持2:2D图形库
- OLED GUI
- OLED驱动
- oled屏资料1
- OLED
- OLED
- OLED
- 28035spi驱动OLED
- K60 OLED驱动
- SSD1306 OLED 驱动
- Arduino驱动SSD1306 OLED
- Java 序列化 (Serializable) 的作用
- Java中对象存储位置
- DZ论坛变灰色方法
- Unable to allocate and lock memory. The virtual machine will be paused. Please close applications to
- 网站信息采集
- 为OLED屏增加GUI支持1:OLED驱动
- ubuntu 下修改mantis bug严重等级为 A,B,C,D,E
- “[DBNETLIB][ConnectionOpen(connect()).]SQL Server 不存在或拒绝访问 ”的解决方法之一
- seeting菜单界面形成--优化
- MPAndroidChart开源图表库(一)之饼状图
- Java并发库(十九):同步集合类的使用BlockingQueue、
- 训练自己
- 画画板--第三方开源--DrawableView
- bless 概念