资讯详情

基于3线spi通信的oled(cubemx图形化编程软件)

简介

spi通信原理

SPI是串行外设界面(Serial Peripheral Interface)缩写是一种高速、全双工、同步通信总线,芯片管脚只占用四条线,节省了芯片管脚,同时也是PCB由于这种简单易用的特点,越来越多的芯片集成了这种通信协议,节省了空间,提供了便利。比如flash闪存芯片W25Q64等。

在这里插入图片描述

  • CPOL代表的是SCK时钟线闲置状态下的电平,如CPOL为0时,SCK闲置时钟线为0,反之亦然。如下图所示。
  • CPHA代表的是SCK在奇数边缘采样或在数边缘采样,如下图所示CPHA=0时,在奇数边缘采样,即绿线;当CPHA=1时,在偶数边沿采样,就是上面标着2、4、6……的地方。

一般的SPI为4-wire模式 芯片管脚上只有四条线。 MISO(Master Input Slave Output): 从设备数据输入主要设备数据输出。 MOSI(Master Output Slave Input):从设备数据输出输入主器件数据。 SCK(Slava Clock): 时钟信号,由主设备控制发出。 NSS(CS): 主设备控制从设备中选择信号。NSS从设备中选择低电平。

SPI还有3-wire模式 芯片的管脚只占3(我们的)OLED正是这种模式) MISO/MOSI: 主从双向通信。 SCK(Slava Clock): 由主设备控制发出的时钟信号。 NSS(CS): 主设备控制从设备中选择信号。NSS从设备中选择低电平。 其实质把MISO和MIOSI合成一条,如下图所示。

OLED介绍

OLED的基础介绍

OLED定义和优势

OLED,即有机发光二极管(Organic Light-Emitting Diode),又称有机电 激光显示(Organic Electroluminesence Display, OELD)。OLED由于具有自发光、无背光源、对比度高、厚度薄、视角广、反应速度快、柔性面板、使用温度范围广、结构简单、工艺简单等优良特点,被认为是下一代平面显示器的新兴应用技术。

OLED显示技术具有自发光的特点,采用非常薄的有机材料涂层和玻璃基板,当电流通过时,这些有机材料会发光,OLED从2003年开始,这种显示设备视角大,可以节约电能。MP应用于3播放器。

  • LCD都需要背光,而且OLED不需要,因为它是自发光的。同样的显示,OLED效果更好。以目前的技术,OLED尺寸难以大规模化,但分辨率确实很高。

  • ALINETEK的0.96寸OLED模块 模块有两种选择:单色和双色。单色为纯蓝色,双色为黄色和蓝色。单色模块的每个像素点只有亮点和不亮点,没有颜色区别; 尺寸小,显示尺寸为0.96英寸,模块只有27英寸mm26mm大小; 该模块的分辨率为12864;

  • 该模块提供了多种接口方式,包括6800和8080两种并行接口方式 4线的串行SPI接口方式、 3线的串行SPI接口方式、IIC接口方式; 不需要高压,直接3.3V你可以工作。 OLED选择模块工作模式 通过模块的四种模式BS1/BS设置(硬件设置),BS1/BS如表所示: 其他引脚的描述如下:

  • VCC:电源3.3V供电。

  • GND:地线,和VCC同时收到同一台单片机,只有3台.3的压差,收到其他地方,不能保证是3.3V是的,可能会烧坏。

  • SCL:OLED从时钟信号;

  • SDA:硬件内部的数据线MISO和MOSI连接在一起,但这里只作为MOSI数据线使用

  • RST(RES):硬复位OLED;

  • D/C(RS):命令/数据标志(0、读写命令;1、读写数据)。

我们只需要使用后三个命令来锁定相应的位置 :

  • 设置页面地址命令:在命令模式下ssd1306发送B0是第一页,发B7就是第8页。
  • 要找到列地址,需要同时设置两个命令,一个是列地址低4个命令,另一个是列地址高4个命令。如果我目前想锁定第125列,125对应的16进制是0x7D,所以我只需要同时发00x17和0x0D可以(没有顺序)

