程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

STM32F103 SPI软件模拟(SSD1306)

有关SPI通信协议我们在《通信协议-SPI》已经进行了详细的介绍,因此这一节不再重复介绍。

一、软件/硬件SPI

想要控制STM32产生SPI方式的通讯,可以采用软件模拟或硬件SPI这两种方式。

1.1 软件模拟

所谓软件模拟,即直接使用CPU内核按照SPI协议的要求控制GPIO输出高低电平。

1.2 硬件SPI

硬件SPI是指直接利用STM32芯片中的硬件SPI外设,该硬件SPI外设跟USART串口外设类似,只要配置好对应的寄存器, 外设就会产生标准串口协议的时序。

使用它的SPI外设则可以方便地通过外设寄存器产生SPI协议方式的通讯,如初始化好SPI外设后, 只需要把某寄存器位置1,那么外设就会控制对应的SCKMOSI/MISO线自动进行SPI数据传输,而不需要内核直接控制引脚的电平。

相对来说,硬件SPI直接使用外设来控制引脚,可以减轻CPU的负担。不过使用硬件SPI时必须使用某些固定的引脚作为SCLMOSI/MISO, 软件模拟SPI则可以使用任意GPIO引脚,相对比较灵活。

在本开发板中,由于STM32F103RCT6芯片引脚较少,资源比较紧张, 在设计硬件时不方便使用硬件SPI指定的引脚连接外部设备,所以在控制程序上这里使用软件模拟SPI的方式。

二、OLED128x64SSD1306

2.1 回顾

有关OLED128x64(SSD1306)可以参考《Mini2440裸机开发之SPI(OLED SSD1306)》小节中的介绍;

img

在《Mini2440裸机开发之SPI(OLED SSD1306)》我们介绍了SSD1306的常用命令,以及SPI通信方式。

