本帖最后由 jinglixixi_457498010 于 2022-7-4 09:39 编辑

CH32V307开发板是一款评估板,故其外设的配置较为简单,要想丰富自己的外设资源,可通过扩展接口来实现。
作为人机交互的重要桥梁,显示功能是不可或缺的,否则只能靠串口来观察结果,这会感到十分的不便。
这里选用的显示器件是一款I2C接口的双色OLED屏,可直接与扩展接口相连接。
为便于插接使用,OLED屏与开发板的连接关系为:
CLK---PB13
DIN---PB14
由于是初次以RT-Thread Studio在CH32V307上驱动OLED屏显示,这里是直接使用所掌握的GPIO口用法,以软件模拟的方式来驱动OLED屏显示。
完成,对2个引脚输出高低电平的语句设置为:
#define OLED_SCLK_Set() GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_SET)
#define OLED_SCLK_Clr() GPIO_WriteBit(GPIOB, GPIO_Pin_13, Bit_RESET)
#define OLED_SDIN_Set()  GPIO_WriteBit(GPIOB,GPIO_Pin_14, Bit_SET)
#define OLED_SDIN_Clr() GPIO_WriteBit(GPIOB, GPIO_Pin_14, Bit_RESET)

对OLED屏所用引脚的配置函数:
void app_OLED_Init(void)
  • {
  •     GPIO_InitTypeDef GPIO_InitStructure = {0};
  •     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  •     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14;
  •     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  •     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  •     GPIO_Init(GPIOB, &GPIO_InitStructure);
  • }
  • 复制代码

    以软件方式模拟字节数据发送的函数为:
    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();
  •         Delay_Us1(2);
  •         da=da<<1;
  •         OLED_SCLK_Set();
  •         Delay_Us1(2);
  •         OLED_SCLK_Clr();
  •         Delay_Us1(2);
  •      }
  • }
  • 复制代码
    由于CH32V307的主频速度比较高,为此在控制GPIO口输出高低电平信号时,需加相应的延时以保证信号的可靠的产生作用。
    以字节数据模拟发送为基础,实现字符显示的函数为:
    void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t 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);
  •          }
  • }
  • 复制代码
    以字符显示函数为依托,字符串显示函数的内容为:
    void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t 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(uint8_t x,uint8_t y,uint8_t no)
  • {
  •     uint8_t 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;
  •     }
  • }
  • 复制代码
    有了以上函数的支持,通过主程序的设计就可实现图1和图2的显示显示,其相应的主程序为:
    int main(void)
  • {
  •     rt_kprintf("MCU: CH32V307\n");
  •     rt_kprintf("SysClk: %dHz\n",SystemCoreClock);
  •     rt_kprintf("www.wch.cn\n");
  •     LED1_BLINK_INIT();
  •     LED2_BLINK_INIT();
  •     GPIO_ResetBits(GPIOA,GPIO_Pin_0);
  •     app_OLED_Init();
  •     OLED_Init();
  •     OLED_Clear();
  •     OLED_ShowString(0,0,"CH32V307 TEST",16);
  •     OLED_ShowString(0,2,"OLED Display",16);
  •     OLED_ShowCHinese(0,4,0);
  •     OLED_ShowCHinese(20,4,1);
  •     OLED_ShowCHinese(40,4,2);
  •     OLED_ShowCHinese(60,4,3);
  •     OLED_ShowCHinese(80,4,4);
  •     OLED_ShowCHinese(100,4,5);
  •     OLED_ShowCHinese(30,6,6);
  •     OLED_ShowCHinese(50,6,7);
  •     OLED_ShowCHinese(70,6,8);
  •     while(1)
  •    {
  •              GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
  •              GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_SET);
  •              rt_thread_mdelay(500);
  •              GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
  •              GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
  •              rt_thread_mdelay(500);
  •     }
  • }
  • 复制代码
    经程序的编译下载,即可观察到预期的效果。
    image.png
    图1 显示字符效果
    image.png
    图2显示中文效果
    通过OLED屏驱动功能的实现,既得到了预期的设计目标,有巩固了对GPIO口的掌握,可谓是一举多得。