STM32 SPI通信--OLED

发布者:王大雷最新更新时间:2017-10-26 来源: eefocus关键字:STM32  SPI通信  OLED 手机看文章 扫描二维码
随时随地手机看文章

一、0.96寸OLED

STM32 <wbr>SPI通信--OLED

二、原理图

STM32 <wbr>SPI通信--OLED

二、GPIO模拟SPI

1. 硬件连接

通过引脚和模块电路图可以分析出SPI的电路连接

OLED                    STM32

GND      <---------->   GND

VCC      <---------->   3.3V

D0       <---------->   PA4(CLK)

D1       <---------->   PA3(MOSI)

RES      <---------->   PA2(RET复位)

DC       <---------->   PA1(命令|数据dc)

CS       <---------->   GND

2. 软件驱动STM32 <wbr>SPI通信--OLED

STM32 <wbr>SPI通信--OLED

STM32 <wbr>SPI通信--OLED

由OLED模块数据手册上SPI的操作时序图写出由GPIO口模拟的SPI驱动代码,模块只支持向模块写数据不能读数据,所以只需要写SPI发送即可

2.1 “SPI.h”

#define OLED_CMD 0   //命令声明

#define OLED_DATA 1 //数据声明

#define OLED_CLK    PAout(4)    // CLK时钟    d0

#define OLED_MOSI   PAout(3)    // MOSI     d1

#define OLED_RST    PAout(2)    // RET复位    ret

#define OLED_DC     PAout(1)    // 命令|数据    dc  (0表传输命令1表传输数据)

void OLED_SPI_Init(void); //配置MCU的SPI

void SPI_WriteByte(uint8_t addr,uint8_t data); //向寄存器地址写一个byte的数据

void WriteCmd(unsigned char cmd); //写命令

void WriteDat(unsigned char data); //写数据

2.2 “SPI.c”

void OLED_SPI_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);//使能PA端口时钟

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //端口配置

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出

    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz

    GPIO_Init(GPIOA,&GPIO_InitStructure);//根据设定参数初始化GPIOA

}

 

            

void SPI_WriteByte(unsigned char data,unsigned char cmd)

{

    unsigned char i=0;

    OLED_DC =cmd;

    OLED_CLK=0;

    for(i=0;i<8;i++)

    {

        OLED_CLK=0;

        if(data&0x80)OLED_MOSI=1; //从高位到低位

        else OLED_MOSI=0;

        OLED_CLK=1;

        data<<=1;

    }

    OLED_CLK=1;

    OLED_DC=1;

}

void WriteCmd(unsigned char cmd)

{

    SPI_WriteByte(cmd,OLED_CMD);

}

void WriteData(unsigned char data)

{

    SPI_WriteByte(data,OLED_DATA);

}

三、STM32对OLED模块的控制

3.1 指令集

STM32 <wbr>SPI通信--OLED

3.2 “OLED.h”

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

void OLED_ON(void);//唤醒OLED

void OLED_OFF(void);//OLED休眠

void OLED_Refresh_Gram(void);//更新显存到OLED

void OLED_Clear(void);//清屏

void OLED_DrawPoint(u8 x,u8 y,u8 t);//画点

void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);//填充

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode);//显示字符

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);//显示2个数字

void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size);//显示字符串

3.3 “OLED.c”

//OLED的显存

//存放格式如下.

//[0]0 1 2 3 ... 127    

//[1]0 1 2 3 ... 127    

//[2]0 1 2 3 ... 127    

//[3]0 1 2 3 ... 127    

//[4]0 1 2 3 ... 127    

//[5]0 1 2 3 ... 127    

//[6]0 1 2 3 ... 127    

//[7]0 1 2 3 ... 127           

u8 OLED_GRAM[128][8];   

void OLED_DLY_ms(unsigned int ms)

{                         

  unsigned int a;

  while(ms)

  {

    a=1335;

    while(a--);

    ms--;

  }

}

void OLED_Init(void)

