眼花缭乱的意思是什么| 叫人挪车打什么电话| 口臭吃什么药最有效| 左侧卵巢囊性包块是什么意思| 莓茶什么人不适合喝| 蒙羞是什么意思| 有机会是什么意思| 肌肉痉挛用什么药能治好| 肌酐偏低有什么危害| 双子座女和什么星座最配| 尚可是什么意思| 夜里睡觉手麻是什么原因| 肩周炎挂什么科| 脑梗应该挂什么科| 泡黄芪水喝有什么好处| 尿蛋白低是什么原因| 2019什么年| LOP是什么胎位| 长沙有什么区| 狗狗为什么喜欢舔人| 喉炎吃什么药| 夏至节气吃什么| 试纸一深一浅说明什么| 梅毒是什么样的| 脸颊两侧长痘痘什么原因| 脚裂口子是什么原因| 长期失眠应该吃什么药| 读书破万卷下一句是什么| 溃疡是什么病| 马齿苋有什么功效| 一竖一点念什么| 拔罐挂什么科| 神经根型颈椎病吃什么药| 3月11日是什么星座| 血肌酐低是什么原因| 用激素药有什么副作用| 女人什么时候最想男人| 不以为然什么意思| 西贝是什么| 肚脐眼中间疼是什么原因| 猪头肉是什么意思| 精液发黄是什么原因引起的| 4月7号是什么星座| 正常人为什么会得梅毒| 蛋蛋冰凉潮湿什么原因| 香薰是什么| 吃什么可以让奶水增多| 梦见别人家盖房子是什么意思| 米五行属什么| 小孩吃什么通便降火| 颐养天年是什么意思| 子宫收缩是什么感觉| 吃饭恶心是什么原因| 睾丸潮湿是什么原因| 孤寡是什么意思| 吃饱就犯困是什么原因| 头疼恶心是什么症状| 化妆品有什么| 什么颜色不显黑| 乜是什么意思| 女命带驿马是什么意思| 乳头内陷是什么原因| 褪黑素不能和什么一起吃| 孟子姓什么| 无咎是什么意思| 什么钙片补钙效果好| 手指爆皮是什么原因| 桦树茸泡水喝有什么功效| 肿瘤指标偏高什么意思| 诗情画意是什么意思| 骨折后吃什么好的快| 便秘喝什么茶| 突然心跳加快是什么原因| 什么的海底| 小孩脸上长痣是什么原因引起的| 夫妻肺片有什么材料| 甲状腺结节挂什么科室| 孕囊小是什么原因| 国防部部长什么级别| 沙发适合什么发型| 什么是中医学| 楷字五行属什么| 点状强回声是什么意思| 屁股痒用什么药膏| 前列腺b超能检查出什么| 脚底发热是什么原因| 情缘是什么意思| l1椎体在什么位置| 段子是什么意思| 前列腺用什么药| 女性什么时候最容易怀孕| 吃了火龙果小便红色是什么原因| 芳华什么意思| 衡于虑的衡什么意思| 法西斯是什么| bg是什么| dl什么意思| 外阴萎缩是什么症状| 古代上班叫什么| ir是什么意思| 男性解脲支原体是什么病| lge是什么意思| 226是什么意思| who是什么意思| hello什么意思| 蜈蚣代表什么生肖| 尿酸高是什么| 什么是有机磷农药| 什么是蓝颜知己| 小孩肚子疼挂什么科| 玉对人身体健康有什么好处| 曹操的脸谱是什么颜色| 什么牌子的益生菌调理肠胃比较好| 墓志铭什么意思| 邪魅是什么意思| 淋巴细胞是什么意思| 一什么而入| 西红柿炒什么好吃| 凝聚力是什么意思| 脚脱皮什么原因| 子宫内膜异位症有什么症状| 胃阴虚有什么症状| 咳嗽吃什么消炎药| 性功能障碍挂什么科| 华佗发明了什么| 无什么于事| 绿草如茵是什么生肖| 假冒警察什么罪怎么判| 企鹅代表什么生肖| 遗传是什么意思| 晴水翡翠属于什么档次| 男人说做朋友代表什么| 物料是什么意思| 铜陵有什么好玩的地方| 脆生生是什么意思| 小孩子发烧是什么原因引起的| 奥特曼有什么| 中药学是干什么的| 娇兰属于什么档次| 恩五行属什么| 仙人掌有什么作用| 肺炎吃什么水果| 肋软骨炎吃什么药| 庸人自扰之是什么意思| 手脚麻木挂什么科| 什么时候开放二胎| 红楼梦结局是什么| 脸发麻是什么原因| cpc是什么| 脾大是什么意思| 江苏有什么山| 敢是什么意思| 做免疫组化意味什么| 九月二十五是什么星座| 阿司匹林什么时候吃| 什么颜色加什么颜色是紫色| 血红蛋白偏高是什么原因| 什么是信仰| 是故是什么意思| 脂肪疝是什么病| 03年是什么命| mz是什么意思| 结节性红斑是什么原因引起的| 什么的夏夜| 7月1号什么星座| 什么是造口| 大象什么颜色| 上海新华医院擅长什么| 烂好人什么意思| 什么就像什么一样| 蜜蜂是什么牌子| 什么是纤维| 吃什么清肺养肺| 流汗有什么好处| 北京市长是什么级别| 清明上河图描绘的是什么季节的景象| 嘴唇红润是表示什么| 什么什么不生| ncs是什么意思| 什么是混合痔| 脾肺气虚吃什么中成药| 舌头有麻木感什么原因| nba什么时候开始| 六合是什么意思| 什么花一年四季都开花| bb霜和cc霜有什么区别| 解解乏是什么意思| 又什么又什么造句| 八婆什么意思| 点状强回声是什么意思| 突然流鼻血是什么征兆| cartier什么牌子| 是什么| 深覆合是什么样子的| 圣旨是什么意思| 黑卡是什么意思| 怕得什么| 颈椎痛吃什么药最好| 什么牌子的钙片好| 西洋参不能和什么一起吃| 一什么水塔| 吃了鸡蛋不能吃什么| 十二指肠球部溃疡吃什么药| 小暑吃什么食物| 红斑狼疮是一种什么病| 夕阳无限好是什么意思| 世上谁嫌男人丑的前一句是什么| 胃难受想吐是什么原因| 血糖高吃什么| 大腿内侧发黑是什么原因| cct是什么意思| 皮炎吃什么药| 豆角和什么不能一起吃| 骨折移位有什么感觉| 开黄腔什么意思| 法兰绒是什么面料| 110斤穿什么码衣服| 飞刀是什么意思| 流弹是什么意思| 龟苓膏是什么做的| 晚上十点多是什么时辰| 口唇发绀是什么意思| 星期一左眼皮跳是什么预兆| 法令纹深是什么原因| 小叶增生是什么原因导致的| 吃什么可以养胃| 环移位了会出现什么症状| 口角炎涂什么药膏| 冻干粉是什么| 什么是人棉| 戴帽子是什么意思| 呵护是什么意思| 牛肉炒什么菜好吃| 浑水摸鱼什么意思| 日语牙白什么意思| 什么叫2型糖尿病| 办护照需要什么材料| 1月11日是什么星座| 9月是什么季节| 什么是肺部腺性肿瘤| 腰疼不能弯腰是什么原因引起的| 不能生育的女人有什么特征| 神经性皮炎吃什么药| 2009年属什么| 国防科技大学毕业是什么军衔| 三十六计的第一计是什么| 山楂和什么相克| msa是什么| 琥珀色是什么颜色| 十二指肠球部溃疡a1期是什么意思| 什么什么自语| winner什么意思| 万中无一什么意思| 1942年属什么生肖| 一什么鸟窝| 不可什么什么| 泽五行属什么| 女的什么时候退休| 多吃洋葱有什么好处| aids是什么病的简称| 大学生村官是什么编制| 尿道口灼热感吃什么药最快| 经常勃起是什么原因| 57年的鸡是什么命| 百度
打印
[RISC-V MCU 应用开发]

