首页 > 其他分享 >STM32 HAL库F103系列之OLED显示一个字符

STM32 HAL库F103系列之OLED显示一个字符

时间:2024-04-10 22:00:52浏览次数:19  
标签:HAL PIN oled STM32 OLED wr GPIO define

原理图:

OLED对应IO口

OLED_CS对应OV_WRST,即:PD6;

OLED_RS对应OV_SCL,即:PD3,高电平为命令,低电平为数据;

OLED_WR对应OV_RRST,即:PG14;

OLED_RD 对应DCMI_SDA,即:PG13;

OLED_RST对应DCMI_RESET,即:PG15;

OLED_D[7:0]对应DCMI_D[7:0],即:PC[7:0]

配置步骤:

1,确定IO连接关系

        开发板OLED接口原理图

2,初始化IO口

        初始化连接OLED的各个IO口

3,编写8080接口函数

        oled_wr_byte

4,编写OLED初始化函数

        编写oled_init函数,完成初始化序列配置

5,编写OLED画点函数

        编写oled_draw_point函数,实现OLED任意位置画点

oled.c函数编程步骤

1、建立OLED的GRAM

2、画点函数实现代码

3、16*16大小,字符A的点阵数据数组:

4、字符显示代码

5、初始化OLED(SSD1306)

6、SSD1306(8080时序)写时序

7、void oled_draw_point_test(uint8_t x, uint8_t y)函数

8、void oled_clear(void)函数

源码

oled.c

#include "stdlib.h"
#include "./BSP/OLED/oled.h"
#include "./BSP/OLED/oledfont.h"
#include "./SYSTEM/delay/delay.h"

//建立OLED的GRAM
static uint8_t g_oled_gram[128][8];

void oled_refresh_gram(void)
{
    uint8_t i,n;

    for (i = 0; i < 8; i++)
    {
        oled_wr_byte(0xb0 + i, OLED_CMD) ;  /* 设置页地址(0~7)*/
        oled_wr_byte(0x00, OLED_CMD) ;      /* 设置显示位置-列低地址 */ 
        oled_wr_byte(0x10, OLED_CMD) ;      /* 设置显示位置-列高地址 */
        
        for (n = 0; n < 128; n++)
        {
            oled_wr_byte( g_oled_gram[ n ][ i ], OLED_DATA) ;
        }
    }
}

//画点函数实现代码
void oled_draw_point(uint8_t  x, uint8_t  y, uint8_t  dot) 
{
    uint8_t pos, bx, temp = 0;
    
    if (x > 127 || y > 63)  return;    /* 超出范围了 */
    
    pos = y / 8;    /*  页地址 */
    bx = y % 8;     /*  计算y在对应字节里面的位置 */
    temp = 1 << bx; /*  转换后y对应的bit位置 */

    if ( dot )  /*  画实心点 */
        g_oled_gram[ x ][ pos ] |= temp;
    else
        g_oled_gram[ x ][ pos ] &= ~temp;
}

/* 16*16大小,字符A的点阵数据数组:*/
uint8_t oled_ascii_1608[]=
{
  0x00,0x04,0x00,0x3C,0x03,0xC4,0x1C,0x40,
  0x07,0x40,0x00,0xE4,0x00,0x1C,0x00,0x04
} ;

//字符显示代码
void oled_show_char_test(uint8_t  x, uint8_t  y, uint8_t mode)
{
    uint8_t temp, t1, t;
    uint8_t y0 = y;                 /* 保存y的初值 */

    for(t = 0; t < 16; t++)         /* 总共16个字节,要遍历一遍 */
    {
        temp = oled_ascii_1608[t];  /* 依次获取点阵数据 */

        for(t1 = 0; t1 < 8; t1++)
        {
            if(temp & 0X80)     /* 这个点有效,需要画出来 */
                oled_draw_point(x, y, mode);
            else                /* 这个点无效,不需要画出来 */
                oled_draw_point(x, y, !mode);

            temp <<= 1;         /* 低位数据往高位移位,最高位数据直接丢弃 */
            y++;                /* y坐标自增 */

            if((y - y0) == 16)  /* 显示完一列了 */
            {
                y = y0;         /* y坐标复位 */
                x++;            /* x坐标递增 */
                break;          /* 跳出 for循环 */
            }
        }
    }
}


/**
 * @brief       初始化OLED(SSD1306)
 * @param       无
 * @retval      无
 */