后续我们又在《linux驱动移植-SPI驱动移植(OLED SSD1306》中介绍了SPI设备驱动的编写,并以OLED SSD1306作为学习SPI的测试设备。

2.2 硬件接线

SSD1306选定SPI接口方式,SPI引脚定义:

  • CS:片选信号;连接是STM32F103PC0引脚;
  • DC:命令数据选择引脚;连接STM32F103PC1引脚;
    • 0:读写命令;
    • 1:读写数据;
  • RES:模块复位引脚,低电平有效;连接STM32F103PC2引脚;
  • D1MOSI引脚,SPI数据线,主设备输出从设备输入引脚;连接STM32F103PC3引脚;
  • D0SCLK引脚,SPI时钟线;连接STM32F103PC4引脚;
  • VCC:电源正极3.3~5V,连接STM32F103PC5引脚;
  • GND:电源地,连接STM32F103PC6引脚。

三、OLED源码实现

3.1 GPIO初始化

配置PC0~PC6引脚,均配置为通用推挽输出,最大速度2MHZ

/*******************************************************************************************
 *4线SPI使用说明:
 *VBT 供内部DC-DC电压,3.3~4.3V,如果使用5V电压,为保险起见串一个100~500欧的电阻
 *VCC 供内部逻辑电压 1.8~6V   
 *GND 地

 *BS0 低电平
 *BS1 低电平
 *BS2 低电平

 *CS  片选管脚
 *DC  命令数据选择管脚
 *RES 模块复位管脚 
 *D0(SCLK) ,时钟脚,由MCU控制
 *D1(MOSI) ,主输出从输入数据脚,由MCU控制

 *D2 悬空      
 *D3-D7 , 低电平 , 也可悬空,但最好设为低电平
 *RD  低电平 ,也可悬空,但最好设为低电平
 *RW  低电平 ,也可悬空,但最好设为低电平
 *RD  低电平 ,也可悬空,但最好设为低电平   
************************************************************************************************/

//************************************************************12864端口定义*********************************
#define OLED_GND   PCout(6)				 //GND
#define OLED_VCC   PCout(5)				 //VCC
#define OLED_SCL   PCout(4)              //串行时钟线
#define OLED_SDA   PCout(3)              //串行数据线
#define OLED_RST   PCout(2)              //硬复位
#define OLED_DC    PCout(1)              //命令/数据标志 0:读写命令  1:读写数据
#define OLED_CS    PCout(0)              //片选信号

/*******************************************************************************
 *
 *		Description:  初始化所用到的引脚
 *
 ******************************************************************************/
void OLED12864_GPIO_Init(void)         //初始化所用到的引脚
{
     gpio_init(PC0,GPO_PUSH_PULL_2,HIGH);
     gpio_init(PC1,GPO_PUSH_PULL_2,HIGH);
     gpio_init(PC2,GPO_PUSH_PULL_2,HIGH);
     gpio_init(PC3,GPO_PUSH_PULL_2,HIGH);
     gpio_init(PC4,GPO_PUSH_PULL_2,HIGH);
	 gpio_init(PC5,GPO_PUSH_PULL_2,HIGH);
	 gpio_init(PC6,GPO_PUSH_PULL_2,LOW);
};

3.2 写命令

写命令需要将DC设置为低电平,然后发送一个字节的命令即可;

/*******************************************************************************
 *
 *		Description:  写命令 DC=0   CS=0 CLK上升沿数据传递 
 *					  数据从高位开始写入
 *
 ******************************************************************************/
 void OLED_Wcmd(u8 cmd) 				  //写命令
 {
    u8 i;
    OLED_CS=0;                       //片选
	OLED_DC=0;						 //写命令
    for(i=0;i<8;i++)
	{
	  OLED_SCL=0;
	  if(cmd&0x80)
	     OLED_SDA=1;
	  else
	     OLED_SDA=0;
	  OLED_SCL=1;
	  cmd <<=1;
	}
	OLED_CS=1;						//锁存
 }

3.3 写数据

写数据需要将DC设置为高电平,然后发送一个字节的数据即可;

/*******************************************************************************
 *
 *		Description:  写数据 DC=1   CS=0 CLK上升沿数据传递 
 *					  数据从高位开始写入  
 *
 ******************************************************************************/
 void OLED_Wdata(u8 data) 			  //写数据
 {
    u8 i;
    OLED_CS=0;                       //片选
	OLED_DC=1;						 //写数据
    for(i=0;i<8;i++)
	{
	  OLED_SCL=0;
	  if(data&0x80)
	     OLED_SDA=1;
	  else
	     OLED_SDA=0;
	  OLED_SCL=1;
	  data <<=1;
	}
	OLED_CS=1;						//锁存
 }

3.4 设置OLED坐标

设置R坐标需要使用到两个命令:

  • 设置页地址,使用单字节指令: 0xB0H + A[3:0]
  • 设置列地址,使用单字节指令: 0x00H / 0x10H (低/高)+ A[3:0]

实现如下:

/***************************************************************************************************
 *
 *	  Description:  OLED12864设置坐标    一个ASCII字符字符占用6*8    6列8行
 *   		   x :  设置列地址0~0X7F
 *			   y :  设置页地址0~7 
 *
 **************************************************************************************************/ 
void OLED_Pos(u8 x,u8 y)     			  //坐标设定
{
  OLED_Wcmd(0xB0+y);
  OLED_Wcmd(((x&0xF0)>>4)|0x10);          //设置列地址高四位
  OLED_Wcmd((x&0x0F)|0x01);				  //设置列地址低四位
} 

3.5 清屏

清屏需要将OLED所有的页数据清零;

//**************************************清屏*******************************
void OLED_Clear(void)
{
	u8 x;
	u8 y;	
	for(y=0;y<8;y++)
	{
		OLED_Wcmd(0xB0+y);             //选择页
		OLED_Wcmd(0x01);
		OLED_Wcmd(0x10);
		for(x=0;x<0x80;x++)
			OLED_Wdata(0x00);		   //每次清1列
	}
}

3.6 OLED初始化

初始化代码如下所示,这里我们就不深究每个命令的含义了,具体查看数据手册;

/***************************************************************************************************
 *
 *	  Description:  OLED12864初始化
 *
 *
**************************************************************************************************/ 
 void OLED12864_Init(void)			  //初始化配置
 {
   OLED_SCL=1;
   OLED_CS=0;
   OLED_RST=0;
   delay_ms(50);              //复位
   OLED_RST=1;
   OLED_Wcmd(0xAE);            //显示关     
   OLED_Wcmd(0x00)   ;         //设置列低位地址
   OLED_Wcmd(0x10);            //设置列高位地址
   OLED_Wcmd(0x40);            //--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
   OLED_Wcmd(0X81);            //设置对比度   
   OLED_Wcmd(0xCF);            //值越大 越亮  
   OLED_Wcmd(0xA1);            //设置列左右反置     0xa0左右反置 0xa1正常
   OLED_Wcmd(0xC8);            //设置行上下反置     0xc0上下反置 0xc8正常
   OLED_Wcmd(0xA6);            //设置正常显示
   OLED_Wcmd(0x20);            //设置页地址模式 (0x00/0x01/0x02)
   OLED_Wcmd(0x02);            
   OLED_Wcmd(0x8D);			   //设置电荷磊开关
   OLED_Wcmd(0x14);			   //电荷磊开
   OLED_Wcmd(0xA4);            //字符显示开关 0xA4:开  0xA5:关
   OLED_Wcmd(0xA6);            // 背景色显示开关  0xA6:关   0xA7:开
   OLED_Wcmd(0xAF);            //显示开 
   OLED_Clear();               //初始清屏
   OLED_Pos(0,0);  
 }

3.7 显示字符

关于字符的显示原理这里不重复介绍了,具体可以查看《Mini2440裸机开发之LCD编程(GB2312ASCII字库制作)》。

/******************************************************************************
 *
 *		 oled128x64点阵  分为八页  每页128个字符	  一页中的每一列即一个字符(8位) 共128列
                         每次写入一个字符  即写入一页中的一列    从上到下依次为D0~D7
						 采用串行SPI方式写入   是从高位(D7)到低位(D0)依次写入
 *		 初始化步骤:1.关闭显示
 					 2.设置对比度
                     3.设置页地址
					 4.设置列地址
					 5.电荷磊设置
					 6.显示开
					 7.清屏 写入'\0'
 *
 *
 ****************************************************************************/


/*****************************************************************************************************
 *
 *		从ASCII 0x20 开始的点阵    一个字节占6行8列 
 *					   取模方式    列行式 低位在前  
 *
 *
 *****************************************************************************************************/
const u8 ASCII6x8[][6] =
{
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp		  ASCII 0x20
    { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },   // !
    { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
    { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // #
    { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $
    { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 },   // %
    { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 },   // &
    { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 },   // '
    { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 },   // (
    { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 },   // )
    { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 },   // *
    { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 },   // +
    { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 },   // ,
    { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 },   // -
    { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
    { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 },   // /
    { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0
    { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1
    { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2
    { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3
    { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4
    { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5
    { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6
    { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7
    { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8
    { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9
    { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 },   // :
    { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 },   // ;
    { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
    { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
    { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
    { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
    { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
    { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C },   // A
    { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B
    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
    { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D
    { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E
    { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F
    { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G
    { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H
    { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I
    { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J
    { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K
    { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L
    { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M
    { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N
    { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O
    { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P
    { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q
    { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R
    { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 },   // S
    { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T
    { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U
    { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V
    { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W
    { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 },   // X
    { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y
    { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z
    { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [
    { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // 55
    { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ]
    { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^
    { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 },   // _
    { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 },   // '
    { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 },   // a
    { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b
    { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 },   // c
    { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F },   // d
    { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 },   // e
    { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f
    { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C },   // g
    { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h
    { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i
    { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 },   // j
    { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k
    { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l
    { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m
    { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n
    { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 },   // o
    { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 },   // p
    { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC },   // q
    { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r
    { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 },   // s
    { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t
    { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u
    { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v
    { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w
    { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
    { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C },   // y
    { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z
    { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }    // horiz lines
};

/*****************************************************************************************************
 *
 *		从ASCII 0x20 开始的点阵    一个字节16行8列 
 *					   取模方式    列行式 低位在前  
 *
 *
 ***************************************************************************************************/
const u8  ASCII16x8[][16]=
{
  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
  0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//016
  0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//117
  0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//218
  0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//319
  0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//420
  0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//521
  0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//622
  0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//723
  0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//824
  0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//925
  0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//:26
  0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//;27
  0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//<28
  0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//=29
  0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//>30
  0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//?31
  0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@32
  0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A33
  0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B34
  0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C35
  0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D36
  0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E37
  0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F38
  0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G39
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H40
  0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I41
  0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J42
  0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K43
  0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L44
  0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M45
  0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N46
  0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O47
  0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P48
  0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q49
  0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R50
  0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S51
  0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T52
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U53
  0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V54
  0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W55
  0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X56
  0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y57
  0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z58
  0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[59
  0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\60
  0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//]61
  0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^62
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_63
  0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//`64
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a65
  0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b66
  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c67
  0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d68
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e69
  0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f70
  0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g71
  0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h72
  0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i73
  0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j74
  0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k75
  0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l76
  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m77
  0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n78
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o79
  0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p80
  0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q81
  0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r82
  0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s83
  0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t84
  0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u85
  0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v86
  0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w87
  0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x88
  0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y89
  0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z90
  0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{91
  0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//|92
  0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//}93
  0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~94
};
/*****************************************************************************************************
 *
 *		从ASCII 0x20 开始的点阵    一个字节8行16列 
 *					   取模方式    列行式 低位在前  
 *
 *
 ***************************************************************************************************/
const u8 CHINESE8x16[][16]=
{
  0x00,0x00,0x20,0x28,0x24,0x94,0xB4,0x5C,0x32,0x54,0x54,0x54,0x14,0x10,0x10,0x00,   /*"安",0*/
  0x00,0x00,0x14,0x7C,0x0A,0x78,0x5C,0x6A,0x54,0x6A,0x58,0x26,0x5A,0x40,0x40,0x00,   /*"徽",1*/
  0x00,0x00,0x40,0x54,0x3C,0x04,0x44,0x5C,0x74,0x7C,0x54,0x4A,0x4E,0x46,0x40,0x00,   /*"理",2*/
  0x00,0x00,0x40,0x40,0x40,0x44,0x44,0x24,0x5C,0x44,0x44,0x40,0x40,0x40,0x00,0x00,   /*"工",3*/
  0x00,0x00,0x00,0x00,0x50,0x48,0x28,0x1E,0x28,0x28,0x48,0x48,0x40,0x40,0x00,0x00,   /*"大",4*/
  0x00,0x00,0x08,0x28,0x28,0x2A,0x28,0x9A,0x6E,0x2C,0x27,0x24,0x24,0x04,0x00,0x00,   /*"学",5*/
  0x00,0x40,0x48,0x28,0x18,0x2C,0x40,0x48,0x34,0x2A,0x48,0x4C,0x40,0x40,0x00,0x00,   /*"欢",6*/
  0x00,0x00,0x40,0x3A,0x48,0x40,0x5C,0x54,0x4A,0x7E,0x44,0x44,0x5C,0x40,0x00,0x00,   /*"迎",7*/
  0x00,0x10,0x10,0x08,0x7C,0x02,0x28,0x08,0x04,0x8A,0x78,0x08,0x04,0x24,0x00,0x00,   /*"你",8*/
};
3.7.1 1ASCII字符86
 /*******************************************************************************************************
  *
  *  Functon:      OLED_P6x8Str(u8 x,u8 y,u8 *str)
  *  Description:   写入一组标准ASCII字符串  
  *  Parameter  :  显示的位置(x,y),y为页范围0~7,要显示的字符串
  *        	  x :	设置列地址0~0X7F
  *			  y :   设置页地址0~7 
  *                 一个字节占8行6列          
  *
*********************************************************************************************************/  
void OLED_P6x8Str(u8 x,u8 y,u8 *str)	     //6列8行  一列8位
{
  u8 i=0;
  u8 j=0;
  u8 k=0;      
  while (str[j]!='\0')
  {  
    while((str[j]<0x20)||(str[j]>0x80))	 //当写入的没有对应的点阵时 显示空格
		  str[j]=32;     
    k =str[j]-32;
    if(x>121)
	{
	     x=0;
		 y++;
	}
    OLED_Pos(x,y);    			           //选中坐标
  	for(i=0;i<6;i++)     
  	   OLED_Wdata(ASCII6x8[k][i]);  	  //写入一个字节
  	x+=6;
  	j++;
  }
}
5.7.2 1ASCII字符168
 /*******************************************************************************************************
  *
  *  Functon:      OLED_P16x8Str(u8 x,u8 y,u8 *str)
  *  Description:   写入一组标准ASCII字符串  
  *  Parameter  :  显示的位置(x,y),y为页范围0~7,要显示的字符串
  *        	  x :	设置列地址0~0X7F
  *			  y :   设置页地址0~7 
  *	                一个字节占16行8列
  *    
*********************************************************************************************************/
 void OLED_P16x8Str(u8 x,u8 y,u8 *str)
  {
     u8 i=0;
	 u8 j=0;
	 u8 k=0;
	 while(str[j]!='\0')
	 {
	    while((str[j]<0x20)||(str[j]>0x80))	 //当写入的没有对应的点阵时 显示空格
		    str[j]=32;                         
		k=str[j]-32;
		if(x>120)                            //列溢出 写入下一页
		{
		  x=0;
		  y++;
		}
  	    OLED_Pos(x,y);                       //选中页和列坐标
	    for(i=0;i<8;i++)			         //写入上八行
	    {
	     OLED_Wdata(ASCII16x8[k][i]);  
	    }
		OLED_Pos(x,y+1);
		for(i=0;i<8;i++)			         //写入下八行
		{
		  OLED_Wdata(ASCII16x8[k][i+8]);
		}
		x+=8;                               //x坐标右移8位 准备写入下一个字节
		j++;                                //下一个字符 
	 }
}
3.7.3 1个汉字816
/*******************************************************************************************************
  *
  *  Functon:      OLED_P8x16Chi(u8 x,u8 y,u8 *str)
  *  Description:   写入一组汉字
  *  Parameter  :  显示的位置(x,y),y为页范围0~7,要显示的字符串
  *        	  x :	设置列地址0~0X7F
  *			  y :   设置页地址0~7 
  *	                一个字占8行16列
  *    
*********************************************************************************************************/
void OLED_P8x16Chi(u8 x,u8 y,u8 *str)
{
     u8 i=0;
	 u8 j=0;
	 u8 k=0;
	 while(str[j]!='\0')
	 {              
		if(x>120)                            //列溢出 写入下一页
		{
		  x=0;
		  y++;
		}
  	    OLED_Pos(x,y);                       //选中页和列坐标
	    for(i=0;i<16;i++)			         //写入字
	    {
	     OLED_Wdata(CHINESE8x16[k][i]);  
	    }
		x+=16;                               //x坐标右移8位 准备写入下一个字节
		j+=2;                                 //下一个字
		k++;
	 }
}

3.8 实现功能

这里我们通过OLED实时输出RTC时间。

3.8.1 main函数实现
int main()
{
   u8 *time;
   STM32_Clock_Init(9);         	                //系统时钟初始化

   STM32_NVIC_Init(2,USART1_IRQn,0,1);		        //串口中断优先级初始化,其中包括中断使能
   usart_init(USART_1,115200);				        //串口1初始化,波特率115200 映射到PA9 PA10

   STM32_NVIC_Init(2,RTC_IRQn,0,1);		            //RTC中断优先级初始化,其中包括中断使能
   while(RTC_Init());                               //RTC初始化

   time = RTCTime();
   OLED12864_GPIO_Init();                           //GPIO初始化
   OLED12864_Init();                                //OLED初始化
   OLED_P16x8Str(45,0,"OLED");	                    //调用LCD_P8x16Str字符串显示函数,在第0页即第一行的第45列开始,显示字符串“OLED"
   OLED_P8x16Chi(16,6,"安徽理工大学");
   while(1)
   {
       time = RTCTime();
       OLED_P6x8Str(8,4,time);      //显示当前时间
	   delay_ms(1000);
   } 
}
3.8.2 测试

编译程序并下载测试,这里我们需要按照2.2节进行硬件接线,OLED测试效果如下;

下图是使用逻辑分析器捕捉到的模拟SPI信号;

并且在右上角可以看到时钟频率大概在1.67MHz

四、源码下载

源码下载路径:stm32f103

posted @ 2024-12-23 23:58  大奥特曼打小怪兽  阅读(1240)  评论(0)    收藏  举报
如果有任何技术小问题,欢迎大家交流沟通,共同进步