中国围棋天元赛挑战者决定战 唐韦星赢挑战权

[复制链接]
6421|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 RISCVLAR 于 2021-3-30 19:34 编辑

CH32V103应用教程——硬件SPI驱动OLED

前面章节介绍了使用模拟SPI驱动OLED,本章教程将介绍使用硬件SPI驱动OLED。

1、SPI简介及相关函数介绍
关于SPI,在前面章节已进行过介绍,在此不再赘述。

2、硬件设计
本章教程主要使用硬件SPI驱动OLED屏,所用OLED屏为7引脚0.96寸OLED屏。程序中配置PA5作为D0线,PA7作为D1线,PA2连接RES线,PA3连接DC线,PA4连接CS线,具体连接方式如下:
  • PA5连接OLED屏的D0引脚
  • PA7连接OLED屏的D1引脚
  • PA2连接OLED屏的RES引脚
  • PA3连接OLED屏的DC引脚
  • PA4连接OLED屏的CS引脚

3软件设计
硬件SPI驱动OLED相较于软件驱动OLED,主要在时序配置变化部分有所改变,与模拟IIC和硬件IIC的区别类似,硬件SPI驱动OLED具体程序如下:
spi.h文件
#ifndef __SPI_H
#define __SPI_H

#include "ch32v10x_conf.h"
#include "stdlib.h"

