[IDE] 【RISC-V MCU CH32V103测评】+硬件IIC驱动OLED

[复制链接]
 楼主| qjp1988113 发表于 2020-11-27 14:54 | 显示全部楼层 |阅读模式
看别人在论坛里移植了个小游戏,我也想尝试一把。这不先来调下OLED的显示。
坛里有人用软件IIC做了,那么今天我们来用硬件IIC试一下,看看能否驱动成功呢?
我们先来配置IIC,我们选择IIC1来驱动OLED,因为IIC2已经被我分配给EEPROM了。
我们查看手册,得知:
M1.png
我们匹配:
//OLED
VCC-->3V3
SCL-->PB6(I2C1_SCL)
SDA-->PB7(I2C1_SDA)
GND-->GND

对OLED的IIC通讯与其他IIC元件没有什么不同。根据原理图提供:
M2png.png
得知OLED从机地址为:0x78。OLED板已经带了上拉,不然开发板上没有,还得接2个上拉电阻呢。
IIC正常的读写时序:
M3.png

但这里我们仅仅对屏幕写操作,不读取任何。
IIC写单个字节的流程是:发送起始信号-->发送从机地址-->等待应答-->发送要写入的寄存器地址-->等待应答-->发送字节-->等待应答-->发送停止信号。

现在开始对IIC1进行初始化:
  1. void IIC1_Init( u32 bound, u16 address )
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     I2C_InitTypeDef I2C_InitTSturcture;

  5.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  6.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );

  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init( GPIOB, &GPIO_InitStructure );

  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  13.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  14.     GPIO_Init( GPIOB, &GPIO_InitStructure );

  15.     I2C_InitTSturcture.I2C_ClockSpeed = bound;
  16.     I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
  17.     I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
  18.     I2C_InitTSturcture.I2C_OwnAddress1 = address;
  19.     I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
  20.     I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  21.     I2C_Init( I2C1, &I2C_InitTSturcture );

  22.     I2C_Cmd( I2C1, ENABLE );

  23.     I2C_AcknowledgeConfig( I2C1, ENABLE );
  24. }
定义OLED写一个字节的函数(这里控制OLED其实只应用到了写):
  1. //发送一个字节
  2. //mode:数据/命令标志 0,表示命令;1,表示数据;
  3. void OLED_WR_Byte(uint8_t dat,uint8_t mode)
  4. {
  5.     while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
  6.     I2C_GenerateSTART( I2C1, ENABLE );

  7.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
  8.     I2C_Send7bitAddress( I2C1, 0X78, I2C_Direction_Transmitter );

  9.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
  10.     if(mode)
  11.         I2C_SendData( I2C1, (u8)(0x40&0x00FF) );
  12.     else
  13.         I2C_SendData( I2C1, (u8)(0x00&0x00FF) );

  14.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  15.     if( I2C_GetFlagStatus( I2C1, I2C_FLAG_TXE ) !=  RESET )
  16.     {
  17.     I2C_SendData( I2C1, dat );
  18.     }

  19.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
  20.     I2C_GenerateSTOP( I2C1, ENABLE );

  21. }
我们在定义刷新显示缓存数据的函数:
  1. //更新显存到OLED
  2. void OLED_Refresh(void)
  3. {
  4.     uint8_t i,n;
  5.     for(i=0;i<8;i++)
  6.     {
  7.         OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
  8.         OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
  9.         OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
  10. I2C_Send7bitAddress( I2C1, 0X78, I2C_Direction_Transmitter );

  11.         while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
  12.         I2C_SendData( I2C1, (u8)(0x40&0x00FF) );

  13.         while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  14.         for(n=0;n<128;n++)
  15.         {
  16.             if( I2C_GetFlagStatus( I2C1, I2C_FLAG_TXE ) !=  RESET )
  17.             {
  18.             I2C_SendData( I2C1, OLED_GRAM[n][i] );
  19.             }
  20.             while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
  21.         }

  22.         I2C_GenerateSTOP( I2C1, ENABLE );
  23.   }

  24. }
其他的一些OLED控制函数就没有什么的了(直接调用上面2个函数即可)。
OLED全面的文件:
oled.h:
  1. /*
  2. * oled.h
  3. *
  4. *  Created on: Nov 26, 2020
  5. *      Author: Administrator
  6. */

  7. #ifndef OLED_H_
  8. #define OLED_H_

  9. #include "ch32v10x.h"

  10. #define OLED_ADDRESS    0x78 //通过调整0R电阻,屏可以选择0x78  0x7A两个地址   默认为0x78

  11. #define OLED_CMD  0 //写命令
  12. #define OLED_DATA 1 //写数据