void oled_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    
    __HAL_RCC_GPIOC_CLK_ENABLE();     /* 使能PORTC时钟 */
    __HAL_RCC_GPIOD_CLK_ENABLE();     /* 使能PORTD时钟 */
    __HAL_RCC_GPIOG_CLK_ENABLE();     /* 使能PORTG时钟 */
    
    /* PC0 ~ 7 设置 */
    gpio_init_struct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;                
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM;        /* 中速 */
    HAL_GPIO_Init(GPIOC, &gpio_init_struct);                /* PC0 ~ 7 设置 */

    gpio_init_struct.Pin = GPIO_PIN_3|GPIO_PIN_6;           /* PD3, PD6 设置 */
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM;        /* 中速 */
    HAL_GPIO_Init(GPIOD, &gpio_init_struct);                /* PD3, PD6 设置 */
    
    gpio_init_struct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_MEDIUM;        /* 中速 */
    HAL_GPIO_Init(GPIOG, &gpio_init_struct);                /* WR/RD/RST引脚模式设置 */

    OLED_WR(1);
    OLED_RD(1);

    OLED_CS(1);
    OLED_RS(1);
    
    /* 复位时序 */
    OLED_RST(0);
    delay_ms(100);
    OLED_RST(1);

    oled_wr_byte(0xAE, OLED_CMD);   /* 关闭显示 */
    oled_wr_byte(0xD5, OLED_CMD);   /* 设置时钟分频因子,震荡频率 */
    oled_wr_byte(80, OLED_CMD);     /* [3:0],分频因子;[7:4],震荡频率 */
    oled_wr_byte(0xA8, OLED_CMD);   /* 设置驱动路数 */
    oled_wr_byte(0X3F, OLED_CMD);   /* 默认0X3F(1/64) */
    oled_wr_byte(0xD3, OLED_CMD);   /* 设置显示偏移 */
    oled_wr_byte(0X00, OLED_CMD);   /* 默认为0 */

    oled_wr_byte(0x40, OLED_CMD);   /* 设置显示开始行 [5:0],行数. */

    oled_wr_byte(0x8D, OLED_CMD);   /* 电荷泵设置 */
    oled_wr_byte(0x14, OLED_CMD);   /* bit2,开启/关闭 */
    oled_wr_byte(0x20, OLED_CMD);   /* 设置内存地址模式 */
    oled_wr_byte(0x02, OLED_CMD);   /* [1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; */
    oled_wr_byte(0xA1, OLED_CMD);   /* 段重定义设置,bit0:0,0->0;1,0->127; */
    oled_wr_byte(0xC8, OLED_CMD);   /* 设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 */
    oled_wr_byte(0xDA, OLED_CMD);   /* 设置COM硬件引脚配置 */
    oled_wr_byte(0x12, OLED_CMD);   /* [5:4]配置 */

    oled_wr_byte(0x81, OLED_CMD);   /* 对比度设置 */
    oled_wr_byte(0xEF, OLED_CMD);   /* 1~255;默认0X7F (亮度设置,越大越亮) */
    oled_wr_byte(0xD9, OLED_CMD);   /* 设置预充电周期 */
    oled_wr_byte(0xf1, OLED_CMD);   /* [3:0],PHASE 1;[7:4],PHASE 2; */
    oled_wr_byte(0xDB, OLED_CMD);   /* 设置VCOMH 电压倍率 */
    oled_wr_byte(0x30, OLED_CMD);   /* [6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; */

    oled_wr_byte(0xA4, OLED_CMD);   /* 全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) */
    oled_wr_byte(0xA6, OLED_CMD);   /* 设置显示方式;bit0:1,反相显示;0,正常显示 */
    oled_wr_byte(0xAF, OLED_CMD);   /* 开启显示 */
    
}

//SSD1306(8080时序)写时序
void oled_data_out(uint8_t data)
{
    GPIOC->ODR = (GPIOC->ODR & 0XFF00) | (data & 0X00FF);
}


static void oled_wr_byte(uint8_t data, uint8_t cmd)
{
    OLED_RS (cmd);  /* 数据类型,由传参决定 */
    OLED_CS ( 0 );  /* 拉低片选线,选中SSD1306 */
    OLED_WR ( 0 );  /* 拉低WR线,准备数据 */
    oled_data_out(data); /* WR低电平期间,准备数据 */
    OLED_WR ( 1 );  /* 在WR上升沿,数据发出 */
    OLED_CS ( 1 );  /* 取消片选 */
    OLED_RS ( 1 );  /* 释放RS线,恢复默认 */
}

void oled_draw_point_test(uint8_t x, uint8_t y)
{
    /* 页地址模式 */
    uint8_t page_num = y / 8;
    
    /* 1、发送页地址 */
    oled_wr_byte(0xB0 | page_num, OLED_CMD);
    
    /* 2、发送列地址 */
    oled_wr_byte((x & 0x0F) | 0x00, OLED_CMD);      /* 列地址低四位 */
    oled_wr_byte((x & 0xF0) >> 4 | 0x10, OLED_CMD); /* 列地址高四位 */
    
    /* 3、发送1字节数据 */
    oled_wr_byte(1 << (y % 8), OLED_DATA);
}

