五、STM32标准库硬件SPI驱动OLED(基于SSD1106)

1、驱动芯片及MCU介绍

        SSD1106是一款常用于嵌入式设备中的小型屏幕OLED(有机发光二极管)显示器驱动芯片 ,被广泛应用于各种嵌入式设备中,本示例程序基于SSD1106驱动芯片的OLED显示屏。

        本次示例采用STM32F103系列MCU,使用标准库硬件SPI驱动OLED屏幕,相较于IIC,刷新速度更快更加稳定,本示例程序以刷新显存方式驱动OLED,通过对不同显示页显存处理来实现图标裁剪显示等操作。

        显示效果:(小刺猬以100ms移动一个像素点的方式移动)

2、工程说明

本次示例程序需要使用资源如下:

1、一组硬件SPI

2、一个通用定时器用于移动图标刷新时间

3、程序部分

1、主函数

#include "stm32f10x.h"
#include "printfsupport.h"
#include "Timer.h"
#include "OLED_12864.h" 


//图片显示函数声明
void Photo_Show(void);

uint8_t  abscissa  = 0;			//图标横坐标
uint8_t  ordinate  = 16;		//图标纵坐标
uint8_t  Refresh_Flag = 0;		//图标刷新标志

int main(void)
{
	//打印信息接口
	Printf_Init(115200);
	//OLED初始化
	OLED_Init();	
	//定时器2配置
	Timer2_Config();
	//主循环
	while(1)
	{
		//图片显示
		Photo_Show();
	}
}

//图片显示测试
void Photo_Show(void)
{
    OLED_VRAM_Clear();          //清屏
    OLED_VRAM_SymbolWrite(0,0,0,Symbol_Test_Photo); //显示图标
    OLED_VRAM_SymbolWrite(abscissa,ordinate,0,Symbol_Hedgehog); //显示图标
    OLED_VRAM_RemapReflesh();   //刷新显存

	while(1)
	{

		if(Refresh_Flag)
		{
			Refresh_Flag = 0;
			//擦除图标移动区域显存
			OLED_VRAM_AreaClear(0,16,128,48);
			//显示图标
			OLED_VRAM_SymbolWrite(abscissa,ordinate,0,Symbol_Hedgehog); 
			//刷新显存
    		OLED_VRAM_RemapReflesh();   
		}
	}
}

2、用于控制刷新时间和坐标的定时器配置

#include "Timer.h"

extern uint8_t  abscissa,ordinate,Refresh_Flag;		//图标横坐标 图标纵坐标 刷新标志

//定时器2配置
void Timer2_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;	

	// 开启定时器时钟,即内部时钟CK_INT=72M
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	
	// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period = 1000 - 1;
	// 时钟预分频数
    TIM_TimeBaseStructure.TIM_Prescaler = 7200-1;	
	// 时钟分频因子 
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
	// 计数器计数模式,设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 		
	// 重复计数器的值,没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;	
	// 初始化定时器
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
	// 清除计数器中断标志位
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	// 开启计数器中断
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

    // 设置中断组为
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);		
	// 设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn ;	
	// 设置主优先级为 3
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;	 
	// 设置抢占优先级为0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;	
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);	
		
	// 使能计数器
    TIM_Cmd(TIM2, ENABLE);
}


//定时器中断
void  TIM2_IRQHandler (void)
{
	if(TIM_GetITStatus( TIM2, TIM_IT_Update) != RESET) 
	{	
		TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);  

        //横坐标移动
        abscissa ++;
        abscissa %= (128-80);
        //刷新显存标志
        if(Refresh_Flag == 0)
        {
            Refresh_Flag = 1;
        }
	}		 	
}

3、硬件OLED配置接口(c源文件) , 图片显示驱动接口篇幅太长,不一一贴出。

#include "stm32f10x.h"
#include "OLED_Symbol.h"
#include "OLED_12864.h" 
#include "stdio.h"
#include "string.h"

//OLED虚拟映射内存
uint8_t OLED_VRAM[VRAM_LOGIC_PAGE_MAX][VRAM_LOGIC_COLUMN_MAX];
uint8_t OLED_VRAM1[VRAM_LOGIC_PAGE_MAX][VRAM_LOGIC_COLUMN_MAX];

//延时
void delay_ms(uint32_t time)
{
    uint16_t temp=7200;
    
    while(time--)
    {
        while(temp--){};     
    }
}

/*-------------------------------SSD1106驱动函数-------------------------------*/
/*************************************************
Function:     OLED_Init
Description:  初始化SSD1106
Parameter:    None     
Return:       None
Others:       None  
*************************************************/ 	 			    
void OLED_Init(void)
{ 	
 	GPIO_InitTypeDef  GPIO_InitStructure;
    SPI_InitTypeDef   SPI_InitStructure;  
    //时钟配置  	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
    //SPI1 CS引脚软件控制
    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);
    //SPI1 SCK MOSI引脚硬件控制
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    // D/C RES引脚软件控制
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);     

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOC,&GPIO_InitStructure);  
    //SPI Configration
	SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex;           //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;	               	            //设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		                    //设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		                            //串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	                            //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		                            //NSS信号软件管理
	SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8;		    //定义波特率预分频的值:波特率预分频值为8
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;          	            //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_Init(SPI2, &SPI_InitStructure);                                         //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
    SPI_Cmd(SPI2, ENABLE);                                                      //使能SPI外设	
 
    OLED_RST_Set();
	delay_ms(100);
	OLED_RST_Clr();
	delay_ms(100);
	OLED_RST_Set(); 
    delay_ms(100);

    OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
	OLED_WR_Byte(0x02,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
	OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
	OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WR_Byte(0x12,OLED_CMD);
	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
	OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WR_Byte(0x02,OLED_CMD);//
	OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
	OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
	OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
	OLED_WR_Byte(0xAF,OLED_CMD);/*display ON*/ 
	OLED_Clear();               //清屏
	OLED_Set_Pos(0,0); 	        //设置原点
} 