//-----------------OLED端口定义----------------

//#define OLED_SCL_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_0)//SCL
//#define OLED_SCL_Set() GPIO_SetBits(GPIOA,GPIO_Pin_0)
//
//#define OLED_SDA_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_1)//SDA
//#define OLED_SDA_Set() GPIO_SetBits(GPIOA,GPIO_Pin_1)

#define OLED_RES_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_2)//RES
#define OLED_RES_Set() GPIO_SetBits(GPIOA,GPIO_Pin_2)

#define OLED_DC_Clr()  GPIO_ResetBits(GPIOA,GPIO_Pin_3)//DC
#define OLED_DC_Set()  GPIO_SetBits(GPIOA,GPIO_Pin_3)

#define OLED_CS_Clr()  GPIO_ResetBits(GPIOA,GPIO_Pin_4)//CS
#define OLED_CS_Set()  GPIO_SetBits(GPIOA,GPIO_Pin_4)

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

u8 SPI1_ReadWriteByte(u8 TxData);
void OLED_ClearPoint(u8 x,u8 y);
void OLED_ColorTurn(u8 i);
void OLED_DisplayTurn(u8 i);
void OLED_WR_Byte(u8 dat,u8 mode);
void OLED_DisPlay_On(void);
void OLED_DisPlay_Off(void);
void OLED_Refresh(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode);
void OLED_DrawCircle(u8 x,u8 y,u8 r);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode);
void OLED_ShowChar6x8(u8 x,u8 y,u8 chr,u8 mode);
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode);
void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode);
void OLED_ScrollDisplay(u8 num,u8 space,u8 mode);
void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode);
void OLED_Init(void);

#endif
spi.h文件主要进行OLED端口相关定义和函数声明;
spi.c文件
#include "spi.h"
#include "stdlib.h"
#include "oledfont.h"
#include "debug.h"

u8 OLED_GRAM[144][8];

/*******************************************************************************
* Function Name  : SPI1_ReadWriteByte
* Description    : SPI1 read or write one byte.
* Input          : TxData: write one byte data.
* Return         : Read one byte data.
*******************************************************************************/
u8 SPI1_ReadWriteByte(u8 TxData)
{
    u8 i=0;

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)  //等待发送缓冲区为空,TXE事件
    {
        i++;
        if(i>200)return 0;
    }

    SPI_I2S_SendData(SPI1, TxData);    //写入数据寄存器,把要写入的数据写入发送缓冲区,即通过外设SPI1发送一个数据
    i=0;

    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //等待接收缓冲区非空,RXNE事件
    {
        i++;
        if(i>200)return 0;
    }

    return SPI_I2S_ReceiveData(SPI1);  //读取数据寄存器,获取接收缓冲区数据,即返回SPI1最近接收到的数据
}