void oled_clear(void)
{
    uint8_t i, n;

    for (i = 0; i < 8; i++)
    {
        oled_wr_byte (0xb0 + i, OLED_CMD); /* 设置页地址(0~7) */
        oled_wr_byte (0x00, OLED_CMD);     /* 设置显示位置—列低地址 */
        oled_wr_byte (0x10, OLED_CMD);     /* 设置显示位置—列高地址 */

        for (n = 0; n < 128; n++)
        {
            oled_wr_byte(0x00, OLED_DATA);
        }
    }
}

oled.h 

#ifndef __OLED_H
#define __OLED_H

#include "stdlib.h" 
#include "./SYSTEM/sys/sys.h"


/******************************************************************************************/
/* OLED 8080 模式引脚 定义 */

/* 片选脚 */
#define OLED_CS_PORT                GPIOD
#define OLED_CS_PIN                 GPIO_PIN_6
#define OLED_CS_CLK_ENABLE()        do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)   /* PD口时钟使能 */

/* 数据类型脚 命令/数据*/
#define OLED_RS_PORT                GPIOD
#define OLED_RS_PIN                 GPIO_PIN_3
#define OLED_RS_CLK_ENABLE()        do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)   /* PD口时钟使能 */

/* 向OLED读取数据脚 */
#define OLED_RD_PORT                GPIOG
#define OLED_RD_PIN                 GPIO_PIN_13
#define OLED_RD_CLK_ENABLE()        do{ __HAL_RCC_GPIOG_CLK_ENABLE(); }while(0)   /* PG口时钟使能 */

/* 向OLED写入数据脚 */
#define OLED_WR_PORT                GPIOG
#define OLED_WR_PIN                 GPIO_PIN_14
#define OLED_WR_CLK_ENABLE()        do{ __HAL_RCC_GPIOG_CLK_ENABLE(); }while(0)   /* PG口时钟使能 */

/* 复位脚 */
#define OLED_RST_PORT               GPIOG
#define OLED_RST_PIN                GPIO_PIN_15
#define OLED_RST_CLK_ENABLE()       do{ __HAL_RCC_GPIOG_CLK_ENABLE(); }while(0)   /* PG口时钟使能 */

/* 数据脚 */
#define OLED_DATA_PORT               GPIOC
#define OLED_DATA_PIN                GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7
#define OLED_DATA_CLK_ENABLE()       do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)   /* PC口时钟使能 */
/******************************************************************************************/

/* OLED 8080模式相关端口控制函数 定义 */
#define OLED_RST(x)     do{ x ? \
                                  HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET) : \
                                  HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET); \
                        }while(0)       /* 设置RST引脚 */

#define OLED_CS(x)      do{ x ? \
                                  HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_SET) : \
                                  HAL_GPIO_WritePin(OLED_CS_PORT, OLED_CS_PIN, GPIO_PIN_RESET); \
                        }while(0)       /* 设置CS引脚 */
#define OLED_RS(x)      do{ x ? \
                                  HAL_GPIO_WritePin(OLED_RS_PORT, OLED_RS_PIN, GPIO_PIN_SET) : \
                                  HAL_GPIO_WritePin(OLED_RS_PORT, OLED_RS_PIN, GPIO_PIN_RESET); \
                        }while(0)       /* 设置RS引脚 */
                              
#define OLED_WR(x)      do{ x ? \
                                  HAL_GPIO_WritePin(OLED_WR_PORT, OLED_WR_PIN, GPIO_PIN_SET) :  \
                                  HAL_GPIO_WritePin(OLED_WR_PORT, OLED_WR_PIN, GPIO_PIN_RESET); \
                        } while (0)     /* 设置WR引脚 */

#define OLED_RD(x)      do{ x ? \
                                  HAL_GPIO_WritePin(OLED_RD_PORT, OLED_RD_PIN, GPIO_PIN_SET) : \
                                  HAL_GPIO_WritePin(OLED_RD_PORT, OLED_RD_PIN, GPIO_PIN_RESET); \
                        }while(0)       /* 设置RD引脚 */

/* 命令/数据 定义 */
#define OLED_CMD        0       /* 写命令 */
#define OLED_DATA       1       /* 写数据 */

/******************************************************************************************/
    
static void oled_wr_byte(uint8_t data, uint8_t cmd);    /* 写一个字节到OLED */
void oled_init(void);           /* OLED初始化 */


#endif



 

 main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/OLED/oled.h"