4、图片资源


#include "stdint.h"
#include "OLED_Symbol.h"

const unsigned char Test_Photo[]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x88,0x10,0xF8,0x08,0xE8,0x08,0xF8,0x00,0xF0,0x00,0xFC,
0x00,0x44,0xC8,0x00,0x00,0x90,0x90,0x90,0x10,0xFC,0x10,0x14,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x10,0x09,0x27,0x10,0x0F,0x10,0x27,0x00,0x07,0x20,0x3F,
0x00,0x00,0x3F,0x10,0x00,0x10,0x1F,0x08,0x00,0x0F,0x10,0x38,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

const unsigned char Hedgehog[] = {
0x00,0x80,0x80,0xC0,0x30,0x38,0x84,0x06,0x2E,0x0A,0x02,0xC0,0x01,0x01,0x87,0x31,
0x01,0x01,0x03,0x31,0x01,0x00,0x88,0x82,0xE6,0x38,0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,
0xE0,0xC0,0x40,0xC0,0xC0,0xC0,0xC0,0x40,0xC0,0xC0,0xC0,0x80,0x80,0xC0,0x80,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xC0,0x41,0x7F,0xA1,0x8C,0x85,0x82,0xFA,0xF6,0x72,0x72,0x5C,0x18,0x1D,0x1D,
0x06,0x06,0x06,0x07,0x02,0x02,0x07,0x07,0x87,0xC1,0x41,0x23,0x13,0x10,0x08,0x48,
0x18,0x1D,0x3C,0x68,0x48,0x91,0x31,0x60,0xC0,0xC0,0x41,0x40,0xE1,0x41,0x01,0x01,
0x03,0x03,0x03,0x02,0x04,0x0C,0x0E,0x18,0x1C,0x78,0x60,0x60,0xF0,0xF0,0xC0,0xC0,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x91,0xD9,0x7E,0x3F,0x37,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x22,0x21,0x04,0x04,0x20,0x00,0x01,0x00,0x88,
0x80,0x01,0x00,0x18,0x80,0x1F,0x08,0x24,0x26,0x18,0x33,0xED,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x09,0x1D,0xFF,0xF9,
0xB8,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x02,0x13,0xDB,0xFF,0x77,0x33,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0E,0x7F,0x80,0x82,0x02,0x00,0x10,0x10,0x02,0x00,0x20,0x20,0x80,
0x84,0x80,0x80,0x40,0x40,0x2C,0x20,0x10,0x19,0x0C,0x02,0x01,0x00,0x00,0x00,0x00,
0x80,0x60,0x10,0x08,0x80,0x40,0xA0,0xA0,0xC0,0x00,0x20,0xE0,0xF8,0x3A,0x3E,0x0F,
0x0B,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
0x00,0x00,0x00,0x01,0x0D,0x2F,0x7F,0xF2,0xF0,0xB0,0x80,0x80,0x80,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x03,0x04,0x00,0x00,0xC1,0x06,0x07,0x07,0x81,0x80,0x80,0x00,0x01,0x01,0x81,0x81,
0x83,0x82,0x82,0x82,0x42,0x42,0x62,0x26,0x26,0x32,0x1B,0x18,0x18,0x18,0x0C,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x07,0x0C,0x3C,0x7C,
0x5C,0x58,0x78,0x78,0x78,0x70,0x30,0x30,0x30,0x30,0x30,0x20,0x30,0x30,0x30,0x38,
0x30,0x10,0x10,0x38,0x38,0x10,0x10,0x18,0x18,0x18,0x38,0x38,0x3C,0x48,0x4C,0x4C,
0x28,0x2C,0x2C,0x1A,0x09,0x08,0x04,0x04,0x04,0x05,0x07,0x07,0x01,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

struct OLED_SymbolStruct  Symbol_Test_Photo={128,16,256,1,Test_Photo};                              //单个符号宽度128个像素 高度16个像素 占用256个字节 共1个符号 正常显示
struct OLED_SymbolStruct  Symbol_Hedgehog={80,47,480,1,Hedgehog};                                   //单个符号宽度80个像素 高度47个像素 占用480个字节 共1个符号 正常显示

图标定义头文件

#ifndef __OLED_SYMBOL_H
#define __OLED_SYMBOL_H
#include "stdint.h"
#include "stm32f10x.h"



struct  OLED_SymbolStruct
{
     uint16_t             Width;                          //单个符号宽度         单位像素
     uint16_t             Height;                         //单个符号高度         单位像素
     uint16_t             Bytes;                          //单个符号占用字节数      
     uint16_t             Number;                         //全体符号数量    
     const unsigned char* Symbol_Array;                   //符号数据数组
};


extern struct OLED_SymbolStruct  Symbol_Test_Photo;
extern struct OLED_SymbolStruct  Symbol_Hedgehog;



#endif

驱动演示完毕,取模软件为PCtoLCD2002完美版,软件资源及代码均已免费上传,如有需要自取。

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值