打印
[APM32E1]

【APM32E103xE测评】+驱动OLED屏

[复制链接]
1176|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
    OLED屏在低功耗产品中应用比较广泛,该款屏幕模块尺寸为0.96英寸,主要由裸屏和底板PCB组成,裸屏由SSD1306驱动。这种小屏显示模块支持SPI、IIC通讯方式进行驱动,此次使用IIC通讯方式驱动。使用I2C接口时,SSD1306允许有最多两个7位的IIC地址,同样通过相应的IO口拉低拉高来切换,一般默认是0x3c,在屏幕模块的背面,可以看到一个I2C地址切换提示,需要改变模块I2C地址时,只需要把提示位置的电阻取下焊接到另外一端即可。要注意的是板上的IIC地址是加上了第零位读写位后的数值,即0x78 = 0x3c<<1,0x7A = 0x3d<<1。
     至于如何使用IIC与SSD1306进行时序的写入,某宝上免费提供参考资料,这里就不再赘述了,直接上部分应用代码啦!实际应用中GPIOB0连接模块的SCL引脚,GPIOB1连接模块的SDA引脚,使用“PCtoLCD2002”取模工具取模部分汉字与二进制图片。
#include "main.h"
#include "oled.h"
#include "delay.h"
#include "bmp.h"

volatile uint32_t tick = 0;

void Delay(void);

int main(void)
{
                u8 t;
    APM_MINI_LEDInit(LED2);
    APM_MINI_LEDInit(LED3);
                SysTick_Config(SystemCoreClock / 1000);
    OLED_Init();                       
                OLED_Clear();
                t=' ';
    while (1)
    {
      delay_ms(500);
                        APM_MINI_LEDOn(LED2);
                        APM_MINI_LEDOn(LED3);
                        delay_ms(500);
                        APM_MINI_LEDOff(LED2);
                        APM_MINI_LEDOff(LED3);
                       
                        OLED_Clear();
                        OLED_ShowCHinese(10,0,25);//欢
                        OLED_ShowCHinese(18+10,0,26);//迎
                        OLED_ShowCHinese(36+10,0,27);//使
                        OLED_ShowCHinese(54+10,0,28);//用
                        OLED_ShowString(6,3,"APM32E103ZE",16);
                        OLED_ShowString(6,6,"2022-05-15",16);
                        delay_ms(800);
      OLED_Clear();
                        OLED_ShowCHinese(10,0,20);//极
                        OLED_ShowCHinese(18+10,0,21);//海
                        OLED_ShowCHinese(36+10,0,22);//半
                        OLED_ShowCHinese(54+10,0,23);//导
                        OLED_ShowCHinese(72+10,0,24);//体
                        OLED_ShowString(16,3,"Mini Board",16);
                        OLED_ShowChar(48,6,t,16);//显示ASCII字符
                        delay_ms(50);
                        t++;
                        if(t>'~')t=' ';
                        OLED_ShowNum(103,6,t,3,16);//显示ASCII字符的码值        
                        delay_ms(1000);
                        OLED_Clear();
                        OLED_DrawBMP(0,0,128,8,BMP2);  //图片显示(图片显示慎用,生成的字表较大,会占用较多空间,FLASH空间8K以下慎用)
                        delay_ms(1000);
    }
}

void Delay(void)
{
    volatile uint32_t delay = 0x3fffff;
   
    while(delay--);
}
#ifndef __OLED_H
#define __OLED_H

#include "apm32e10x.h"
#include "apm32e10x_gpio.h"
#include "apm32e10x_rcm.h"
#include "stdlib.h"          
#include "stdint.h"

#define OLED_MODE 0
#define SIZE 8
#define XLevelL                0x00
#define XLevelH                0x10
#define Max_Column        128
#define Max_Row                64
#define        Brightness        0xFF
#define X_WIDTH         128
#define Y_WIDTH         64                                                              
//-----------------OLED IIC端口定义----------------
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"           
#include "delay.h"