//反显函数
void OLED_ColorTurn(u8 i)
{
    if(i==0)
        {
            OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
        }
    if(i==1)
        {
            OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
        }
}

//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{
    if(i==0)
        {
            OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
            OLED_WR_Byte(0xA1,OLED_CMD);
        }
    if(i==1)
        {
            OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
            OLED_WR_Byte(0xA0,OLED_CMD);
        }
}

void OLED_WR_Byte(u8 dat,u8 cmd)
{

    if(cmd)
      OLED_DC_Set();
    else
      OLED_DC_Clr();

    OLED_CS_Clr();

    SPI1_ReadWriteByte(dat);

    OLED_CS_Set();

    OLED_DC_Set();
}

//开启OLED显示
void OLED_DisPlay_On(void)
{
    OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
    OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
    OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}

//关闭OLED显示
void OLED_DisPlay_Off(void)
{
    OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
    OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
    OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
}

//更新显存到OLED
void OLED_Refresh(void)
{
    u8 i,n;
    for(i=0;i<8;i++)
    {
       OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
       OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
       OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
       for(n=0;n<128;n++)
       OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
    }
}
//清屏函数
void OLED_Clear(void)
{
    u8 i,n;
    for(i=0;i<8;i++)
    {
       for(n=0;n<128;n++)
            {
             OLED_GRAM[n][i]=0;//清除所有数据
            }
    }
    OLED_Refresh();//更新显示
}

//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
    u8 i,m,n;
    i=y/8;
    m=y%8;
    n=1<<m;
    if(t){OLED_GRAM[x][i]|=n;}
    else
    {
        OLED_GRAM[x][i]=~OLED_GRAM[x][i];
        OLED_GRAM[x][i]|=n;
        OLED_GRAM[x][i]=~OLED_GRAM[x][i];
    }
}

//画线
//x1,y1:起点坐标
//x2,y2:结束坐标
void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode)
{
    u16 t;
    int xerr=0,yerr=0,delta_x,delta_y,distance;
    int incx,incy,uRow,uCol;
    delta_x=x2-x1; //计算坐标增量
    delta_y=y2-y1;
    uRow=x1;//画线起点坐标
    uCol=y1;
    if(delta_x>0)incx=1; //设置单步方向
    else if (delta_x==0)incx=0;//垂直线
    else {incx=-1;delta_x=-delta_x;}
    if(delta_y>0)incy=1;
    else if (delta_y==0)incy=0;//水平线
    else {incy=-1;delta_y=-delta_x;}
    if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
    else distance=delta_y;
    for(t=0;t<distance+1;t++)
    {
        OLED_DrawPoint(uRow,uCol,mode);//画点
        xerr+=delta_x;
        yerr+=delta_y;
        if(xerr>distance)
        {
            xerr-=distance;
            uRow+=incx;
        }
        if(yerr>distance)
        {
            yerr-=distance;
            uCol+=incy;
        }
    }
}
//x,y:圆心坐标
//r:圆的半径
void OLED_DrawCircle(u8 x,u8 y,u8 r)
{
    int a, b,num;
    a = 0;
    b = r;
    while(2 * b * b >= r * r)
    {
        OLED_DrawPoint(x + a, y - b,1);
        OLED_DrawPoint(x - a, y - b,1);
        OLED_DrawPoint(x - a, y + b,1);
        OLED_DrawPoint(x + a, y + b,1);

        OLED_DrawPoint(x + b, y + a,1);
        OLED_DrawPoint(x + b, y - a,1);
        OLED_DrawPoint(x - b, y - a,1);
        OLED_DrawPoint(x - b, y + a,1);

        a++;
        num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
        if(num > 0)
        {
            b--;
            a--;
        }
    }
}