int main(void)
{
    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    delay_init(72);                         /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    oled_init();
    oled_clear();
//一下四行是oled上画一个点
//    oled_draw_point_test(0, 0);
//    oled_draw_point_test(10, 0);
//    oled_draw_point_test(10, 10);
//    oled_draw_point_test(20, 20);
    
    oled_show_char_test(10, 10 ,1);
    oled_refresh_gram();
    
    while (1)
    {
        delay_ms(500);
        LED0_TOGGLE();                      /* LED0闪烁 */
    }

标签:HAL,PIN,oled,STM32,OLED,wr,GPIO,define
From: https://blog.csdn.net/2302_79878697/article/details/137611693

相关文章

  • 蓝桥杯STM32G431RBT6-各个外设的配置过程
    LED,按键配置LED点亮,按键采集按键值前期准备:通过Cubemx生成一个源文件方便后续直接使用。  源文件准备完毕以后开始进行按键和LED的配置LED对比芯片引脚连接图可以知道8个LED分别连接在GPIOC的如下8个引脚中      Cubemx中......
  • 基于STM32的户外环境监测系统(三)
     光照强度模块   在基于STM32的户外环境监测系统中集成光照强度模块时,需要考虑以下注意事项:选择合适的光照传感器:选择适合户外环境监测的光照传感器,如光敏电阻(LDR)、光敏电容、光电二极管(PD)、光电晶体管等。根据项目需求考虑测量范围、响应频率、精度等因素进行选择。......
  • 有效提升Halcon二次开发调试效率的插件 HalconAssit
    HalconAssit开发背景:大家好,我是HalconAssit得作者。首先得解释下开发这款工具的得原因。作为视觉工程师,可以说Halcon大家应该或多或少都接触过。功能非常强大,算子非常全,开发的自由度也非常高,但是唯一的得缺点应该是GUI支持这块稍显欠缺。在我也c#做halcon二次开发的时候,发现......
  • STM32F4 CubeMax 主从定时器同步 设定脉冲输出控制步进电机
    实验准备开发板:STM32F411E-DISCO或其它开发板(FirmwarePackage根据开发板下载)软件:KeiluVision5、STM32CubeMX(FirmwarePackage:STM32CubeFW_F4V1.23.0)实验原理利用CubeMX根据芯片手册配置定时器同步来实现自定义脉冲数PWM输出对电机进行控制。主定时器产生PWM波,从定时......
  • STM32外部中断小记
    一、EXTI配置步骤//1.配置RCC时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟,AFIO:GPIO复用/重映射功能//2.配置EXTIGPIO端口及工作模式(输入模式)//3.配置EXTI中断线、模式(上升沿、下降沿......
  • STM32F103C8T6 技术参数和性能特点
    STM32F103C8T6是意法半导体(STMicroelectronics)生产的一款基于ARMCortex-M3内核的32位微控制器。它具有以下主要功能: 1.ARMCortex-M3内核:STM32F103C8T6采用32位ARMCortex-M3内核,工作频率最高可达72MHz,提供较高的处理能力。 2.存储器:内置高达64kB的闪......
  • STLINK-V3PWR连接STM32最小系统板方法(含引脚分布)
    前段时间导师给我了一个STLINK-V3PWR,让我试着用它下载程序到STM32单片机上,我找了半天发现网上资源挺少的,于是自己搞了一下,从官网下载了相关的规格书,然后连了一下。下面是我自己找的官方资源然后翻译的。下面是STLINK-V3PWR的调试端口引脚分布。手上只有STM32F103C6T6A......
  • 初学STM32 SDIO (三)
    1.STM32的SDIO功能框图​ STM32控制器有一个SDIO,由两部分组成:SDIO适配器和APB2接口,SDIO适配器提供SDIO主机功能,可以提供SD时钟、发送命令和进行数据传输。APB2接口用于控制器访问SDIO适配器寄存器并且可以产生中断和DMA请求信号。​ SDIO使用两个时钟信号,一个是SDIO适配......
  • 配置STM32单片机的两个高速输入端子接受AB相高速脉冲信号输入的方法
    目录1.配置GPIO引脚:2.配置TIM计数器:3.配置中断:4.计数器值的获取:        要使用STM32单片机的两个高速输入端子接受AB相高速脉冲信号输入,并使用TIM计数器的不同通道对每相的计数,请按照以下步骤操作:1.配置GPIO引脚:        首先,需要将两个高速输入......
  • 初学STM32 SDIO (二)
    ​ SD命令由主机发出,以广播命令和寻址命令为例,广播命令是针对与SD主机总线连接的所有从设备发送的,寻址命令是指定某个地址设备进行命令传输。1.SD命令格式SD命令格式固定为48bit,都是通过CMD线连续传输的,数据线不参与。起始位和终止位:命令的主体包含在起始位与终止位之间,它......