{

    OLED_SPI_Init();

    OLED_CLK = 1;

    OLED_RST = 0;

    OLED_DLY_ms(100);

    OLED_RST = 1;

    //从上电到下面开始初始化要有足够的时间,即等待RC复位完毕

    WriteCmd(0xAE);         // Display Off (0x00)

    WriteCmd(0xD5);

    WriteCmd(0x80);         // Set Clock as 100 Frames/Sec

    WriteCmd(0xA8);

    WriteCmd(0x3F);         // 1/64 Duty (0x0F~0x3F)

    WriteCmd(0xD3);

    WriteCmd(0x00);         // Shift Mapping RAM Counter (0x00~0x3F)

    WriteCmd(0x40 | 0x00);  // Set Mapping RAM Display Start Line (0x00~0x3F)

    WriteCmd(0x8D);

    WriteCmd(0x10 | 0x04);  // Enable Embedded DC/DC Converter (0x00/0x04)

    WriteCmd(0x20);

    WriteCmd(0x02);         // Set Page Addressing Mode (0x00/0x01/0x02)

    WriteCmd(0xA0 | 0x01);  // Set SEG/Column Mapping    

    WriteCmd(0xC0);  // Set COM/x Scan Direction   

    WriteCmd(0xDA);

    WriteCmd(0x02 | 0x10);  // Set Sequential Configuration (0x00/0x10)

    WriteCmd(0x81);

    WriteCmd(0xCF);         // Set SEG Output Current

    WriteCmd(0xD9);

    WriteCmd(0xF1);         // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock

    WriteCmd(0xDB);

    WriteCmd(0x40);         // Set VCOM Deselect Level

    WriteCmd(0xA4 | 0x00);  // Disable Entire Display On (0x00/0x01)

    WriteCmd(0xA6 | 0x00);  // Disable Inverse Display On (0x00/0x01)

    WriteCmd(0xAE | 0x01);  // Display On (0x01)

    OLED_Clear();  //初始清屏   

}

void OLED_ON(void)

{

    WriteCmd(0X8D);  //设置电荷泵

    WriteCmd(0X14);  //开启电荷泵

    WriteCmd(0XAF);  //OLED唤醒

}

void OLED_OFF(void)

{

    WriteCmd(0X8D);  //设置电荷泵

    WriteCmd(0X10);  //关闭电荷泵

    WriteCmd(0XAE);  //OLED休眠

}

void OLED_Refresh_Gram(void)

{

    u8 i,n;         

    for(i=0;i<8;i++)  

    {  

        WriteCmd(0xb0+i);   //设置页地址(0~7)

        WriteCmd(0x00);      //设置显示位置—列低地址

        WriteCmd(0x10);      //设置显示位置—列高地址   

        for(n=0;n<128;n++)WriteData(OLED_GRAM[n][i]); 

    }   

}

void OLED_Clear(void)  

{  

    u8 i,n;  

    for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00;  

    OLED_Refresh_Gram();//更新显示

}

            

void OLED_DrawPoint(u8 x,u8 y,u8 t)

{

    u8 pos,bx,temp=0;

    if(x>127||y>63)return;//超出范围了.

    pos=7-y/8;

    bx=y%8;

    temp=1<<(7-bx);

    if(t)OLED_GRAM[x][pos]|=temp;

    else OLED_GRAM[x][pos]&=~temp;     

}

            

void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)  

{  

    u8 x,y;  

    for(x=x1;x<=x2;x++)

    {

        for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);

    }                                                       

    OLED_Refresh_Gram();//更新显示

}

 

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)

{                   

    u8 temp,t,t1;

    u8 y0=y;

    u8 csize=(size/8+((size%8)?1:0))*(size/2);      //得到字体一个字符对应点阵集所占的字节数

    chr=chr-' ';//得到偏移后的值        

    for(t=0;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;

            }

        }    

    }          

}

//m^n函数

u32 mypow(u8 m,u8 n)

{

    u32 result=1;    

    while(n--)result*=m;    

    return result;

}                 

 

      

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)

{           

    u8 t,temp;

    u8 enshow=0;                           

    for(t=0;t

    {

        temp=(num/mypow(10,len-t-1));

        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); 

    }

 

void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size)