//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size1:选择字体 6x8/6x12/8x16/12x24
//mode:0,反色显示;1,正常显示
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode)
{
    u8 i,m,temp,size2,chr1;
    u8 x0=x,y0=y;
    if(size1==8)size2=6;
    else size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
    chr1=chr-' ';  //计算偏移后的值
    for(i=0;i<size2;i++)
    {
        if(size1==8)
            {temp=asc2_0806[chr1][i];} //调用0806字体
        else if(size1==12)
            {temp=asc2_1206[chr1][i];} //调用1206字体
        else if(size1==16)
            {temp=asc2_1608[chr1][i];} //调用1608字体
        else if(size1==24)
            {temp=asc2_2412[chr1][i];} //调用2412字体
        else return;
        for(m=0;m<8;m++)
        {
            if(temp&0x01)OLED_DrawPoint(x,y,mode);
            else OLED_DrawPoint(x,y,!mode);
            temp>>=1;
            y++;
        }
        x++;
        if((size1!=8)&&((x-x0)==size1/2))
        {x=x0;y0=y0+8;}
        y=y0;
  }
}


//显示字符串
//x,y:起点坐标
//size1:字体大小
//*chr:字符串起始地址
//mode:0,反色显示;1,正常显示
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode)
{
    while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
    {
        OLED_ShowChar(x,y,*chr,size1,mode);
        if(size1==8)x+=6;
        else x+=size1/2;
        chr++;
  }
}

//m^n
u32 OLED_Pow(u8 m,u8 n)
{
    u32 result=1;
    while(n--)
    {
      result*=m;
    }
    return result;
}

//显示数字
//x,y :起点坐标
//num :要显示的数字
//len :数字的位数
//size:字体大小
//mode:0,反色显示;1,正常显示
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode)
{
    u8 t,temp,m=0;
    if(size1==8)m=2;
    for(t=0;t<len;t++)
    {
        temp=(num/OLED_Pow(10,len-t-1))%10;
        if(temp==0)
        {
            OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
        }
        else
        {
          OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
        }
  }
}

//显示汉字
//x,y:起点坐标
//num:汉字对应的序号
//mode:0,反色显示;1,正常显示
void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode)
{
    u8 m,temp;
    u8 x0=x,y0=y;
    u16 i,size3=(size1/8+((size1%8)?1:0))*size1;  //得到字体一个字符对应点阵集所占的字节数
    for(i=0;i<size3;i++)
    {
        if(size1==16)
                {temp=Hzk1[num][i];}//调用16*16字体
        else if(size1==24)
                {temp=Hzk2[num][i];}//调用24*24字体
        else if(size1==32)
                {temp=Hzk3[num][i];}//调用32*32字体
        else if(size1==64)
                {temp=Hzk4[num][i];}//调用64*64字体
        else return;
        for(m=0;m<8;m++)
        {
            if(temp&0x01)OLED_DrawPoint(x,y,mode);
            else OLED_DrawPoint(x,y,!mode);
            temp>>=1;
            y++;
        }
        x++;
        if((x-x0)==size1)
            {
                x=x0;
                y0=y0+8;
            }
        y=y0;
    }
}

//num 显示汉字的个数
//space 每一遍显示的间隔
//mode:0,反色显示;1,正常显示
void OLED_ScrollDisplay(u8 num,u8 space,u8 mode)
{
    u8 i,n,t=0,m=0,r;
    while(1)
    {
        if(m==0)
        {
            OLED_ShowChinese(128,24,t,16,mode); //写入一个汉字保存在OLED_GRAM[][]数组中
            t++;
        }
        if(t==num)
        {
            for(r=0;r<16*space;r++)      //显示间隔
             {
                for(i=1;i<144;i++)
                    {
                        for(n=0;n<8;n++)
                        {
                            OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
                        }
                    }
                OLED_Refresh();
             }
            t=0;
        }
        m++;
        if(m==16){m=0;}
        for(i=1;i<144;i++)   //实现左移
        {
            for(n=0;n<8;n++)
            {
                OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
            }
        }
        OLED_Refresh();
    }
}

//x,y:起点坐标
//sizex,sizey,图片长宽
//BMP[]:要写入的图片数组
//mode:0,反色显示;1,正常显示
void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)
{
    u16 j=0;
    u8 i,n,temp,m;
    u8 x0=x,y0=y;
    sizey=sizey/8+((sizey%8)?1:0);
    for(n=0;n<sizey;n++)
    {
         for(i=0;i<sizex;i++)
         {
                temp=BMP[j];
                j++;
                for(m=0;m<8;m++)
                {
                    if(temp&0x01)OLED_DrawPoint(x,y,mode);
                    else OLED_DrawPoint(x,y,!mode);
                    temp>>=1;
                    y++;
                }
                x++;
                if((x-x0)==sizex)
                {
                    x=x0;
                    y0=y0+8;
                }
                y=y0;
     }
     }
}

//OLED的初始化
void OLED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_4);                      //CS引脚PA4置高电平

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

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI通讯方向为双线全双工方式
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;      //设置SPI为主机端模式
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  //设置SPI通讯的数据帧大小为8位
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;         //设置SPI的时钟极性为低电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;       //设置SPI的时钟相位为在SCK的奇数边沿采集数据
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;          //设置NSS引脚(即片选引脚)的使用模式为软件模式
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //设置波特率分频因子为4分频
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //设置数据传输为高位数据在前
    SPI_InitStructure.SPI_CRCPolynomial = 7;           //SPI的CRC校验中多项式的值
    SPI_Init(SPI1, &SPI_InitStructure);                //初始化SPI
    SPI_Cmd(SPI1, ENABLE);                             //使能SPI1外设

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    OLED_RES_Clr();
    Delay_Ms(200);
    OLED_RES_Set();

    OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
    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  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
    OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
    OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
    OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
    OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset   Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WR_Byte(0x00,OLED_CMD);//-not offset
    OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
    OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
    OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
    OLED_WR_Byte(0x12,OLED_CMD);
    OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
    OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
    OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WR_Byte(0x02,OLED_CMD);//
    OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
    OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
    OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
    OLED_Clear();
    OLED_WR_Byte(0xAF,OLED_CMD);
}
sp.c文件主要进行OLED显示相关函数的配置。关于函数的具体功能请查看程序中函数具体注释,在此不再一一介绍。
main.c文件
/********************************** (C) COPYRIGHT *******************************
* File Name          : main.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2020/04/30
* Description        : Main program body.
*******************************************************************************/

#include "debug.h"
#include "spi.h"
#include "bmp.h"

/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Return         : None
*******************************************************************************/
int main(void)
{
    u8 t=' ';
    Delay_Init();
    OLED_Init();
    OLED_ColorTurn(0);  //0正常显示,1 反色显示
    OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
    while(1)
    {
        OLED_ShowPicture(0,0,128,64,BMP1,1);
        OLED_Refresh();
        Delay_Ms(5000);
        OLED_Clear();
        OLED_ShowChinese(0,0,0,16,1); //沁
        OLED_ShowChinese(18,0,1,16,1);//恒
        OLED_ShowChinese(36,0,2,16,1);//微
        OLED_ShowChinese(54,0,3,16,1);//电
        OLED_ShowChinese(72,0,4,16,1);//子
        OLED_ShowString(8,16,"SPI Drive OLED",16,1);
        OLED_ShowString(20,32,"2021/03/23",16,1);
        OLED_ShowString(0,48,"ASCII:",16,1);
        OLED_ShowString(63,48,"CODE:",16,1);
        OLED_ShowChar(48,48,t,16,1);//显示ASCII字符
        t++;
        if(t>'~')t=' ';
        OLED_ShowNum(103,48,t,3,16,1);
        OLED_Refresh();
        Delay_Ms(500);
        OLED_ScrollDisplay(5,4,1);
    }
}
main.c文件主要进行OLED屏显示操作,显示图片、汉字等信息。

4下载验证
将编译好的程序下载到开发版并复位,OLED显示如下:

86、硬件SPI驱动OLED.rar

498.67 KB

相关帖子

沙发
51xlf| | 2021-4-5 09:41 | 只看该作者
使用硬件SPI比用模拟SPI好
板凳
i1mcu| | 2021-4-5 09:41 | 只看该作者
可以选择SPI或者IIC通讯吗
评论
RISCVLAR 2021-4-9 10:47 回复TA
需根据OLED屏的引脚来进行选择 
地板
pmp| | 2021-4-5 09:41 | 只看该作者
OLED我用的是SPI的程序
5
mmbs| | 2021-4-5 09:42 | 只看该作者
            