/**********************************************
//IIC Start
**********************************************/
void IIC_Start()
{
        OLED_SCLK_Set();
        OLED_SDIN_Set();
        OLED_SDIN_Clr();
        OLED_SCLK_Clr();
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{
        OLED_SCLK_Set() ;
        //OLED_SCLK_Clr();
        OLED_SDIN_Clr();
        OLED_SDIN_Set();
       
}

void IIC_Wait_Ack()
{
        OLED_SCLK_Set() ;
        OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
**********************************************/

void Write_IIC_Byte(unsigned char IIC_Byte)
{
        unsigned char i;
        unsigned char m,da;
        da=IIC_Byte;
        OLED_SCLK_Clr();
        for(i=0;i<8;i++)               
        {
                        m=da;
                m=m&0x80;
                if(m==0x80)
                {OLED_SDIN_Set();}
                else OLED_SDIN_Clr();
                        da=da<<1;
                OLED_SCLK_Set();
                OLED_SCLK_Clr();
                }
}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
   IIC_Start();
   Write_IIC_Byte(0x78);            //Slave address,SA0=0
        IIC_Wait_Ack();       
   Write_IIC_Byte(0x00);                        //write command
        IIC_Wait_Ack();       
   Write_IIC_Byte(IIC_Command);
        IIC_Wait_Ack();       
   IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
   IIC_Start();
   Write_IIC_Byte(0x78);                        //D/C#=0; R/W#=0
        IIC_Wait_Ack();       
   Write_IIC_Byte(0x40);                        //write data
        IIC_Wait_Ack();       
   Write_IIC_Byte(IIC_Data);
        IIC_Wait_Ack();       
   IIC_Stop();
}
void OLED_WR_Byte(unsigned dat,unsigned cmd)
{
        if(cmd)
                        {

   Write_IIC_Data(dat);
   
                }
        else {
   Write_IIC_Command(dat);
               
        }


}


/********************************************
// fill_Picture
********************************************/
void fill_picture(unsigned char fill_Data)
{
        unsigned char m,n;
        for(m=0;m<8;m++)
        {
                OLED_WR_Byte(0xb0+m,0);                //page0-page1
                OLED_WR_Byte(0x00,0);                //low column start address
                OLED_WR_Byte(0x10,0);                //high column start address
                for(n=0;n<128;n++)
                        {
                                OLED_WR_Byte(fill_Data,1);
                        }
        }
}


/***********************Delay****************************************/
void Delay_50ms(unsigned int Del_50ms)
{
        unsigned int m;
        for(;Del_50ms>0;Del_50ms--)
                for(m=6245;m>0;m--);
}
/*
void Delay_1ms(unsigned int Del_1ms)
{
        unsigned char j;
        while(Del_1ms--)
        {       
                for(j=0;j<123;j++);
        }
}
*/
//坐标设置

        void OLED_Set_Pos(unsigned char x, unsigned char y)
{         OLED_WR_Byte(0xb0+y,OLED_CMD);
        OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
        OLED_WR_Byte((x&0x0f),OLED_CMD);
}             
//开启OLED显示   
void OLED_Display_On(void)
{
        OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
        OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
        OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
        OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
        OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
        OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}                                            

void OLED_Clear(void)  
{  
        u8 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(0,OLED_DATA);
        } //更新显示
}
void OLED_On(void)  
{  
        u8 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(1,OLED_DATA);
        } //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示                                 