{   

    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!

    {       

        if(x>(128-(size/2))){x=0;y+=size;}

        if(y>(64-size)){y=x=0;OLED_Clear();}

        OLED_ShowChar(x,y,*p,size,1);    

        x+=size/2;

        p++;

    }  

四、用STM32的SPI资源

也可以不使用GPIO口模拟,使用STM32的SPI资源,驱动代码如下:

void OLED_SPI_Init(void)

{

   

    GPIO_InitTypeDef GPIO_InitStructure;

    SPI_InitTypeDef SPI_InitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|

    RCC_APB2Periph_SPI1, ENABLE ); //①GPIO,SPI 时钟使能

    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); //①初始化 GPIO

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2;//端口配置

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出

    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度为50MHz

    GPIO_Init(GPIOA,&GPIO_InitStructure);//根据设定参数初始化GPIOA

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置 SPI 全双工

    SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置 SPI 工作模式:设置为主 SPI

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 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_16; //预分频 256

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从 MSB 位开始

    SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值计算的多项式

    SPI_Init(SPI1, &SPI_InitStructure); //②根据指定的参数初始化外设 SPIx 寄存器

    SPI_Cmd(SPI1, ENABLE); //③使能 SPI 外设

    //SPI1_ReadWriteByte(0xff);//④启动传输

}

void OLED_WB(uint8_t data)

{

   

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

   

    SPI_I2S_SendData(SPI1, data);

}

void SPI_WriteByte(unsigned char data,unsigned char cmd)

{

    unsigned char i=0;

    OLED_DC =cmd;

    OLED_WB(data);

}


关键字:STM32  SPI通信  OLED 引用地址:STM32 SPI通信--OLED

上一篇:STM32——高级定时器的应用
下一篇:STM32-AHB、APB1、APB2的使(失)能函数

推荐阅读最新更新时间:2024-03-16 15:41

为何首款OLED电视采用弧形屏幕?
    科技博客Digital Trend撰文讨论了三星和LG第一款在美上市的OLED电视。并对电视采用弧形屏幕的原因进行了分析。以下为文章主要内容:LG和三星为他们的OLED电视好好在美国进行了一番炒作。他们向媒体喋喋不休的推荐新电视的出色表现。但是,似乎所有问题都走向了同一个元素:弧形屏幕。为什么这些电视采用弧形设计?弧形设计的OLED电视有什么特殊吗?未来三星会在美国推出平面设计的OLED电视吗?  原因并不简单 如果你问LG或三星,你会得到一个标准化答案。精明的市场营销和公关的团队,早就准备好了这些问题的答案。但是,三星在韩国推出的OLED电视既有平面的也有弧形的。所以,三星和LG必然有他们自己的考量。 首先,可以看一下
