查看: 1484|回复: 0
收起左侧

第八十七章:CH32V103应用教程——硬件SPI驱动OLED

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-5-1 16:42:35 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 草帽王子 于 2021-9-10 18:23 编辑

    前面章节介绍了使用模拟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文件
    1. #ifndef __SPI_H
    2. #define __SPI_H

    3. #include "ch32v10x_conf.h"
    4. #include "stdlib.h"

    5. //-----------------OLED端口定义----------------

    6. //#define OLED_SCL_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_0)//SCL
    7. //#define OLED_SCL_Set() GPIO_SetBits(GPIOA,GPIO_Pin_0)
    8. //
    9. //#define OLED_SDA_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_1)//SDA
    10. //#define OLED_SDA_Set() GPIO_SetBits(GPIOA,GPIO_Pin_1)

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

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

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

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

    19. u8 SPI1_ReadWriteByte(u8 TxData);
    20. void OLED_ClearPoint(u8 x,u8 y);
    21. void OLED_ColorTurn(u8 i);
    22. void OLED_DisplayTurn(u8 i);
    23. void OLED_WR_Byte(u8 dat,u8 mode);
    24. void OLED_DisPlay_On(void);
    25. void OLED_DisPlay_Off(void);
    26. void OLED_Refresh(void);
    27. void OLED_Clear(void);
    28. void OLED_DrawPoint(u8 x,u8 y,u8 t);
    29. void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode);
    30. void OLED_DrawCircle(u8 x,u8 y,u8 r);
    31. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode);
    32. void OLED_ShowChar6x8(u8 x,u8 y,u8 chr,u8 mode);
    33. void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode);
    34. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode);
    35. void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode);
    36. void OLED_ScrollDisplay(u8 num,u8 space,u8 mode);
    37. void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode);
    38. void OLED_Init(void);

    39. #endif
    复制代码
    spi.h文件主要进行OLED端口相关定义和函数声明;
    spi.c文件
    1. #include "spi.h"
    2. #include "stdlib.h"
    3. #include "oledfont.h"
    4. #include "debug.h"

    5. u8 OLED_GRAM[144][8];

    6. /*******************************************************************************
    7. * Function Name  : SPI1_ReadWriteByte
    8. * Description    : SPI1 read or write one byte.
    9. * Input          : TxData: write one byte data.
    10. * Return         : Read one byte data.
    11. *******************************************************************************/
    12. u8 SPI1_ReadWriteByte(u8 TxData)
    13. {
    14.     u8 i=0;

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

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

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

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

    29. //反显函数
    30. void OLED_ColorTurn(u8 i)
    31. {
    32.     if(i==0)
    33.         {
    34.             OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
    35.         }
    36.     if(i==1)
    37.         {
    38.             OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
    39.         }
    40. }

    41. //屏幕旋转180度
    42. void OLED_DisplayTurn(u8 i)
    43. {
    44.     if(i==0)
    45.         {
    46.             OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
    47.             OLED_WR_Byte(0xA1,OLED_CMD);
    48.         }
    49.     if(i==1)
    50.         {
    51.             OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
    52.             OLED_WR_Byte(0xA0,OLED_CMD);
    53.         }
    54. }

    55. void OLED_WR_Byte(u8 dat,u8 cmd)
    56. {

    57.     if(cmd)
    58.       OLED_DC_Set();
    59.     else
    60.       OLED_DC_Clr();

    61.     OLED_CS_Clr();

    62.     SPI1_ReadWriteByte(dat);

    63.     OLED_CS_Set();

    64.     OLED_DC_Set();
    65. }

    66. //开启OLED显示
    67. void OLED_DisPlay_On(void)
    68. {
    69.     OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
    70.     OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
    71.     OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
    72. }

    73. //关闭OLED显示
    74. void OLED_DisPlay_Off(void)
    75. {
    76.     OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
    77.     OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
    78.     OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
    79. }

    80. //更新显存到OLED
    81. void OLED_Refresh(void)
    82. {
    83.     u8 i,n;
    84.     for(i=0;i<8;i++)
    85.     {
    86.        OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
    87.        OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
    88.        OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
    89.        for(n=0;n<128;n++)
    90.        OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
    91.     }
    92. }
    93. //清屏函数
    94. void OLED_Clear(void)
    95. {
    96.     u8 i,n;
    97.     for(i=0;i<8;i++)
    98.     {
    99.        for(n=0;n<128;n++)
    100.             {
    101.              OLED_GRAM[n][i]=0;//清除所有数据
    102.             }
    103.     }
    104.     OLED_Refresh();//更新显示
    105. }

    106. //画点
    107. //x:0~127
    108. //y:0~63
    109. //t:1 填充 0,清空
    110. void OLED_DrawPoint(u8 x,u8 y,u8 t)
    111. {
    112.     u8 i,m,n;
    113.     i=y/8;
    114.     m=y%8;
    115.     n=1<<m;
    116.     if(t){OLED_GRAM[x][i]|=n;}
    117.     else
    118.     {
    119.         OLED_GRAM[x][i]=~OLED_GRAM[x][i];
    120.         OLED_GRAM[x][i]|=n;
    121.         OLED_GRAM[x][i]=~OLED_GRAM[x][i];
    122.     }
    123. }

    124. //画线
    125. //x1,y1:起点坐标
    126. //x2,y2:结束坐标
    127. void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode)
    128. {
    129.     u16 t;
    130.     int xerr=0,yerr=0,delta_x,delta_y,distance;
    131.     int incx,incy,uRow,uCol;
    132.     delta_x=x2-x1; //计算坐标增量
    133.     delta_y=y2-y1;
    134.     uRow=x1;//画线起点坐标
    135.     uCol=y1;
    136.     if(delta_x>0)incx=1; //设置单步方向
    137.     else if (delta_x==0)incx=0;//垂直线
    138.     else {incx=-1;delta_x=-delta_x;}
    139.     if(delta_y>0)incy=1;
    140.     else if (delta_y==0)incy=0;//水平线
    141.     else {incy=-1;delta_y=-delta_x;}
    142.     if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
    143.     else distance=delta_y;
    144.     for(t=0;t<distance+1;t++)
    145.     {
    146.         OLED_DrawPoint(uRow,uCol,mode);//画点
    147.         xerr+=delta_x;
    148.         yerr+=delta_y;
    149.         if(xerr>distance)
    150.         {
    151.             xerr-=distance;
    152.             uRow+=incx;
    153.         }
    154.         if(yerr>distance)
    155.         {
    156.             yerr-=distance;
    157.             uCol+=incy;
    158.         }
    159.     }
    160. }
    161. //x,y:圆心坐标
    162. //r:圆的半径
    163. void OLED_DrawCircle(u8 x,u8 y,u8 r)
    164. {
    165.     int a, b,num;
    166.     a = 0;
    167.     b = r;
    168.     while(2 * b * b >= r * r)
    169.     {
    170.         OLED_DrawPoint(x + a, y - b,1);
    171.         OLED_DrawPoint(x - a, y - b,1);
    172.         OLED_DrawPoint(x - a, y + b,1);
    173.         OLED_DrawPoint(x + a, y + b,1);

    174.         OLED_DrawPoint(x + b, y + a,1);
    175.         OLED_DrawPoint(x + b, y - a,1);
    176.         OLED_DrawPoint(x - b, y - a,1);
    177.         OLED_DrawPoint(x - b, y + a,1);

    178.         a++;
    179.         num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
    180.         if(num > 0)
    181.         {
    182.             b--;
    183.             a--;
    184.         }
    185.     }
    186. }



    187. //在指定位置显示一个字符,包括部分字符
    188. //x:0~127
    189. //y:0~63
    190. //size1:选择字体 6x8/6x12/8x16/12x24
    191. //mode:0,反色显示;1,正常显示
    192. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode)
    193. {
    194.     u8 i,m,temp,size2,chr1;
    195.     u8 x0=x,y0=y;
    196.     if(size1==8)size2=6;
    197.     else size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
    198.     chr1=chr-' ';  //计算偏移后的值
    199.     for(i=0;i<size2;i++)
    200.     {
    201.         if(size1==8)
    202.             {temp=asc2_0806[chr1][i];} //调用0806字体
    203.         else if(size1==12)
    204.             {temp=asc2_1206[chr1][i];} //调用1206字体
    205.         else if(size1==16)
    206.             {temp=asc2_1608[chr1][i];} //调用1608字体
    207.         else if(size1==24)
    208.             {temp=asc2_2412[chr1][i];} //调用2412字体
    209.         else return;
    210.         for(m=0;m<8;m++)
    211.         {
    212.             if(temp&0x01)OLED_DrawPoint(x,y,mode);
    213.             else OLED_DrawPoint(x,y,!mode);
    214.             temp>>=1;
    215.             y++;
    216.         }
    217.         x++;
    218.         if((size1!=8)&&((x-x0)==size1/2))
    219.         {x=x0;y0=y0+8;}
    220.         y=y0;
    221.   }
    222. }


    223. //显示字符串
    224. //x,y:起点坐标
    225. //size1:字体大小
    226. //*chr:字符串起始地址
    227. //mode:0,反色显示;1,正常显示
    228. void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode)
    229. {
    230.     while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
    231.     {
    232.         OLED_ShowChar(x,y,*chr,size1,mode);
    233.         if(size1==8)x+=6;
    234.         else x+=size1/2;
    235.         chr++;
    236.   }
    237. }

    238. //m^n
    239. u32 OLED_Pow(u8 m,u8 n)
    240. {
    241.     u32 result=1;
    242.     while(n--)
    243.     {
    244.       result*=m;
    245.     }
    246.     return result;
    247. }

    248. //显示数字
    249. //x,y :起点坐标
    250. //num :要显示的数字
    251. //len :数字的位数
    252. //size:字体大小
    253. //mode:0,反色显示;1,正常显示
    254. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode)
    255. {
    256.     u8 t,temp,m=0;
    257.     if(size1==8)m=2;
    258.     for(t=0;t<len;t++)
    259.     {
    260.         temp=(num/OLED_Pow(10,len-t-1))%10;
    261.         if(temp==0)
    262.         {
    263.             OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
    264.         }
    265.         else
    266.         {
    267.           OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
    268.         }
    269.   }
    270. }

    271. //显示汉字
    272. //x,y:起点坐标
    273. //num:汉字对应的序号
    274. //mode:0,反色显示;1,正常显示
    275. void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode)
    276. {
    277.     u8 m,temp;
    278.     u8 x0=x,y0=y;
    279.     u16 i,size3=(size1/8+((size1%8)?1:0))*size1;  //得到字体一个字符对应点阵集所占的字节数
    280.     for(i=0;i<size3;i++)
    281.     {
    282.         if(size1==16)
    283.                 {temp=Hzk1[num][i];}//调用16*16字体
    284.         else if(size1==24)
    285.                 {temp=Hzk2[num][i];}//调用24*24字体
    286.         else if(size1==32)
    287.                 {temp=Hzk3[num][i];}//调用32*32字体
    288.         else if(size1==64)
    289.                 {temp=Hzk4[num][i];}//调用64*64字体
    290.         else return;
    291.         for(m=0;m<8;m++)
    292.         {
    293.             if(temp&0x01)OLED_DrawPoint(x,y,mode);
    294.             else OLED_DrawPoint(x,y,!mode);
    295.             temp>>=1;
    296.             y++;
    297.         }
    298.         x++;
    299.         if((x-x0)==size1)
    300.             {
    301.                 x=x0;
    302.                 y0=y0+8;
    303.             }
    304.         y=y0;
    305.     }
    306. }

    307. //num 显示汉字的个数
    308. //space 每一遍显示的间隔
    309. //mode:0,反色显示;1,正常显示
    310. void OLED_ScrollDisplay(u8 num,u8 space,u8 mode)
    311. {
    312.     u8 i,n,t=0,m=0,r;
    313.     while(1)
    314.     {
    315.         if(m==0)
    316.         {
    317.             OLED_ShowChinese(128,24,t,16,mode); //写入一个汉字保存在OLED_GRAM[][]数组中
    318.             t++;
    319.         }
    320.         if(t==num)
    321.         {
    322.             for(r=0;r<16*space;r++)      //显示间隔
    323.              {
    324.                 for(i=1;i<144;i++)
    325.                     {
    326.                         for(n=0;n<8;n++)
    327.                         {
    328.                             OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
    329.                         }
    330.                     }
    331.                 OLED_Refresh();
    332.              }
    333.             t=0;
    334.         }
    335.         m++;
    336.         if(m==16){m=0;}
    337.         for(i=1;i<144;i++)   //实现左移
    338.         {
    339.             for(n=0;n<8;n++)
    340.             {
    341.                 OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
    342.             }
    343.         }
    344.         OLED_Refresh();
    345.     }
    346. }

    347. //x,y:起点坐标
    348. //sizex,sizey,图片长宽
    349. //BMP[]:要写入的图片数组
    350. //mode:0,反色显示;1,正常显示
    351. void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)
    352. {
    353.     u16 j=0;
    354.     u8 i,n,temp,m;
    355.     u8 x0=x,y0=y;
    356.     sizey=sizey/8+((sizey%8)?1:0);
    357.     for(n=0;n<sizey;n++)
    358.     {
    359.          for(i=0;i<sizex;i++)
    360.          {
    361.                 temp=BMP[j];
    362.                 j++;
    363.                 for(m=0;m<8;m++)
    364.                 {
    365.                     if(temp&0x01)OLED_DrawPoint(x,y,mode);
    366.                     else OLED_DrawPoint(x,y,!mode);
    367.                     temp>>=1;
    368.                     y++;
    369.                 }
    370.                 x++;
    371.                 if((x-x0)==sizex)
    372.                 {
    373.                     x=x0;
    374.                     y0=y0+8;
    375.                 }
    376.                 y=y0;
    377.      }
    378.      }
    379. }

    380. //OLED的初始化
    381. void OLED_Init(void)
    382. {
    383.     GPIO_InitTypeDef GPIO_InitStructure;
    384.     SPI_InitTypeDef  SPI_InitStructure;

    385.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );

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

    391.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7;
    392.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //复用推挽输出
    393.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    394.     GPIO_Init( GPIOA, &GPIO_InitStructure );

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

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

    410.     OLED_RES_Clr();
    411.     Delay_Ms(200);
    412.     OLED_RES_Set();

    413.     OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
    414.     OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
    415.     OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
    416.     OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    417.     OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
    418.     OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
    419.     OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    420.     OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    421.     OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
    422.     OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
    423.     OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
    424.     OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset   Shift Mapping RAM Counter (0x00~0x3F)
    425.     OLED_WR_Byte(0x00,OLED_CMD);//-not offset
    426.     OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
    427.     OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    428.     OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
    429.     OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    430.     OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
    431.     OLED_WR_Byte(0x12,OLED_CMD);
    432.     OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
    433.     OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
    434.     OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    435.     OLED_WR_Byte(0x02,OLED_CMD);//
    436.     OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
    437.     OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
    438.     OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    439.     OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
    440.     OLED_Clear();
    441.     OLED_WR_Byte(0xAF,OLED_CMD);
    442. }
    复制代码
    sp.c文件主要进行OLED显示相关函数的配置。关于函数的具体功能请查看程序中函数具体注释,在此不再一一介绍。
    main.c文件
    1. /********************************** (C) COPYRIGHT *******************************
    2. * File Name          : main.c
    3. * Author             : WCH
    4. * Version            : V1.0.0
    5. * Date               : 2020/04/30
    6. * Description        : Main program body.
    7. *******************************************************************************/

    8. #include "debug.h"
    9. #include "spi.h"
    10. #include "bmp.h"

    11. /*******************************************************************************
    12. * Function Name  : main
    13. * Description    : Main program.
    14. * Input          : None
    15. * Return         : None
    16. *******************************************************************************/
    17. int main(void)
    18. {
    19.     u8 t=' ';
    20.     Delay_Init();
    21.     OLED_Init();
    22.     OLED_ColorTurn(0);  //0正常显示,1 反色显示
    23.     OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
    24.     while(1)
    25.     {
    26.         OLED_ShowPicture(0,0,128,64,BMP1,1);
    27.         OLED_Refresh();
    28.         Delay_Ms(5000);
    29.         OLED_Clear();
    30.         OLED_ShowChinese(0,0,0,16,1); //沁
    31.         OLED_ShowChinese(18,0,1,16,1);//恒
    32.         OLED_ShowChinese(36,0,2,16,1);//微
    33.         OLED_ShowChinese(54,0,3,16,1);//电
    34.         OLED_ShowChinese(72,0,4,16,1);//子
    35.         OLED_ShowString(8,16,"SPI Drive OLED",16,1);
    36.         OLED_ShowString(20,32,"2021/03/23",16,1);
    37.         OLED_ShowString(0,48,"ASCII:",16,1);
    38.         OLED_ShowString(63,48,"CODE:",16,1);
    39.         OLED_ShowChar(48,48,t,16,1);//显示ASCII字符
    40.         t++;
    41.         if(t>'~')t=' ';
    42.         OLED_ShowNum(103,48,t,3,16,1);
    43.         OLED_Refresh();
    44.         Delay_Ms(500);
    45.         OLED_ScrollDisplay(5,4,1);
    46.     }
    47. }
    复制代码
    main.c文件主要进行OLED屏显示操作,显示图片、汉字等信息。


    4、下载验证

    将编译好的程序下载到开发版并复位,OLED显示如下:
    CH32V CH573单片机芯片-第八十七章:CH32V103应用教程——硬件SPI驱动OLEDrisc-v单片机中文社区(1)
    86、硬件SPI驱动OLED.rar
    CH32V CH573单片机芯片-第八十七章:CH32V103应用教程——硬件SPI驱动OLEDrisc-v单片机中文社区(2) 86、硬件SPI驱动OLED.rar (498.67 KB, 下载次数: 18)
    链接:https://pan.baidu.com/s/1uRJECYrw8yt6VHo_veoNow
    提取码:ap6v
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第八十六章:CH32V103应用教程——模拟SPI驱动OLED
    下一篇:第八十八章:CH32V103应用教程——步进电机驱动
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-11-26 09:51 , Processed in 0.304108 second(s), 48 queries .

    快速回复 返回顶部 返回列表