//size:选择字体 16/12
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
{             
        unsigned char c=0,i=0;       
                c=chr-' ';//得到偏移后的值                       
                if(x>Max_Column-1){x=0;y=y+2;}
                if(Char_Size ==16)
                        {
                        OLED_Set_Pos(x,y);       
                        for(i=0;i<8;i++)
                        OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
                        OLED_Set_Pos(x,y+1);
                        for(i=0;i<8;i++)
                        OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
                        }
                        else {       
                                OLED_Set_Pos(x,y);
                                for(i=0;i<6;i++)
                                OLED_WR_Byte(F6x8[c][i],OLED_DATA);
                               
                        }
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{
        u32 result=1;         
        while(n--)result*=m;   
        return result;
}                                  
//显示2个数字
//x,y :起点坐标         
//len :数字的位数
//size:字体大小
//mode:模式        0,填充模式;1,叠加模式
//num:数值(0~4294967295);                           
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{                
        u8 t,temp;
        u8 enshow=0;                                                  
        for(t=0;t<len;t++)
        {
                temp=(num/oled_pow(10,len-t-1))%10;
                if(enshow==0&&t<(len-1))
                {
                        if(temp==0)
                        {
                                OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
                                continue;
                        }else enshow=1;
                          
                }
                 OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
        }
}
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
        unsigned char j=0;
        while (chr[j]!='\0')
        {                OLED_ShowChar(x,y,chr[j],Char_Size);
                        x+=8;
                if(x>120){x=0;y+=2;}
                        j++;
        }
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{                                  
        u8 t,adder=0;
        OLED_Set_Pos(x,y);       
    for(t=0;t<16;t++)
                {
                                OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
                                adder+=1;
     }       
                OLED_Set_Pos(x,y+1);       
    for(t=0;t<16;t++)
                        {       
                                OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
                                adder+=1;
      }                                       
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{        
unsigned int j=0;
unsigned char x,y;
  
  if(y1%8==0) y=y1/8;      
  else y=y1/8+1;
        for(y=y0;y<y1;y++)
        {
                OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
            {      
                    OLED_WR_Byte(BMP[j++],OLED_DATA);                   
            }
        }
}

//初始化SSD1306                                            
void OLED_Init(void)
{        
          GPIO_Config_T  configStruct;
                /* enable the OLED GPIO clock */
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB);
    /* configure OLED GPIO pin */
                configStruct.pin = (GPIO_PIN_0 | GPIO_PIN_1);
    configStruct.mode = GPIO_MODE_OUT_PP;
    configStruct.speed = GPIO_SPEED_50MHz;
          GPIO_Config(GPIOB, &configStruct);
       
          GPIO_SetBits(GPIOB,GPIO_PIN_0|GPIO_PIN_1);       
       
    delay_ms(800);
    OLED_WR_Byte(0xAE,OLED_CMD);//--display off
                OLED_WR_Byte(0x00,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  
                OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
                OLED_WR_Byte(0x81,OLED_CMD); // contract control
                OLED_WR_Byte(0xFF,OLED_CMD);//--128   
                OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
                OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
                OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
                OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
                OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
                OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
                OLED_WR_Byte(0x00,OLED_CMD);//
               
                OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
                OLED_WR_Byte(0x80,OLED_CMD);//
               
                OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
                OLED_WR_Byte(0x05,OLED_CMD);//
               
                OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
                OLED_WR_Byte(0xF1,OLED_CMD);//
               
                OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
                OLED_WR_Byte(0x12,OLED_CMD);//
               
                OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
                OLED_WR_Byte(0x30,OLED_CMD);//
               
                OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
                OLED_WR_Byte(0x14,OLED_CMD);//
               
                OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}  
       编译完成后,使用JLink的SWD方式下载到开发板中,重启开发板,显示效果如下:

使用特权

评论回复
评论
Fordhs168 2022-6-1 17:31 回复TA
好东西 
沙发
WoodData| | 2022-5-23 14:29 | 只看该作者
学习学习

使用特权

评论回复
板凳
liqingfeng123| | 2022-5-24 09:40 | 只看该作者
给力,好东西~

使用特权

评论回复
地板
janewood| | 2022-5-28 12:53 | 只看该作者
SSD1306支持彩色屏幕吗

使用特权

评论回复
5
mollylawrence| | 2022-5-28 13:19 | 只看该作者
APM32E103和f103有区别吗  

使用特权

评论回复
6
pmp| | 2022-5-28 13:39 | 只看该作者
学习一下,谢谢分析的。  

使用特权

评论回复
7
dspmana| | 2022-5-28 14:18 | 只看该作者
主要是看单片机的性能。   

使用特权

评论回复
8
minzisc| | 2022-5-28 15:06 | 只看该作者
APM32E103可以吗?

使用特权

评论回复
9
rosemoore| | 2022-5-28 16:28 | 只看该作者
这个是spi的屏幕吗

使用特权

评论回复
10
wangdezhi| | 2022-5-28 17:07 | 只看该作者
可以获取所有的汉字字幕吗?

使用特权

评论回复
11
JunKook| | 2022-5-28 21:14 | 只看该作者
janewood 发表于 2022-5-28 12:53
SSD1306支持彩色屏幕吗

支持的

使用特权

评论回复
12
JunKook| | 2022-5-28 21:17 | 只看该作者
wangdezhi 发表于 2022-5-28 17:07
可以获取所有的汉字字幕吗?

用字模提取工具PCtoLCD2002可以获取

使用特权

评论回复
13
JunKook| | 2022-5-28 21:17 | 只看该作者
rosemoore 发表于 2022-5-28 16:28
这个是spi的屏幕吗

这个是IIC驱动

使用特权

评论回复
14
JunKook| | 2022-5-28 21:17 | 只看该作者
minzisc 发表于 2022-5-28 15:06
APM32E103可以吗?

极海全系列MCU均可以驱动OLED屏

使用特权

评论回复
15
JunKook| | 2022-5-28 21:19 | 只看该作者
mollylawrence 发表于 2022-5-28 13:19
APM32E103和f103有区别吗

极海103的E系列和F系列差异详见此文https://bbs.21ic.com/icview-3223260-1-1.html

使用特权

评论回复
16
caigang13| | 2022-6-1 19:07 | 只看该作者
IIC驱动就是刷新频率慢了

使用特权

评论回复
17
AloneKaven| | 2022-11-4 21:45 | 只看该作者
SSD1306支持彩色屏幕吗?

使用特权

评论回复
18
Undshing| | 2023-1-3 16:07 | 只看该作者
主要是看单片机的性能

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

1005

帖子

6

粉丝