cubemx的配置

新建工程

1. 打开 STM32CubeMX 软件,点击“新建工程”

2. 选择 MCU 和封装

3.配置时钟

RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器) 选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz 修改 HCLK 的值为 72 后,输入回车,软件会自动修改所有配置

4. 配置调试模式

非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器 SYS 设置,选择 Debug 为 Serial Wire

5.1 SPI参数配置

  • 在 Connectivity 中选择 SPI1 设置
  • 并选择 Transmit Only Master 只发送主模式(因为我们只需要向OLED写指令与数据就能使用OLED了,不需要从OLED接收数据)
  • 不开启 NSS 即不使用硬件片选信号(NSS直接选择外部引出的任意引脚为输出模式即可)
  • 配置成时钟4分频

这些配置从上到下分别是:

  • Frame Format:主从模式选择
  • Data Size:一次传输数据大小
  • First Bit:数据是高位在先还是低位在先
  • prescaler(for Baud Rate):分频值
  • Clock Polarity(CPOL):时钟空闲时的电平
  • Clock Phase(CPHA):数据取样是在奇数取样还是在偶数取样(1Edge是奇数取样,2Edge是偶数取样)

对于正点原子的nano板子(STM32F103RBT6)来说,配置之后就会锁定两个引脚,一个是PA5(SCK),一个是PA7(MOSI),具体如下图所示。

5.2 GPIO参数配置

还有RST引脚和D/C引脚直接配置成推挽输出模式,如图:

5.3.1 工程配置1

5.3.2 工程配置2

5.4 生成工程

6 软件编写

6.1 keil内工程配置

先建立oled.c和oled.h两个文件 在魔术棒这里面 点击这里把oled.h文件的路劲包含进工程里面 这个User文件是我在外面创建的文件

Debug这里配置成DAP烧录(针对正点nano最新的板子,旧板子用ST-Link即可) 进入右边的Settings里面,配置Flash Download中的下载后自动复位勾上 检查这里是否连上,若未显示这个只需在左下脚的Connect下拉框中选择under Reset(前先复位再烧录)即可,若还是没有连上则还有其他问题,检查硬件连接(是否连上,是否供电不足),软件ch340、st-link驱动是否安装等。

6.1 代码编写

#ifndef __OLED_H__
#define __OLED_H__

#include "main.h"
#include "spi.h"
#include "gpio.h"


//修改对应的SPI句柄
#define OLED_SPI hspi1

//数据、命令引脚
#define Data_Cmd_Pin GPIO_PIN_4
#define Data_Cmd_GPIO_Port GPIOA

//复位脚
#define OLED_RST_Pin GPIO_PIN_6
#define OLED_RST_GPIO_Port GPIOA

//对该位写1或0
#define Data_Cmd_State(__D_C_State__) HAL_GPIO_WritePin(Data_Cmd_GPIO_Port, Data_Cmd_Pin, (GPIO_PinState)(__D_C_State__))
#define OLED_RST_State(__RST_State__) HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, (GPIO_PinState)(__RST_State__))



/*OLED初始化*/
void OLED_Init(void);

/*清屏*/
void OLED_Clear(void);

/* 显示一个数字或英文 x位置,y时页位置(注意这里字符默认是高2页,宽8位的), data是数据,type是类型是数字还是字符 */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t data);

/*显示字符串*/
void OLED_ShowString(uint8_t x, uint8_t y,  const char *fmt, ...);


#endif

#include "oled.h"
#include "stdarg.h"
#include "stdio.h"



#define OLED_CMD 0
#define OLED_DAT 1

const unsigned char F8x16[];

//初始化命令
uint8_t CMD_Data[]={ 
        
0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,
0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,				
0xD8, 0x30, 0x8D, 0x14, 0xAF};