oled.c
  1. /*
  2. * oled.c
  3. *
  4. *  Created on: Nov 26, 2020
  5. *      Author: Administrator
  6. */

  7. /*
  8. * i2c_eeprom.c
  9. *
  10. *  Created on: Nov 21, 2020
  11. *      Author: Administrator
  12. */
  13. #include "oled.h"
  14. #include "oledfont.h"
  15. #include "debug.h"

  16. uint8_t OLED_GRAM[144][8];

  17. /*******************************************************************************
  18. * Function Name  : IIC_Init
  19. * Description    : Initializes the IIC peripheral.
  20. * Input          : None
  21. * Return         : None
  22. *******************************************************************************/
  23. void IIC1_Init( u32 bound, u16 address )
  24. {
  25.     GPIO_InitTypeDef GPIO_InitStructure;
  26.     I2C_InitTypeDef I2C_InitTSturcture;

  27.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  28.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE );

  29.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  30.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  31.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  32.     GPIO_Init( GPIOB, &GPIO_InitStructure );

  33.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  34.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  35.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  36.     GPIO_Init( GPIOB, &GPIO_InitStructure );

  37.     I2C_InitTSturcture.I2C_ClockSpeed = bound;
  38.     I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
  39.     I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
  40.     I2C_InitTSturcture.I2C_OwnAddress1 = address;
  41.     I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
  42.     I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  43.     I2C_Init( I2C1, &I2C_InitTSturcture );

  44.     I2C_Cmd( I2C1, ENABLE );

  45.     I2C_AcknowledgeConfig( I2C1, ENABLE );
  46. }

  47. /*******************************************************************************
  48. * Function Name  : AT24CXX_Init
  49. * Description    : Initializes AT24xx EEPROM.
  50. * Input          : None
  51. * Return         : None
  52. ********************************************************************************/
  53. void OLED_Init(void)
  54. {
  55.     //VCC GND 定义
  56.     GPIO_InitTypeDef GPIO_InitStructure;
  57.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );

  58.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_8;
  59.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  60.     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  61.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  62.     //PB5-->VCC PB8-->GND
  63.     GPIO_WriteBit(GPIOB, GPIO_Pin_5, Bit_SET);//PB5=1
  64.     GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);//PB8=0
  65.     Delay_Ms(500);//等待供电稳定,可能不需要
  66.     //IIC 初始化 SALVE ADD 0x78
  67.     IIC1_Init( 100000, 0x78);
  68.     //OLED 初始化指令
  69.     OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
  70.     OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  71.     OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  72.     OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  73.     OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
  74.     OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
  75.     OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
  76.     OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
  77.     OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
  78.     OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  79.     OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
  80.     OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset   Shift Mapping RAM Counter (0x00~0x3F)
  81.     OLED_WR_Byte(0x00,OLED_CMD);//-not offset
  82.     OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
  83.     OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
  84.     OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
  85.     OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  86.     OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
  87.     OLED_WR_Byte(0x12,OLED_CMD);
  88.     OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
  89.     OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
  90.     OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
  91.     OLED_WR_Byte(0x02,OLED_CMD);//
  92.     OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
  93.     OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
  94.     OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
  95.     OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
  96.     OLED_Clear();
  97.     OLED_WR_Byte(0xAF,OLED_CMD);
  98. }

  99. //延时
  100. void IIC_delay(void)
  101. {
  102.     Delay_Us(4);
  103. }

  104. //反显函数
  105. void OLED_ColorTurn(uint8_t i)
  106. {
  107.     if(i==0)
  108.     {
  109.         OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
  110.     }
  111.     if(i==1)
  112.     {
  113.         OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
  114.     }
  115. }

  116. //屏幕旋转180度
  117. void OLED_DisplayTurn(uint8_t i)
  118. {
  119.     if(i==0)
  120.     {
  121.         OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
  122.         OLED_WR_Byte(0xA1,OLED_CMD);
  123.     }
  124.     if(i==1)
  125.     {
  126.         OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
  127.         OLED_WR_Byte(0xA0,OLED_CMD);
  128.     }
  129. }


  130. //发送一个字节
  131. //mode:数据/命令标志 0,表示命令;1,表示数据;
  132. void OLED_WR_Byte(uint8_t dat,uint8_t mode)
  133. {
  134.     while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
  135.     I2C_GenerateSTART( I2C1, ENABLE );

  136.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
  137.     I2C_Send7bitAddress( I2C1, 0X78, I2C_Direction_Transmitter );

  138.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
  139.     if(mode)
  140.         I2C_SendData( I2C1, (u8)(0x40&0x00FF) );
  141.     else
  142.         I2C_SendData( I2C1, (u8)(0x00&0x00FF) );

  143.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  144.     if( I2C_GetFlagStatus( I2C1, I2C_FLAG_TXE ) !=  RESET )
  145.     {
  146.     I2C_SendData( I2C1, dat );
  147.     }

  148.     while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
  149.     I2C_GenerateSTOP( I2C1, ENABLE );

  150. }

  151. //开启OLED显示
  152. void OLED_DisPlay_On(void)
  153. {
  154.     OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
  155.     OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
  156.     OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
  157. }

  158. //关闭OLED显示
  159. void OLED_DisPlay_Off(void)
  160. {
  161.     OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
  162.     OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
  163.     OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
  164. }

  165. //更新显存到OLED
  166. void OLED_Refresh(void)
  167. {
  168.     uint8_t i,n;
  169.     for(i=0;i<8;i++)
  170.     {
  171.         OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
  172.         OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
  173.         OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
  174.         while( I2C_GetFlagStatus( I2C1, I2C_FLAG_BUSY ) != RESET );
  175.         I2C_GenerateSTART( I2C1, ENABLE );

  176.         while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_MODE_SELECT ) );
  177.         I2C_Send7bitAddress( I2C1, 0X78, I2C_Direction_Transmitter );

  178.         while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) );
  179.         I2C_SendData( I2C1, (u8)(0x40&0x00FF) );

  180.         while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );

  181.         for(n=0;n<128;n++)
  182.         {
  183.             if( I2C_GetFlagStatus( I2C1, I2C_FLAG_TXE ) !=  RESET )
  184.             {
  185.             I2C_SendData( I2C1, OLED_GRAM[n][i] );
  186.             }
  187.             while( !I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED ) );
  188.         }

  189.         I2C_GenerateSTOP( I2C1, ENABLE );
  190.   }

  191. }
  192. //清屏函数
  193. void OLED_Clear(void)
  194. {
  195.     uint8_t i,n;
  196.     for(i=0;i<8;i++)
  197.     {
  198.        for(n=0;n<128;n++)
  199.         {
  200.          OLED_GRAM[n][i]=0;//清除所有数据
  201.         }
  202.   }
  203.     OLED_Refresh();//更新显示
  204. }

  205. //画点
  206. //x:0~127
  207. //y:0~63
  208. //t:1 填充 0,清空
  209. void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t)
  210. {
  211.     uint8_t i,m,n;
  212.     i=y/8;
  213.     m=y%8;
  214.     n=1<<m;
  215.     if(t){OLED_GRAM[x][i]|=n;}
  216.     else
  217.     {
  218.         OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  219.         OLED_GRAM[x][i]|=n;
  220.         OLED_GRAM[x][i]=~OLED_GRAM[x][i];
  221.     }
  222. }

  223. //画线
  224. //x1,y1:起点坐标
  225. //x2,y2:结束坐标
  226. void OLED_DrawLine(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t mode)
  227. {
  228.     uint16_t t;
  229.     int xerr=0,yerr=0,delta_x,delta_y,distance;
  230.     int incx,incy,uRow,uCol;
  231.     delta_x=x2-x1; //计算坐标增量
  232.     delta_y=y2-y1;
  233.     uRow=x1;//画线起点坐标
  234.     uCol=y1;
  235.     if(delta_x>0)incx=1; //设置单步方向
  236.     else if (delta_x==0)incx=0;//垂直线
  237.     else {incx=-1;delta_x=-delta_x;}
  238.     if(delta_y>0)incy=1;
  239.     else if (delta_y==0)incy=0;//水平线
  240.     else {incy=-1;delta_y=-delta_x;}
  241.     if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
  242.     else distance=delta_y;
  243.     for(t=0;t<distance+1;t++)
  244.     {
  245.         OLED_DrawPoint(uRow,uCol,mode);//画点
  246.         xerr+=delta_x;
  247.         yerr+=delta_y;
  248.         if(xerr>distance)
  249.         {
  250.             xerr-=distance;
  251.             uRow+=incx;
  252.         }
  253.         if(yerr>distance)
  254.         {
  255.             yerr-=distance;
  256.             uCol+=incy;
  257.         }
  258.     }
  259. }
  260. //x,y:圆心坐标
  261. //r:圆的半径
  262. void OLED_DrawCircle(uint8_t x,uint8_t y,uint8_t r)
  263. {
  264.     int Na, Nb,num;
  265.     Na = 0;
  266.     Nb = r;
  267.     while(2 * Nb * Nb >= r * r)
  268.     {
  269.         OLED_DrawPoint(x + Na, y - Nb,1);
  270.         OLED_DrawPoint(x - Na, y - Nb,1);
  271.         OLED_DrawPoint(x - Na, y + Nb,1);
  272.         OLED_DrawPoint(x + Na, y + Nb,1);

  273.         OLED_DrawPoint(x + Nb, y + Na,1);
  274.         OLED_DrawPoint(x + Nb, y - Na,1);
  275.         OLED_DrawPoint(x - Nb, y - Na,1);
  276.         OLED_DrawPoint(x - Nb, y + Na,1);

  277.         Na++;
  278.         num = (Na * Na + Nb * Nb) - r*r;//计算画的点离圆心的距离
  279.         if(num > 0)
  280.         {
  281.             Nb--;
  282.             Na--;
  283.         }
  284.     }
  285. }

  286. //在指定位置显示一个字符,包括部分字符
  287. //x:0~127
  288. //y:0~63
  289. //size1:选择字体 6x8/6x12/8x16/12x24
  290. //mode:0,反色显示;1,正常显示
  291. void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t size1,uint8_t mode)
  292. {
  293.     uint8_t i,m,temp,size2,chr1;
  294.     uint8_t x0=x,y0=y;
  295.     if(size1==8)size2=6;
  296.     else size2=(size1/8+((size1%8)?1:0))*(size1/2);  //得到字体一个字符对应点阵集所占的字节数
  297.     chr1=chr-' ';  //计算偏移后的值
  298.     for(i=0;i<size2;i++)
  299.     {
  300.         if(size1==8)
  301.               {temp=asc2_0806[chr1][i];} //调用0806字体
  302.         else if(size1==12)
  303.         {temp=asc2_1206[chr1][i];} //调用1206字体
  304.         else if(size1==16)
  305.         {temp=asc2_1608[chr1][i];} //调用1608字体
  306.         else if(size1==24)
  307.         {temp=asc2_2412[chr1][i];} //调用2412字体
  308.         else return;
  309.         for(m=0;m<8;m++)
  310.         {
  311.             if(temp&0x01)OLED_DrawPoint(x,y,mode);
  312.             else OLED_DrawPoint(x,y,!mode);
  313.             temp>>=1;
  314.             y++;
  315.         }
  316.         x++;
  317.         if((size1!=8)&&((x-x0)==size1/2))
  318.         {x=x0;y0=y0+8;}
  319.         y=y0;
  320.   }
  321. }


  322. //显示字符串
  323. //x,y:起点坐标
  324. //size1:字体大小
  325. //*chr:字符串起始地址
  326. //mode:0,反色显示;1,正常显示
  327. void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t size1,uint8_t mode)
  328. {
  329.     while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
  330.     {
  331.         OLED_ShowChar(x,y,*chr,size1,mode);
  332.         if(size1==8)x+=6;
  333.         else x+=size1/2;
  334.         chr++;
  335.   }
  336. }

  337. //m^n
  338. uint32_t OLED_Pow(uint8_t m,uint8_t n)
  339. {
  340.     uint32_t result=1;
  341.     while(n--)
  342.     {
  343.       result*=m;
  344.     }
  345.     return result;
  346. }

  347. //显示数字
  348. //x,y :起点坐标
  349. //num :要显示的数字
  350. //len :数字的位数
  351. //size:字体大小
  352. //mode:0,反色显示;1,正常显示
  353. void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size1,uint8_t mode)
  354. {
  355.     uint8_t t,temp,m=0;
  356.     if(size1==8)m=2;
  357.     for(t=0;t<len;t++)
  358.     {
  359.         temp=(num/OLED_Pow(10,len-t-1))%10;
  360.             if(temp==0)
  361.             {
  362.                 OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
  363.       }
  364.             else
  365.             {
  366.               OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
  367.             }
  368.   }
  369. }

  370. //显示汉字
  371. //x,y:起点坐标
  372. //num:汉字对应的序号
  373. //mode:0,反色显示;1,正常显示
  374. void OLED_ShowChinese(uint8_t x,uint8_t y,uint8_t num,uint8_t size1,uint8_t mode)
  375. {
  376.     uint8_t m,temp;
  377.     uint8_t x0=x,y0=y;
  378.     uint16_t i,size3=(size1/8+((size1%8)?1:0))*size1;  //得到字体一个字符对应点阵集所占的字节数
  379.     for(i=0;i<size3;i++)
  380.     {
  381.         if(size1==16)
  382.                 {temp=Hzk1[num][i];}//调用16*16字体
  383.         else if(size1==24)
  384.                 {temp=Hzk2[num][i];}//调用24*24字体
  385.         else if(size1==32)
  386.                 {temp=Hzk3[num][i];}//调用32*32字体
  387.         else if(size1==64)
  388.                 {temp=Hzk4[num][i];}//调用64*64字体
  389.         else return;
  390.         for(m=0;m<8;m++)
  391.         {
  392.             if(temp&0x01)OLED_DrawPoint(x,y,mode);
  393.             else OLED_DrawPoint(x,y,!mode);
  394.             temp>>=1;
  395.             y++;
  396.         }
  397.         x++;
  398.         if((x-x0)==size1)
  399.         {x=x0;y0=y0+8;}
  400.         y=y0;
  401.     }
  402. }

  403. //num 显示汉字的个数
  404. //space 每一遍显示的间隔
  405. //mode:0,反色显示;1,正常显示
  406. void OLED_ScrollDisplay(uint8_t num,uint8_t space,uint8_t mode)
  407. {
  408.     uint8_t i,n,t=0,m=0,r;
  409.     while(1)
  410.     {
  411.         if(m==0)
  412.         {
  413.         OLED_ShowChinese(128,24,t,16,mode); //写入一个汉字保存在OLED_GRAM[][]数组中
  414.             t++;
  415.         }
  416.         if(t==num)
  417.             {
  418.                 for(r=0;r<16*space;r++)      //显示间隔
  419.                  {
  420.                     for(i=1;i<144;i++)
  421.                         {
  422.                             for(n=0;n<8;n++)
  423.                             {
  424.                                 OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
  425.                             }
  426.                         }
  427.            OLED_Refresh();
  428.                  }
  429.         t=0;
  430.       }
  431.         m++;
  432.         if(m==16){m=0;}
  433.         for(i=1;i<144;i++)   //实现左移
  434.         {
  435.             for(n=0;n<8;n++)
  436.             {
  437.                 OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
  438.             }
  439.         }
  440.         OLED_Refresh();
  441.     }
  442. }

  443. //x,y:起点坐标
  444. //sizex,sizey,图片长宽
  445. //BMP[]:要写入的图片数组
  446. //mode:0,反色显示;1,正常显示
  447. void OLED_ShowPicture(uint8_t x,uint8_t y,uint8_t sizex,uint8_t sizey,uint8_t BMP[],uint8_t mode)
  448. {
  449.     uint16_t j=0;
  450.     uint8_t i,n,temp,m;
  451.     uint8_t x0=x,y0=y;
  452.     sizey=sizey/8+((sizey%8)?1:0);
  453.     for(n=0;n<sizey;n++)
  454.     {
  455.          for(i=0;i<sizex;i++)
  456.          {
  457.                 temp=BMP[j];
  458.                 j++;
  459.                 for(m=0;m<8;m++)
  460.                 {
  461.                     if(temp&0x01)OLED_DrawPoint(x,y,mode);
  462.                     else OLED_DrawPoint(x,y,!mode);
  463.                     temp>>=1;
  464.                     y++;
  465.                 }
  466.                 x++;
  467.                 if((x-x0)==sizex)
  468.                 {
  469.                     x=x0;
  470.                     y0=y0+8;
  471.                 }
  472.                 y=y0;
  473.      }
  474.      }
  475. }

编译下载.查看OLED现象:
M5.gif





lzbf 发表于 2021-2-21 20:26 | 显示全部楼层
可以移植lvgl到这个处理器吗   
lzbf 发表于 2021-2-21 20:30 | 显示全部楼层
               
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

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