[手机便携]
STM32固件库实现点亮LED
前言 使用固件库点亮LED 提示:以下是本篇文章正文内容 一、原理图 二、软件设计 在工程之上新建“bsp_led.c”及“bsp_led.h”文件,这些文件不属于STM32 标准库的内容,是由我们自己根据应用需要编写的,编程步骤如下: 使能 GPIO 端口时钟; 初始化 GPIO 目标引脚为推挽输出模式; 编写简单测试程序,控制 GPIO 引脚输出高、低电平 三、代码 1.LED 灯引脚宏定义 在编写应用程序的过程中,要考虑更改硬件环境的情况,即提高可移植性。 这个时候一般把硬件相关的部分使用宏来封装,若更改了硬件环境,只修改这些硬件相关的宏即可,这 些定义一般存储在头文件,即本例子中的“bsp_led.h”
[单片机]
<font color='red'>STM32</font>固件库实现点亮LED
基于 STM32和机智云物联网平台的农作物需水量统计系统
本文由机智云开发者利用农业物联网的相关优势,搭建了一个基于机智云物联网平台的农作物需水量计算系统,利用传感器采集农作物的现场环境信息后通过 ZigBee 协议发送到数据处理终端,根据设置的作物生长系数计算出对应的作物需水量;同时将相关的数据经过 4G 模块传输至机智云物联网平台,实现用户足不出户即可了解到农作物的相关信息,为制定合理的灌溉制度提供数据参考,达成适时灌溉和节约用水等目的。 1 系统总体设计 基于机智云物联网平台的农作物需水量计算系统,利用嵌入式微控制器采集作物的温湿度、风速环境信息,同时采用 ZigBee 技术进行数据的传输,将采集的作物环境信息传输至数据处理终端;当数据处理终端接收到相关的数据后,对作物需水量进
[单片机]
基于 <font color='red'>STM32</font>和机智云物联网平台的农作物需水量统计系统
STM32 之 ISP下载
(1) 首先是调整启动方式: 下载时:Boot0设置为1,Boot1设置为0,即从系统存储器(System Memory)启动。 运行时:Boot0设置为0,Boot1设置为0,即从用户闪存存储器(User Falsh)启动。 (2)打开Flash Loader Demo ,选择串口,波特率,设置无效验 (3)自动探测到Falsh的大小 (4)自动检测到单片机型号 (5)这里选择要烧写的文件(我这里选择扩展名为.hex的文件) (6)选择HEX文件 (7)开始烧写并效验 注意: (1)下载时的启动方式和下载完运行的启动方式是不同的,第一步已经讲明白了。 (2)如果打开软件
[单片机]
<font color='red'>STM32</font> 之 ISP下载
Q3 OLED手机屏全球规模达到47亿美元 2020年比例将上升至53%
有机构预测OLED显示屏市场将会迎来高速增长,受苹果和三星电子OLED显示屏的大量使用。预计到2018年会有更多的厂商加入到这个行列来。2020年,这一比例将有望上升至53%。 据报道,市场调研公司IHS Markit周四发布报告称,今年第三季度全球智能手机用OLED显示屏的市场规模达到47亿美元,较去年同期的36亿美元激增了30%。 作为一种新型的屏幕类型,OLED有着无需背光源,可以自发光,可视角度更大、色彩更丰富、节能显著、可柔性弯曲等优点。随着苹果跟随部分中国厂商、三星电子,开始在旗舰智能手机iPhone X开始采用OLED显示屏,预计到2018年将会有更多的手机厂商和型号采用OLED显示屏。IHS Market此
[电源管理]
STM32_EXIT中断
今天的软件工程下载地址(360云盘): https://yunpan.cn/cPhvyer3vIwXh 访问密码 57e1 STM32F10x的资料可以在我360云盘下载: https://yunpan.cn/crBUdUGdYKam2 访问密码 ca90 工程概要说明:定义一个按键(可自己定义),每按键一次,响应中断一次,在中断函数中LED提示灯变化一次,用户可更加实际情况在中断函数做出相应操作,这里只是一个模板。 关于“STM32F103 EXIT中断” 我把重要的几点在下面分别讲述,若不明白,请关注微信公众号“EmbeddDeveloper”查阅或留言。 一、RCC时钟配置 该函数位于在bsp.c
[单片机]
STM32_EXIT中断
STM32学习之使用库函数编写串口通信
注:使用的芯片是STM32F103ZET6 一、串口初始化部分的程序 1.初始化时钟   因为要使用串口1这个外设,因此在使用之前就需要开启串口1的时钟,并且之后还需要设置IO输入输出的模式,在这里我们也需要开启GPIO的时钟。程序如下: //初始化串口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //初始化GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);   可是为什么要初始化时钟呢在《STM32中文参考手册_V10》的RCC中有这样一句话“当外设时钟没有启用时,软件不能读出
[单片机]
<font color='red'>STM32</font>学习之使用库函数编写串口<font color='red'>通信</font>
STM32 IO模拟串口程序
  随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。这种情况下下,采集会需要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的单片机只提供一个串口,那么另一个串口只能靠程序模拟。   1、串口传输协议   首先,必须要知道串口通讯时数据是怎样传输的?这里以异步传输字符为例子,如下图所示:      一般字符传输都采用:1位起始位,8位数据位,1位停止位,没有校验位 的形式传输,其他形式的这里不讲。串口异步传输在空闲状态时都必须是高电平。第一位传输的是起始位,起始位会将原来空闲时的高电平拉成低电平,起
[单片机]
<font color='red'>STM32</font> IO模拟串口程序
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved