搜索

[RISC-V MCU 应用开发] 第八十七章、CH32V103应用教程——硬件SPI驱动OLED

[复制链接]
45|27
 楼主 | 2021-3-30 19:34 | 显示全部楼层 |阅读模式
本帖最后由 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文件
  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显示如下:
图片1.png

86、硬件SPI驱动OLED.rar

498.67 KB, 下载次数: 26

使用特权

评论回复

相关帖子

| 2021-4-5 09:41 | 显示全部楼层
使用硬件SPI比用模拟SPI好

使用特权

评论回复
| 2021-4-5 09:41 | 显示全部楼层
可以选择SPI或者IIC通讯吗

使用特权

评论回复

评论

RISCVLAR 2021-4-9 10:47 回复TA
需根据OLED屏的引脚来进行选择 
| 2021-4-5 09:41 | 显示全部楼层
OLED我用的是SPI的程序

使用特权

评论回复
| 2021-4-5 09:42 | 显示全部楼层
            

使用特权

评论回复
| 2021-4-5 09:45 | 显示全部楼层
刷新的速度怎么样

使用特权

评论回复

评论

RISCVLAR 2021-4-9 10:48 回复TA
相比模拟SPI驱动OLED好一些 
| 2021-4-5 09:45 | 显示全部楼层
多少人在玩oled

使用特权

评论回复
| 2021-4-5 09:46 | 显示全部楼层
软件管脚模拟SPI吧  

使用特权

评论回复
| 2021-4-5 09:46 | 显示全部楼层
oled显示屏的接口是spi吗

使用特权

评论回复

评论

RISCVLAR 2021-4-9 10:52 回复TA
是的 
| 2021-4-5 09:46 | 显示全部楼层
如何更改SPI驱动   

使用特权

评论回复
| 2021-4-5 09:47 | 显示全部楼层
可以驱动TFT吗   

使用特权

评论回复
| 2021-4-5 09:47 | 显示全部楼层
怎么提高刷屏速度   

使用特权

评论回复

评论

RISCVLAR 2021-4-9 11:02 回复TA
可通过修改分频系数来提高速度 
| 2021-4-5 09:47 | 显示全部楼层
可以用硬件SPI方式的  

使用特权

评论回复

评论

RISCVLAR 2021-4-9 10:50 回复TA
该贴用的就是硬件SPI 
| 2021-4-5 09:47 | 显示全部楼层
方便很多   

使用特权

评论回复
| 2021-4-5 09:47 | 显示全部楼层
谢谢版主分享的资料。   

使用特权

评论回复
| 2021-4-5 09:47 | 显示全部楼层
能用3线SPI的oled显示么  

使用特权

评论回复
| 2021-4-5 09:47 | 显示全部楼层
用IO模拟SPI时序  

使用特权

评论回复
| 2021-4-5 09:47 | 显示全部楼层
oled spi方式 DC线接哪里  

使用特权

评论回复

评论

RISCVLAR 2021-4-9 10:50 回复TA
此处接PA3引脚 
| 2021-4-5 09:47 | 显示全部楼层
怎么修改oled呢?   

使用特权

评论回复
| 2021-4-5 09:48 | 显示全部楼层
               

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表