OLED屏幕使用的是7针SPI协议,使用DMA进行传输,同时使用“闪存”。
文件下载连接:STM32 使用硬件SPI驱动0.96寸七针OLED显示器(HAL库)
* 定义模拟显存
*/
static uint8_t oled_gram[128][8];
一、CUBEMX配置
1.时钟配置
2.SPI配置
SPI Mode选择:Transmit Only Master
Transmit Only Master 仅发送主模式
各个Setting的配置:
3.GPIO配置
GPIO引脚为:
二、代码部分
OLED.c
#include "oled.h"
#include "oledFont.h"
#include <string.h>
/*********************************************************************
* ????
*/
#define OLED_CS_H() HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_SET)
#define OLED_CS_L() HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_RESET)
#define OLED_DC_H() HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET)
#define OLED_DC_L() HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET)
#define OLED_RST_H() HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET)
#define OLED_RST_L() HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_RESET)
#define OLED_CMD 0
#define OLED_DATA 1
/*********************************************************************
* ??????
*/
#define PAGE_SIZE 8
#define WIDTH 128
/*********************************************************************
* ??????
*/
extern SPI_HandleTypeDef hspi1;
/*********************************************************************
* 定义模拟显存
*/
static uint8_t oled_gram[128][8];
uint32_t FPS;
uint32_t FPS_Count = 0;
/*********************************************************************
* ???????
*/
static void OLED_WriteByte(uint8_t data, uint8_t cmd);
static void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t mode);
static uint32_t OLED_MyPow(uint8_t m, uint8_t n);
void OLED_WR_Byte(uint8_t dat,uint8_t cmd);
void OLED_DisShowCHinese(uint8_t x,uint8_t y,uint8_t* pChar,uint8_t size1,uint8_t mode);
/*********************************************************************
* @fn OLED_WriteData
*
* @brief ??OLED???h?????
*
* @param data - ?????????/??????
* len - ????????
* cmd - ????/?????? 0,???????;1,???????
*
* @return none
*/
static void OLED_WriteByte(uint8_t data, uint8_t cmd)
{
if (cmd)
OLED_DC_H();
else
OLED_DC_L();
//OLED_CS_L();
HAL_SPI_Transmit(&hspi1, &data, 1, 0x00FF);
//OLED_CS_H();
OLED_DC_H();
}
/*********************************************************************
//u8 OLED_GRAM[8][128]; //定义模拟显存
//画点
//x:0~127
//y:0~63
//t:1(OLED_LED_LIGHTUP) 填充 ; 0(OLED_LED_EXTINGUISH),清空
*/
static void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t mode)
{
uint8_t pos, bx, temp = 0;
if (x > 127 || y > 63) //超出范围了.
return;
pos = 7 - y / 8;
bx = y % 8;
temp = 1 << (7 - bx);
if (mode)
oled_gram[x][pos] |= temp;
else
oled_gram[x][pos] &=~temp;
}
/*********************************************************************
* @fn OLED_MyPow
*
* @brief m^n
*
* @param m, n
*
* @return result
*/
static uint32_t OLED_MyPow(uint8_t m, uint8_t n)
{
uint32_t result = 1;
while (n--)
result *= m;
return result;
}
/*********************************************************************
* ??????
*/
/*********************************************************************
* @fn OLED_DisplayOn
*
* @brief ????OLED???
*
* @param none
*
* @return none
*/
void OLED_DisplayOn(void)
{
// uint8_t data[3];
// data[0] = 0x8D; // SET DCDC????
// data[1] = 0x14; // DCDC ON
// data[2] = 0xAF; // DISPLAY ON
// OLED_WriteData(data, 3, OLED_CMD);
OLED_WriteByte(0X8D, OLED_CMD); //SET DCDC????
OLED_WriteByte(0X14, OLED_CMD); //DCDC ON
OLED_WriteByte(0XAF, OLED_CMD); //DISPLAY ON
}
/*********************************************************************
* @fn OLED_DisplayOn
*
* @brief ???OLED???
*
* @param none
*
* @return none
*/
void OLED_DisplayOff(void)
{
// uint8_t data[3];
// data[0] = 0x8D; // SET DCDC????
// data[1] = 0x10; // DCDC OFF
// data[2] = 0xAE; // DISPLAY OFF
// OLED_WriteData(data, 3, OLED_CMD);
OLED_WriteByte(0X8D, OLED_CMD); //SET DCDC????
OLED_WriteByte(0X10, OLED_CMD); //DCDC OFF
OLED_WriteByte(0XAE, OLED_CMD); //DISPLAY OFF
}
/*********************************************************************
* @fn OLED_Refresh
*
* @brief ???OLED
*
* @param none
*
* @return none
*/
void OLED_Refresh(void)
{
++FPS_Count;
HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)oled_gram, 128 * 8);
}
/*********************************************************************
* @fn OLED_Clear
*
* @brief ????
*
* @param none
*
* @return none
*/
void OLED_Clear(void)
{
uint8_t i, j;
for (i = 0; i < 128; i++)
for (j = 0; j < 8; j++)
oled_gram[i][j] = 0;
OLED_Refresh();
}
/*********************************************************************
* @fn OLED_Fill
*
* @brief ???????K??????
*
* @param x1,y1,x2,y2 - ???????????
* mode - 0:???; 1:???
*
* @return none
*/
void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)
{
uint8_t x, y;
for (x = x1; x <= x2; x++)
for (y = y1; y <= y2; y++)
OLED_DrawPoint(x, y, mode);
OLED_Refresh();
}
/*********************************************************************
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0(OLED_DISPLAYCHAR_REVERSE)反白显示;1(OLED_DISPLAYCHAR_NORMAL),正常显示
//size:选择字体 8/12/16/24 (列高)
*/
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode)
{
uint8_t temp, t, t1;
uint8_t y0 = y;
uint8_t cSize = (size / 8 + ((size % 8) ? 1:0)) * (size / 2); //得到字体一个字符对应点阵集所占的字节数
chr = chr - ' ';//得到偏移后的值
for(t = 0; t < cSize; t++)
{
if (size == 12)
temp = asc2_1206[chr][t]; //调用1206字体
else if (size == 16)
temp = asc2_1608[chr][t]; //调用1608字体
else if (size == 24)
temp = asc2_2412[chr][t]; //调用2412字体
else
return; //没有的字库
for(t1 = 0; t1 < 8; t1++)
{
if (temp & 0x80)
OLED_DrawPoint(x , y, mode);
else
OLED_DrawPoint(x, y, !mode);
temp <<= 1;
y++;
if ((y - y0) == size)
{
y = y0;
x++;
break;
}
}
}
}
/*********************************************************************
* @fn OLED_ShowNum
*
*/
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size)
{
uint8_t t, temp;
uint8_t enShow = 0;
for (t = 0; t < len; t++)
{
temp = (num / OLED_MyPow(10, len - t - 1)) % 10;
if(enShow == 0 && t < (len - 1))
{
if(temp == 0)
{
OLED_ShowChar(x + (size / 2) * t, y ,' ', size, 1);
continue;
}
else
enShow = 1;
}
OLED_ShowChar(x + (size / 2) * t, y, temp + '0', size, 1);
}
}
//显示字符串
//x,y:起点坐标
//*p:字符串起始地址
//mode:0(OLED_DISPLAYCHAR_REVERSE)反白显示;1(OLED_DISPLAYCHAR_NORMAL),正常显示
//size:选择字体 12/16/24
void OLED_ShowString(uint8_t x, uint8_t y,uint8_t *pChar, uint8_t size1,uint8_t mode)
{
while(*pChar!='\0')
{
if(((*pChar>=' ')&&(*pChar<='~')))
{
if(size1==8)
{
if( (x+6)>128 )
x=0;
y=y+size1;
}
else if( (x+size1/2) > 128)
{
x=0;
y=y+size1;
}
OLED_ShowChar(x,y,*pChar,size1,mode);
if(size1==8)x+=6;
else x+=size1/2;
pChar++;
}
else
{
if(size1==8)
{
if( (x+6)>128 )
x=0;
y=y+size1;
}
else if( (x+size1) > 128)
{
x=0;
y=y+size1;
}
OLED_DisShowCHinese(x,y,pChar,size1,mode);
if(size1==8)x+=6;
else x+=size1;
pChar+=2;
}
}
OLED_Refresh();
}
void OLED_WR_Byte(uint8_t dat,uint8_t cmd)
{
OLED_CS_L();
if(cmd)
OLED_DC_H();
else
OLED_DC_L();
HAL_SPI_Transmit(&hspi1,&dat,1,10);
OLED_DC_H();
OLED_CS_H();
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WriteByte(0xb0+y,OLED_CMD);
OLED_WriteByte(((x&0xf0)>>4)|0x10,OLED_CMD);
OLED_WriteByte((x&0x0f),OLED_CMD);
}
//显示汉字
void OLED_DisShowCHinese(uint8_t x,uint8_t y,uint8_t* pChar,uint8_t size1,uint8_t mode)
{
int index=0;
uint8_t m,temp;
uint8_t x0=x,y0=y;
uint16_t i,size3=(size1/8+((size1%8)?1:0))*size1; //得到字体一个字符对应点阵集所占的字节数
for(i=0;i<size3;i++)
{
if(size1==16)
{
for (index=0;index<sizeof(Hzk)/35;index++)
{
if(Hzk[index].name[0] == pChar[0]&&Hzk[index].name[1] == pChar[1])//对比汉字区码位码
temp=Hzk[index].dat[i];
}
}
// else if(size1==24)
// {temp=Hzk2[num][i];}//调用24*24字体
// else if(size1==32)
// {temp=Hzk3[num][i];}//调用32*32字体
// else if(size1==64)
// {temp=Hzk4[num][i];}//调用64*64字体
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((x-x0)==size1)
{x=x0;y0=y0+8;}
y=y0;
}
}
/********************************************************************************
* @函数名: OLED_DrawBMP
* @函数描述: 在指定位置显示一张图片
* @函数作者: 矛盾聚合体
* @输入参数:
参数名 参数类型 参数描述
@x0: unsignedchar 左上角x坐标,0~127
@y0: unsignedchar 左上角y坐标,0~7
@x1: unsignedchar 右下角x坐标,0~127
@y1: unsignedchar 左下角y坐标,0~7
@BMP[]: unsignedchar 图片数据
* @返回值: void
* @其他:
********************************************************************************/
void OLED_DrawBMP(uint8_t x, uint8_t y, const char* name)
{
// 查找BMP数据
const picture* bmp_data = NULL;
for (int i = 0; i < sizeof(BMP) / sizeof(picture); i++) {
if (strcmp(BMP[i].name, name) == 0) {
bmp_data = &BMP[i];
break;
}
}
if (bmp_data == NULL) {
return; // 找不到对应的BMP数据
}
// 每张图片的宽度和高度
uint8_t width = 64;
uint8_t height = 64;
// 计算图片数据分割位置
uint16_t split_index = (height / 2) * width;
// 绘制上半部分数据
for (uint16_t byte_index = 0; byte_index < split_index; byte_index++) {
uint8_t data = bmp_data->dat[byte_index];
for (uint8_t bit = 0; bit < 8; bit++) {
uint8_t x_pos = x + (byte_index % width);
uint8_t y_pos = y + (byte_index / width) * 8 + bit;
uint8_t mode = (data >> bit) & 0x01; // 提取每个位的值
OLED_DrawPoint(x_pos, y_pos, mode);
}
}
// 绘制下半部分数据
for (uint16_t byte_index = split_index; byte_index < sizeof(bmp_data->dat); byte_index++) {
uint8_t data = bmp_data->dat[byte_index];
for (uint8_t bit = 0; bit < 8; bit++) {
uint8_t x_pos = x + (byte_index % width);
uint8_t y_pos = y + (byte_index / width) * 8 + bit + (height / 2) * 8;
uint8_t mode = (data >> bit) & 0x01; // 提取每个位的值
OLED_DrawPoint(x_pos, y_pos, mode);
}
}
// OLED_Refresh();
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP1(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const char* name) {
// 查找BMP数据
const picture* bmp_data = NULL;
for (int i = 0; i < sizeof(BMP) / sizeof(picture); i++) {
if (strcmp(BMP[i].name, name) == 0) {
bmp_data = &BMP[i];
break;
}
}
if (bmp_data == NULL) {
return; // 找不到对应的BMP数据
}
// 计算图片的宽度和高度
uint8_t width = x1 - x0 + 1;
uint8_t height = y1 - y0 + 1;
// 计算图片数据分割位置
uint16_t split_index = ((height + 1) / 2) * width;
// 绘制上半部分数据
for (uint16_t byte_index = 0; byte_index < split_index; byte_index++) {
uint8_t data = bmp_data->dat[byte_index];
for (uint8_t bit = 0; bit < 8; bit++) {
uint8_t x_pos = x0 + (byte_index % width);
uint8_t y_pos = y0 + (byte_index / width) * 8 + bit;
uint8_t mode = (data >> bit) & 0x01; // 提取每个位的值
OLED_DrawPoint(x_pos, y_pos, mode);
}
}
// 绘制下半部分数据
for (uint16_t byte_index = split_index; byte_index < sizeof(bmp_data->dat); byte_index++) {
uint8_t data = bmp_data->dat[byte_index];
for (uint8_t bit = 0; bit < 8; bit++) {
uint8_t x_pos = x0 + (byte_index % width);
uint8_t y_pos = y0 + (byte_index / width) * 8 + bit + (height / 2) * 8;
uint8_t mode = (data >> bit) & 0x01; // 提取每个位的值
OLED_DrawPoint(x_pos, y_pos, mode);
}
}
OLED_Refresh();
}
/*********************************************************************
* @fn OLED_Init
*
* @brief ??'??OLED
*
* @param none
*
* @return none
*/
void OLED_Init(void)
{
OLED_CS_L();
OLED_RST_L();
HAL_Delay(200);
OLED_RST_H();
OLED_WriteByte(0xAE,OLED_CMD); //??????
OLED_WriteByte(0xD5,OLED_CMD); //?????????????,?????
OLED_WriteByte(0x80,OLED_CMD); //[3:0],???????;[7:4],?????
OLED_WriteByte(0xA8,OLED_CMD); //????????�??
OLED_WriteByte(0X3F,OLED_CMD); //I??0X3F(1/64)
OLED_WriteByte(0xD3,OLED_CMD); //???????t??
OLED_WriteByte(0X00,OLED_CMD); //I???0
OLED_WriteByte(0x40,OLED_CMD); //?????????'?? [5:0],????.
OLED_WriteByte(0x8D,OLED_CMD); //????????
OLED_WriteByte(0x14,OLED_CMD); //bit2??????/???
OLED_WriteByte(0x20,OLED_CMD); //?????????g?
OLED_WriteByte(0x01,OLED_CMD); //[1:0],00??????g?;01??????g?;10,????g?;I??10;
OLED_WriteByte(0x21,OLED_CMD);//????????
OLED_WriteByte(0x00,OLED_CMD);
OLED_WriteByte(0x7f,OLED_CMD);
OLED_WriteByte(0x22,OLED_CMD);//????????
OLED_WriteByte(0x00,OLED_CMD);
OLED_WriteByte(0x07,OLED_CMD);
OLED_WriteByte(0xA1,OLED_CMD); //???????????,bit0: 0,0->0;1,0->127;
OLED_WriteByte(0xC0,OLED_CMD); //????COM?????;bit3: 0,???g?;1,?????g? COM[N-1]->COM0;N:????�??
OLED_WriteByte(0xDA,OLED_CMD); //????COM???????????
OLED_WriteByte(0x12,OLED_CMD); //[5:4]????
OLED_WriteByte(0x81,OLED_CMD); //????????
OLED_WriteByte(0xEF,OLED_CMD); //1~255;I??0X7F (????????,??????)
OLED_WriteByte(0xD9,OLED_CMD); //????????????
OLED_WriteByte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WriteByte(0xDB,OLED_CMD); //????VCOMH ???????
OLED_WriteByte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
OLED_WriteByte(0xA4,OLED_CMD); //??????????;bit0:1,????;0,???;(????/????)
OLED_WriteByte(0xA6,OLED_CMD); //??????????;bit0:1,???????;0,???????
OLED_WriteByte(0xAF,OLED_CMD); //???????
OLED_Clear();
}
/*********************************************************************
*********************************************************************/
oled.h
#ifndef HARDWARE_OLED_H_
#define HARDWARE_OLED_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
* @fn OLED_DisplayOn
*
* @brief ????OLED???
*
* @param none
*
* @return none
*/
void OLED_DisplayOn(void);
/*********************************************************************
* @fn OLED_DisplayOn
*
* @brief ???OLED???
*
* @param none
*
* @return none
*/
void OLED_DisplayOff(void);
/*********************************************************************
* @fn OLED_Refresh
*
* @brief ???OLED
*
* @param none
*
* @return none
*/
void OLED_Refresh(void);
/*********************************************************************
* @fn OLED_Clear
*
* @brief ????
*
* @param none
*
* @return none
*/
void OLED_Clear(void);
/*********************************************************************
* @fn OLED_Fill
*
* @brief ???????K??????
*
* @param x1,y1,x2,y2 - ???????????
* mode - 0:???; 1:???
*
* @return none
*/
void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode);
/*********************************************************************
* @fn OLED_ShowChar
*
* @brief ???????????h?????,?????????????
*
* @param x - 0 ~ 127
* y - 0 ~ 63
* char - ASC2???
* size - ??????: 12/16/24
* mode - 0:???????; 1:???????
*
* @return none
*/
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size, uint8_t mode);
/*********************************************************************
* @fn OLED_ShowNum
*
* @brief ???????????
*
* @param x??y - ???????
* num - ???
* len - ???????
* size - ??????: 12/16/24
*
* @return none
*/
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size);
/*********************************************************************
* @fn OLED_ShowString
*
* @brief ????????????????
*
* @param x??y - ???????
* *pChar - ???????'???
* size - ??????: 12/16/24
*
* @return none
*/
void OLED_ShowString(uint8_t x, uint8_t y,uint8_t *pChar, uint8_t size1,uint8_t mode);
void OLED_WR_Byte(uint8_t dat,uint8_t cmd);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_DisShowCHinese(uint8_t x,uint8_t y,uint8_t* pChar,uint8_t size1,uint8_t mode);
void OLED_DrawBMP(uint8_t x, uint8_t y, const char* name);
void OLED_DrawBMP1(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const char* name);
/*********************************************************************
* @fn OLED_Init
*
* @brief ??'??OLED
*
* @param none
*
* @return none
*/
void OLED_Init(void);
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
/*********************************************************************
*********************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* HARDWARE_OLED_H_ */