6
1988020566| | 2021-4-5 09:45 | 只看该作者
刷新的速度怎么样
评论
RISCVLAR 2021-4-9 10:48 回复TA
相比模拟SPI驱动OLED好一些 
7
lzbf| | 2021-4-5 09:45 | 只看该作者
多少人在玩oled
8
youtome| | 2021-4-5 09:46 | 只看该作者
软件管脚模拟SPI吧  
9
cemaj| | 2021-4-5 09:46 | 只看该作者
oled显示屏的接口是spi吗
评论
RISCVLAR 2021-4-9 10:52 回复TA
是的 
10
cemaj| | 2021-4-5 09:46 | 只看该作者
如何更改SPI驱动   
11
jimmhu| | 2021-4-5 09:47 | 只看该作者
可以驱动TFT吗   
12
uptown| | 2021-4-5 09:47 | 只看该作者
怎么提高刷屏速度   
评论
RISCVLAR 2021-4-9 11:02 回复TA
可通过修改分频系数来提高速度 
13
lzbf| | 2021-4-5 09:47 | 只看该作者
可以用硬件SPI方式的  
评论
RISCVLAR 2021-4-9 10:50 回复TA
该贴用的就是硬件SPI 
14
1988020566| | 2021-4-5 09:47 | 只看该作者
方便很多   
15
mmbs| | 2021-4-5 09:47 | 只看该作者
谢谢版主分享的资料。   
16
youtome| | 2021-4-5 09:47 | 只看该作者
能用3线SPI的oled显示么  
17
pmp| | 2021-4-5 09:47 | 只看该作者
用IO模拟SPI时序  
18
cemaj| | 2021-4-5 09:47 | 只看该作者
oled spi方式 DC线接哪里  
评论
RISCVLAR 2021-4-9 10:50 回复TA
此处接PA3引脚 
19
i1mcu| | 2021-4-5 09:47 | 只看该作者
怎么修改oled呢?   
20
jimmhu| | 2021-4-5 09:48 | 只看该作者
               
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

296

帖子

44

粉丝
乌龟死了有什么预兆 恢复伤口吃什么好得快 做包皮手术挂什么科 梦见父亲死了是什么意思 内窗是什么意思
三候是什么意思 为什么会勃起 马超属什么生肖 高铁动力来源是什么 石榴石一般什么价位
女人下面 什么味道 乙肝两对半45阳性是什么意思 roa胎位是什么意思 邮戳是什么意思 武汉有什么好吃的
cip号是什么 喝酒容易醉是什么原因 谷雨是什么季节 陶土色大便是什么颜色 月经老提前是什么原因
八字七杀是什么意思hcv8jop3ns4r.cn 唐氏综合征是什么病shenchushe.com 什么是牙周炎hcv9jop6ns3r.cn 滴虫性阴炎用什么药效果最好wzqsfys.com 本科和专科有什么区别hcv8jop7ns2r.cn
绞肠痧是什么病hcv8jop8ns6r.cn 东星斑为什么这么贵hcv8jop8ns4r.cn 主管护师是什么职称hcv8jop3ns1r.cn 孕妇有狐臭擦什么最好hcv8jop6ns2r.cn 硫磺皂有什么作用hebeidezhi.com
什么时候三伏天hcv7jop9ns7r.cn 汗疱疹是什么原因引起的hcv8jop1ns6r.cn 包皮炎挂什么科hcv9jop2ns0r.cn 粗钢是什么hcv8jop4ns4r.cn 微光是什么意思xianpinbao.com
石榴什么时候开花hcv7jop9ns1r.cn 依巴斯汀片是什么药hcv8jop8ns2r.cn 病毒性感冒咳嗽吃什么药效果好hcv7jop7ns0r.cn 阴唇长什么样hcv7jop5ns5r.cn 秋刀鱼是什么鱼hcv8jop5ns2r.cn
百度