stm32与OLED屏接口的引脚介绍:

      CS————GPIOD3;

      RST————GPIOD4;

      DC—————GPIOD5;

      D0——————GPIOD6;

      D1——————GPIOD7;

上是我参考别人的oled引脚的接线

但是 我买的oled模块和别人的不是很一样,虽然也是spi通信的

看一下我的接线:

模块与stm32:

GND--GND

VCC--3.3v

SCL--PD6  :这个是时钟

SDA--PD7 :这个是传输数据的,也就是数据线spi本应是两条的,但是屏幕并没有返回值,所以只有一条了

RES--PD4 :复位,

DC--PD5  :这个是命令或数据指示位,当为高电平的时候表示数据,低电平的时候表示命令

根据上面的取模方式,就要有相对应的代码才行:

下面这行代码就是对应的这种取模方式,这个是32*32的汉字.

void OLED_ShowChinese(int x, int y, const unsigned char *p)
{
    int i = 0;
    OLED_Coord(x, y);
    for(i = 0; i < 32; i+=2)   //因为汉字是占了屏幕里的两行,所以要有上下两个部分. 汉字的宽是32个像素.
    {
        SPI_Write(p[i], OLED_Data);
    }
    OLED_Coord(x, y+1);
    for(i = 1; i < 32; i+=2)
    {
        SPI_Write(p[i], OLED_Data);
    }
}

////////////////////////////////////////////////////////////////////////////////

下面我们要用stm32自带的spi库去配置oled屏幕

我们先看接线:

单片机                        -----oled屏幕

SPI1->CS      ------ PA4----CS      这个是片选,我的屏幕上没有

SPI1->CLK    ------ PA5 ----D0     这个是spi
SPI1->MISO  ------ PA6-----D1     这个是spi

SPI1->MOSI  ------ PA7

                             PD4-----RST   (???这个我也有一点怀疑是不是spi的一部分),从源程序来看并不是.源程序中,只是在屏幕初始化的时候用了一下,其他时候没有出现.
                             PD5-----DC     这个不是,就配置成普通的输出就行
 
 
其实这样看,感觉oled用的spi并不是很完整,也许是我的到的源程序没有按照标准的spi编写.
我的想法是这样,先用stm32配置一个标准的spi程序,然后把屏接上去,看一看行不行.
 
 
本来想用stm32的spi实现,但是出了一点问题:
不知道为什么,总是多出一些小点.先存个档,以后查看问题出在哪里吧.
 

对应的程序:
oled.c文件:

#include "oled.h"
#include "stm32f10x.h" const unsigned char xing[]=
{ 0x10,0x40,0x10,0x22,0xF0,0x15,0x1F,0x08,
0x10,0x16,0xF0,0x21,0x40,0x40,0x3C,0x42,
0x10,0x42,0x10,0x42,0xFF,0x7F,0x10,0x42,
0x10,0x42,0x10,0x42,0x00,0x40,0x00,0x00};/*"姓",0*/
const unsigned char A[]=
{ 0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02,
0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20};/*"A",0*/
const unsigned char ming[]=
{ 0x00,0x04,0x20,0x04,0x20,0x04,0x10,0x02,
0x08,0xFE,0x14,0x43,0x67,0x43,0x84,0x42,
0x44,0x42,0x24,0x42,0x14,0x42,0x0C,0x42,
0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00};/*"名",0*/
const unsigned char ASCII_Colon[]=
{ 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,
0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00};/*":",0*/
const unsigned char xue[]=
{ 0x40,0x04,0x30,0x04,0x11,0x04,0x96,0x04,
0x90,0x04,0x90,0x44,0x91,0x84,0x96,0x7E,
0x90,0x06,0x90,0x05,0x98,0x04,0x14,0x04,
0x13,0x04,0x50,0x04,0x30,0x04,0x00,0x00};/*"学",0*/
const unsigned char hao[]=
{ 0x80,0x00,0x80,0x00,0x80,0x00,0xBE,0x06,
0xA2,0x05,0xA2,0x04,0xA2,0x04,0xA2,0x04,
0xA2,0x44,0xA2,0x84,0xA2,0x44,0xBE,0x3C,
0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00};/*"号",0*/ const unsigned char liao[] = // 瞭望,不知道为什么不行,这个好像是定义了一个结构体,实际上,我可以让文字的显示更加灵活.
{
0x10,0x04,0x10,0x03,0xD0,0x00,0xFF,0xFF,
0x90,0x80,0x10,0x41,0x00,0x20,0xFC,0x1F,
0x04,0x00,0x04,0x00,0x04,0x00,0xFE,0x3F,
0x04,0x40,0x00,0x40,0x00,0x70,0x00,0x00,
};
const unsigned char wang[] =
{
0x10,0x04,0x10,0x03,0xD0,0x00,0xFF,0xFF,
0x90,0x20,0x18,0x11,0xE8,0x8F,0x08,0x81,
0xE8,0x5F,0x08,0x21,0xFF,0x17,0x08,0x38,
0x0A,0x46,0x8C,0x81,0x08,0xE0,0x00,0x00
}; /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/ void OLED_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct; //开启GPIOD的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //设置GPIO的基本参数
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //输出速度50MHz
GPIO_Init(GPIOD, &GPIO_InitStruct); GPIO_SetBits(GPIOD, GPIO_Pin_4 | GPIO_Pin_5 );
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/
//下面是spi的协议实现部分
void SPI_Write(char data, int Mode)
{
if(Mode)
{
OLED_DC(1); //DC引脚输入高,表示写数据
}
else
{
OLED_DC(0); //DC引脚输入低,表示写命令
}
//OLED_CS(0); //CS引脚输入低,片选使能 SPI_I2S_SendData(SPI1, data);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//判断有没有传输完,对于传输是很重要的. OLED_DC(0); //DC引脚输入低, 命令行恢复默认.
//OLED_CS(1); //CS引脚输入高,片选失能
} void spi1(void) //spi1的配置.
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure; //经常把这个开关忘掉 /* SPI的IO口和SPI外设打开时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//也经常把这个忘掉 /* SPI的IO口设置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7); //PA5.6.7上拉
/***************************************************************************/
/************************* 设置SPI的参数 ***********************************/
/***************************************************************************/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//选择全双工SPI模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8位SPI
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟悬空高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //在第二个时钟采集数据
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //Nss使用软件控制
/* 选择波特率预分频为256 */
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//从最高位开始传输
SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Cmd(SPI1, ENABLE);
SPI_Init(SPI1, &SPI_InitStructure);
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/
//坐标的实现
void OLED_Coord(unsigned char x, unsigned char y)
{
SPI_Write((0xb0+(y & 0x0f)), OLED_Order); //设置OLED显示的页
SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//设置OLED水平坐标的高4位 根据上面那张图分析,这是取x的高四位,
SPI_Write((x & 0x0f)|0x01, OLED_Order); //设置OLED水平坐标的低4位 至于为什么要|0x01,可能是为了防止太靠边。
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/
void OLED_Clear(void)
{
int i = 0, j = 0;
for(i = 0; i < 8; i++)
{
OLED_Coord(0, i);
for(j = 0; j < 128; j++)
{
SPI_Write(0x00, OLED_Data);
}
}
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/
void OLED_Display_Off(void)
{
//电荷泵设置(初始化时必须打开,否则看不到显示)
SPI_Write(0x8D, OLED_Order);
SPI_Write(0x10, OLED_Order);//bit2 0:关闭 1:打开
SPI_Write(0xAE, OLED_Order);//0xAE:关闭显示
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/
void OLED_Display_On(void)
{
//电荷泵设置(初始化时必须打开,否则看不到显示)
SPI_Write(0x8D, OLED_Order);
SPI_Write(0x14, OLED_Order);//bit2 0:关闭 1:打开
SPI_Write(0xAF, OLED_Order);//0xAF:开显示
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/ void OLED_Init(void)
{
OLED_GPIO_Init(); OLED_RST(1);
delay(6000); //这里有一个延迟,即便是使用滴答定时器也终究是delay,所以怎样去除这个delay呢?
OLED_RST(0);
delay(6000); //怎样去除这个delay呢???
OLED_RST(1); SPI_Write(0xAE, OLED_Order);//0xAE:关显示 SPI_Write(0x00, OLED_Order);//设置低列地址
SPI_Write(0x10, OLED_Order);//设置高列地址 //设置行显示的开始地址(0-63)
//40-47: (01xxxxx)
SPI_Write(0x40, OLED_Order); //设置对比度
SPI_Write(0x81, OLED_Order);
SPI_Write(0xff, OLED_Order);//这个值越大,屏幕越亮(和上条指令一起使用)(0x00-0xff) SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置, 0xA0: 正常显示(默认0xA0)
SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置, 0xC0: 正常显示(默认0xC0) //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
//0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
SPI_Write(0xA6, OLED_Order); SPI_Write(0xA8, OLED_Order);//设置多路复用率(1-64)
SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默认为3f) //设置显示抵消移位映射内存计数器
SPI_Write(0xD3, OLED_Order);
SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默认为0x00) //设置显示时钟分频因子/振荡器频率
SPI_Write(0xD5, OLED_Order);
//低4位定义显示时钟(屏幕的刷新时间)(默认:0000)分频因子= [3:0]+1
//高4位定义振荡器频率(默认:1000)
SPI_Write(0x80, OLED_Order);// //时钟预充电周期
SPI_Write(0xD9, OLED_Order);
SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1; [7:4] PHASE 2 //设置COM硬件应脚配置
SPI_Write(0xDA, OLED_Order);
SPI_Write(0x12, OLED_Order);//[5:4] 默认:01 SPI_Write(0xDB, OLED_Order);//
SPI_Write(0x40, OLED_Order);// //设置内存寻址方式
SPI_Write(0x20, OLED_Order);
//00: 表示水平寻址方式
//01: 表示垂直寻址方式
//10: 表示页寻址方式(默认方式)
SPI_Write(0x02, OLED_Order);// //电荷泵设置(初始化时必须打开,否则看不到显示)
SPI_Write(0x8D, OLED_Order);
SPI_Write(0x14, OLED_Order);//bit2 0:关闭 1:打开 //设置是否全部显示 0xA4: 禁止全部显示
SPI_Write(0xA4, OLED_Order); //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)
//0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)
SPI_Write(0xA6, OLED_Order);// SPI_Write(0xAF, OLED_Order);//0xAF:开显示 SPI_Write(0xAF, OLED_Order);//0xAF:开显示 OLED_Clear();
} /*******************************************************************************
* 函 数 名 :
* 函数功能 :
* 输 入 :
* 输 出 : 无
*******************************************************************************/
void OLED_ShowChinese(int x, int y, const unsigned char *p)
{
int i = 0;
OLED_Coord(x, y);
for(i = 0; i < 32; i+=2) //因为汉字是占了屏幕里的两行,所以要有上下两个部分. 汉字的宽是32个像素.
{
SPI_Write(p[i], OLED_Data);
}
OLED_Coord(x, y+1);
for(i = 1; i < 32; i+=2)
{
SPI_Write(p[i], OLED_Data);
}
} /*******************************************************************************
* 函 数 名 : OLED_ShowChar
* 函数功能 : 输出一个ascii
* 输 入 :
* 输 出 : 无
*******************************************************************************/
void OLED_ShowChar(int x, int y, const unsigned char *p)
{
int i = 0;
OLED_Coord(x, y);
for(i = 0; i < 16; i+=2)
{
SPI_Write(p[i], OLED_Data);
}
OLED_Coord(x, y+1);
for(i = 1; i < 16; i+=2)
{
SPI_Write(p[i], OLED_Data);
}
}

oled.h文件:

#ifndef _oled_H
#define _oled_H
#include "stm32f10x.h"
extern const unsigned char xing[];
extern const unsigned char A[];
extern const unsigned char ming[];
extern const unsigned char ASCII_Colon[];
extern const unsigned char xue[];
extern const unsigned char hao[];
extern const unsigned char liao[];
extern const unsigned char wang[]; //也不知上面这些define是否应该定义在.h文件,是不是定义在.c文件中更合理,感觉不是,因为定义在.h中主函数可以调用头文件来应用.[]???
#define OLED_CS(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_3):GPIO_ResetBits(GPIOD, GPIO_Pin_3) //X为1时对应GPIO端口输出高电平,X为0时对应GPIO端口输出低电平 #define OLED_RST(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_4):GPIO_ResetBits(GPIOD, GPIO_Pin_4) #define OLED_DC(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_5):GPIO_ResetBits(GPIOD, GPIO_Pin_5) #define OLED_D0(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_6):GPIO_ResetBits(GPIOD, GPIO_Pin_6) #define OLED_D1(X) X?GPIO_SetBits(GPIOD, GPIO_Pin_7):GPIO_ResetBits(GPIOD, GPIO_Pin_7) #define OLED_Order 0//定义写命令 我以前粘贴的时候,这里虽然没有出错,但是在相应的.c文件中出现了错误.就是因为这里粘贴了不该粘贴的东西.
#define OLED_Data 1//定义写数据 void OLED_GPIO_Init(void);
void delay(u32 i);
void SPI_Write(char data, int Mode);
void OLED_Coord(unsigned char x, unsigned char y);
void OLED_Clear(void);
void OLED_Display_Off(void);
void OLED_Display_On(void);
void OLED_Init(void);
void OLED_ShowChinese(int x, int y, const unsigned char *p);
void OLED_ShowChar(int x, int y, const unsigned char *p);
void spi1(void); #endif

下面是主函数:

/*******************************************************************************
*
* 普中科技
--------------------------------------------------------------------------------
* 实 验 名 : 蜂鸣器实验
* 实验说明 : 通过IO产生一定频率的脉冲实现蜂鸣器发声
* 连接方式 :
* 注 意 : 所用函数在beep.c文件内
*******************************************************************************/ //#include "stm32f10x.h"
#include "public.h" //公共函数头文件
#include "oled.h" //#include "beep.h" //蜂鸣器函数头文件 /****************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Output : None
* Return : None
****************************************************************************/
int main()
{
//SysClockInit();
SystemInit(); //这里还是有点问题的,我该怎样甚至时钟的函数.
//OLED_GPIO_Init();
spi1();
OLED_Init(); //程序就是一层一层的,协议也是一层一层的.应该学会去拨开.
OLED_ShowChinese(, , xing);//‘姓’ //这个xing[]的数组是定义在.c文件中的,用extern在.h文件中拓展,之后主函数里include相应的.h就可以在main函数里进行调用这个变量了.
OLED_ShowChinese(, , ming);//‘名’
//OLED_ShowChar(36, 0, ASCII_Colon);//‘:’
OLED_ShowChinese(, , xue);//‘学’
OLED_ShowChinese(, , hao);//‘号’
//OLED_ShowChar(36, 2, ASCII_Colon);//‘:’ OLED_ShowChinese(, , liao);//‘瞭’
OLED_ShowChinese(, , wang);//‘望’
//OLED_ShowChar(36, 4, ASCII_Colon);//‘:’
while()
{ } }
 
 

oled的一套stm32实验2(自己的实验)的更多相关文章

  1. oled的一套stm32实验1

    详细的oled介绍:http://blog.sina.com.cn/s/blog_57ad1bd20102wtq8.html 整理自:https://www.cnblogs.com/wp2312139 ...

  2. [nRF51822] 12、基础实验代码解析大全 · 实验19 - PWM

    一.PWM概述: PWM(Pulse Width Modulation):脉冲宽度调制技术,通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形. PWM 的几个基本概念: 1) 占空比:占空比是指 ...

  3. [nRF51822] 11、基础实验代码解析大全 · 实验16 - 内部FLASH读写

     一.实验内容: 通过串口发送单个字符到NRF51822,NRF51822 接收到字符后将其写入到FLASH 的最后一页,之后将其读出并通过串口打印出数据. 二.nRF51822芯片内部flash知识 ...

  4. [nRF51822] 10、基础实验代码解析大全 · 实验15 - RTC

    一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻 ...

  5. [nRF51822] 9、基础实验代码解析大全 · 实验12 - ADC

    一.本实验ADC 配置 分辨率:10 位. 输入通道:5,即使用输入通道AIN5 检测电位器的电压. ADC 基准电压:1.2V. 二.NRF51822 ADC 管脚分布 NRF51822 的ADC ...

  6. 实验四 Android程序设计 实验报告

    实验四 Android程序设计 实验报告 目录 代码托管地址 Android程序设计-1 Android程序设计-2 Android程序设计-3 Android程序设计-4 Android程序设计-5 ...

  7. 20175212童皓桢 Java实验二-面向对象程序设计实验报告

    20175212童皓桢 Java实验二-面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设 ...

  8. 20175316 盛茂淞 2018-2019-2 《Java程序设计》实验二 面向对象程序设计 实验报告

    20175316 盛茂淞 2018-2019-2 <Java程序设计>实验二 面向对象程序设计 实验报告 (一)单元测试 在 IDEA中我们把产品代码放在src目录中,把测试代码放在tes ...

  9. 20172302《程序设计与数据结构》实验四Android程序设计实验报告

    课程:<程序设计与数据结构> 班级: 1723 姓名: 侯泽洋 学号:20172302 实验教师:王志强老师 实验日期:2018年5月30日 必修/选修: 必修 1.实验内容 (1)And ...

随机推荐

  1. ios程序启动过程和UIWidnow介绍

    一.iOS程序的完整启动过程(有storyboard) 1.先执行main函数,main内部会调用UIApplicationMain函数 2.UIApplicationMain函数里面做了什么事情: ...

  2. XTUOJ 1205 Range

    Range Time Limit : 1000 MS Memory Limit : 65536 KB Problem Description For an array, the range funct ...

  3. 洛谷 P3040 [USACO12JAN]贝尔分享Bale Share

    P3040 [USACO12JAN]贝尔分享Bale Share 题目描述 Farmer John has just received a new shipment of N (1 <= N & ...

  4. 洛谷 P1591 阶乘数码

    P1591 阶乘数码 题目描述 求n!中某个数码出现的次数. 输入输出格式 输入格式: 第一行为t(≤10),表示数据组数.接下来t行,每行一个正整数n(≤1000)和数码a. 输出格式: 对于每组数 ...

  5. iOS项目开发实战——iOS网络编程获取网页Html源码

    现在我们身处互联网的时代.不论什么一个软件或是App,都会或多或少与网络打交道,并不断发生数据交互.一个没有涉及网络编程的应用会显得比較low,这里我们将会開始使用Swift开发iOS应用,而且主要来 ...

  6. 第二天,导出文件sql,查询,视图view,聚合函数,反模式,字符串处理函数

    //把数据库导出到脚本文件mysqldump -uroot -p1234 --databases abc > d:/a/abc.sql CREATE TABLE stud( id INT PRI ...

  7. 【Django】ContentType组件

    目录 理解 表结构 使用 @ 好,现在我们有这样一个需求,我们的商城里有很多的商品,然而节日要来了,我们要搞活动. 那么,我们就要设计优惠券,优惠券都有什么类型呢?满减的.折扣的.立减的.等等等... ...

  8. unalias---取消命令别名

    unalias命令用来取消命令别名,是为shell内建命令. 选项 -a:取消所有命令别名. 实例 使用unalias命令将已经设置的命令别名"cc"取消,输入如下命令: unal ...

  9. intent- 启动其他应用

    今天需要在图库中实现对相机的调用,代码如下 Intent intent = new Intent(Intent.ACTION_VIEW); ComponentName componetName = n ...

  10. holder.js如何使用

    holder.js的使用 一.总结 一句话总结:使用:holder.js后面接图片宽高 <img src="holder.js/300x200" /> 1.holder ...