//向设备写控制命令
void OLED_WR_CMD(uint8_t cmd)
{ 
        
	Data_Cmd_State(OLED_CMD);//低电平是命令
	HAL_SPI_Transmit(&OLED_SPI, &cmd, 1, 0xff);
	Data_Cmd_State(1);//恢复
}

//向设备写数据
void OLED_WR_DATA(uint8_t data)
{ 
        
	Data_Cmd_State(OLED_DAT);//高电平是数据
	HAL_SPI_Transmit(&OLED_SPI, &data, 1, 0xff);
	Data_Cmd_State(1);//恢复
}

//初始化oled屏幕
void OLED_Init(void)
{ 
        
	OLED_RST_State(0);	
	HAL_Delay(200);
	OLED_RST_State(1);

	for(int16_t i=0; i<sizeof(CMD_Data); i++)
	{ 
        
		OLED_WR_CMD(CMD_Data[i]);
	}

	OLED_Clear();
}

//清屏
void OLED_Clear(void)
{ 
        	    
	for(int i=0;i<8;i++) 
	{ 
          
		OLED_WR_CMD(0xb0+i);
		OLED_WR_CMD (0x00); 
		OLED_WR_CMD (0x10); 
		for(int n=0;n<128;n++)
			OLED_WR_DATA(0x00);
	}
}

//设置光标坐标
void OLED_Set_Pos(uint8_t x, uint8_t y) 
{ 
        
	//0xb0~0xb7共8页
	//每一页,128列,一列1个字节,共128个字节
	//第一页的地址加上后面的y就是,对应的y页地址
	OLED_WR_CMD(0xb0+y);
	
	
	//设置列地址高4位
	OLED_WR_CMD((x>>4)|0x10);//取x的高4位
	//设置列地址低4位
	OLED_WR_CMD(x&0x0f);//取x的低4位
}

//写一个字节到指定坐标
void WriteByte(uint8_t x, uint8_t y, uint8_t data)
{ 
        
	OLED_Set_Pos(x, y);
	OLED_WR_DATA(data);
}


//显示一个数字或英文
//x位置,y时页位置,data是数据
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t data)
{ 
        
	//一个英文字符占8个列,16个行。
	#define Echar (16*8/8) + 1
	int num = 0;
	
	while(data != F8x16[num])//找到对应的字符在数组中的位置
	{ 
        
		num += Echar;
	}
	
	for(int i=0; i<2; i++)
	{ 
        
		for(int j=0; j<8; j++)
		{ 
        
			//拿出data对应数组的字符
			WriteByte(x+j, y+i, F8x16[num+1 + (i*8) + j]);
		}
	}
}

/* OLED显示一串字符 */
static char dat[128];	//16*8
void OLED_ShowString(uint8_t x, uint8_t y,  const char *fmt, ...)
{ 
        
	//printf方法
	va_list args;
	va_start(args, fmt);
	vsnprintf(dat, sizeof(dat) - 1, fmt, args);//把从args中得到的字符加入dat数组中
	va_end(args);
	
	int i=0;
	while(dat[i] != '\0')
	{ 
        
		OLED_ShowChar(x, y, dat[i++]);
		x += 8;//x的坐标移动到下一个字符的位置去
	}
}


/*英文字符*/
const unsigned char F8x16[] =
{ 
        
  ' ',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
  '!',0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
  '\'',0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 2
  '#',0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
  '$',0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
  '%',0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
  '&',0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
  '\'',0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
  '(',0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
  ')',0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
  '*',0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
  '+',0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
  ',',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
  '-',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
  '.',0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
  '/',0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
  '0',0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
  '1',0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
  '2',0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
  '3',0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
  '4',0x00,0x00,0xC0,0x20,0x10,0xF8, 

标签: 直接绿色激光二极管二极管2c3蓝双色二极管

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台