历史上的今天
今天是:2024年10月14日(星期一)
2020年10月14日 | 为OLED屏增加GUI支持1:OLED驱动
2020-10-14 来源:eefocus
说明:
一个可穿戴项目中使用到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)
{
史海拾趣
|
本帖最后由 paulhyde 于 2014-9-15 03:17 编辑 有那位高人能提供智能循迹小车驱动电路的pcb呀 核心板芯片是pc9s12xs128的 电机驱动电路的芯片是33886的 或是其他的芯片耶可以 还有能否提供光电探测板的电路图和pcb 在这 ...… 查看全部问答> |
|
手册上只说了超过设定值,告警标志位会置位,但是如何查询到呢?单片机在那个Alarm Search(ECh)命令发出后,18B20里面也没有寄存器可以读到报警位啊? 现在只能用软件方式查询,当前温度值与实现设定好的TH,TL的比较关系,从而判断是否超过了温 ...… 查看全部问答> |
|
Microsoft Communication Controls Version 6.0 不支持此接口 RT. 我用vc6.0新建了个对话框的工程,添加MSComm控件时,出现了上面的提示,无法插入该控件。 这个该如何解决?… 查看全部问答> |
|
24系列存储器内部没有型号标志信息,在我的板上装有不同型号的24IC,写个程序来判断该24系列IC的地址、存储容量和页写缓冲。各位大虾给个思路啊… 查看全部问答> |
|
我碰到了一个奇怪的问题。我的设计中用到的FPGA是stratix II GX,我的程序在这个FPGA中一直运行正常,两天前,我将它放到高低温箱中作测试,在高低温箱中只是做了常温测试,前两个小时运行正常,突然FPGA就运行不正常了,经过检查发现:FPGA中的PLL ...… 查看全部问答> |
|
实现功能:我用串口接收PC端一串数据 然后在把数组中的数据发送给串口 传到PC 遇到问题:串口接收正常 但是发送每次只能发送一两个数据 环境 :串口5 中断接收 请大家帮忙分析下原因 谢谢! ...… 查看全部问答> |
|
用点阵做了一个时钟程序 用timer0 控制点阵刷新 用timer2 使用异步时钟32768计时 现在遇到一个问题 做了一个滚动字幕 希望每十分钟显示一次 那么应该每十分钟关闭一次timer0 的溢出中断 在 ...… 查看全部问答> |
|
我发现很郁闷的问题。我下载了程序到里面,直接上电,发现晶振不启振。上了好几次电。都是不起振。 然后我用仿真的方法,看代码是怎么回事,rtc配置的地方单步走,发现晶振又启振了 而且很正常。我试试了两块板子,都是这种情况。 很郁闷 ...… 查看全部问答> |




